Skip to content

Commit c339ea4

Browse files
committed
docs(claude/agents): runnable worktrees section + recipes
Document the new `worktree` config block, `afx dev` / `--stop` commands, and the design choices that drive them (URLs are load-bearing → serial swap; cleanup is process-based → PTY-group kill + OS port reclaim). Includes a "Runnable Worktree Recipes" subsection with ready-to-paste blocks for pnpm monorepo, npm, yarn, bun, cargo, poetry/uv, and go mod — calling out that Codev does NOT auto-detect the stack; users pick the recipe matching their toolchain. Also documents the orphan-recovery one-liner (`lsof -ti :<port> | xargs kill`) for the case where Tower hard-crashes mid-dev and a process survives outside Codev's records. CLAUDE.md and AGENTS.md kept in sync (identical content per the existing convention). Refs cluesmith#689.
1 parent b76aa20 commit c339ea4

2 files changed

Lines changed: 254 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,133 @@ Codev provides five CLI tools. For complete reference documentation, see:
275275
- **[consult](codev/resources/commands/consult.md)** - AI consultation (general, protocol, stats)
276276
- **[team](codev/resources/commands/team.md)** - Team coordination (list, message, update, add)
277277

278+
## Runnable Worktrees
279+
280+
When configured, each builder worktree (`.builders/<id>/`) becomes runnable — reviewers can spin up a dev server against the builder's branch without `cd`'ing, manually installing, or finding the right command. Opt-in via `.codev/config.json`; unconfigured repos see zero behavior change.
281+
282+
### Config: the `worktree` block
283+
284+
```jsonc
285+
{
286+
"worktree": {
287+
"symlinks": ["..."], // glob patterns of files to symlink from root into each new worktree
288+
"postSpawn": ["..."], // shell commands run inside each new worktree after createWorktree
289+
"devCommand": "..." // consumed by `afx dev <builder-id>`
290+
}
291+
}
292+
```
293+
294+
- `symlinks`: globs resolve from the workspace root; matches symlink into the worktree at the same relative path. Root `.env` and `.codev/config.json` are *always* symlinked regardless. **Symlinks, not copies** — edits to main's env files reflect instantly in any running dev session.
295+
- `postSpawn`: each command runs sequentially with `cwd` = worktree path. Non-zero exit aborts the spawn loud (half-built worktree stays for inspection).
296+
- `devCommand`: the foreground command that starts your dev server. Required for `afx dev` to work.
297+
298+
**Codev does not auto-detect your stack.** Pick the recipe below that matches your toolchain.
299+
300+
### CLI
301+
302+
```bash
303+
afx dev <builder-id> # start the dev server in <builder-id>'s worktree
304+
afx dev --stop # stop the currently running dev PTY
305+
```
306+
307+
Only one dev PTY runs at a time (by design — see "URLs are load-bearing" below). Running `afx dev` while another builder's dev is up prompts for swap. Same-builder requests print the existing terminal URL and exit.
308+
309+
### URLs are load-bearing
310+
311+
The dev PTY uses **the same ports and URLs as main** intentionally. OAuth callbacks, CORS allowlists, cookie scoping, CSP `connect-src`, webhook URLs are all keyed off origin — running the worktree on a different port would break them. Consequence: stop main's `pnpm dev` before `afx dev`. If you don't, the spawned dev fails at bind time with its own `EADDRINUSE`.
312+
313+
### Cleanup semantics
314+
315+
`afx dev --stop` and the swap path kill the entire PTY process group (SIGTERM, escalating to SIGKILL after 5s via `PtySession.kill`). That signals every grandchild of a monorepo dev orchestrator (`pnpm dev`, `turbo dev`, `pnpm -r --parallel run dev`, etc.) simultaneously. The OS reclaims ports as a consequence — Codev never touches ports directly.
316+
317+
**Orphan recovery** — if Tower itself hard-crashes mid-dev and a process is left holding a port outside Codev's records:
318+
319+
```bash
320+
lsof -ti :<port> | xargs kill # one port
321+
lsof -ti :3000,:3001,:4000 | xargs kill # several at once
322+
```
323+
324+
### Runnable Worktree Recipes
325+
326+
Ready-to-paste blocks per stack. Adjust ports / paths to your project.
327+
328+
**pnpm monorepo (Next.js + Turbo style):**
329+
```json
330+
{
331+
"worktree": {
332+
"symlinks": [".env.local", ".env.development.local", "packages/*/.env", "packages/*/.env.local", "turbo.json"],
333+
"postSpawn": ["pnpm install --frozen-lockfile"],
334+
"devCommand": "pnpm dev"
335+
}
336+
}
337+
```
338+
339+
**npm (single package):**
340+
```json
341+
{
342+
"worktree": {
343+
"symlinks": [".env.local", ".env.development"],
344+
"postSpawn": ["npm ci"],
345+
"devCommand": "npm run dev"
346+
}
347+
}
348+
```
349+
350+
**yarn:**
351+
```json
352+
{
353+
"worktree": {
354+
"symlinks": [".env.local"],
355+
"postSpawn": ["yarn install --frozen-lockfile"],
356+
"devCommand": "yarn dev"
357+
}
358+
}
359+
```
360+
361+
**bun:**
362+
```json
363+
{
364+
"worktree": {
365+
"symlinks": [".env.local"],
366+
"postSpawn": ["bun install --frozen-lockfile"],
367+
"devCommand": "bun dev"
368+
}
369+
}
370+
```
371+
372+
**cargo (Rust):**
373+
```json
374+
{
375+
"worktree": {
376+
"symlinks": [".env"],
377+
"postSpawn": [],
378+
"devCommand": "cargo run"
379+
}
380+
}
381+
```
382+
383+
**poetry / uv (Python):**
384+
```json
385+
{
386+
"worktree": {
387+
"symlinks": [".env", ".env.local"],
388+
"postSpawn": ["uv sync"],
389+
"devCommand": "uv run python -m myapp"
390+
}
391+
}
392+
```
393+
394+
**go mod:**
395+
```json
396+
{
397+
"worktree": {
398+
"symlinks": [".env"],
399+
"postSpawn": ["go mod download"],
400+
"devCommand": "go run ./cmd/server"
401+
}
402+
}
403+
```
404+
278405
## Architect-Builder Pattern
279406

