Fix: run container as host user, let Electron manage A2A servers

Two fixes:
1. Add --user $(id -u):$(id -g) and -e HOME to container run so Claude
   Code doesn't run as root (--dangerously-skip-permissions is rejected
   by claude when running as root/sudo).

2. Remove redundant `node start.js --ui-mode=headless` from start.sh.
   The Electron app already manages server startup via server-management.js
   (lock file check → spawn headless servers → wait for health). Running
   a second server process causes port conflicts and double-start noise.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Eli 2026-03-09 13:34:42 +01:00
commit 0028ef4262

View file

@ -74,14 +74,18 @@ mkdir -p "\$HOME/.anthropic"
# ── Start agents container ───────────────────────────────────────────────
# Mount project at the same absolute path so host and container paths match.
# CS Core sets agent working dirs to host paths; the wrapper relays PWD.
# Run as uid/gid of the current user so Claude Code doesn't run as root
# (--dangerously-skip-permissions is blocked when running as root).
echo "→ Starting agents container '\$CONTAINER_NAME'..."
"\$RUNTIME" run -d \\
--name "\$CONTAINER_NAME" \\
--user "\$(id -u):\$(id -g)" \\
-v "\$PROJECT_DIR:\$PROJECT_DIR" \\
-v "\$HOME/.anthropic:\$HOME/.anthropic:ro" \\
-e ANTHROPIC_API_KEY="\${ANTHROPIC_API_KEY:-}" \\
-e CS_WORKFLOW_DIR="\$PROJECT_DIR/workflow" \\
-e PROJECT_ROOT_DIR="\$PROJECT_DIR" \\
-e HOME="\$HOME" \\
"\$IMAGE_NAME" \\
sleep infinity
@ -113,40 +117,21 @@ if [[ -z "\${DISPLAY:-}" && -z "\${WAYLAND_DISPLAY:-}" ]]; then
fi
# ── Put claude wrapper first on PATH ────────────────────────────────────
# Electron inherits this PATH and passes it to the A2A server it spawns,
# so the servers can locate the bin/claude wrapper inside the container.
export PATH="\$PROJECT_DIR/bin:\$PATH"
# ── Launch CS Core A2A servers in background ─────────────────────────────
echo "→ Starting Context Studio Core (A2A servers)..."
CS_CORE_DIR="\$CS_CORE" \\
CS_WORKFLOW_DIR="\$PROJECT_DIR/workflow" \\
PROJECT_ROOT_DIR="\$PROJECT_DIR" \\
node "\$CS_CORE/core/start.js" --ui-mode=headless &
CS_CORE_PID=\$!
# ── Wait for registry to be ready (port 8000) ───────────────────────────
echo -n "→ Waiting for A2A registry..."
for _i in \$(seq 1 30); do
if curl -sf http://localhost:8000/health >/dev/null 2>&1; then
echo " ready."
break
fi
echo -n "."
sleep 0.5
done
echo ""
# ── Launch Electron UI ───────────────────────────────────────────────────
echo "→ Launching Context Studio UI..."
# ── Launch Context Studio (Electron manages A2A server startup) ──────────
# The Electron app checks for a lock file; if servers aren't running it
# spawns core/start.js --ui-mode=headless internally and waits for health.
echo "→ Launching Context Studio..."
CS_CORE_DIR="\$CS_CORE" \\
CS_WORKFLOW_DIR="\$PROJECT_DIR/workflow" \\
PROJECT_ROOT_DIR="\$PROJECT_DIR" \\
"\$CS_CORE/app/node_modules/.bin/electron" "\$CS_CORE/app"
# ── Electron closed — stop A2A servers and container ─────────────────────
echo "→ UI closed. Stopping A2A servers..."
kill "\$CS_CORE_PID" 2>/dev/null || true
wait "\$CS_CORE_PID" 2>/dev/null || true
echo "→ Stopping agents container..."
# ── Electron closed — stop container ─────────────────────────────────────
echo "→ UI closed. Stopping agents container..."
"\$RUNTIME" rm -f "\$CONTAINER_NAME" 2>/dev/null || true
START
chmod +x "$project_dir/start.sh"