Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fc73457
feat(picker): match every profile against the repo, not just the 19 w…
Imdeadpool1 Jul 26, 2026
cce1777
fix(test): make cue handoff tests e2e, drop the global mock.module leak
Imdeadpool1 Jul 26, 2026
36e5075
chore: delete 733 lines of verified dead code
Imdeadpool1 Jul 26, 2026
7e337c7
docs(dead-code): mark the report superseded, record the false-positiv…
Imdeadpool1 Jul 26, 2026
7d34aeb
feat(brief): hand the agent verified facts about the directory it lau…
Imdeadpool1 Jul 27, 2026
7973afe
feat(picker): let the model rerank profile matches, without ever wait…
Imdeadpool1 Jul 27, 2026
7c8494a
feat(picker): scope remembered stacks to the repo you launch in
Imdeadpool1 Jul 27, 2026
b029942
feat(picker): scope pair affinity to the repo you launch in
Imdeadpool1 Jul 27, 2026
c157281
feat(picker): scope Recent by repository, not by path prefix
Imdeadpool1 Jul 27, 2026
5eb0ccd
fix(picker): rank suggested stacks by what you actually launch here
Imdeadpool1 Jul 27, 2026
fdd083b
fix(suggest): score skills on what the user actually said
Imdeadpool1 Jul 27, 2026
ae59ebf
fix(auth): keep concurrent sessions from revoking each other's tokens
Imdeadpool1 Jul 27, 2026
cbeeb6b
fix(auth): read the default account's identity where Claude Code keep…
Imdeadpool1 Jul 28, 2026
6385de5
fix(resolver): follow symlinked skill directories
Imdeadpool1 Aug 5, 2026
120e327
feat(core): keep ego-browser loaded in every project
Imdeadpool1 Aug 7, 2026
788d72d
feat(security): gate freshly-fetched skills through NVIDIA SkillSpector
Imdeadpool1 Aug 7, 2026
8112f7b
fix(materializer): stop unresolving the live runtime path mid-swap
Imdeadpool1 Aug 7, 2026
ceebde6
refactor(picker): pull the shared visual primitives out of card and p…
Imdeadpool1 Aug 7, 2026
062b40a
chore: integrity-protocol wording, tag hooks, two new profiles
Imdeadpool1 Aug 7, 2026
0c0f25b
Merge origin/main into fix/oauth-identity-desync
Imdeadpool1 Aug 7, 2026
c495340
fix(liedetector): one ~N% raster, a drift guard, and hook test covera…
NagyVikt Aug 7, 2026
b0c3400
Merge origin/main into fix/oauth-identity-desync
Imdeadpool1 Aug 7, 2026
a5dc3a1
Merge remote-tracking branch 'origin/main' into fix/oauth-identity-de…
Imdeadpool1 Aug 7, 2026
80a6b47
fix(codex): share AuthMux login with Cue runtimes (#141)
NagyVikt Aug 10, 2026
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# agent-codex-sync-codex-auth-into-cue-runtimes-2026-08-10-11-56 (minimal / T1)

Branch: `agent/<your-name>/<branch-slug>`

Describe the change in a sentence or two. Commit message is the spec of record.

## Handoff

- Handoff: change=`agent-codex-sync-codex-auth-into-cue-runtimes-2026-08-10-11-56`; branch=`agent/<your-name>/<branch-slug>`; scope=`TODO`; action=`continue this sandbox or finish cleanup after a usage-limit/manual takeover`.
- Copy prompt: Continue `agent-codex-sync-codex-auth-into-cue-runtimes-2026-08-10-11-56` on branch `agent/<your-name>/<branch-slug>`. Work inside the existing sandbox, review `openspec/changes/agent-codex-sync-codex-auth-into-cue-runtimes-2026-08-10-11-56/notes.md`, continue from the current state instead of creating a new sandbox, and when the work is done run `gx branch finish --branch agent/<your-name>/<branch-slug> --base dev --via-pr --wait-for-merge --cleanup`.

## Cleanup

- [ ] Run: `gx branch finish --branch agent/<your-name>/<branch-slug> --base dev --via-pr --wait-for-merge --cleanup`
- [ ] Record PR URL + `MERGED` state in the completion handoff.
- [ ] Confirm sandbox worktree is gone (`git worktree list`, `git branch -a`).
# Codex auth sync

- Cause: Cue launches Codex with a profile-isolated `CODEX_HOME`, while AuthMux manages `~/.codex/auth.json`.
- Fix: copy canonical auth into the selected runtime before launch, then copy refreshed runtime auth back after exit.
- Verification: `bun test src/lib/codex-auth-sync.test.ts`; `bunx tsc --noEmit`.
20 changes: 19 additions & 1 deletion src/commands/launch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/

import { spawn } from "node:child_process";
import { readFile } from "node:fs/promises";
import { copyFile, readFile } from "node:fs/promises";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { basename, dirname, join, resolve, sep } from "node:path";
import { homedir } from "node:os";
Expand Down Expand Up @@ -205,6 +205,16 @@ function execAgent(bin: string, args: string[], env: NodeJS.ProcessEnv): Promise
});
}

