feat(check): show quota reset timestamps in check output (#633)#634
Conversation
`codex-multi-auth check` printed the percentage left in each quota window but never said when those windows reset, so users had to look the reset time up elsewhere. Append the absolute reset clock to each window in the `check` health line: live session OK (5h 100%, resets 18:10 | 7d 93%, resets 13:50 on Jul 29) Reuses the existing reset formatter from `lib/quota-probe.ts` (exported as `formatQuotaResetAt` and given an injectable `now` for deterministic tests) rather than introducing a second reset format. Times are local, 24-hour, and gain a day suffix once the reset is past midnight. The reset suffix is opt-in via `CompactQuotaFormatOptions.showReset`, so the width-constrained surfaces that share these formatters -- dashboard rows, the account menu, and `forecast` -- keep their existing output. `formatQuotaSnapshotForDashboard` is the only `check` caller and is the sole place that opts in. Also widen the `styleQuotaSummary` segment pattern to accept the reset suffix. Without this the appended text fails the anchored percent match and every quota segment silently falls back to the muted tone, losing the red/yellow/green quota colouring. A missing or malformed reset timestamp drops only the reset clause; the percentage and the account check itself are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xetj6c94ZqD7a5n7G9M5Ro
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
📝 WalkthroughWalkthroughquota reset timestamps are now formatted locally, threaded through quota summaries, displayed by Changesquota reset details
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant authCheck
participant quotaProbe
participant quotaFormatters
participant terminal
authCheck->>quotaProbe: live-probe stored account
quotaProbe-->>authCheck: quota percentages and resetAtMs
authCheck->>quotaFormatters: format account quota summary
quotaFormatters-->>terminal: live session OK with reset details
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/reference/commands.md`:
- Around line 47-76: The command documentation incorrectly says check probes
only enabled accounts and omits the required release note. Update the
description to say it processes each configured/stored account, matching the
behavior in health-check.ts around the account iteration and re-enable path; add
an upgrade note describing the changed output and explicitly state whether any
npm scripts changed, keeping the documented flags and workflow consistent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: cb630094-f90d-4922-bdf8-ddddfe0fa7f1
📒 Files selected for processing (6)
docs/features.mddocs/reference/commands.mdlib/codex-manager/formatters/quota-formatters.tslib/codex-manager/health-check.tslib/quota-probe.tstest/codex-manager-formatters.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (14)
docs/features.md
📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)
Update
docs/features.mdfor capability coverage changes
Files:
docs/features.md
docs/**/*.md
📄 CodeRabbit inference engine (docs/STYLE_GUIDE.md)
docs/**/*.md: User-facing documentation should follow the page template: Title and one-line lead, Quick path commands, Core operational workflow, Troubleshooting or failure handling, and Related links
Use short sections and scan-friendly tables in documentation where they improve clarity
Prefer direct, actionable language in documentation
Use runnable command examples in documentation
Explain expected outcomes after critical commands in documentation
Keep terminology consistent with runtime names in documentation
Avoid speculative language when behavior is deterministic in documentation
Put the user problem in the first paragraph before implementation detail
Use descriptive page titles such ascodex-multi-auth Featuresinstead of generic titles on public docs
Do not repeat keyword lists in every section; search terms should appear only where they help a developer understand the page
Canonical command family iscodex-multi-auth ...
Canonical runtime root is~/.codex/multi-auth
Runtime rotation must be described as default-on unless the release policy changes
Legacy command/path references belong only in migration contexts in documentation
Compatibility aliases (codex multi auth,codex multi-auth,codex multiauth) belong only in command reference, troubleshooting, or migration contexts
Keep command flags aligned with runtime usage text in documentation
Avoid non-runnable command snippets in documentation
Avoid conflicting path guidance across documentation
Avoid legacy-first onboarding language in documentation
docs/**/*.md: Document Codex CLI multi-account capabilities, including account management, switching, health checks, recovery, project-scoped storage, runtime rotation, governance, and local bridge integrations.
Keep governance data local under~/.codex/multi-auth; this is not a hosted multi-user service.
Usage ledger entries must be redacted and must not contain prompts or tokens.
Accountpauseanddrainpolicies must be enforced at runt...
Files:
docs/features.mddocs/reference/commands.md
!{dist,dist/**}/**
📄 CodeRabbit inference engine (AGENTS.md)
Source code lives in root
index.ts,lib/, andscripts/directories;dist/is generated output and should not be edited
Files:
docs/features.mddocs/reference/commands.mdtest/codex-manager-formatters.test.tslib/quota-probe.tslib/codex-manager/health-check.tslib/codex-manager/formatters/quota-formatters.ts
docs/**
⚙️ CodeRabbit configuration file
keep README, SECURITY, and docs consistent with actual CLI flags and workflows. whenever behavior changes, require updated upgrade notes and mention new npm scripts.
Files:
docs/features.mddocs/reference/commands.md
docs/reference/**/*.md
📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)
Update relevant command/settings/path references in reference documentation when runtime changes occur
New flags/settings/paths must be reflected in
docs/reference/*
Files:
docs/reference/commands.md
docs/reference/commands.md
📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)
Verify CLI flags documented in references match runtime parser/usage output
Files:
docs/reference/commands.md
test/**/*.test.ts
📄 CodeRabbit inference engine (test/AGENTS.md)
test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js
Files:
test/codex-manager-formatters.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Do not use
as any,@ts-ignore, or@ts-expect-errorTypeScript escape hatches
Files:
test/codex-manager-formatters.test.tslib/quota-probe.tslib/codex-manager/health-check.tslib/codex-manager/formatters/quota-formatters.ts
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
Do not hardcode OAuth ports; use existing constants/helpers for port configuration
Files:
test/codex-manager-formatters.test.tslib/quota-probe.tslib/codex-manager/health-check.tslib/codex-manager/formatters/quota-formatters.ts
{scripts,test}/**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
Do not use bare recursive delete logic in Windows-sensitive scripts/tests without retry handling for transient
EBUSY/EPERM/ENOTEMPTYerrors
Files:
test/codex-manager-formatters.test.ts
**/*.{js,ts,mjs,cjs}
📄 CodeRabbit inference engine (README.md)
**/*.{js,ts,mjs,cjs}: Store multi-account OAuth credentials and configuration under~/.codex/multi-auth/directory structure with separate files for settings, accounts, flagged accounts, quota cache, runtime observability, usage ledger, policies, profiles, and budget guards
Allow override of the multi-auth root storage directory via theCODEX_MULTI_AUTH_DIRenvironment variable, defaulting to~/.codex/multi-auth/if not set
Implement runtime account rotation through a loopback-only local proxy that is enabled by default and can be disabled viaCODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY=0environment variable
Respect opt-out flags for automatic Codex app bind installation (CODEX_MULTI_AUTH_APP_BIND_INSTALL=0) and launcher routing installation (CODEX_MULTI_AUTH_APP_LAUNCHER_INSTALL=0), performing these only on first CLI run when opted in
Use request timeout and stream stall timeout environment variable overrides (CODEX_AUTH_FETCH_TIMEOUT_MSandCODEX_AUTH_STREAM_STALL_TIMEOUT_MS) when making OAuth or API requests
Support stateful Responsesbackground: truemode as an opt-in feature viaCODEX_AUTH_BACKGROUND_RESPONSES=1orbackgroundResponsessettings field only when explicitly enabled
Implement bounded outbound request budgets per session to prevent a single prompt from walking the entire account pool indefinitely
Disable whole-pool replay by default when every account is rate-limited and trigger short cooldowns instead of aggressive rotation after repeated cross-account 5xx error bursts
Stagger proactive account refresh operations to reduce background refresh bursts across the account pool
For thecodex-multi-auth-codexwrapper, handleauth ...subcommands locally and forward all other commands to the official Codex CLI without modification
Implement account selection and switching with health-aware logic that considers account quota, cooldown state, and recent runtime metrics
Support project-scoped account storage under `~/.codex/multi-auth/...
Files:
test/codex-manager-formatters.test.tslib/quota-probe.tslib/codex-manager/health-check.tslib/codex-manager/formatters/quota-formatters.ts
test/**
⚙️ CodeRabbit configuration file
tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.
Files:
test/codex-manager-formatters.test.ts
lib/**/*.ts
📄 CodeRabbit inference engine (lib/AGENTS.md)
lib/**/*.ts: All public exports should flow throughlib/index.tsor documented package subpaths
Module dependencies must stay acyclic and follow the layering: types/constants → storage → accounts → runtime → manager/CLI; lower layers must never import from higher ones
Shared types/helpers must belong in the lower layer with higher layers re-exporting for surface compatibility instead of lower layers importing back from facades likelib/storage.ts
Never suppress type errors
Files:
lib/quota-probe.tslib/codex-manager/health-check.tslib/codex-manager/formatters/quota-formatters.ts
lib/**
⚙️ CodeRabbit configuration file
focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.
Files:
lib/quota-probe.tslib/codex-manager/health-check.tslib/codex-manager/formatters/quota-formatters.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T10:26:51.543Z
Learning: Packaged Codex app integration must use reversible configuration and launcher binds rather than patching official app files.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T10:26:51.543Z
Learning: Usage ledger rows must remain local-only and must not contain prompts, tokens, authorization headers, raw account emails, or raw sensitive account IDs.
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.
Applied to files:
test/codex-manager-formatters.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.
Applied to files:
test/codex-manager-formatters.test.ts
🔇 Additional comments (5)
lib/quota-probe.ts (1)
269-295: LGTM!Also applies to: 313-313
lib/codex-manager/formatters/quota-formatters.ts (1)
6-6: LGTM!Also applies to: 33-55, 64-70, 104-166, 172-188
lib/codex-manager/health-check.ts (1)
147-151: LGTM!Also applies to: 259-263
test/codex-manager-formatters.test.ts (1)
13-22: LGTM!Also applies to: 160-291
docs/features.md (1)
17-17: LGTM!
The existing command-level coverage asserted only that the health line contained "live session OK", so it passed whether or not the reset times rendered at all. The formatter was covered; the wiring was not. Add two tests that drive `runCodexMultiAuthCli(["auth", "check"])` through the real health-check and formatter, mocking only the network probe, and assert the printed line: one for both windows carrying a reset clock, one for a window whose reset timestamp is absent or zero. Verified these fail when `showReset` is flipped off, so they pin the behavior rather than passing vacuously. The reset clock is local-timezone, so the day suffix is matched loosely instead of pinned to one zone. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xetj6c94ZqD7a5n7G9M5Ro
The new `check` section claimed it live-probes "each enabled account". It does neither part of that: health-check.ts iterates every stored account, and re-enables a disabled one whose token is still usable (`account.enabled = true`). `fix` is the command that skips disabled accounts, which is where the wrong wording came from. Reported by CodeRabbit on PR #634. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xetj6c94ZqD7a5n7G9M5Ro
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/reference/commands.md (1)
64-69: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick windocument the locale-dependent reset date shape
docs/reference/commands.md:67says resets print asHH:MM on Mon DD, butlib/quota-probe.ts:294andlib/runtime/quota-headers.ts:143usetoLocaleDateString(undefined, { month: "short", day: "2-digit" }), so month text and ordering follow the host locale outside en-US. update the docs or pinen-USin both formatter path andlib/quota-probe.ts:294. also add a regression test for non-US locales if this is an emitted output contract.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/reference/commands.md` around lines 64 - 69, The reset-time documentation incorrectly guarantees an English `Mon DD` shape while formatting uses the host locale. Update the reset-time section in commands.md to describe locale-dependent month text and ordering, and add a regression test covering a non-US locale for the emitted reset output.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/codex-manager-cli.test.ts`:
- Around line 3287-3333: Update the test case around runCodexMultiAuthCli to
freeze Vitest’s clock using the captured now value, provision a second account
whose output crosses a day boundary, and configure its quota data as needed.
Assert the check output for both accounts, verifying each line uses the same
frozen reference time for reset-time formatting; restore the clock after the
test.
- Around line 3354-3369: Update the test case around
quotaProbeMocks.fetchCodexQuotaSnapshot and runCodexMultiAuthCli to provide
primary with a valid resetAtMs while keeping secondary.resetAtMs at 0. Change
the assertion to require mixed output: primary’s reset clause must be present,
while secondary’s reset clause remains omitted.
---
Outside diff comments:
In `@docs/reference/commands.md`:
- Around line 64-69: The reset-time documentation incorrectly guarantees an
English `Mon DD` shape while formatting uses the host locale. Update the
reset-time section in commands.md to describe locale-dependent month text and
ordering, and add a regression test covering a non-US locale for the emitted
reset output.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 45088b26-132a-4623-b251-435d71dc9f80
📒 Files selected for processing (2)
docs/reference/commands.mdtest/codex-manager-cli.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (12)
docs/reference/**/*.md
📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)
Update relevant command/settings/path references in reference documentation when runtime changes occur
New flags/settings/paths must be reflected in
docs/reference/*
Files:
docs/reference/commands.md
docs/reference/commands.md
📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)
Verify CLI flags documented in references match runtime parser/usage output
Files:
docs/reference/commands.md
docs/**/*.md
📄 CodeRabbit inference engine (docs/STYLE_GUIDE.md)
docs/**/*.md: User-facing documentation should follow the page template: Title and one-line lead, Quick path commands, Core operational workflow, Troubleshooting or failure handling, and Related links
Use short sections and scan-friendly tables in documentation where they improve clarity
Prefer direct, actionable language in documentation
Use runnable command examples in documentation
Explain expected outcomes after critical commands in documentation
Keep terminology consistent with runtime names in documentation
Avoid speculative language when behavior is deterministic in documentation
Put the user problem in the first paragraph before implementation detail
Use descriptive page titles such ascodex-multi-auth Featuresinstead of generic titles on public docs
Do not repeat keyword lists in every section; search terms should appear only where they help a developer understand the page
Canonical command family iscodex-multi-auth ...
Canonical runtime root is~/.codex/multi-auth
Runtime rotation must be described as default-on unless the release policy changes
Legacy command/path references belong only in migration contexts in documentation
Compatibility aliases (codex multi auth,codex multi-auth,codex multiauth) belong only in command reference, troubleshooting, or migration contexts
Keep command flags aligned with runtime usage text in documentation
Avoid non-runnable command snippets in documentation
Avoid conflicting path guidance across documentation
Avoid legacy-first onboarding language in documentationDocument the complete
codex-multi-authcapability surface, including account management, forecasting, runtime rotation, governance, recovery, project-scoped storage, terminal workflows, bridge integrations, and optional plugin-host functionality.
Files:
docs/reference/commands.md
!{dist,dist/**}/**
📄 CodeRabbit inference engine (AGENTS.md)
Source code lives in root
index.ts,lib/, andscripts/directories;dist/is generated output and should not be edited
Files:
docs/reference/commands.mdtest/codex-manager-cli.test.ts
docs/**
⚙️ CodeRabbit configuration file
keep README, SECURITY, and docs consistent with actual CLI flags and workflows. whenever behavior changes, require updated upgrade notes and mention new npm scripts.
Files:
docs/reference/commands.md
test/**/*.test.ts
📄 CodeRabbit inference engine (test/AGENTS.md)
test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js
Files:
test/codex-manager-cli.test.ts
test/**/codex-manager-cli.test.ts
📄 CodeRabbit inference engine (test/AGENTS.md)
Test CLI settings management across 5 panels with Q cancel handling in codex-manager-cli.test.ts
Files:
test/codex-manager-cli.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Do not use
as any,@ts-ignore, or@ts-expect-errorTypeScript escape hatches
Files:
test/codex-manager-cli.test.ts
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
Do not hardcode OAuth ports; use existing constants/helpers for port configuration
Files:
test/codex-manager-cli.test.ts
{scripts,test}/**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
Do not use bare recursive delete logic in Windows-sensitive scripts/tests without retry handling for transient
EBUSY/EPERM/ENOTEMPTYerrors
Files:
test/codex-manager-cli.test.ts
**/*.{js,ts,mjs,cjs}
📄 CodeRabbit inference engine (README.md)
**/*.{js,ts,mjs,cjs}: Store multi-account OAuth credentials and configuration under~/.codex/multi-auth/directory structure with separate files for settings, accounts, flagged accounts, quota cache, runtime observability, usage ledger, policies, profiles, and budget guards
Allow override of the multi-auth root storage directory via theCODEX_MULTI_AUTH_DIRenvironment variable, defaulting to~/.codex/multi-auth/if not set
Implement runtime account rotation through a loopback-only local proxy that is enabled by default and can be disabled viaCODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY=0environment variable
Respect opt-out flags for automatic Codex app bind installation (CODEX_MULTI_AUTH_APP_BIND_INSTALL=0) and launcher routing installation (CODEX_MULTI_AUTH_APP_LAUNCHER_INSTALL=0), performing these only on first CLI run when opted in
Use request timeout and stream stall timeout environment variable overrides (CODEX_AUTH_FETCH_TIMEOUT_MSandCODEX_AUTH_STREAM_STALL_TIMEOUT_MS) when making OAuth or API requests
Support stateful Responsesbackground: truemode as an opt-in feature viaCODEX_AUTH_BACKGROUND_RESPONSES=1orbackgroundResponsessettings field only when explicitly enabled
Implement bounded outbound request budgets per session to prevent a single prompt from walking the entire account pool indefinitely
Disable whole-pool replay by default when every account is rate-limited and trigger short cooldowns instead of aggressive rotation after repeated cross-account 5xx error bursts
Stagger proactive account refresh operations to reduce background refresh bursts across the account pool
For thecodex-multi-auth-codexwrapper, handleauth ...subcommands locally and forward all other commands to the official Codex CLI without modification
Implement account selection and switching with health-aware logic that considers account quota, cooldown state, and recent runtime metrics
Support project-scoped account storage under `~/.codex/multi-auth/...
Files:
test/codex-manager-cli.test.ts
test/**
⚙️ CodeRabbit configuration file
tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.
Files:
test/codex-manager-cli.test.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Keep all governance and account data local under `~/.codex/multi-auth`; do not implement it as a hosted multi-user service.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Runtime account rotation must be local-only and default-on for forwarded official Codex Responses/model traffic.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Apply `evaluateRuntimePolicy` before account selection so pause/drain settings, budgets, routing profiles, and capability checks are enforced at runtime.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Per-invocation account force-pins must be ephemeral, fail-hard, and must never modify the persisted `switch` pin.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Keep wrapper-launched CLI provider configuration isolated using a shadow `CODEX_HOME`; do not alter normal official Codex state.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Provide reversible desktop-app binding and launcher routing without patching official Codex application files.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Record usage as redacted local ledger rows and summaries; never store prompts or tokens.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Store bridge client tokens only as hashes and safe prefixes; plain tokens must use the `cma_local_*` form and must not be re-exposed after creation.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Support bridge token lifecycle operations for creation, listing, rotation, and revocation without exposing old secrets.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Use canonical local storage under `~/.codex/multi-auth`, with Storage V3 migrations from older layouts and recovery support for interrupted or partially applied writes.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Support project-scoped account pools while sharing identity across linked worktrees of the same repository.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Synchronize the selected account into official `~/.codex` authentication files when plain Codex use requires it.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Use browser-first OAuth with device-auth and manual callback-paste fallbacks for remote, headless, non-browser, or non-TTY environments.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Provide fast and deep health checks, quota reset visibility, flagged-account verification, safe repair, diagnostics, and backup restore workflows.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:10.485Z
Learning: Expose deterministic CLI and integration entry points for account switching, forecasting, reporting, runtime status, bridge operations, history, and wrapper launching.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:18.390Z
Learning: `codex-multi-auth` is the primary account-manager CLI; compatibility aliases and wrapper entrypoints must preserve their documented routing and forwarding behavior.
Learnt from: CR
Repo: ndycode/codex-multi-auth
Timestamp: 2026-07-23T11:38:18.390Z
Learning: The documented public command, flag, JSON, CSV, exit-code, and non-TTY behaviors are compatibility surfaces and should remain stable.
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.
Applied to files:
test/codex-manager-cli.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.
Applied to files:
test/codex-manager-cli.test.ts
🔇 Additional comments (1)
docs/reference/commands.md (1)
47-81: add the required upgrade note
docs/reference/commands.md:47documents a user-visiblecheckoutput change, but this changed section still has no upgrade note or statement about npm scripts. this is the same unresolved requirement from the prior review; add the note or link to the existing release note and explicitly state whether npm scripts changed.as per coding guidelines, behavior changes require updated upgrade notes and mention of new npm scripts. as per path instructions, docs must stay consistent with actual cli workflows.
Sources: Coding guidelines, Path instructions
| it("check prints the reset time for each quota window", async () => { | ||
| const now = Date.now(); | ||
| storageMocks.loadAccounts.mockResolvedValueOnce({ | ||
| version: 3, | ||
| activeIndex: 0, | ||
| activeIndexByFamily: { codex: 0 }, | ||
| accounts: [ | ||
| { | ||
| accountId: "acc_reset", | ||
| email: "reset@example.com", | ||
| refreshToken: "refresh-reset", | ||
| accessToken: "access-reset", | ||
| expiresAt: now + 60 * 60 * 1000, | ||
| addedAt: now - 1_000, | ||
| lastUsed: now - 1_000, | ||
| enabled: true, | ||
| }, | ||
| ], | ||
| }); | ||
| quotaProbeMocks.fetchCodexQuotaSnapshot.mockResolvedValueOnce({ | ||
| status: 200, | ||
| model: DEFAULT_MODEL, | ||
| primary: { | ||
| usedPercent: 70, | ||
| windowMinutes: 300, | ||
| resetAtMs: now + 3 * 60 * 60 * 1000, | ||
| }, | ||
| secondary: { | ||
| usedPercent: 10, | ||
| windowMinutes: 10080, | ||
| resetAtMs: now + 5 * 24 * 60 * 60 * 1000, | ||
| }, | ||
| }); | ||
| const logSpy = silenceConsole("log"); | ||
| const { runCodexMultiAuthCli } = await import("../lib/codex-manager.js"); | ||
|
|
||
| const exitCode = await runCodexMultiAuthCli(["auth", "check"]); | ||
| expect(exitCode).toBe(0); | ||
|
|
||
| const line = logSpy.mock.calls | ||
| .map((call) => String(call[0])) | ||
| .find((text) => text.includes("live session OK")); | ||
| expect(line).toBeDefined(); | ||
| expect(line).toMatch( | ||
| /live session OK \(5h 30%, resets \d{2}:\d{2}( on \w{3} \d{2})? \| 7d 90%, resets \d{2}:\d{2} on \w{3} \d{2}\)/, | ||
| ); | ||
| }); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
add a multi-account, fixed-clock regression
test/codex-manager-cli.test.ts:3288 captures the wall clock but provisions only one account. that cannot catch a check implementation using different reference times for different output lines, which is part of this pr’s contract. freeze time with vitest and add a second account near a day boundary; assert both lines use the same reference-time behavior.
as per path instructions, tests must stay deterministic and include regression coverage for changed behavior.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test/codex-manager-cli.test.ts` around lines 3287 - 3333, Update the test
case around runCodexMultiAuthCli to freeze Vitest’s clock using the captured now
value, provision a second account whose output crosses a day boundary, and
configure its quota data as needed. Assert the check output for both accounts,
verifying each line uses the same frozen reference time for reset-time
formatting; restore the clock after the test.
Source: Path instructions
| quotaProbeMocks.fetchCodexQuotaSnapshot.mockResolvedValueOnce({ | ||
| status: 200, | ||
| model: DEFAULT_MODEL, | ||
| primary: { usedPercent: 70, windowMinutes: 300 }, | ||
| secondary: { usedPercent: 10, windowMinutes: 10080, resetAtMs: 0 }, | ||
| }); | ||
| const logSpy = silenceConsole("log"); | ||
| const { runCodexMultiAuthCli } = await import("../lib/codex-manager.js"); | ||
|
|
||
| const exitCode = await runCodexMultiAuthCli(["auth", "check"]); | ||
| expect(exitCode).toBe(0); | ||
|
|
||
| const line = logSpy.mock.calls | ||
| .map((call) => String(call[0])) | ||
| .find((text) => text.includes("live session OK")); | ||
| expect(line).toContain("live session OK (5h 30% | 7d 90%)"); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
exercise one missing reset independently
test/codex-manager-cli.test.ts:3357 omits the reset timestamp from primary as well as setting secondary.resetAtMs to 0. the test therefore never proves that one window keeps its reset clause while the other omits it. give primary a valid reset timestamp and assert the mixed output.
as per path instructions, tests must demand regression cases for the changed behavior.
proposed test adjustment
- primary: { usedPercent: 70, windowMinutes: 300 },
+ primary: {
+ usedPercent: 70,
+ windowMinutes: 300,
+ resetAtMs: now + 60 * 60 * 1000,
+ },
secondary: { usedPercent: 10, windowMinutes: 10080, resetAtMs: 0 },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test/codex-manager-cli.test.ts` around lines 3354 - 3369, Update the test
case around quotaProbeMocks.fetchCodexQuotaSnapshot and runCodexMultiAuthCli to
provide primary with a valid resetAtMs while keeping secondary.resetAtMs at 0.
Change the assertion to require mixed output: primary’s reset clause must be
present, while secondary’s reset clause remains omitted.
Source: Path instructions
…dates Two review findings from PR #634, both valid. Greptile: health-check captures `now` once, before the sequential network probes, so threading it into the formatter made the "is today" decision go stale on a run that crosses local midnight. It also silently moved `isQuotaCacheEntryExhausted(snapshot, now)` from call time to run-start time, which was never intended. Reverting health-check.ts to main fixes both -- the formatter's `now` already defaults to `Date.now()` per call, and it stays injectable for tests. CodeRabbit: `formatQuotaResetAt` builds the date half with `toLocaleDateString(undefined, ...)`, so month text and field order follow the host locale. Documenting the output as `HH:MM on Mon DD` claimed a stability the formatter does not provide. The docs now say the date shape is locale-dependent and label the example as en-US. The same assumption was baked into the new command-level regex (`\w{3} \d{2}`), which matches only en-US -- it fails on de-DE (`29. Juli`), ja-JP, fr-FR, and en-GB (`29 Jul`). That assertion is now structural. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xetj6c94ZqD7a5n7G9M5Ro
|
Addressed in 5f3b37e. Both bots found something real. Greptile — stale calendar-day reference ( Correct, and the impact was wider than flagged.
CodeRabbit — locale-dependent reset date: valid, fixed (docs only).
The same assumption was in my new command-level regex, and it was worse than a docs nit —
That assertion is now structural ( Caveat on the "non-US locale regression test" ask: I could not execute one. Node ignores Declined: the
Verification after the changes: Note for anyone reading the checks: GitHub Actions has never run in this repo. 243 runs created, 0 ever completed, oldest stuck since 2026-05-10; every push/PR workflow shows zero runs while Dependabot's sit queued indefinitely. |
Summary
codex-multi-auth check#633:codex-multi-auth checknow prints when each quota window resets, not just how much is left.checkonly. The dashboard, account menu, andforecastshare these formatters and keep their existing width.What Changed
checkhealth lines now carry an absolute reset clock per window:lib/quota-probe.ts— the privateformatResetAtbecomes the exportedformatQuotaResetAt, and takes an injectablenowMsso the same-day branch is testable without freezing the clock. Behavior is otherwise unchanged.lib/codex-manager/formatters/quota-formatters.ts— new opt-inCompactQuotaFormatOptions.showResetthreaded throughformatCompactQuotaSnapshot/formatAccountQuotaSummary.formatQuotaSnapshotForDashboard(the onlycheckcaller, despite the name) opts in.lib/codex-manager/health-check.ts— passes the run's singlenowso every account line in onecheckshares a reference time.codex-multi-auth checksection indocs/reference/commands.mddocumenting the format, the timezone, and the fallbacks;docs/features.mdrow updated.Three deliberate deviations from the issue
Window labels stay derived, not hardcoded. The issue proposes relabeling the second window
5h, but labels come fromwindowMinutes(quota-formatters.ts#L93-L102);quotais the fallback when the backend omits the window length. Hardcoding would print a wrong label for accounts whose headers lack it — which is exactly the case shown in the issue's "current output".Format is
HH:MM/HH:MM on Mon DD, notJul 29, 2026 1:50 PM. The repo already had a reset formatter with this shape, used byformatQuotaSnapshotLine. Adding the issue's 12-hour US-style variant would leave two reset formats in one product, and it costs ~30 extra columns on a line that already carries the account label twice over. Both windows are at most seven days, so the year is never ambiguous. Happy to switch if you'd rather match the issue literally.Scoped to
check, notfix --live.fix --liveprints a nearly identicallive session OK (...)line viarepair-commands.ts, but the issue asks forcheck. Left alone; easy follow-up if wanted.One trap worth calling out
styleQuotaSummarymatched segments against an anchored/^([0-9a-zA-Z]+)\s+(\d{1,3})%$/. Appending, resets ...fails that anchor, so every quota segment would have fallen through to themutedbranch and silently lost its red/yellow/green tone. The pattern now captures the reset tail and mutes only that part, keeping the percentage toned. Covered by a regression test.Validation
npm run lintnpm run typechecknpm test— 5186 passed, 3 skipped (336 files)npm test -- test/documentation.test.tsnpm run buildUnit — nine tests in
test/codex-manager-formatters.test.ts: the opt-in boundary (default output unchanged), both windows rendering resets, same-day vs. next-week formatting, missing/NaN/negative/Infinitytimestamps keeping the percentage, theshowQuotaDetails: falsepath, and thestyleQuotaSummarytone regression. Expectations derive from the sameIntlcalls the formatter uses, so they hold in any timezone rather than pinning one.Command-level — two tests in
test/codex-manager-cli.test.tsdriverunCodexMultiAuthCli(["auth", "check"])through the realrunHealthCheckand the real formatter, mocking onlyfetchCodexQuotaSnapshot, and assert the actual printed line:Both were mutation-checked: flipping
showResettofalsemakes the first fail, so they pin behavior rather than passing vacuously. Worth flagging that the pre-existingcheckassertions matched onlystringContaining("live session OK")and would have passed whether or not reset times rendered at all — the formatter was covered, the wiring was not.End-to-end — the real
scripts/codex-multi-auth.js checkbinary was run against the compileddist/, with a synthetic three-account pool in an isolatedCODEX_MULTI_AUTH_DIRand onlyglobalThis.fetchstubbed to return genuine Codex quota headers. Storage, health-check, formatter, and stdout all ran for real:One run covers same-day vs. next-week formatting (acct 1), a window with no reset header (acct 2,
7d 98%stands alone), and thequotalabel fallback plus a malformedx-codex-secondary-reset-at: "not-a-real-date"(acct 3) — the bad timestamp is dropped and the percentage survives, with no probe failure. Reset input was exercised both as-reset-after-secondsand as an absolute ISO-reset-at.The colour claim above was verified on this same binary by forcing
isTTY. With the fix,100%keeps the green quota tone and only the label and, resets …are dim. Rebuildingdist/with the original anchored regex collapses the whole segment into a single dim wrapper and the green disappears:Still not done: a run against real credentials. This dev machine has no account pool (
No accounts configured; no~/.codex/multi-auth/openai-codex-accounts.json, noprojects/scope), and I did not import the local~/.codex/auth.jsontoken to manufacture one. So every result above uses synthetic headers. Worth onecodex-multi-auth checkon a real account before merging to confirm the live backend's header shape matches what this assumes.Docs and Governance Checklist
docs/getting-started.md— onboarding flow unchangeddocs/features.mdupdateddocs/reference/commands.mdupdateddocs/upgrade.md— no migration behavior changeSECURITY.md/CONTRIBUTING.mdreviewed — no impact; reset times are already-fetched quota metadata, no tokens or emails added to outputRisk and Rollback
resetAtMswas already parsed and cached. Blast radius is bounded byshowResetdefaulting tofalse— every non-checkcaller is byte-identical.Additional Notes
Reset times are rendered in the local system timezone, documented in
docs/reference/commands.md. Users who want a stable zone can setTZ.🤖 Generated with Claude Code
https://claude.ai/code/session_01Xetj6c94ZqD7a5n7G9M5Ro
note: greptile review for oc-chatgpt-multi-auth. cite files like
lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.Greptile Summary
This PR adds quota reset times to the
checkcommand. The main changes are:Confidence Score: 5/5
This looks safe to merge.
Important Files Changed
Reviews (4): Last reviewed commit: "fix(check): drop the stale reference tim..." | Re-trigger Greptile
Context used (4)