diff --git a/HANDOVER.md b/HANDOVER.md new file mode 100644 index 0000000..59fd524 --- /dev/null +++ b/HANDOVER.md @@ -0,0 +1,84 @@ +# Handover — Context Studio Wizard + +_Last updated: 2026-03-09_ + +## Current status + +The wizard runs end-to-end. The generated project (`thewiztest`) starts the container +and opens the Electron UI. **The last fix was NOT yet confirmed working by the user.** +The session ended before the user could test it. + +## What was fixed this session (newest first) + +### 1. `bin/claude` — workdir fallback (UNVERIFIED — last fix, not yet tested) +**File:** `lib/container.sh` → generated `bin/claude` +**Symptom:** `[Server:err] claude-code is required but not found` → `[Server] Exited with code 1` → all agents fail to start +**Root cause:** When Electron spawns `node core/start.js`, its cwd is `~/.context-studio/core`. The `bin/claude` wrapper used `--workdir "$PWD"` in `podman exec`. That directory isn't mounted in the container → podman fails → returns non-zero → claude appears "missing". +**Fix:** If `$PWD` is not under `$PROJECT_DIR`, fall back to `$PROJECT_DIR` as the container workdir. +**Also patched:** `thewiztest/bin/claude` + +### 2. Container runs as root → `--dangerously-skip-permissions` rejected +**File:** `lib/container.sh` → generated `start.sh` +**Symptom:** `--dangerously-skip-permissions cannot be used with root/sudo privileges` +**Fix:** Added `--user "$(id -u):$(id -g)"` and `-e HOME="$HOME"` to `podman run` +**Why it works:** Host user `elmar` = uid 1000 = `node` user in `node:22` image → permissions match +**Also patched:** `thewiztest/start.sh` + +### 3. Electron manages server startup — removed redundant headless node +**File:** `lib/container.sh` → generated `start.sh` +**Symptom:** Would have caused port conflicts +**Fix:** Removed `node start.js --ui-mode=headless &` from start.sh. The Electron app's `server-management.js` checks the lock file and spawns servers itself. +**Also patched:** `thewiztest/start.sh` + +### 4. Electron must be launched separately +**File:** `lib/container.sh` +**Symptom:** UI never opened — servers ran but no window +**Root cause:** `node core/start.js --ui-mode=electron` does NOT launch Electron. It logs "Electron app started separately" and only manages A2A servers. +**Fix (later superseded):** Direct Electron launch via `$CS_CORE/app/node_modules/.bin/electron $CS_CORE/app` + +## What still needs verifying + +1. **Does the server now start without the `claude-code missing` error?** + - Run `./start.sh` in `thewiztest/` + - Watch for `[12:xx:xx] ✅ All agent servers started` (no `Server startup failed`) + - The Electron UI should open and kai's terminal should start without root errors + +2. **`localhost:null` network error** — this is downstream of (1). If servers start cleanly, the registry port gets written to the lock file and `localhost:null` disappears. + +3. **Kai can't connect to the internet** — mentioned by user but not investigated. Could be: + - Container network settings (Podman default: slirp4netns, should have internet) + - ANTHROPIC_API_KEY not set or not passed into container + - Proxy/VPN issue on the host network + +## Key architecture facts + +### How CS Core + Electron work together +- `electron app/` starts the UI +- Electron's `server-management.js` checks `workflow/data/` for a lock file +- If no lock file → it spawns `node core/start.js --ui-mode=headless` as a child process +- Child process inherits Electron's `process.env` including PATH (with `bin/claude`) +- When the requirements check runs `claude --version`, it finds `bin/claude` in PATH +- `bin/claude` proxies to `podman exec cs- claude --version` +- Container must be running BEFORE Electron is launched (start.sh handles this) + +### Path that must be mounted in container +Only `$PROJECT_DIR` is mounted (at the same absolute path). NOT: +- `~/.context-studio/core` +- `~/.anthropic` (mounted read-only separately) +- Any other host path + +### Generated files per project +- `bin/claude` — wrapper with hardcoded `PROJECT_DIR` and `CONTAINER_NAME` +- `start.sh` — starts container as `$(id -u):$(id -g)`, exports PATH, launches Electron +- `stop.sh` — force-removes container +- `update.sh` — git pull core, npm update claude-code in container, apt upgrade + +## File locations +- Wizard: `/home/elmar/Projects/ContextStudioWizard/` +- Test project: `/home/elmar/Projects/thewiztest/` +- Core (read-only!): `/home/elmar/.context-studio/core/` +- Wizard repo remote: check `git remote -v` in ContextStudioWizard + +## What NOT to do +- Never modify `~/.context-studio/core` — it is read-only +- Never commit or push to the core repo diff --git a/README.md b/README.md index c89f5ff..ba9267f 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,40 @@ ## ✨ What it does -One command. One conversation. A complete project drops out: +One command. A complete project drops out: ``` ~/.context-studio/core/ ← 🔧 installed once, shared globally -~/projects/my-project/ -├── .devcontainer/ ← 🐳 Node 22 · Rust · Claude Code · Electron deps +~/Projects/my-project/ +├── .devcontainer/ ← 🐳 Node 22 · Rust · Claude Code ├── workflow/ ← 🤖 agents, roles, A2A config, project docs -└── src/ ← 💻 your code +├── src/ ← 💻 your code +├── bin/claude ← 🔀 wrapper: routes claude → container +├── start.sh ← ▶️ start container + Context Studio UI +├── stop.sh ← ⏹️ stop the agents container +└── update.sh ← 🔄 update core, claude-code, OS packages ``` -Open in devcontainer → start Context Studio → talk to your agent team. +Run `./start.sh` → Podman container starts → Electron UI opens → talk to your agent team. + +--- + +## 🏗️ Architecture (Option B) + +``` +HOST CONTAINER (cs-) +───────────────────────────── ──────────────────────── +Context Studio Core (Electron) ←─── All Claude Code agents + starts A2A servers mounted at same abs path + opens Electron UI bin/claude wrapper routes + manages workflow every claude call here +``` + +- **CS Core** runs on the host (Electron UI, no display issues) +- **All agents** run inside the Podman container as the current user (not root) +- **`bin/claude`** is prepended to PATH so CS Core's server process finds it automatically +- **Paths match** host ↔ container (project mounted at the same absolute path) --- @@ -32,8 +54,6 @@ Open in devcontainer → start Context Studio → talk to your agent team. **Auto-install supported on:** Arch · Debian/Ubuntu · RHEL/Fedora · openSUSE -> The wizard detects your distro and installs `git` and `podman`/`docker` automatically if they are missing. SSH key and API key must be set up by you. - --- ## 🚀 Usage @@ -44,57 +64,50 @@ Open in devcontainer → start Context Studio → talk to your agent team. The wizard guides you through: -1. 🔧 **Core setup** — clones `context-studio-core` to `~/.context-studio/core/` (once) +1. 🔧 **Core setup** — clones `context-studio-core` to `~/.context-studio/core/` (once, shared) 2. 📝 **Project name & location** 3. ⚙️ **Workflow** — generate from scratch _or_ clone an existing repo 4. 🤖 **Agent preset** _(if generating)_ | Preset | Agents | |--------|--------| - | `minimal` | 🎯 coordinator · 2× coder · researcher · tester | - | `standard` | 🎯🎯 2× coordinator · 3× coder · 2× researcher · tester · reviewer | + | `minimal` | 5 agents: coordinator · 2× coder · researcher · tester | + | `standard` | 9 agents: 2× coordinator · 3× coder · 2× researcher · tester · reviewer | -5. ✅ **Done** — git repo initialized, devcontainer ready +5. ✅ **Done** — project created, git repo initialized + +> ⚠️ **First `./start.sh`** builds the container image. Expect 5–15 min. Subsequent starts are instant. --- -## 📂 Open the project +## ▶️ Starting your project -**🖥️ VS Code** ```bash -code ~/projects/my-project # → "Reopen in Container" +cd ~/Projects/my-project +./start.sh ``` -**⌨️ CLI** -```bash -cd ~/projects/my-project -docker build -t my-project .devcontainer/ -docker run -it --rm \ - -v "$(pwd)":/workspace \ - -v "$HOME/.context-studio/core":/opt/context-studio/core \ - -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \ - my-project bash -``` +This will: +1. Build the container image if not yet built (first run: 5–15 min) +2. Start the Podman container (agents run here as your user, not root) +3. Launch the Context Studio Electron UI +4. When you close the UI → container is stopped automatically -**▶️ Start Context Studio** _(inside container)_ ```bash -node $CS_CORE_DIR/core/start.js # Electron UI -node $CS_CORE_DIR/core/start.js --ui-mode=headless # servers only +./stop.sh # force-stop container without closing the UI +./update.sh # update core, claude-code inside container, OS packages ``` --- -## 🌍 Mobility +## 🔄 How `bin/claude` works -Commit your project. On any machine: +CS Core on the host needs to call `claude`. Instead of using the host's `claude`, `start.sh` prepends `bin/claude` to `PATH`. This wrapper: -```bash -git clone -cd my-project -code . # done -``` - -> Core is re-cloned automatically on first run. Only `ANTHROPIC_API_KEY` is needed on the host. +1. Checks the agents container is running +2. Relays the call into the container via `podman exec` +3. Passes the working directory (falling back to project root if cwd isn't mounted) +4. All agents — including the main coordinator — run **inside the container** --- @@ -103,10 +116,12 @@ code . # done ``` 🧙 wizard.sh ← entry point 📁 lib/ - utils.sh ← prompts, colors, helpers + utils.sh ← prompts, colors, gum helpers + prereqs.sh ← auto-install git + podman/docker core.sh ← global core install/update project.sh ← devcontainer + project scaffold workflow.sh ← generate or clone workflow config + container.sh ← generates start/stop/update/bin/claude 📁 templates/ Dockerfile ← Node 22 + Rust + build tools + Claude Code devcontainer.json ← mounts, env vars, VS Code extensions @@ -116,3 +131,22 @@ code . # done 📁 roles/ ← coordinator, coder, researcher, tester, reviewer 📁 hooks/rules/ ← per-role tool restrictions ``` + +--- + +## ⚠️ Hard rules + +- **`~/.context-studio/core` is READ-ONLY** — never modify, commit, or push to it +- It is a shared global dependency; the wizard only clones and `npm install`s it + +--- + +## 🌍 Portability + +Commit your project. On any machine: + +```bash +git clone +cd my-project +./start.sh # wizard re-runs if core missing; image builds on first run +```