280407
The Architect-Builder pattern enables parallel AI-assisted development:

CLAUDE.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,133 @@ Codev provides five CLI tools. For complete reference documentation, see:
275275
- **[consult](codev/resources/commands/consult.md)** - AI consultation (general, protocol, stats)
276276
- **[team](codev/resources/commands/team.md)** - Team coordination (list, message, update, add)
277277

278+
## Runnable Worktrees
279+
280+
When configured, each builder worktree (`.builders/<id>/`) becomes runnable — reviewers can spin up a dev server against the builder's branch without `cd`'ing, manually installing, or finding the right command. Opt-in via `.codev/config.json`; unconfigured repos see zero behavior change.
281+
282+
### Config: the `worktree` block
283+
284+
```jsonc
285+
{
286+
"worktree": {
287+
"symlinks": ["..."], // glob patterns of files to symlink from root into each new worktree
288+
"postSpawn": ["..."], // shell commands run inside each new worktree after createWorktree
289+
"devCommand": "..." // consumed by `afx dev <builder-id>`
290+
}
291+
}
292+
```
293+
294+
- `symlinks`: globs resolve from the workspace root; matches symlink into the worktree at the same relative path. Root `.env` and `.codev/config.json` are *always* symlinked regardless. **Symlinks, not copies** — edits to main's env files reflect instantly in any running dev session.
295+
- `postSpawn`: each command runs sequentially with `cwd` = worktree path. Non-zero exit aborts the spawn loud (half-built worktree stays for inspection).
296+
- `devCommand`: the foreground command that starts your dev server. Required for `afx dev` to work.
297+
298+
**Codev does not auto-detect your stack.** Pick the recipe below that matches your toolchain.
299+
300+
### CLI
301+
302+
```bash
303+
afx dev <builder-id> # start the dev server in <builder-id>'s worktree
304+
afx dev --stop # stop the currently running dev PTY
305+
```
306+
307+
Only one dev PTY runs at a time (by design — see "URLs are load-bearing" below). Running `afx dev` while another builder's dev is up prompts for swap. Same-builder requests print the existing terminal URL and exit.
308+
309+
### URLs are load-bearing
310+
311+
The dev PTY uses **the same ports and URLs as main** intentionally. OAuth callbacks, CORS allowlists, cookie scoping, CSP `connect-src`, webhook URLs are all keyed off origin — running the worktree on a different port would break them. Consequence: stop main's `pnpm dev` before `afx dev`. If you don't, the spawned dev fails at bind time with its own `EADDRINUSE`.
312+
313+
### Cleanup semantics
314+
315+
`afx dev --stop` and the swap path kill the entire PTY process group (SIGTERM, escalating to SIGKILL after 5s via `PtySession.kill`). That signals every grandchild of a monorepo dev orchestrator (`pnpm dev`, `turbo dev`, `pnpm -r --parallel run dev`, etc.) simultaneously. The OS reclaims ports as a consequence — Codev never touches ports directly.
316+
317+
**Orphan recovery** — if Tower itself hard-crashes mid-dev and a process is left holding a port outside Codev's records:
318+
319+
```bash
320+
lsof -ti :<port> | xargs kill # one port
321+
lsof -ti :3000,:3001,:4000 | xargs kill # several at once
322+
```
323+
324+
### Runnable Worktree Recipes
325+
326+
Ready-to-paste blocks per stack. Adjust ports / paths to your project.
327+
328+
**pnpm monorepo (Next.js + Turbo style):**
329+
```json
330+
{
331+
"worktree": {
332+
"symlinks": [".env.local", ".env.development.local", "packages/*/.env", "packages/*/.env.local", "turbo.json"],
333+
"postSpawn": ["pnpm install --frozen-lockfile"],
334+
"devCommand": "pnpm dev"
335+
}
336+
}
337+
```
338+
339+
**npm (single package):**
340+
```json
341+
{
342+
"worktree": {
343+
"symlinks": [".env.local", ".env.development"],
344+
"postSpawn": ["npm ci"],
345+
"devCommand": "npm run dev"
346+
}
347+
}
348+
```
349+
350+
**yarn:**
351+
```json
352+
{
353+
"worktree": {
354+
"symlinks": [".env.local"],
355+
"postSpawn": ["yarn install --frozen-lockfile"],
356+
"devCommand": "yarn dev"
357+
}
358+
}
359+
```
360+
361+
**bun:**
362+
```json
363+
{
364+
"worktree": {
365+
"symlinks": [".env.local"],
366+
"postSpawn": ["bun install --frozen-lockfile"],
367+
"devCommand": "bun dev"
368+
}
369+
}
370+
```
371+
372+
**cargo (Rust):**
373+
```json
374+
{
375+
"worktree": {
376+
"symlinks": [".env"],
377+
"postSpawn": [],
378+
"devCommand": "cargo run"
379+
}
380+
}
381+
```
382+
383+
**poetry / uv (Python):**
384+
```json
385+
{
386+
"worktree": {
387+
"symlinks": [".env", ".env.local"],
388+
"postSpawn": ["uv sync"],
389+
"devCommand": "uv run python -m myapp"
390+
}
391+
}
392+
```
393+
394+
**go mod:**
395+
```json
396+
{
397+
"worktree": {
398+
"symlinks": [".env"],
399+
"postSpawn": ["go mod download"],
400+
"devCommand": "go run ./cmd/server"
401+
}
402+
}
403+
```
404+
278405
## Architect-Builder Pattern
279406

280407
The Architect-Builder pattern enables parallel AI-assisted development:

0 commit comments

Comments
 (0)