/** Keep Cue's isolated CODEX_HOME in sync with Codex/AuthMux's canonical auth. */
export async function syncCodexAuth(source: string, destination: string): Promise<boolean> {
try {
await copyFile(source, destination);
return true;
} catch {
return false;
}
}

/**
* Whether the interactive MCP toggle should open this launch. Only when stdin
* is a TTY, AND either the user forced it (`--cue-pick-mcps`) or there's no
Expand Down Expand Up @@ -2712,6 +2722,11 @@ export async function run(args: string[]): Promise<number> {
// re-login.
const stopReconciler =
agentKind === "claude-code" ? startCredentialReconciler(runtimeKey) : undefined;
const canonicalCodexAuth = join(homedir(), ".codex", "auth.json");
const runtimeCodexAuth = join(runtime.runtimeDir, "auth.json");
if (agentKind === "codex") {
await syncCodexAuth(canonicalCodexAuth, runtimeCodexAuth);
}
let exitCode: number;
try {
exitCode = await execAgent(realBin, [...briefArgs, ...parsed.passthrough], childEnv);
Expand All @@ -2721,6 +2736,9 @@ export async function run(args: string[]): Promise<number> {
// Persist any /login done inside the session to its account dir now —
// don't leave the only live rotated token stranded in the per-account runtime.
if (agentKind === "claude-code") await rescueRuntimeCredsToOwner(runtimeKey);
if (agentKind === "codex") {
await syncCodexAuth(runtimeCodexAuth, canonicalCodexAuth);
}
// Post-session runtime GC: the child has exited, so this costs zero launch
// latency. Throttled (~once/day) and never touches the runtime we just used.
try { await maybeAutoGc(runtimeKey); } catch { /* GC is best-effort */ }
Expand Down
31 changes: 31 additions & 0 deletions src/lib/codex-auth-sync.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { afterEach, describe, expect, test } from "bun:test";
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";

import { syncCodexAuth } from "../commands/launch";

describe("syncCodexAuth", () => {
const dirs: string[] = [];

afterEach(async () => {
await Promise.all(dirs.splice(0).map((dir) => rm(dir, { recursive: true, force: true })));
});

test("copies canonical Codex auth into a Cue runtime", async () => {
const dir = await mkdtemp(join(tmpdir(), "cue-codex-auth-"));
dirs.push(dir);
const source = join(dir, "source.json");
const destination = join(dir, "runtime.json");
await writeFile(source, '{"tokens":{"access_token":"test"}}\n');

expect(await syncCodexAuth(source, destination)).toBe(true);
expect(await readFile(destination, "utf8")).toBe(await readFile(source, "utf8"));
});

test("fails open when no canonical login exists", async () => {
const dir = await mkdtemp(join(tmpdir(), "cue-codex-auth-"));
dirs.push(dir);
expect(await syncCodexAuth(join(dir, "missing.json"), join(dir, "runtime.json"))).toBe(false);
});
});
Loading