Skip to content

Commit 551cc38

Browse files
Mossakaclaude
andauthored
fix: remove .claude.json file bind mount regression (#911)
* fix: remove .claude.json file bind mount regression File bind mounts on Linux prevent atomic writes (temp file + rename() returns EBUSY). Claude Code uses atomic writes for ~/.claude.json config, causing silent failure with 0 tool calls. The writable home volume already provides a writable $HOME, and entrypoint.sh creates .claude.json from CLAUDE_CODE_API_KEY_HELPER env var. Fixes github/gh-aw#16214 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove stale docker-manager reference in entrypoint Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b3356df commit 551cc38

File tree

2 files changed

+5
-18
lines changed

2 files changed

+5
-18
lines changed

containers/agent/entrypoint.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ if [ -n "$CLAUDE_CODE_API_KEY_HELPER" ]; then
147147
fi
148148
echo "[entrypoint] ✓ Claude Code API key helper validated: $CLAUDE_CODE_API_KEY_HELPER"
149149
else
150-
# File exists but no apiKeyHelper - write it (overwrites empty {} created by docker-manager)
150+
# File exists but no apiKeyHelper - write it
151151
echo "[entrypoint] Claude Code config file exists but missing apiKeyHelper, writing..."
152152
echo "{\"apiKeyHelper\":\"$CLAUDE_CODE_API_KEY_HELPER\"}" > "$CONFIG_FILE"
153153
chmod 666 "$CONFIG_FILE"

src/docker-manager.ts

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -549,23 +549,10 @@ export function generateDockerCompose(
549549
// This is safe as ~/.claude contains only Claude-specific state, not credentials
550550
agentVolumes.push(`${effectiveHome}/.claude:/host${effectiveHome}/.claude:rw`);
551551

552-
// Mount ~/.claude.json for Claude Code authentication configuration
553-
// This file must be accessible in chroot mode for Claude Code to find apiKeyHelper
554-
// We create the file if it doesn't exist, then mount it
555-
const claudeJsonPath = path.join(effectiveHome, '.claude.json');
556-
if (!fs.existsSync(claudeJsonPath)) {
557-
// Create parent directory if needed
558-
const parentDir = path.dirname(claudeJsonPath);
559-
if (!fs.existsSync(parentDir)) {
560-
fs.mkdirSync(parentDir, { recursive: true, mode: 0o755 });
561-
}
562-
// Create empty file that will be populated by entrypoint
563-
// Use 0o666 mode to allow container root to write and host user to read
564-
// The entrypoint script runs as root and modifies this file
565-
fs.writeFileSync(claudeJsonPath, '{}', { mode: 0o666 });
566-
logger.debug(`Created ${claudeJsonPath} for chroot mounting`);
567-
}
568-
agentVolumes.push(`${claudeJsonPath}:/host${claudeJsonPath}:rw`);
552+
// NOTE: ~/.claude.json is NOT bind-mounted as a file. File bind mounts on Linux
553+
// prevent atomic writes (temp file + rename), which Claude Code requires.
554+
// The writable home volume provides a writable $HOME, and entrypoint.sh
555+
// creates ~/.claude.json with apiKeyHelper content from CLAUDE_CODE_API_KEY_HELPER.
569556

570557
// Mount ~/.cargo and ~/.rustup for Rust toolchain access
571558
// On GitHub Actions runners, Rust is installed via rustup at $HOME/.cargo and $HOME/.rustup

0 commit comments

Comments
 (0)