Share Docker agent auth across containers#96
Conversation
johannesjo
left a comment
There was a problem hiding this comment.
Review
Clean implementation — opt-in setting flows nicely from UI → store → IPC → backend, tests cover the important cases, and pre-creating the host directory to avoid root-ownership is a good detail.
Issues
1. hostDir is the same for all entries in an agent's config array (electron/ipc/pty.ts:616)
Currently every agent has exactly one config dir, but the data structure is Record<string, string[]>. If an agent ever gets multiple entries, both container paths would be backed by the same host directory, causing cross-contamination.
Suggested fix — incorporate relDir into the host path:
const hostDir = path.join(home, '.parallel-code', 'agent-auth', agentCommand, relDir);Or simplify the type to Record<string, string> since arrays aren't actually needed today.
2. Command matching uses the raw args.command string (electron/ipc/pty.ts:567-573)
If a user specifies a full path (e.g., /usr/local/bin/claude) or the command includes arguments, the AGENT_CONFIG_DIRS lookup silently fails. Consider matching against path.basename(agentCommand) or documenting that only bare command names are supported.
Minor
- The
for...ofloop over a single-element array feels like dead code — either the type should bestringor the host-dir path needs to account for multiple entries (see above).
Overall this is solid and well-tested. The first point is the only one I'd want addressed before merge.
|
Thank you very much for this! <3 |
There was a problem hiding this comment.
Pull request overview
This PR adds an opt-in Docker setting to persist agent authentication across container runs by threading a new preference from the UI into PTY spawn and bind-mounting per-agent auth directories inside Docker. In the broader codebase, it extends the existing Docker isolation flow so repeat agent logins are no longer required for supported CLIs.
Changes:
- Adds a persisted
shareDockerAgentAuthsetting, default state, store setter, and Settings UI checkbox. - Forwards the new setting through renderer → IPC → PTY spawn validation.
- Mounts per-agent auth directories for supported Docker agents and adds PTY tests for enabled/disabled/unknown-agent cases.
Review note: the feature direction makes sense, but I found blocking issues around persistence/autosave and the security/robustness of the host auth directory creation.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/store/ui.ts |
Adds the setter used by the new Docker auth-sharing preference. |
src/store/types.ts |
Extends persisted/app store types with the new boolean flag. |
src/store/store.ts |
Re-exports the new store setter. |
src/store/persistence.ts |
Saves and restores the new preference in persisted state. |
src/store/core.ts |
Introduces the default false value in initial app state. |
src/components/TerminalView.tsx |
Sends the preference with SpawnAgent IPC requests. |
src/components/SettingsDialog.tsx |
Adds the Docker auth-sharing checkbox and explanatory copy. |
electron/ipc/register.ts |
Validates the new IPC boolean argument in the main process. |
electron/ipc/pty.ts |
Adds supported agent config-dir mappings and Docker bind mounts for shared auth. |
electron/ipc/pty.test.ts |
Tests shared-auth mount behavior for supported, disabled, and unknown-agent cases. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| keybindingMigrationDismissed: store.keybindingMigrationDismissed || undefined, | ||
| focusMode: store.focusMode || undefined, | ||
| verboseLogging: store.verboseLogging || undefined, | ||
| shareDockerAgentAuth: store.shareDockerAgentAuth || undefined, |
| if (shareAgentAuth) { | ||
| for (const relDir of AGENT_CONFIG_DIRS[agentCommand] ?? []) { | ||
| const hostDir = path.join(home, '.parallel-code', 'agent-auth', agentCommand); | ||
| fs.mkdirSync(hostDir, { recursive: true }); |
| fs.mkdirSync(hostDir, { recursive: true }); | ||
| mounts.push('-v', `${hostDir}:${DOCKER_CONTAINER_HOME}/${relDir}`); |
- Use path.basename() for agent command lookup so full paths work - Incorporate relDir into hostDir to avoid cross-contamination if an agent has multiple config dirs in future - Create host auth dirs with mode 0o700 to restrict access to credentials - Degrade gracefully if mkdirSync fails rather than aborting Docker spawn - Add shareDockerAgentAuth to autosave snapshot so toggling persists immediately Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude stores its main auth config in ~/.claude.json (at HOME level) in addition to ~/.claude/ — without mounting this file, credentials written in the first container are lost when the container exits and the next container prompts for login again. Also add a note to the new-task Docker info message when auth sharing is enabled so users know credentials will carry over. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
An empty file causes Claude to reject it as invalid JSON on startup. Seed it with a valid empty object so the container starts cleanly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
UpdateReview issues addressedAll issues raised in the review have been addressed:
Additional changes since the original PR
Test results✅ Claude Code — auth persists correctly across containers; no login prompt on second container. |
|
Thank you very much! |
Summary
Docker-mode agents currently start with a fresh writable home each time, so users have to re-sign into Claude, Codex, Gemini, OpenCode, or Copilot for every new Docker container. That repeated authentication overhead makes Docker isolation less appealing, especially when creating multiple worktrees or trying short-lived tasks.
This PR adds an opt-in setting to share agent auth across Linux containers. When enabled, the app creates a user-owned host directory under
~/.parallel-code/agent-auth/<agent>and bind-mounts it into that agent's config directory inside Docker, such as/tmp/.codexor/tmp/.claude. Signing in once inside a Docker container then persists for later Docker containers of the same agent type, including containers launched from different worktrees.Implementation
shareDockerAgentAuthsetting and a checkbox in Settings.claude->/tmp/.claudecodex->/tmp/.codexgemini->/tmp/.geminiopencode->/tmp/.config/opencodecopilot->/tmp/.config/github-copilotLimitations
~/.codexor~/.claude; it persists credentials created inside Docker after the setting is enabled.Validation
npm test -- electron/ipc/pty.test.tsnpm run typechecknpm run lint -- --quietnpm run format:checknpm run check.