Fix end-to-end startup: project registration, credentials, trust dialog, ready marker

- start.sh: auto-register project in ~/.config/context-studio/projects/ before
  launching Electron — without this acquireProjectLock() silently skips writing
  the lock file, waitForServers() never finds the registry port, all agent ports
  stay null (localhost:null errors)

- start.sh: mount all known Claude Code credential locations into container
  (~/.claude/.credentials.json, ~/.claude.json, $CLAUDE_CONFIG_DIR variants)
  not just ~/.anthropic which was empty on this system

- bin/claude: create /tmp/cs-ready-<agentId> on host after 3s delay so CS Core's
  CLI ready marker poll resolves instead of timing out after 10s

- workflow.sh: add hasTrustDialogAccepted:true to all agent settings.json so
  claude goes straight to priming without the folder trust dialog

- prereqs.sh: add ensure_api_key() — checks all credential locations, prompts
  with masked input if none found, offers to save to shell profile

- wizard.sh: trap SIGINT for graceful abort — gum confirm popup, reverts created
  project dir and cloned core dir, leaves installed packages untouched

- core.sh: set _WIZARD_CORE_CLONED=true before clone for cleanup tracking

- electron-config.js: increase serverStartupTimeout 30s→90s (config file in
  core/config/, not source — safe to edit)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Eli 2026-03-09 21:20:25 +01:00
commit 7c9b61bfce
7 changed files with 325 additions and 80 deletions

View file

@ -41,6 +41,21 @@ else
WORKDIR="\$PROJECT_DIR"
fi
# ── CS Core ready marker ────────────────────────────────────────────────
# CS Core polls /tmp/cs-ready-<agentId> on the host to know when the CLI
# banner is visible and /prime can be injected. Claude runs inside the
# container so it cannot create this file on the host itself.
# We infer the agent ID from the PTY working directory (CS Core sets it to
# workflow/agents/<agentId>) and create the marker after a short delay.
_is_interactive=true
for _arg in "\$@"; do
case "\$_arg" in --version|--help|-h|-v) _is_interactive=false; break ;; esac
done
if [[ "\$_is_interactive" == "true" && "\$PWD" == "\$PROJECT_DIR/workflow/agents/"* ]]; then
_AGENT_ID="\$(basename "\$PWD")"
(sleep 3 && touch "/tmp/cs-ready-\$_AGENT_ID") &
fi
# Pass through TTY if available, relay working directory into container
if [ -t 0 ]; then
exec "\$RUNTIME" exec -it --workdir "\$WORKDIR" "\$CONTAINER_NAME" claude "\$@"
@ -82,6 +97,22 @@ fi
# ── Ensure ~/.anthropic exists (Claude Code stores auth/config here) ─────
mkdir -p "\$HOME/.anthropic"
# ── Build credential mounts ───────────────────────────────────────────────
# Claude Code may store credentials in various locations depending on version
# and whether CLAUDE_CONFIG_DIR is set. Mount whichever files exist.
_CREDS_ARGS=()
_CREDS_ARGS+=("-v" "\$HOME/.anthropic:\$HOME/.anthropic:ro")
_claude_dir="\${CLAUDE_CONFIG_DIR:-\$HOME/.claude}"
if [[ -f "\$_claude_dir/.credentials.json" ]]; then
_CREDS_ARGS+=("-v" "\$_claude_dir/.credentials.json:\$_claude_dir/.credentials.json:ro")
fi
if [[ -f "\$HOME/.claude.json" ]]; then
_CREDS_ARGS+=("-v" "\$HOME/.claude.json:\$HOME/.claude.json:ro")
fi
if [[ -n "\${CLAUDE_CONFIG_DIR:-}" && -f "\$CLAUDE_CONFIG_DIR/.claude.json" ]]; then
_CREDS_ARGS+=("-v" "\$CLAUDE_CONFIG_DIR/.claude.json:\$CLAUDE_CONFIG_DIR/.claude.json:ro")
fi
# ── 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.
@ -92,7 +123,7 @@ echo "→ Starting agents container '\$CONTAINER_NAME'..."
--name "\$CONTAINER_NAME" \\
--user "\$(id -u):\$(id -g)" \\
-v "\$PROJECT_DIR:\$PROJECT_DIR" \\
-v "\$HOME/.anthropic:\$HOME/.anthropic:ro" \\
"\${_CREDS_ARGS[@]}" \\
-e ANTHROPIC_API_KEY="\${ANTHROPIC_API_KEY:-}" \\
-e CS_WORKFLOW_DIR="\$PROJECT_DIR/workflow" \\
-e PROJECT_ROOT_DIR="\$PROJECT_DIR" \\
@ -121,6 +152,45 @@ if [[ ! -d "\$CS_CORE/app/node_modules" ]]; then
(cd "\$CS_CORE" && npm install) || { echo "npm install failed." >&2; exit 1; }
fi
# ── Register project with Context Studio (required for lock file to be written) ──
# CS Core's acquireProjectLock() skips writing the lock file if the project
# isn't registered in ~/.config/context-studio/projects/<uuid>.json.
# Without the lock file, waitForServers() can never find the registry port
# and always times out — causing localhost:null errors in the UI.
_CS_PROJECTS_DIR="\$HOME/.config/context-studio/projects"
mkdir -p "\$_CS_PROJECTS_DIR"
_WORKFLOW_DIR="\$PROJECT_DIR/workflow"
_already_registered=false
for _f in "\$_CS_PROJECTS_DIR"/*.json; do
if [[ -f "\$_f" ]] && python3 -c "
import json,sys
d=json.load(open(sys.argv[1]))
sys.exit(0 if d.get('workflowDir') == sys.argv[2] else 1)
" "\$_f" "\$_WORKFLOW_DIR" 2>/dev/null; then
_already_registered=true
break
fi
done
if [[ "\$_already_registered" == "false" ]]; then
_UUID=\$(python3 -c "import uuid; print(uuid.uuid4())")
_NOW=\$(python3 -c "from datetime import datetime,timezone; print(datetime.now(timezone.utc).isoformat())")
python3 -c "
import json, sys
data = {
'id': sys.argv[1],
'name': sys.argv[2],
'workflowDir': sys.argv[3],
'user': 'default',
'created': sys.argv[4],
'lastOpened': sys.argv[4]
}
with open(sys.argv[5], 'w') as f:
json.dump(data, f, indent=2)
f.write('\n')
" "\$_UUID" "\$(basename "\$PROJECT_DIR")" "\$_WORKFLOW_DIR" "\$_NOW" "\$_CS_PROJECTS_DIR/\$_UUID.json"
echo "→ Registered project with Context Studio"
fi
# ── Check display for Electron UI ───────────────────────────────────────
if [[ -z "\${DISPLAY:-}" && -z "\${WAYLAND_DISPLAY:-}" ]]; then
echo "⚠ No display detected (DISPLAY / WAYLAND_DISPLAY not set)."