Skip to content
Merged
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
5 changes: 5 additions & 0 deletions docs/reference/storage-paths.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Override root:
| Accounts backup | `~/.codex/multi-auth/openai-codex-accounts.json.bak` |
| Accounts WAL | `~/.codex/multi-auth/openai-codex-accounts.json.wal` |
| Flagged accounts | `~/.codex/multi-auth/openai-codex-flagged-accounts.json` |
| Flagged accounts backup | `~/.codex/multi-auth/openai-codex-flagged-accounts.json.bak` |
| Quota cache | `~/.codex/multi-auth/quota-cache.json` |
| Logs | `~/.codex/multi-auth/logs/codex-plugin/` |
| Cache | `~/.codex/multi-auth/cache/` |
Expand All @@ -36,6 +37,10 @@ Ownership note:
- `~/.codex/multi-auth/*` is managed by this project.
- `~/.codex/accounts.json` and `~/.codex/auth.json` are managed by official Codex CLI.

Backup metadata:

- `getBackupMetadata()` reports deterministic snapshot lists for the canonical account pool (primary, WAL, `.bak`, `.bak.1`, `.bak.2`, and discovered manual backups) and flagged-account state (primary, `.bak`, `.bak.1`, `.bak.2`, and discovered manual backups). Cache-like artifacts and `.reset-intent` markers are excluded from recovery candidates.

---

## Project-Scoped Account Paths
Expand Down
4 changes: 3 additions & 1 deletion index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3180,7 +3180,9 @@ while (attempted.size < Math.max(1, accountCount)) {
await clearAccounts();
await clearFlaggedAccounts();
invalidateAccountManagerCache();
console.log("\nDeleted all accounts. Starting fresh.\n");
console.log(
"\nCleared saved accounts from active storage. Recovery snapshots remain available. Starting fresh.\n",
);
}
break;
}
Expand Down
10 changes: 3 additions & 7 deletions lib/codex-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
type QuotaCacheEntry,
} from "./quota-cache.js";
import {
clearAccounts,
getStoragePath,
loadFlaggedAccounts,
loadAccounts,
Expand Down Expand Up @@ -3650,12 +3651,7 @@ async function runDoctor(args: string[]): Promise<number> {
}

async function clearAccountsAndReset(): Promise<void> {
await saveAccounts({
version: 3,
accounts: [],
activeIndex: 0,
activeIndexByFamily: {},
});
await clearAccounts();
}

async function handleManageAction(
Expand Down Expand Up @@ -3808,7 +3804,7 @@ async function runAuthLogin(): Promise<number> {
if (menuResult.mode === "fresh" && menuResult.deleteAll) {
await runActionPanel("Reset Accounts", "Deleting all saved accounts", async () => {
await clearAccountsAndReset();
console.log("Deleted all accounts.");
console.log("Cleared saved accounts from active storage. Recovery snapshots remain available.");
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}, displaySettings);
continue;
}
Expand Down
27 changes: 26 additions & 1 deletion lib/runtime-paths.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { homedir } from "node:os";
import { join, win32 } from "node:path";
import { join, normalize, win32 } from "node:path";
import { existsSync, readdirSync } from "node:fs";

function firstNonEmpty(values: Array<string | undefined>): string | null {
Expand Down Expand Up @@ -72,6 +72,22 @@ function deduplicatePaths(paths: string[]): string[] {
return result;
}

function pathsEqualNormalized(a: string, b: string): boolean {
const normalizePath = (value: string): string => {
const trimmed = value.trim();
if (process.platform === "win32") {
const normalized = win32.normalize(trimmed);
const root = win32.parse(normalized).root;
const withoutTrailing =
normalized === root ? normalized : normalized.replace(/[\\/]+$/, "");
return withoutTrailing.toLowerCase();
}
const normalized = normalize(trimmed);
return normalized === "/" ? "/" : normalized.replace(/\/+$/, "");
};
return normalizePath(a) === normalizePath(b);
}
Comment thread
greptile-apps[bot] marked this conversation as resolved.

/**
* Detects whether a directory contains known Codex storage indicators.
*
Expand Down Expand Up @@ -169,13 +185,22 @@ export function getCodexMultiAuthDir(): string {
return fromEnv;
}

const codexHomeFromEnv = (process.env.CODEX_HOME ?? "").trim();
const defaultCodexHome = join(getResolvedUserHomeDir(), ".codex");
const isExplicitNonDefaultHome =
codexHomeFromEnv.length > 0 && !pathsEqualNormalized(codexHomeFromEnv, defaultCodexHome);

const primary = join(getCodexHomeDir(), "multi-auth");
const fallbackCandidates = deduplicatePaths([
...getFallbackCodexHomeDirs().map((dir) => join(dir, "multi-auth")),
getLegacyCodexDir(),
]);
const orderedCandidates = deduplicatePaths([primary, ...fallbackCandidates]);

if (isExplicitNonDefaultHome) {
return primary;
}

// Prefer candidates that actually contain account storage. This prevents
// accidentally switching to a fresh empty directory that only has settings files.
for (const candidate of orderedCandidates) {
Expand Down
Loading