Repository navigation
fix(externagent): run claude and codex against their own homes, never copy their tokens - #643
Open
ion-alpha-dev wants to merge 2 commits into
Open
ion-alpha-dev wants to merge 2 commits into
ion-alpha-dev wants to merge 2 commits into
Conversation
The claude backend used to read the user's Claude Code credential file and config out of ~/.claude and copy them into a per-run directory for each episode. Flynn handled the OAuth token itself, and a token the CLI refreshed mid-episode was refreshed only in the copy. The backend now keeps a Claude Code home of its own under the data directory. The user signs the CLI in to it once with the CLI's own login, and every probe and episode points the CLI at it through CLAUDE_CONFIG_DIR. Flynn never reads, copies or deletes the token; the CLI writes it at sign-in and refreshes it in place. The user's own home, settings, hooks and MCP servers are no longer read at all. SandboxConfig gains AuthDirWritable so an episode may write such a dedicated home. A user's own CLI home stays read-only to the child, as before. When claude is installed but not signed in, the onboarding message now prints the sign-in command for Flynn's home, quoted for PowerShell on Windows and for sh elsewhere. Signed-off-by: Ion Alpha <[email protected]>
The codex backend copied auth.json out of the user's own codex home into a per-run home for every episode. It now gets the same treatment as claude: Flynn keeps a codex home of its own under its data directory, the user signs the CLI in to it once with `codex login` (Flynn prints the exact command), and probes and episodes point the CLI at it through CODEX_HOME with write access, so the CLI refreshes its token in place and Flynn never reads it. The user's config.toml is never on the child's path. A config.toml found in Flynn's own codex home is removed before a spawner is built, so a harness cannot leave one behind to steer a later run. The not-signed-in message for both backends now comes from one helper, and the login command is built by one function per shell. Existing codex users sign in once more; their own ~/.codex is untouched. Signed-off-by: Ion Alpha <[email protected]>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Flynn now keeps a separate home for each external CLI under its data directory (
claude/andcodex/) and runs the CLI against it, instead of copying the user's own credential (~/.claude/.credentials.json, orauth.jsonfrom~/.codexorCODEX_HOME) into a per-run home for every episode. Flynn never reads, copies or stores the token inside.Why
The user's personal sign-in belongs to their own use of the CLI, and Flynn had no reason to handle it. A copied token also lives outside the CLI's control: the CLI cannot refresh the original, and the copy sits in a directory the user never asked for. With a home of its own, each CLI signs in through its own login flow, keeps its token where it put it, and refreshes it in place.
How to verify
go test ./cmd/flynn ./externagentTestDedicatedAuthDirIsWrittenInPlace: a home marked writable (SandboxConfig.AuthDirWritable) is used in place with nothing copied, and an unmarked home stays read-only.TestClaudeHomeIsFlynnsOwnAndNeverTheUsers,TestCodexHomeIsFlynnsOwnAndNeverTheUsers: each backend uses Flynn's home whatever the user's environment variable says, and the home exists before detection. The codex test also checks that aconfig.tomlis removed andauth.jsonis kept, and it fails if the removal is taken out.TestLoginSignsInFlynnsHome: the sign-in message for both backends names the right variable and login command, quotes the path for sh and PowerShell, and never asks for an API key.flynn --model codex(orclaude) with no sign-in; it prints aCODEX_HOME=... codex login(orCLAUDE_CONFIG_DIR=... claude auth login --claudeai) command. After running it, the backend reports itself ready and~/.codex/~/.claudeare unchanged.Notes for reviewers
--model claudeor--model codexsigns in once more. Their own~/.claudeand~/.codexsign-ins are untouched.config.tomlare never on the child's path. Aconfig.tomlfound in Flynn's codex home is removed before a spawner is built, because the child may write that home and nothing Flynn does puts one there.