Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Codex CLI-first multi-account OAuth manager for the official `@openai/codex` CLI
### Option A: Standard install

```bash
npm i -g @openai/codex
npm i -g codex-multi-auth
```

Expand All @@ -74,16 +75,18 @@ codex auth status

### Step-by-step

1. Install global package:
1. Install global packages:
- `npm i -g @openai/codex`
- `npm i -g codex-multi-auth`
2. Run first login flow with `codex auth login`
3. Validate state with `codex auth status` and `codex auth check`
3. Validate state with `codex auth list` and `codex auth check`
4. Confirm routing with `codex auth forecast --live`

### Verification

```bash
codex auth status
codex auth list
codex auth check
```

Expand All @@ -95,7 +98,7 @@ codex auth check

```bash
codex auth login
codex auth status
codex auth list
codex auth check
codex auth forecast --live
```
Expand Down
44 changes: 36 additions & 8 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,24 +89,52 @@ codex auth doctor --json

---

## Soft Reset
## Reset Options

PowerShell:
- Delete a single saved account: `codex auth login` → pick account → **Delete Account**
- Delete saved accounts: `codex auth login` → Danger Zone → **Delete Saved Accounts**
- Reset local state: `codex auth login` → Danger Zone → **Reset Local State**

Exact effects:

| Action | Saved accounts | Flagged/problem accounts | Settings | Codex CLI sync state | Quota cache |
| --- | --- | --- | --- | --- | --- |
| Delete Account | Delete the selected saved account | Delete the matching flagged/problem entry for that refresh token | Keep | Keep | Keep |
| Delete Saved Accounts | Delete all saved accounts | Keep | Keep | Keep | Keep |
| Reset Local State | Delete all saved accounts | Delete all flagged/problem accounts | Keep | Keep | Clear |

To perform the same actions manually:

Delete saved accounts only:

```powershell
Remove-Item "$HOME\.codex\multi-auth\openai-codex-accounts.json" -Force -ErrorAction SilentlyContinue
Remove-Item "$HOME\.codex\multi-auth\openai-codex-flagged-accounts.json" -Force -ErrorAction SilentlyContinue
Remove-Item "$HOME\.codex\multi-auth\settings.json" -Force -ErrorAction SilentlyContinue
codex auth login
Remove-Item "$HOME\.codex\multi-auth\openai-codex-accounts.json.wal" -Force -ErrorAction SilentlyContinue
Remove-Item "$HOME\.codex\multi-auth\openai-codex-accounts.json.bak*" -Force -ErrorAction SilentlyContinue
```

```bash
rm -f ~/.codex/multi-auth/openai-codex-accounts.json
rm -f ~/.codex/multi-auth/openai-codex-accounts.json.wal
rm -f ~/.codex/multi-auth/openai-codex-accounts.json.bak*
```

Bash:
Reset local state (also clears flagged/problem accounts and quota cache; preserves settings and Codex CLI sync state):

```powershell
Remove-Item "$HOME\.codex\multi-auth\openai-codex-accounts.json" -Force -ErrorAction SilentlyContinue
Remove-Item "$HOME\.codex\multi-auth\openai-codex-accounts.json.wal" -Force -ErrorAction SilentlyContinue
Remove-Item "$HOME\.codex\multi-auth\openai-codex-accounts.json.bak*" -Force -ErrorAction SilentlyContinue
Remove-Item "$HOME\.codex\multi-auth\openai-codex-flagged-accounts.json" -Force -ErrorAction SilentlyContinue
Remove-Item "$HOME\.codex\multi-auth\quota-cache.json" -Force -ErrorAction SilentlyContinue
```

```bash
rm -f ~/.codex/multi-auth/openai-codex-accounts.json
rm -f ~/.codex/multi-auth/openai-codex-accounts.json.wal
rm -f ~/.codex/multi-auth/openai-codex-accounts.json.bak*
rm -f ~/.codex/multi-auth/openai-codex-flagged-accounts.json
rm -f ~/.codex/multi-auth/settings.json
codex auth login
rm -f ~/.codex/multi-auth/quota-cache.json
```

---
Expand Down
70 changes: 53 additions & 17 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ import {
} from "./lib/logger.js";
import { checkAndNotify } from "./lib/auto-update-checker.js";
import { handleContextOverflow } from "./lib/context-overflow.js";
import {
DESTRUCTIVE_ACTION_COPY,
deleteAccountAtIndex,
deleteSavedAccounts,
resetLocalState,
} from "./lib/destructive-actions.js";
import {
AccountManager,
getAccountIdCandidates,
Expand All @@ -122,13 +128,11 @@ import {
loadAccounts,
saveAccounts,
withAccountStorageTransaction,
clearAccounts,
setStoragePath,
exportAccounts,
importAccounts,
loadFlaggedAccounts,
saveFlaggedAccounts,
clearFlaggedAccounts,
findMatchingAccountIndex,
StorageError,
formatStorageErrorHint,
Expand Down Expand Up @@ -3101,19 +3105,32 @@ while (attempted.size < Math.max(1, accountCount)) {

if (menuResult.mode === "manage") {
if (typeof menuResult.deleteAccountIndex === "number") {
const target = workingStorage.accounts[menuResult.deleteAccountIndex];
if (target) {
workingStorage.accounts.splice(menuResult.deleteAccountIndex, 1);
clampActiveIndices(workingStorage);
await saveAccounts(workingStorage);
await saveFlaggedAccounts({
version: 1,
accounts: flaggedStorage.accounts.filter(
(flagged) => flagged.refreshToken !== target.refreshToken,
),
try {
const deleted = await deleteAccountAtIndex({
storage: workingStorage,
index: menuResult.deleteAccountIndex,
});
invalidateAccountManagerCache();
console.log(`\nDeleted ${target.email ?? `Account ${menuResult.deleteAccountIndex + 1}`}.\n`);
if (deleted) {
Object.assign(workingStorage, deleted.storage);
Object.assign(flaggedStorage, deleted.flagged);
invalidateAccountManagerCache();
Comment on lines +3113 to +3116
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Object.assign calls are dead code in current control flow.

deleteAccountAtIndex persists changes internally (per lib/destructive-actions.ts two-phase write). after this block, line 3131 hits continue, jumping back to the top of the while(true) loop at line 3029 where workingStorage and flaggedStorage are reloaded from disk anyway. these assignments update local vars that are immediately discarded.

either remove the Object.assign calls or, if keeping them for future use (e.g., skipping reload on the next iteration), add a comment explaining why.

🧹 suggested cleanup
 if (deleted) {
-  Object.assign(workingStorage, deleted.storage);
-  Object.assign(flaggedStorage, deleted.flagged);
   invalidateAccountManagerCache();
   const label =
     deleted.removedAccount.email?.trim() ||
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@index.ts` around lines 3113 - 3116, The Object.assign calls that copy
deleted.storage into workingStorage and deleted.flagged into flaggedStorage
(followed by invalidateAccountManagerCache()) are dead code because
deleteAccountAtIndex performs a two-phase write and the loop immediately
continues and reloads workingStorage/flaggedStorage; either remove those
Object.assign lines and the subsequent invalidateAccountManagerCache() call, or
keep them but add a clear comment in the block (referencing deleted,
workingStorage, flaggedStorage, invalidateAccountManagerCache,
deleteAccountAtIndex) explaining that these assignments are intentionally
retained to support a future optimization to skip the reload on the next
iteration; implement one of those two options.

const label =
deleted.removedAccount.email?.trim() ||
`Account ${menuResult.deleteAccountIndex + 1}`;
const flaggedNote =
deleted.removedFlaggedCount > 0
? ` Removed ${deleted.removedFlaggedCount} matching problem account${deleted.removedFlaggedCount === 1 ? "" : "s"}.`
: "";
console.log(`\nDeleted ${label}.${flaggedNote}\n`);
}
} catch (error) {
const code = (error as NodeJS.ErrnoException | undefined)
?.code;
console.log(
code
? `\nFailed to delete account (${code}). Please retry.\n`
: "\nFailed to delete account. Please retry.\n",
);
}
continue;
}
Expand Down Expand Up @@ -3143,16 +3160,35 @@ while (attempted.size < Math.max(1, accountCount)) {
if (menuResult.mode === "fresh") {
startFresh = true;
if (menuResult.deleteAll) {
await clearAccounts();
await clearFlaggedAccounts();
const result = await deleteSavedAccounts();
invalidateAccountManagerCache();
console.log(
"\nCleared saved accounts from active storage. Recovery snapshots remain available. Starting fresh.\n",
`\n${
result.accountsCleared
? DESTRUCTIVE_ACTION_COPY.deleteSavedAccounts.completed
: "Delete saved accounts completed with warnings. Some saved account artifacts could not be removed; see logs."
}\n`,
);
}
break;
}

if (menuResult.mode === "reset") {
startFresh = true;
const result = await resetLocalState();
invalidateAccountManagerCache();
console.log(
`\n${
result.accountsCleared &&
result.flaggedCleared &&
result.quotaCacheCleared
? DESTRUCTIVE_ACTION_COPY.resetLocalState.completed
: "Reset local state completed with warnings. Some local artifacts could not be removed; see logs."
}\n`,
);
break;
}

startFresh = false;
break;
}
Expand Down
Loading