# claw-forge Commands Reference

Complete reference for all CLI commands and Claude slash commands. For end-to-end workflow
walkthroughs, see [docs/workflows.md](workflows.md). For the project README, see
[README.md](../README.md).

---

## CLI Workflow Commands

Run these in your terminal. All CLI commands accept `--config` to point at a non-default
`claw-forge.yaml`.

---

### `claw-forge init`

#### Purpose
Bootstrap a new project — scaffold `.claude/`, `CLAUDE.md`, `claw-forge.yaml`,
`claw-forge.local.yaml`, `.env.example`, and `app_spec.example.xml`. Run this **once** before writing your spec.

#### When to use
- First command in any new project directory
- After cloning a repo that has no `.claude/` scaffold
- To get `app_spec.example.xml` as a format reference for your spec

#### Usage
```bash
# Bootstrap current directory
claw-forge init

# Bootstrap a specific directory
claw-forge init --project ~/projects/my-app
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--project`, `-p` | path | `.` | Root directory to bootstrap |
| `--config`, `-c` | path | `claw-forge.yaml` | Config file path (created if absent) |

#### What it does internally
1. Creates `claw-forge.yaml` with default providers if not present.
2. Creates a gitignored `claw-forge.local.yaml` overlay (if absent) for per-machine overrides — put secrets/model/provider toggles here so your edits **survive `claw-forge run`** (startup stashes edits to the *tracked* `claw-forge.yaml`, but never touches the gitignored overlay). Ships all-commented, so it's a no-op until you edit it.
3. Creates `.env.example` documenting all environment variables.
4. Detects language/framework from `pyproject.toml`, `package.json`, `go.mod`, etc.
5. Generates `CLAUDE.md` tailored to the detected stack.
6. Creates `.claude/settings.json` (`enableAllProjectMcpServers: true`).
7. Copies 8 slash-command `.md` files into `.claude/commands/`.
8. Copies `app_spec.example.xml` — a full XML format reference for your spec.
9. Prints a next-step hint pointing to `/create-spec` or `claw-forge plan`.

#### Output example
```
✓ Created claw-forge.yaml  (edit providers as needed)
✓ Created claw-forge.local.yaml  (gitignored per-machine overrides)
✓ Created .env.example     (copy to .env and fill keys)
⚠  No .env found — copy .env.example → .env and add your API keys
✓ Stack detected: python / fastapi
✓ Generated CLAUDE.md
✓ Created .claude/ with settings.json
✓ Created app_spec.example.xml  (reference format for your spec)
✓ Scaffolded 8 slash commands → .claude/commands/
  • /create-spec
  • /expand-project
  • /check-code
  ...

Next step: create your project spec.
  Option A — use the Claude slash command:
    Open Claude Code here and run /create-spec

  Option B — paste your PRD into Claude with this prompt:
    "Convert this PRD to claw-forge XML spec format.
     Use app_spec.example.xml in this directory as the template.
     Write the result to app_spec.txt."

  Then run: claw-forge plan app_spec.txt
```

#### Related commands
- **Next:** `/create-spec` (generate spec) → `claw-forge plan` (parse spec → DB)

---

### `claw-forge plan`

#### Purpose
Parse a spec file (`app_spec.txt` or `additions_spec.xml`) and generate the feature
dependency DAG in the state database. This is the planning step — run it after writing
your spec and before `claw-forge run`.

#### When to use
- After `/create-spec` produces `app_spec.txt`
- After converting a PRD to `app_spec.txt` using `app_spec.example.xml` as reference
- Re-running after editing the spec (only new features are added to the DB)
- Re-running on an active project to reconcile — completed tasks are preserved, only new features are added (use `--fresh` to start clean)

#### Usage
```bash
# Parse spec in current directory
claw-forge plan app_spec.txt

# Brownfield additions
claw-forge plan additions_spec.xml

# Use Sonnet instead of Opus (faster/cheaper, lower planning quality)
claw-forge plan app_spec.txt --model claude-sonnet-4-20250514

# Point at a different project
claw-forge plan app_spec.txt --project ~/projects/task-manager

# Reconcile with existing session (default — keeps completed tasks)
claw-forge plan app_spec.txt

# Force a fresh session (wipe and recreate all tasks)
claw-forge plan app_spec.txt --fresh
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `spec` | positional | **required** | Path to `app_spec.txt` or XML spec file |
| `--project`, `-p` | path | `.` | Root directory of the project |
| `--model`, `-m` | string | `claude-opus-4-5` | Model for parsing (Opus recommended) |
| `--concurrency`, `-n` | int | `5` | Used to estimate run time in summary |
| `--config`, `-c` | path | `claw-forge.yaml` | Path to YAML config |
| `--fresh` | flag | `False` | Force a fresh session — create all tasks from scratch. Without this flag, `plan` reconciles with the existing session: completed tasks are preserved, and only new/missing features are added. |

#### What it does internally
1. Validates the spec file exists and is valid XML.
2. Runs `InitializerPlugin` (Opus by default — planning errors cascade through every run).
3. Parses features from `<core_features>` — each bullet becomes one agent task.
4. Builds a dependency DAG from `<implementation_steps>` phase ordering.
5. Appends a terminal **End-to-End Verification** task (unless `spec.append_e2e_task: false`, or the spec already designs e2e work) that depends on every feature and writes + runs e2e/integration tests under `tests/e2e/` against the assembled app — see below.
6. Writes features to the state DB, printing a category table + wave count + ETA.

> **End-to-end guarantee (`spec.append_e2e_task`, default `true`).** Per-feature
> tasks get unit tests, but nothing guarantees the *assembled* app runs — e2e
> tests authored only as spec prose are never turned into tasks, so they go
> missing. `plan` therefore appends a synthetic "End-to-End Verification" task
> that `depends_on` **every** feature (so it dispatches dead last, after the
> whole app has merged) and is charged with writing and running e2e tests under
> `tests/e2e/` and confirming the app starts. It runs as a `coding` task (the
> `testing` plugin only *runs* tests, it doesn't author them). Injection is
> idempotent across re-plans and is skipped when the spec already declares e2e
> work (a feature touching an `e2e`/`integration` path or using e2e vocabulary).
> Set `spec.append_e2e_task: false` in `claw-forge.yaml` to opt out.

#### Output example
```
✅ Spec parsed: TaskFlow API

  Features by Category
  ┌──────────────────────┬───────┐
  │ Category             │ Count │
  ├──────────────────────┼───────┤
  │ Authentication       │    8  │
  │ Task Management      │   22  │
  │ API Layer            │    9  │
  │ Total                │   59  │
  └──────────────────────┴───────┘

  Dependency waves: 4
  Estimated run time: ~24 minutes (at concurrency=5)

  Next: claw-forge run --concurrency 5
```

#### Pro tips
- **Always use Opus** for planning. It produces better DAGs and catches ambiguous features.
  Use `--model sonnet` only if you're iterating quickly and cost matters more than quality.
- **Plan reconciliation** is the default behavior when re-running `plan` on an existing project. Completed tasks stay as-is, failed/pending tasks are retained, and only features missing from the DB are added as new pending tasks. Use `--fresh` to wipe and recreate all tasks from scratch.
- `app_spec.example.xml` (created by `claw-forge init`) shows the full XML schema.

#### Architectural shape attributes

The parser accepts three attributes on `<feature>` that affect dispatcher
behaviour:

| Attribute | Values | Effect |
|---|---|---|
| `shape` | `plugin` / `core` | Plugin = lives in its own directory; core = cross-cutting |
| `plugin` | string | Directory name (under `src/plugins/<name>/`) when `shape="plugin"` |
| `touches_files` | comma-separated paths | Explicit file globs (overrides plugin auto-derivation; required for `shape="core"`) |

When `shape="plugin"` and a `plugin=` attribute is set, `touches_files`
defaults to `["src/plugins/<plugin>/**"]`, giving the dispatcher's
file-claim locks an unambiguous file set per feature.  See
[CLAUDE.md → spec/parser.py](../CLAUDE.md) for detailed semantics.

`shape="core"` without an explicit `touches_files` attribute fails the
parse with a clear error — cross-cutting features can't be auto-derived
from a directory.

#### Related commands
- **Before:** `claw-forge init` → `/create-spec`
- **After:** `claw-forge run`

---

### `claw-forge validate-spec`

#### Purpose
Validates a spec file across 3 layers before it seeds the task DAG. Catches bad bullets
early so agents never receive vague, untestable, or incomplete work orders — the most
common source of agent failure and rework.

#### When to use
- After `/create-spec` writes `app_spec.txt` and before `claw-forge plan`
- After manually editing a spec to verify you haven't broken any bullets
- In CI pipelines to gate `claw-forge plan` on spec quality

#### Usage
```bash
# Full validation — all 3 layers (requires ANTHROPIC_API_KEY for Layer 2)
claw-forge validate-spec app_spec.txt

# Structural + coverage only — zero LLM cost, no API key required
claw-forge validate-spec app_spec.txt --no-llm

# Stricter LLM threshold (default is 7.0)
claw-forge validate-spec app_spec.txt --threshold 8.0

# Use a different model for Layer 2 (default: Haiku)
claw-forge validate-spec app_spec.txt --model claude-sonnet-4-6
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `spec` | positional | **required** | Path to `app_spec.txt` or XML spec file |
| `--no-llm` | flag | `False` | Skip Layer 2 adversarial LLM evaluation |
| `--threshold`, `-t` | float | `7.0` | Layer 2 approval threshold (0–10) |
| `--model`, `-m` | string | `claude-haiku-4-5-20251001` | Model for Layer 2 evaluation |
| `--soft-shape` | flag | `False` | Opt out of strict shape validation (on by default since v0.8.46). Keeps **promotable** Layer 4 WARNINGs (Gaps 3, 5, 9) at WARNING severity instead of ERROR. Heuristic gaps (6, 7) stay WARNING regardless; structural gaps (1, 8, 10) stay ERROR regardless. Use during the migration on-ramp when an older spec hasn't been brought up to strict standards yet. |
| `--strict-shape` | flag | `False` | **Deprecated alias** (v0.8.46+). Strict shape validation is now on by default; this flag is a no-op kept for one release for back-compat with existing scripts. Prints a one-line deprecation notice when used. |
| `--allow-soft-migration-shape` | flag | `False` | Keep Gap 8 (migration-shape candidate) at WARNING severity instead of the v0.8.23+ default of ERROR. Use during migration on-ramp when an existing spec has unannotated migration features. Mirrors the config key `validation.allow_soft_migration_shape`. |
| `--project-root` | path | auto-detected | Override the auto-detected project root used for Layer 4 filesystem checks (Gap 5 plugin-dir-existence; Gap 10 touches_files-resolves-to-real-files). Without this flag, validate-spec walks up from the spec file looking for `.claw-forge.yaml` first, then `.git`. |

#### The 4 layers

**Layer 1 — Structural (deterministic, zero cost)**
Every bullet is checked for:
- **Action-verb prefix** — must start with `User can`, `System returns`, `API validates`, `UI displays`, etc.
- **Measurable outcome** — must contain an observable result: HTTP status code, field name, UI element, redirect target, or event name
- **Atomicity** — no compound connectors (`and then`, `and receive`, `and redirect`) that hide multiple behaviors in one bullet
- **Non-vagueness** — minimum word count; no `etc`, `various`, `stuff`, `things`

Layer 1 violations are **errors** (compound bullets) or **warnings** (missing outcome, vague phrasing).

**Layer 2 — Adversarial LLM evaluation (per category, optional)**
A separate model call grades each category's bullet set on 4 spec-specific dimensions:

| Dimension | Weight | What it checks |
|-----------|--------|----------------|
| Testability | ×3 | Can you write a pass/fail test for every bullet? |
| Atomicity | ×3 | Is each bullet one implementable unit? |
| Specificity | ×2 | Does each bullet name concrete outcomes? |
| ErrorCoverage | ×2 | Does the category cover error and edge cases? |

Categories scoring below `--threshold` emit a WARNING with specific feedback.
Skips gracefully if `ANTHROPIC_API_KEY` is not set — and the skip is **advisory
(INFO, dim)** for greenfield specs (which `/create-spec` just authored to these
same standards, so re-grading is redundant) so it never inflates the warning
count. For a hand-written / imported **brownfield** spec the skip stays a WARNING,
since no LLM enforced quality there and the adversarial grade is worth running.

**Layer 3 — Coverage gap detection (deterministic, zero cost)**
Cross-references `<api_endpoints_summary>` and `<database_schema>` against feature bullets.
Every listed endpoint and table must appear in at least one bullet — otherwise agents will
never implement it.

**Layer 4 — Architectural shape** (catches gaps in `<feature shape>` annotations).

Severity matrix as of v0.8.46 (strict-shape on by default; pass `--soft-shape` to opt out):

| Gap | Check | Default (strict) | --soft-shape |
|-----|-------|-----------------|--------------|
| 1   | `shape="plugin"` missing both `plugin=` and `touches_files=` | ERROR | ERROR |
| 3   | `shape="core"` `touches_files` overlapping a plugin directory | ERROR | WARNING |
| 5   | brownfield-only — `plugin="X"` references nonexistent directory | ERROR | WARNING |
| 6   | heuristic — vertical-looking category with no shape declared | WARNING | WARNING |
| 7   | long core-on-core `depends_on` chain (depth ≥ 4) | WARNING | WARNING |
| 8   | heuristic — description looks migration-related but not `shape="core"` | ERROR | WARNING (via `--allow-soft-migration-shape`) |
| 9   | feature has no explicit `depends_on=` and category words share no keyword with any phase title | ERROR | WARNING |
| 10  | brownfield-only — `touches_files` glob resolves to zero real files | ERROR | ERROR |
| 11  | `shape="plugin"` `touches_files` reach outside its own `src/plugins/<name>/` dir (a shared registration seam) | WARNING | WARNING |

**Heuristic gaps (6, 7) are never promoted to ERROR** even under strict mode, because their vocabulary-driven detection (frozen-set token matching) guarantees false-positives on legitimate cross-cutting code. Hard-erroring would block correct specs.

**Brownfield detection (used by Gaps 5 and 10)** uses layout-agnostic markers (`.git`, `pyproject.toml`, `package.json`, `go.mod`, `Cargo.toml`, `Gemfile`, `build.gradle`, `pom.xml`, `composer.json`, plus legacy `src/plugins/`). Before v0.8.46 this gated on `src/plugins/` only — a circular check that silently disabled Gap 5 for any project not following the claw-forge plugin convention.

**The filesystem Gaps (5, 10) also require the spec itself to be brownfield** (`mode="brownfield"`). A `mode="greenfield"` spec — the `/create-spec` default — describes a project that does not exist yet, so its `plugin=` directories and `touches_files` globs are aspirational; checking them against whatever directory surrounds the spec (e.g. validating the bundled example inside an unrelated git repo) produces only false positives. AlphaStrike-class specs arrive through the brownfield `add` path (`mode="brownfield"`) and stay caught.

**Gap 10 catches the AlphaStrike bug class**: a spec declares `plugin="agent"` (default-resolves to `touches_files=["src/plugins/agent/**"]`) on a codebase that puts agent code at `src/agent/`. The glob matches zero files, the dispatcher's file-claim system silently dispatches with no lock, and parallel agents collide on real shared files. Always ERROR; brownfield-gated only. **Exempt:** globs under `tests/e2e/` or `tests/integration/` — those dirs are created by the terminal End-to-End Verification task, so a zero-match is expected, not a mislocation (a non-test glob beside an exempt one still errors).

**Gap 11 nudges plugins toward auto-discovery**: a `shape="plugin"` feature that declares `touches_files` reaching outside its own `src/plugins/<name>/` directory (e.g. into a central `router.py` or an entry-points table to register itself) is editing a shared file — exactly where parallel plugin agents collide, and what the opt-in `agent.sandbox.fence_to_touches_files` fence forbids at runtime. Always WARNING (never promoted): the fix is convention-based discovery so the feature's footprint stays inside its own dir; if a shared edit is genuinely unavoidable, mark the feature `shape="core"` so the scheduler serializes it. Precondition for enabling the sandbox fence.

**Gap 12 flags an unowned dependency manifest** (brownfield-only): a multi-feature (≥5) spec where no feature declares a dependency manifest (`pyproject.toml`, `package.json`, `Cargo.toml`, `go.mod`, `composer.json`, `Gemfile`, `pubspec.yaml`, `*.csproj`, …) in its `touches_files`. Every feature that adds a dependency then edits the manifest + lockfile as an undeclared side-effect, so parallel agents collide on them (the Acumina conflict class: `pyproject.toml` / `uv.lock` touched by many features, declared by none). Always WARNING (never promoted): the fix is a front-loaded foundation `shape="core"` feature that provisions the full dependency set up front (e.g. `touches_files="pyproject.toml,uv.lock"`), depended on by the rest, so feature agents never touch the manifest. Greenfield specs skip it (the manifest is provisioned by the initializer). At runtime, `git.shared_file_resolution` auto-heals any residual manifest/lockfile collisions during catch-up merges.

Parser-level guards (raise `ValueError` before validate-spec produces structured layers):
- Unknown `shape=` values (e.g. `shape="ploogin"`).
- `shape="core"` without `touches_files=`.

#### What it does internally
1. Parses the spec with `ProjectSpec.from_file()`.
2. Runs Layer 1 structural rules on every bullet.
3. Runs Layer 2 adversarial LLM evaluation per category (if `--no-llm` is not set).
4. Runs Layer 3 coverage gap detection against endpoints and tables.
5. Runs Layer 4 shape-awareness checks on `<feature shape>` annotations.
6. Prints a layered report and exits non-zero if any **errors** are found.

#### Output example
```
Validating: app_spec.txt
  Features:   59
  Categories: 6
  Endpoints:  24
  Tables:     5

Layer 1 (Structural)  PASS  0 errors, 3 warnings
  ⚠ [Task Management] Bullet has no measurable outcome.
    → Add a concrete result: HTTP status code, UI element name, field name.
    Bullet: "User can search tasks"
  ⚠ [API Layer] Bullet is too short (4 words). Minimum is 6.
  ⚠ [UI / UX] Bullet contains vague filler: ['etc'].

Layer 2 (LLM eval)    PASS
  ✓ Authentication & User Management: 8.9/10
  ✓ Task Management: 7.8/10
  ✓ API Layer: 8.2/10
  ✓ UI / UX: 7.1/10

Layer 3 (Coverage)    PASS  0 gaps

✅ Spec passed validation  (3 warnings)

  Next: claw-forge plan app_spec.txt
```

#### Failing example
```
Layer 1 (Structural)  FAIL  1 errors, 2 warnings
  ✗ [Authentication] Compound bullet detected ('and then'). Split into two bullets.
    → Each bullet must be one atomic behavior.
    Bullet: "User can register and then login and receive a JWT token"

✗ Spec has 1 error(s) — fix before running claw-forge plan

  To fix: open Claude Code and run /fix-spec
  Then re-run: claw-forge validate-spec app_spec.txt
```

The re-run hint preserves whatever flags you originally passed
(`--soft-shape` in particular) so iterative fix-spec loops don't
lose context between runs.

Exit code 1, blocks `claw-forge plan`. Run `/fix-spec` in Claude Code to auto-repair the issues
iteratively, then re-run `validate-spec` until clean.

#### Pro tips
- Run `--no-llm` in tight loops when iterating on the spec — it's instant and free.
- Use `--threshold 8.0` for mission-critical apps where you want highly specific bullets.
- In CI, add `claw-forge validate-spec app_spec.txt --no-llm` as a gate before `claw-forge plan`.
- The Layer 3 gap report is the most actionable output — each gap is a feature the agents will silently never implement.

#### Related commands
- **Before:** `/create-spec`
- **If issues found:** `/fix-spec` — auto-repairs issues and re-validates in a loop
- **After:** `claw-forge plan`

---

### `claw-forge import`

#### Purpose
Convert a 3rd-party harness tool export (BMAD, Linear JSON, Jira XML/CSV, or generic markdown
folder) into a claw-forge spec file (`app_spec.txt` or `additions_spec.xml`).

#### When to use
- You have BMAD planning output (`prd.md`, `architecture.md`, `stories/`)
- You exported issues from Linear as JSON
- You exported tickets from Jira as XML or CSV
- You have a folder of markdown files describing features

#### Usage
```bash
# Auto-detect format and convert
claw-forge import ./bmad-output

# Skip confirmation prompt
claw-forge import ./bmad-output --yes

# Use a faster model
claw-forge import ./bmad-output --model claude-sonnet-4-6

# Write to a custom filename
claw-forge import ./bmad-output --out my-spec.xml

# Point at a different project directory
claw-forge import ./linear-export.json --project ~/projects/myapp
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `path` | positional | **required** | Path to harness output folder or file |
| `--project`, `-p` | path | `.` | Project directory (for brownfield detection + output) |
| `--model`, `-m` | string | `claude-opus-4-6` | Model for Claude conversion calls |
| `--yes`, `-y` | flag | `False` | Skip format confirmation prompt |
| `--config`, `-c` | path | `claw-forge.yaml` | Config file path |
| `--out`, `-o` | string | `""` | Output filename (default: auto — `app_spec.txt` or `additions_spec.xml`) |

#### What it does internally
1. Scans the path and detects format (BMAD / Linear / Jira / generic) with confidence score.
2. Shows the detected format and asks for confirmation (unless `--yes`).
3. Extracts epics, stories, tech stack, DB schema, and API endpoints using format-specific rules.
4. Calls Claude once per XML section (overview+tech, core features per epic, DB+API, steps+criteria).
5. Detects greenfield vs brownfield from presence of `brownfield_manifest.json`.
6. Writes `app_spec.txt` (greenfield) or `additions_spec.xml` (brownfield).
7. Shows output stats and next steps.

#### Output example
```
Scanning ./bmad-output...
✓ Detected: BMAD output — prd.md + architecture.md + 2 epics (5 stories)
  Confidence: high

Proceed with import? [Y/n]: Y

Extracting structure...  ✓  2 epics, 5 stories
Converting to spec via Claude...  ✓
Auto-detected: greenfield (no brownfield_manifest.json found)

✓ Written: app_spec.txt
  Features: 23 bullets across 2 categories
  Epics:    2 implementation phases

Next steps:
  1. Review app_spec.txt
  2. claw-forge validate-spec app_spec.txt
  3. claw-forge plan app_spec.txt
```

The importer emits shape-annotated `<feature>` elements for every category
(plugin shape by default; core shape with explicit `touches_files` for
clearly cross-cutting stories), so the spec is expected to pass strict-shape
validation (default since v0.8.46) on the first try.

#### Pro tips
- Use `--yes` in scripts and CI pipelines to skip the confirmation prompt.
- For interactive section-by-section review, use `/import-spec` in Claude Code instead.
- Run `claw-forge analyze` first on brownfield projects to generate `brownfield_manifest.json`.
- The converter uses one Claude call per section to avoid context truncation on large specs.

#### Related commands
- **Before:** `claw-forge analyze` (brownfield), BMAD / Linear / Jira planning tools
- **Interactive version:** `/import-spec` slash command
- **After:** `claw-forge validate-spec`, `claw-forge plan`

---

### `claw-forge run`

#### Purpose
Starts the agent pool, dispatches features from the state DB to coding agents in parallel, and
drives the full implementation loop (code → test → review → merge).

#### When to use
- After `claw-forge plan` to begin building a new project
- After `claw-forge add` or `/expand-project` to build newly added features
- When resuming after an interruption — orphaned `running` tasks from the previous session are automatically reset to `pending` and retried
- For controlled feature sprints with `--concurrency` tuned to your provider tier

#### Usage
```bash
# Standard run (5 concurrent agents, Sonnet, reads claw-forge.yaml)
claw-forge run

# Override project directory
claw-forge run --project ~/projects/taskflow-api

# More concurrency for a large feature set
claw-forge run --concurrency 10

# YOLO mode: skip human-input prompts, max CPU concurrency, aggressive retry
claw-forge run --yolo

# Use a specific model for all coding agents
claw-forge run --model claude-opus-4-20250514

# Use a different config (e.g. high-priority providers)
claw-forge run --config claw-forge.premium.yaml

# Use hashline edit mode — dramatically improves weaker models
# (6.7% → 68.3% benchmark on Grok Code Fast, see docs/agent-skill.md)
claw-forge run --edit-mode hashline
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--config`, `-c` | path | `claw-forge.yaml` | Provider and orchestrator config |
| `--project`, `-p` | path | `.` | Project root directory |
| `--task`, `-t` | string | `coding` | Agent plugin to run (`coding`, `testing`, `reviewing`) |
| `--model`, `-m` | string | `claude-sonnet-4-20250514` | Model identifier for coding agents |
| `--concurrency`, `-n` | int | `5` | Max agents running simultaneously |
| `--yolo` | flag | `False` | Skip human approval gates, max concurrency, aggressive retry.  Autonomous main-worktree cleanup (`handle_uncommitted_at_startup: smart`) is now the default regardless of `--yolo`; explicit config values still win. |
| `--edit-mode` | string | `str_replace` (CLI flag default) | Edit tool format: `str_replace` or `hashline` (content-addressed, better for weaker models). **`claw-forge init` writes `agent.edit_mode: hashline` into the scaffolded `claw-forge.yaml`**, so new projects use hashline unless you explicitly pass `--edit-mode str_replace` or edit the yaml. |
| `--loop-detect-threshold` | int | `5` | Max edits to a single file before the LoopDetectionMiddleware injects a "reconsider" prompt. Set to `0` to disable. When `--edit-mode hashline` is active, threshold auto-raises by 3 (e.g. 5 → 8). |
| `--verify-on-exit/--no-verify-on-exit` | flag | `True` | Inject a pre-completion verification checklist before the agent exits — forces re-reading the spec, running tests, and confirming correctness. Disable for fast iteration / debugging. |
| `--push-after-merge` | flag | `False` | After every successful squash-merge into the target branch, push the target branch to its remote.  Skipped silently when the configured remote doesn't exist or when the merge was a no-op (content already on target).  **Off by default — must be explicitly opted in.** |
| `--push-remote` | string | `"origin"` | Remote name used by `--push-after-merge`.  Override for forks (e.g. `upstream`). |
| `--no-local` | flag | `False` | Ignore the per-machine `claw-forge.local.yaml` overlay and load only the committed base config. Use for reproducible / CI runs. By default, if a sibling `claw-forge.local.yaml` exists it is deep-merged on top of the base before `${ENV}` expansion (e.g. a locally-disabled provider). |

> **Acceptance gating (`agent.acceptance_gate.enabled`, config-only, default `false`).**
> `--verify-on-exit` is a *soft* gate — it asks the agent to self-check before
> exiting. Acceptance gating is the *hard* counterpart: when enabled, after the
> agent reports a task complete claw-forge **runs the project's test command in
> the task's worktree itself** and a non-zero exit blocks completion — the task
> flips to `failed` and the retry loop re-runs the agent with the failures in
> its resume preamble (bounded by `git.retry_attempts`). So "done" means the
> tests actually pass, not that the agent said so. The command auto-detects
> (`pytest`/`npm test`/`cargo test`/`go test`/`make test`) or set
> `agent.acceptance_gate.command`; it **auto-skips** when no test command exists
> (a greenfield project before any framework is in place is never blocked).
> Pairs naturally with the terminal End-to-End Verification task (`spec.append_e2e_task`).
>
> ```yaml
> agent:
>   acceptance_gate:
>     enabled: true
>     # command: "uv run pytest tests/ -q"   # optional override
>     # timeout: 600
> ```

#### What it does internally
1. Loads `claw-forge.yaml`; if a gitignored `claw-forge.local.yaml` sibling exists (and `--no-local` was not passed), deep-merges it on top, then expands `${ENV_VAR}` placeholders.
2. Connects to the state service (starts one if not running).
3. Pulls the feature queue: tasks with status `pending`, `failed`, or `running` (orphaned from a previous interrupted run).
4. Resets any orphaned `running` tasks back to `pending` in the DB so the UI reflects the true state.
5. Spawns up to `--concurrency` Claude Code agent sessions via the provider pool.
6. Each agent runs the TDD loop: write tests → make them pass → commit.
7. On completion, updates feature status in the state DB (Passing / Failed / Blocked).
8. If a feature is Blocked, prompts for human input (unless `--yolo`).
9. Continues until the queue is empty or all remaining features are Blocked/Failed.

#### Real-world example
TaskFlow API has 59 features across 4 waves. You run:

```bash
claw-forge run --concurrency 5 --model claude-sonnet-4-20250514
```

Wave 1 (8 auth features) starts immediately, 5 agents fire in parallel. Wave 2 begins as Wave 1
features reach "Passing" status.

#### Output example
```
claw-forge v0.2.0b1
Project: ~/projects/taskflow-api
Task:    coding
Model:   claude-sonnet-4-20250514
Providers: 3

Dispatching wave 1/4 (8 features, concurrency=5)…
  [1/5] Agent abc123 → "User can register with email and password"
  [2/5] Agent def456 → "User can login and receive JWT tokens"
  [3/5] Agent ghi789 → "System validates email format on registration"
  [4/5] Agent jkl012 → "System hashes passwords with bcrypt"
  [5/5] Agent mno345 → "User can request password reset email"

✅ "User can register" — PASSING (1m 42s, $0.04)
✅ "User can login"    — PASSING (2m 08s, $0.05)
⏳ "Rate limiting"    — waiting on: auth-core (blocked)

Progress: 12/59 passing · 3 in-flight · $0.61 spent
```

#### Pro tips
- Start with `--concurrency 3` on a new project to verify your spec parses cleanly before
  committing to a full parallel run.
- Use `--yolo` only when you trust your spec is precise. Human-input gates exist for a reason.
- Open `claw-forge ui` in a separate terminal while `run` is active to watch the Kanban board.

#### Parallel-safe agents via file-claim locks

When `--concurrency` is greater than 1, two agents working in parallel can collide on the same file — one re-edits a section the other just rewrote, or both append slightly-different stanzas that fight at squash time. File-claim locks prevent that *spatially*: a task declares the files it intends to touch, and the dispatcher refuses to start a second task that wants any of the same files until the first releases.

##### Opt in by declaring `touches_files`

Tasks declare intent on creation. Pass `touches_files` (a list of repo-relative paths) to `POST /sessions/{session_id}/tasks`:

```bash
curl -X POST http://localhost:8420/sessions/$SESSION_ID/tasks \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Add JWT refresh endpoint",
    "description": "...",
    "agent_type": "coding",
    "touches_files": ["claw_forge/auth/jwt.py", "tests/test_jwt.py"]
  }'
```

Before dispatch, the dispatcher POSTs an atomic claim for the listed paths. If any path is already claimed by a *running* task, the dispatcher defers this task to the next dispatch cycle (it stays `pending` and is reconsidered each tick). Tasks **without** a `touches_files` field participate in no locking — they neither acquire claims nor block on existing ones, preserving full backward compatibility for callers and plugins that don't declare intent.

##### Auto-release on terminal status

Claims are scoped to the task and released automatically when the task transitions to `completed`, `failed`, or `paused`. There is no manual unlock step and no way for a forgotten release to deadlock other tasks — once a claiming task leaves the `running` state for any reason (success, error, dispatcher pause), its files become available on the next dispatch cycle.

##### Spatial vs temporal: how this complements merge-gating

File claims and merge-gating (`merged_to_target_branch`) handle two different conflict shapes. They are independent and run concurrently:

- **File claims (spatial)** — "task A and task B want to edit the same file *right now*". Resolved by serialising the two: A holds the claim, B defers.
- **Merge-gating (temporal)** — "task B depends on task A; B should not start until A's squash-merge has landed on `target_branch`". Resolved by holding B in `blocked` until A is `completed AND merged_to_target_branch=True` (see *Merge-gating* in the architecture notes).

A task can be subject to both. A child task that declares `touches_files` for files its parent also touches will (a) wait for its parent to merge before it leaves `blocked` (temporal), and (b) once unblocked, wait for any sibling running task that holds those file claims to release them (spatial).

##### Inspecting claims directly

Three REST endpoints expose the claim state for callers driving the state service directly:

| Endpoint | Purpose |
|---|---|
| `POST /sessions/{session_id}/file-claims` | Atomic claim acquire for a task. Returns `200` on success, `409` with the conflicting task ID on collision. The dispatcher calls this internally — manual callers rarely need it. |
| `DELETE /sessions/{session_id}/file-claims/{task_id}` | Release every claim held by a task. Auto-fires on terminal status; manual call is for diagnostics or tests. |
| `GET /sessions/{session_id}/file-claims` | List current claims (path, holder task ID, acquired-at timestamp). Useful when investigating why a `pending` task is being deferred — the dispatcher logs `deferred: file_claim_conflict`, and this endpoint shows you the holder. |

If a task is repeatedly deferred for many cycles, inspect `GET /file-claims` to see which path is contended; usually it indicates two features were planned to touch the same module and one of them is the obvious owner.

#### Parallelism + architectural shape

The dispatcher consults each task's `shape` attribute when selecting the
next ready task:

| Shape | Dispatch policy |
|---|---|
| `plugin` | Up to `--concurrency N` in parallel; `touches_files` auto-derived from plugin directory |
| `core` | Single-flight (only one core task at a time, regardless of `--concurrency`) |
| _unset_ | Legacy: concurrency cap + file-claim locks only |

This makes high-concurrency runs structurally safe: plugin-shape tasks
operate on disjoint files, so the file-claim locks rarely contend; core
tasks queue serially so cross-cutting middleware/error/DB changes don't
race.  Spec-time classification is the input — see [`/create-spec` Phase
3.25](#create-spec) for how to populate it.

#### Failure modes — `resume_conflict`

When a previously-interrupted task is resumed, the dispatcher attempts a catch-up merge of the target branch into the feature branch *before* the agent runs (via `sync_worktree_with_target` in `claw_forge/git/merge.py`). This eliminates the prior failure pattern where the catch-up only happened at squash time, after the agent had already wasted a turn on stale state.

If the catch-up hits real content conflicts — both `target_branch` and the resumed feature branch modified the same lines of the same file since they diverged — the task is marked `failed` immediately with an `error_message` of the form:

```
resume_conflict: catch-up merge of main into branch failed on N file(s):
foo.py, bar.py. Resolve manually in <worktree-path> (run `git merge main`,
fix conflicts, commit) and requeue the task.
```

The worktree is preserved on disk so you can resolve manually:

```bash
cd .claw-forge/worktrees/<slug>
git merge <target>           # produces conflict markers
# resolve in your editor
git add -A && git commit --no-verify
```

Then requeue the task — click 'Reset All' on the Failed column in the Kanban UI, or POST to the state service: `curl -X POST http://localhost:8420/sessions/$SESSION_ID/tasks/requeue -d '{"statuses":["failed"]}' -H 'Content-Type: application/json'`. The next dispatch syncs cleanly because the resolution commit is now on the feature branch.

If the partial work is throwaway, use `claw-forge worktrees prune --discard` to drop the branch and worktree; the task's next retry will recreate them from current `target_branch`.

A second `resume_conflict` shape — `dirty_worktree: True` — appears when the worktree has uncommitted edits left over from an interrupted run. The dispatcher refuses to merge over uncommitted state to avoid silently overwriting the user's edits; commit or discard them inside the worktree, then requeue.

#### Related commands
- **Before:** `claw-forge plan`, `claw-forge state`
- **During:** `claw-forge status`, `claw-forge ui`, `claw-forge pause`
- **After:** `/check-code`, `/checkpoint`, `/review-pr`

---

### `claw-forge add`

#### Purpose
Adds one or more features to an existing project — either a single feature description or a full
brownfield spec — without touching features that are already passing.

#### When to use
- You want to add a single feature mid-sprint without writing a full spec
- You've generated `additions_spec.xml` via `/create-spec` (brownfield mode)
- A stakeholder requests a new endpoint after the first run finished
- You're iterating on an existing app and want agents to match its existing conventions

#### Usage
```bash
# Single feature, quick add
claw-forge add "User can export tasks as CSV"

# From a brownfield XML spec
claw-forge add --spec additions_spec.xml

# Suppress automatic branch creation
claw-forge add "Add rate limiting" --no-branch

# Target a non-current directory
claw-forge add --spec additions_spec.xml --project ~/projects/myapp
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `feature` | positional | — | Feature description or `@spec-file` path |
| `--spec`, `-s` | path | `None` | Path to brownfield `additions_spec.xml` |
| `--project`, `-p` | path | `.` | Project root directory |
| `--branch/--no-branch` | flag | `True` | Auto-create a git branch for the addition |

#### What it does internally
1. If `--spec` is provided, reads `additions_spec.xml` and loads `brownfield_manifest.json` from
   the project root (if present) to provide existing context.
2. Merges `stack`, `test_baseline`, and `conventions` from the manifest into the agent context.
3. Runs `InitializerPlugin` to parse the new features and append them to the state DB.
4. Prints integration points and constraints from the spec.
5. Suggests a git branch name based on the spec's `<project_name>`.
6. Shows the next command: `claw-forge run`.

#### Real-world example
Your TaskFlow API is live. Product wants Stripe payments. You've run `/create-spec` (brownfield)
to produce `additions_spec.xml`. Now:

```bash
claw-forge add --spec additions_spec.xml
```

#### Output example
```
✅ Brownfield spec: TaskFlow API — Stripe Payments
   Mode: brownfield
   Features to add: 12
   Constraints: 3
   Integration points: 4

Agent context:
  Existing stack: Python / FastAPI / SQLite
  Test baseline: 59 tests passing, 91% coverage
  Conventions: snake_case, async handlers, pydantic v2

  ⚠ Constraints (will be enforced by all agents):
    1. Must not modify existing auth flow
    2. All 59 existing tests must stay green
    3. Follow existing async handler pattern in routers/

  Suggested git branch: feature/stripe-payments

  Next: claw-forge run --project .
```

#### Pro tips
- Always run `claw-forge analyze` first when adding to an existing codebase — it generates
  `brownfield_manifest.json` which gives agents full context about your conventions.
- For a single quick feature, the positional form (`claw-forge add "..."`) is faster than a
  full spec.
- Commit your current state before `claw-forge add` — the auto-branch makes it easy to diff.

#### Related commands
- **Before:** `claw-forge analyze`, `/create-spec` (brownfield mode)
- **After:** `claw-forge run`

---

### `claw-forge fix`

#### Purpose
Runs a reproduce-first bug-fix protocol: the agent writes a failing test that proves the bug,
then makes it pass, then runs the full regression suite to ensure nothing else broke.

#### When to use
- A user reports a bug and you have a clear reproduction path
- CI is failing on a specific test and you want an agent to diagnose and fix it
- You've created a `bug_report.md` via `/create-bug-report` and want to hand it to an agent
- Quick one-liner fix for obvious issues without writing a formal report

#### Usage
```bash
# One-liner description
claw-forge fix "User gets 500 error when resetting password with uppercase email"

# From a structured bug report (recommended for complex bugs)
claw-forge fix --report bug_report.md

# Target a different project
claw-forge fix --report bug_report.md --project ~/projects/taskflow-api

# Don't create a git branch (fix directly on current branch)
claw-forge fix "Missing null check in task serializer" --no-branch
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `description` | positional | `None` | One-line bug description |
| `--report`, `-r` | path | `None` | Path to `bug_report.md` |
| `--project`, `-p` | path | `.` | Project root directory |
| `--branch/--no-branch` | flag | `True` | Create `fix/<slug>` git branch |

#### What it does internally
1. Parses the bug report or description into a `BugReport` object.
2. Creates a `fix/<slug>` git branch (e.g. `fix/uppercase-email-password-reset`).
3. Runs `BugFixPlugin` which spawns a coding agent with the bug context.
4. Agent phase 1 (RED): writes a failing regression test that proves the bug exists.
5. Agent phase 2 (GREEN): modifies source code until the test passes.
6. Agent phase 3 (REFACTOR): runs full test suite; fails if any existing tests break.
7. Reports files modified and the test that was added.

#### Real-world example
A user reports: "I can't reset my password if my email address has any uppercase letters."
You use `/create-bug-report` to generate `bug_report.md`, then:

```bash
claw-forge fix --report bug_report.md
```

#### Output example
```
🐛 Bug: Password reset fails for emails with uppercase letters
[dim]Created branch: fix/password-reset-fails-for-emails-with-uppercase-lett[/dim]

Running bug-fix agent…

  Phase 1 — RED: Writing failing test…
    ✅ test_password_reset_uppercase_email FAILED (as expected)

  Phase 2 — GREEN: Finding root cause…
    Root cause: auth/service.py:142 — email not lowercased before DB lookup
    Fix: add .lower() before query

  Phase 3 — REFACTOR: Running full test suite…
    ✅ 59 tests passed, 0 failed

✅ Bug fix complete
   Files modified: auth/service.py, tests/test_auth.py
   New test: test_password_reset_uppercase_email
```

#### Pro tips
- Use `--report bug_report.md` for anything non-trivial — the structured report gives the agent
  reproduction steps, expected vs actual behaviour, and scope constraints.
- The mandatory regression test is the real value here: the bug can never silently re-appear.
- If the fix attempt fails, the agent explains why — use that output as context for your own fix.

#### Related commands
- **Before:** `/create-bug-report` (generate the structured report)
- **After:** `/check-code`, `/review-pr`

---

### `claw-forge status`

#### Purpose
Shows a zero-friction project status card: progress by phase, active agent state, cost so far,
and the one recommended next action — perfect for re-entry after leaving a session.

#### When to use
- Coming back to a project after a break and want to see where things are
- Something looks stuck and you want to know which feature is Blocked
- You want a quick cost check before letting more agents run
- Before running `/checkpoint` to know the current state of play

#### Usage
```bash
# Default (reads claw-forge.yaml in cwd)
claw-forge status

# Explicit config
claw-forge status --config claw-forge.yaml
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--config`, `-c` | path | `claw-forge.yaml` | Path to YAML config |

#### What it does internally
1. Loads config and connects to the state service (port 8420 by default).
2. Fetches session list and active feature states.
3. Groups features by phase and status (Pending / In Progress / Passing / Failed / Blocked).
4. Calculates per-phase progress bars and overall completion percentage.
5. Shows cost, active agent count, and the recommended next action.

#### Real-world example
You paused a TaskFlow run an hour ago and are back at your desk:

```bash
claw-forge status
```

#### Output example
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  TaskFlow API  ·  claude-sonnet-4-20250514  ·  $2.41 spent
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  Phase 1: Core models + auth    ████████████████ 8/8   ✅ complete
  Phase 2: Task CRUD             ████████████░░░░ 12/16  🔄 in progress
  Phase 3: Notifications         ░░░░░░░░░░░░░░░░ 0/6    ⏳ pending
  Phase 4: Polish                ░░░░░░░░░░░░░░░░ 0/9    ⏳ pending

  Active agents (3):
    Agent a1b2c3 → "User can filter tasks by due date"    (1m 12s)
    Agent d4e5f6 → "System paginates task list responses" (0m 48s)
    Agent g7h8i9 → "User can assign tasks to team members" (2m 03s)

  Blocked (1):
    ⚠ "Webhook notification on task complete" — waiting for human input
    → Run: claw-forge input taskflow-api

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  20/39 features passing  ·  3 in-flight  ·  1 blocked
  Next: answer the blocked feature's question, then continue
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

#### Pro tips
- Run `claw-forge status` before re-running `claw-forge run` — if features are Blocked, answer
  them first with `claw-forge input`.
- The "Next action" line is the most important thing on screen: follow it.
- Alias this to `cf-st` in your shell for speed.

#### Related commands
- **Next:** `claw-forge input`, `claw-forge run`, `/checkpoint`

---

### `claw-forge analyze`

#### Purpose
Scans an existing codebase to understand its stack, test baseline, conventions, and hot files —
then writes `brownfield_manifest.json`, which enables subsequent `add` and `fix` commands to
match your existing patterns.

#### When to use
- Before adding features to a codebase claw-forge has never seen
- When your team has coding conventions you want agents to respect
- After cloning an inherited repository you want to extend
- Before running `/create-spec` in brownfield mode

#### Usage
```bash
# Analyze current directory
claw-forge analyze

# Analyze a specific project
claw-forge analyze --project ~/projects/myapp

# With explicit config
claw-forge analyze --config claw-forge.yaml --project .
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--project`, `-p` | path | `.` | Project root to analyze |
| `--config`, `-c` | path | `claw-forge.yaml` | Path to YAML config |

#### What it does internally
1. Scans file extensions to detect language/framework/database.
2. Parses `pyproject.toml` / `package.json` / `go.mod` for dependencies.
3. Runs `git log --stat` to identify hot files (most frequently changed).
4. Runs the test suite to establish the baseline (N tests, X% coverage).
5. Inspects source files for naming conventions, docstring style, import patterns.
6. Writes `brownfield_manifest.json` to the project root.

#### Real-world example
You're adding Stripe payments to a live FastAPI app:

```bash
cd ~/projects/myapp
claw-forge analyze
```

#### Output example
```
Analyzing ~/projects/myapp…

  Stack detected:
    Language:   Python 3.12
    Framework:  FastAPI 0.111
    Database:   PostgreSQL (asyncpg)
    Testing:    pytest + pytest-asyncio

  Test baseline:
    Tests:      47 passing, 0 failing
    Coverage:   87%
    Last run:   2025-05-14 09:12

  Hot files (git history):
    routers/auth.py        — 34 commits
    services/user.py       — 28 commits
    models/user.py         — 19 commits

  Conventions detected:
    Naming:     snake_case functions, PascalCase models
    Imports:    absolute (from app.routers import ...)
    Docstrings: Google style
    Async:      async/await throughout (no sync handlers)

✅ Wrote brownfield_manifest.json
   Next: /create-spec (brownfield) → claw-forge add --spec additions_spec.xml
```

#### Pro tips
- Commit or stash local changes before `analyze` so the test baseline is clean.
- The hot files list tells you which parts of the codebase are most active — review those areas
  carefully after agents make changes.
- `brownfield_manifest.json` is committed to the repo so all team members get the same context.

#### Related commands
- **After:** `/create-spec` (brownfield mode), `claw-forge add`

---

### `claw-forge ui`

#### Purpose
Launches the real-time Kanban board — a React app that shows every feature's status (Pending,
In Progress, Passing, Failed, Blocked) with live WebSocket updates as agents work.

#### When to use
- Running a large parallel sprint and you want a visual overview
- Sharing progress with a team or stakeholder on a second monitor
- Debugging why certain features are stuck (see the Blocked column in real time)
- Checking cost and provider health at a glance during a run

#### Usage
```bash
# Default: port 5173, connects to state service on :8888
claw-forge ui

# Custom ports
claw-forge ui --port 3000 --state-port 8420

# Don't auto-open browser (useful for headless servers)
claw-forge ui --no-open

# Jump straight to a specific session
claw-forge ui --session a1b2c3d4-e5f6-7890-abcd-ef1234567890
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--port`, `-p` | int | `5173` | Port for the Vite dev server |
| `--state-port` | int | `8888` | Port the state service is running on |
| `--open/--no-open` | flag | `True` | Auto-open browser after 2s |
| `--session`, `-s` | string | `""` | Session UUID to pre-select on the board |

#### What it does internally
1. Checks that Node.js is installed.
2. If `ui/node_modules` doesn't exist, runs `npm install` automatically.
3. Sets `VITE_API_PORT` and `VITE_WS_PORT` env vars from `--state-port`.
4. Starts `npm run dev` in the `ui/` directory.
5. After a 2-second delay, opens `http://localhost:<port>/?session=<session>` in the default
   browser.

#### Real-world example
You start a 50-feature parallel run and want to watch it on your second monitor:

```bash
# Terminal 1: start state service
claw-forge state &

# Terminal 2: start agents
claw-forge run --concurrency 5

# Terminal 3: launch board
claw-forge ui --session $(cat .claw-forge/session-id)
```

#### Output example
```
🔥 Starting claw-forge Kanban UI
   UI:           http://localhost:5173/?session=a1b2c3d4
   State API:    http://localhost:8888
   Press Ctrl+C to stop

  VITE v5.2.0  ready in 312 ms
  ➜  Local:   http://localhost:5173/
  ➜  Network: http://10.0.1.42:5173/
```

Browser shows:
```
┌─────────────────────────────────────────────────────────────┐
│ TaskFlow API · 🟢 claude-oauth  🟢 anthropic-direct         │
│ Progress: ████████████░░░░  20/59 passing · $2.41 · 3 agents│
├──────────────┬──────────────┬──────────────┬────────────────┤
│   PENDING    │ IN PROGRESS  │   PASSING    │    BLOCKED     │
│     39       │      3       │     20       │       1        │
│ ─────────    │ ─────────    │ ─────────    │ ─────────      │
│ Filter tasks │ Assign tasks │ User login   │ Webhook notif. │
│ Export CSV   │ Pagination   │ User register│ (awaiting API  │
│ …            │ Due dates    │ …            │  key input)    │
└──────────────┴──────────────┴──────────────┴────────────────┘
```

## Kanban Board Overview

![Kanban board overview](../website/assets/screenshots/kanban-overview.png)
*The Kanban board shows all features across 5 columns: Pending, Running, Passing, Failed, Blocked*

### Dark Mode

![Dark mode](../website/assets/screenshots/kanban-dark.png)

### Command Palette (⌘K / Ctrl+K)

![Command palette](../website/assets/screenshots/command-palette.png)
*Press ⌘K (Mac) or Ctrl+K (Windows/Linux) to open the command palette*

#### Pro tips
- The Kanban board updates over WebSocket — no refreshing needed.
- The provider health dots (🟢/🟡/🔴) in the header tell you if a provider is circuit-broken.
- Use `--no-open` on a remote machine and tunnel via SSH: `ssh -L 5173:localhost:5173 yourserver`.

#### Related commands
- **Requires:** `claw-forge state` (state service must be running)
- **During:** `claw-forge run`, `claw-forge status`

---

### `claw-forge dev`

#### Purpose
Starts the FastAPI state service (with uvicorn `--reload`) and the Vite HMR dev server in a
single command. Both processes restart automatically on file changes. Optionally also launches
the agent orchestrator with `--run`.

#### When to use
- Developing claw-forge itself and you want hot-reload for both the API and the UI
- Running a project and you want all three processes (state service + UI + agents) from one terminal
- Pointing at a specific project directory to inspect its live state via the Kanban UI

> **Note:** Without `--run`, `claw-forge dev` only starts the servers — it does **not** execute
> agents. Tasks shown as "In Progress" in the UI are from a previous session. Run
> `claw-forge dev --run` (or a separate `claw-forge run`) to drive task execution.

#### Usage
```bash
# State service (hot-reload) + Vite UI only
claw-forge dev

# Also launch the agent orchestrator
claw-forge dev --project /path/to/project --run

# Custom ports
claw-forge dev --state-port 9000 --ui-port 3000

# Point at a different project
claw-forge dev --project ~/projects/my-app

# Don't auto-open browser
claw-forge dev --no-open
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--ui-port` | int | `5173` | Port for the Vite dev server |
| `--state-port` | int | `8420` | Port for the state service API |
| `--project`, `-p` | path | `.` | Project directory (sets DB path and passes to `run`) |
| `--open/--no-open` | flag | `True` | Auto-open browser after 3s |
| `--session`, `-s` | string | `""` | Session UUID to pre-select on the board |
| `--run/--no-run` | flag | `False` | Also launch `claw-forge run` to execute agents |

#### What it does internally
1. Validates that `ui/` source dir and Node.js are present (requires a source checkout).
2. Runs `npm install` if `ui/node_modules` is missing.
3. Launches `claw-forge state --reload` as a subprocess with `CLAW_FORGE_DB_URL` set.
4. Launches `npm run dev` in `ui/` with `VITE_API_PORT` and `VITE_WS_PORT` set.
5. If `--run` is passed, waits 2 seconds for the state service to start, then launches
   `claw-forge run --project <project>` as a third subprocess.
6. On Ctrl+C, terminates all child processes cleanly.

#### Output example
```
🔥 claw-forge dev (API + UI hot-reload)
   UI:        http://localhost:5173  (Vite HMR)
   State API: http://localhost:8420  (uvicorn --reload)
   Database:  /path/to/project/.claw-forge/state.db
   Session:   a1b2c3d4-...
   Agents:    enabled (--run)
   Press Ctrl+C to stop all servers
```

#### Pro tips
- Use `--run` for a one-command workflow: `claw-forge dev --project . --run` starts everything.
- Without `--run`, tasks stuck in "In Progress" are orphaned from a previous run — re-run
  `claw-forge run` (or use `--run`) to resume them. They will be automatically reset to pending.
- `--reload` means any change to `claw_forge/` Python files restarts the state service instantly.

#### Related commands
- **Requires source checkout:** `ui/` directory must exist
- **Alternative (production UI):** `claw-forge ui` (serves pre-built assets, no Node.js HMR)
- **Agents only:** `claw-forge run` (no UI server)

---

### `claw-forge state`

#### Purpose
Start the AgentStateService REST + WebSocket API. The state service powers the Kanban UI
and exposes REST endpoints for session, task, pool, regression, and command management.

#### When to use
- Running the state service standalone (instead of letting `claw-forge run` auto-start it)
- Connecting a PostgreSQL database instead of the default SQLite
- Development mode with hot-reload (`--reload`)
- Running the state service on a custom port or host

#### Usage
```bash
# Start on default port 8420
claw-forge state

# Start with hot-reload for development
claw-forge state --reload

# Start on a custom port, local-only
claw-forge state --port 9000 --host 127.0.0.1

# Start with PostgreSQL
claw-forge state --database-url postgresql+asyncpg://user:pass@host/db
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--port` | int | `8420` | Port to bind the state service on |
| `--host` | string | `state.host` → `0.0.0.0` | Host to bind. Overrides `state.host` in config; falls back to `state.host` then `0.0.0.0`. Use `127.0.0.1` for local-only |
| `--project`, `-p` | path | `.` | Project directory |
| `--config`, `-c` | path | `claw-forge.yaml` | Path to YAML config |
| `--reload` | flag | `False` | Enable hot-reload — restart on Python file changes (dev only) |
| `--database-url` | string | `None` | Database URL override (e.g. `postgresql+asyncpg://user:pass@host/db`). Default: SQLite in `.claw-forge/state.db` |

> **Security — network exposure.** The state service exposes 42 REST endpoints
> (including `/shutdown` and provider toggles) plus a WebSocket. The bind host
> now honours `state.host` in `claw-forge.yaml` (previously this key was ignored
> and the service always bound to `0.0.0.0`). When the resolved host is
> **non-loopback** and no auth token is set, startup prints a warning that the
> control plane is reachable from other machines. Set `state.host: 127.0.0.1`
> for local-only deployments; keep `0.0.0.0` only when you intend cross-machine
> access (e.g. a shared build box) and trust the network.
>
> **Security — opt-in bearer auth.** Set `CLAW_FORGE_STATE_TOKEN` (or
> `state.auth_token` in config) to require `Authorization: Bearer <token>` on
> every REST request and WebSocket handshake. The secret is a shared env var so
> a single `export` covers the server and every client (`run`, `ui`, `status`,
> the dispatcher, and spawned services all read it; `subprocess` inherits the
> env). Browsers pass it to the WebSocket as a `?token=` query param. Auth is
> **off by default** (no token → today's behavior), and setting it suppresses
> the exposure warning above:
>
> ```bash
> export CLAW_FORGE_STATE_TOKEN="$(openssl rand -hex 32)"
> claw-forge run        # server + clients now require the token automatically
> curl -s http://localhost:8420/metrics -H "Authorization: Bearer $CLAW_FORGE_STATE_TOKEN"
> ```
>
> Note: when serving the Kanban UI via `claw-forge ui`, the UI reverse proxy
> holds the token and authenticates upstream on the browser's behalf — bind the
> UI to localhost (the default) so that gateway isn't itself exposed.

#### What it does internally
1. Loads `claw-forge.yaml` for project metadata and provider config.
2. Starts a uvicorn server with the FastAPI state service app.
3. Creates SQLite database at `.claw-forge/state.db` (or connects to the provided `--database-url`).
4. Exposes REST endpoints for sessions, tasks, pool status, and regression.
5. Opens WebSocket at `/ws` for real-time event broadcasting to the Kanban UI.
6. With `--reload`, watches Python source files and restarts on changes.

#### Metrics (`GET /metrics`)

The service exposes Prometheus text-format metrics for scraping into
Grafana/Alertmanager — the machine-readable counterpart to the Kanban board:

```bash
curl -s http://localhost:8420/metrics
```

| Metric | Type | Labels | Meaning |
|--------|------|--------|---------|
| `claw_forge_tasks` | gauge | `status` | Task count per status (scoped to this service's project) |
| `claw_forge_cost_usd_total` | counter | — | Cumulative agent spend (USD) |
| `claw_forge_tokens_total` | counter | `type` (`input`/`output`) | Cumulative tokens |
| `claw_forge_ws_clients` | gauge | — | Live Kanban WebSocket connections |
| `claw_forge_provider_circuit_closed` | gauge | `provider` | `1` when the provider circuit breaker is closed (healthy); active runs only |
| `claw_forge_provider_cost_usd` / `_latency_ms` | gauge | `provider` | Per-provider spend / average latency; active runs only |

The scrape is best-effort: a pool-status hiccup degrades the provider section
rather than failing the whole endpoint.

#### Related commands
- **Uses:** `claw-forge ui` (connects to the state service for the Kanban board)
- **Alternative:** `claw-forge dev` (starts state + UI + agents together)

---

### `claw-forge pause`

#### Purpose
Pause a running project in drain mode — in-flight agents complete their current task,
but no new tasks are dispatched.

#### When to use
- You want to review generated code before more features are built
- A provider is rate-limited and you want to wait before continuing
- You're about to make manual changes and don't want agents conflicting

#### Usage
```bash
# Pause by session ID
claw-forge pause abc-123-def

# Pause on a custom port
claw-forge pause abc-123-def --port 9000
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `project` | positional | **required** | Session ID or project name to pause |
| `--port` | int | `8420` | State service port |

#### What it does internally
1. Sends a pause request to the state service.
2. In-flight agents finish their current task (drain mode).
3. No new tasks are dispatched until `claw-forge resume` is called.
4. The Kanban UI reflects the paused state.

#### Related commands
- **Resume:** `claw-forge resume`
- **Status:** `claw-forge status` (check progress while paused)

---

### `claw-forge resume`

#### Purpose
Resume a paused project — the dispatcher starts accepting new tasks again.

#### When to use
- After `claw-forge pause` when you're ready to continue
- After reviewing Wave 1 output and approving the approach

#### Usage
```bash
# Resume by session ID
claw-forge resume abc-123-def

# Resume on a custom port
claw-forge resume abc-123-def --port 9000
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `project` | positional | **required** | Session ID or project name to resume |
| `--port` | int | `8420` | State service port |

#### What it does internally
1. Sends a resume request to the state service.
2. The dispatcher immediately begins picking up pending tasks.
3. Tasks queued during the pause are dispatched in dependency order.

#### Related commands
- **Pause:** `claw-forge pause`
- **Monitor:** `claw-forge status`, `claw-forge ui`

---

### `claw-forge reset`

#### Purpose
Batch-reset failed and/or blocked tasks back to `pending` so the dispatcher
picks them up on the next run. Mirrors the Kanban UI's "Reset All" buttons
on the Failed and Blocked column headers.

#### When to use
- After a run with transient failures (rate-limit, network blip) when you
  want a fresh attempt
- When a fixed dependency unblocked downstream tasks that are still marked
  `blocked` in the DB
- When `merge_retry_count` or `bugfix_retry_count` hit the cap and you want
  to grant a fresh retry budget after fixing the underlying issue

#### Usage
```bash
# Reset all failed + blocked tasks in the latest session for cwd
claw-forge reset

# Reset only failed tasks
claw-forge reset --status failed

# Reset only rate-limit failures, leave real failures alone
claw-forge reset --error-pattern '%rate_limit%'

# Explicit session id + custom port
claw-forge reset abc-123-def --port 9000
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `session_id` | positional | _auto-resolved_ | Session id to reset. Omit to pick the latest session for `--project`. |
| `--status` | str (repeatable) | `failed`, `blocked` | Status(es) to reset. Pass multiple `--status` flags to widen. |
| `--error-pattern` | str | none | SQL `LIKE` filter on `error_message` (e.g. `'%rate_limit%'`). Only matching tasks reset. |
| `--project` / `-p` | path | `.` | Project directory (scopes the auto-resolved session). |
| `--port` | int | `8420` | State service port. |

#### What it does internally
1. Resolves the session id — uses the positional arg when given, otherwise
   the most recent session for `--project` from `.claw-forge/state.db`.
2. `POST {state-url}/sessions/{id}/tasks/requeue` with body
   `{"statuses": [...], "error_pattern": "..."}`.
3. State service flips each matching task to `pending`, clears
   `error_message`, and zeroes `merge_retry_count` + `bugfix_retry_count`
   so the next dispatch gets a fresh retry budget (the v0.8.45 behaviour).
4. Broadcasts a `feature_update` WebSocket event per affected task so any
   open Kanban UI reflows live.
5. CLI prints the count and a preview of affected task ids.

#### Related commands
- **Monitor:** `claw-forge status`, `claw-forge ui`
- **Pause / resume the whole project:** `claw-forge pause`, `claw-forge resume`
- **Re-dispatch:** `claw-forge run` (after reset)

---

### `claw-forge input`

#### Purpose
List pending human-input questions and answer them interactively. Agents that get stuck
post a question to the state service; this command shows those questions and lets you
respond, unblocking the agent.

#### When to use
- A feature moved to "Blocked" in the Kanban UI
- An agent needs an API key name, design decision, or clarification
- You see `needs_human` status on a task

#### Usage
```bash
# Answer questions for a session
claw-forge input abc-123-def

# On a custom port
claw-forge input abc-123-def --port 9000
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `project` | positional | **required** | Session ID or project name |
| `--port` | int | `8420` | State service port |

#### What it does internally
1. Fetches all tasks with `needs_human` status from the state service.
2. Displays each question with the task name and context.
3. Prompts you for an answer interactively.
4. POSTs your answer to `/sessions/{id}/tasks/{id}/human-input`.
5. The task moves back to `pending` and the dispatcher retries it with your answer injected.

#### Output example
```
🙋 1 pending question for 'taskflow-api':

Task: Email reminders
Q: What is the SendGrid API key env var name?
Your answer: SENDGRID_API_KEY

✅ Answer submitted — task moved to pending
```

#### Related commands
- **YOLO mode:** `claw-forge run --yolo` skips human-input gates entirely
- **Monitor:** `claw-forge status` (shows blocked features)

---

### `claw-forge merge`

#### Purpose
Squash-merge a feature branch to the target branch. Used with `merge_strategy: manual`
in `claw-forge.yaml` to control when completed features land on main.

#### When to use
- You've set `merge_strategy: manual` and want to land a completed feature
- You want to review each feature branch before merging
- You need to merge into a branch other than `main` (e.g. `develop`)

#### Usage
```bash
# List feature branches ready to merge
claw-forge merge

# Squash-merge a specific branch to main
claw-forge merge feat/user-auth

# Merge into a custom target branch
claw-forge merge feat/user-auth --target develop

# Specify project directory
claw-forge merge feat/user-auth --project ~/projects/taskflow-api
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `branch` | positional | `None` | Branch to squash-merge. If omitted, lists available feature branches. |
| `--project`, `-p` | path | `.` | Project directory |
| `--target`, `-t` | string | `main` | Target branch to merge into |

#### What it does internally
1. If no branch is specified, lists branches matching the feature prefix (e.g. `feat/`).
2. Checks out the target branch.
3. Runs `git merge --squash <branch>` to squash all commits into one.
4. Creates a semantic commit message with completed steps, task ID, and session trailers.
5. Cleans up the feature branch and its git worktree (if one exists).

#### Pro tips
- With `merge_strategy: auto` (the default), features are squash-merged automatically on
  passing — you don't need this command.
- Use `merge_strategy: manual` when you want human review of each feature before landing.
- Run `claw-forge merge` (no args) to see which branches are ready.

#### Related commands
- **Before:** `claw-forge run` (features must be passing)
- **After:** `/check-code`, `git push`

---

### `claw-forge version`

#### Purpose
Print the installed claw-forge version.

#### Usage
```bash
claw-forge version
```

#### Output example
```
claw-forge 0.2.0b1
```

---

### `claw-forge export`

#### Purpose
Export session and task data from `state.db` to CSV (flat or per-table), SQL (sqlite-importable
dump), or JSON. Pure SQLite reads — no state service dependency, safe to run while a session is
active.

#### When to use
- Cost / progress reports for stakeholders
- Spreadsheet analysis of agent activity (per-task, per-category, per-provider)
- Backups of completed sessions before pruning the state DB
- Migrating session history to another machine via SQL round-trip

#### Usage
```bash
# Latest session, flat CSV (default)
claw-forge export

# All sessions as SQL dump (importable via `sqlite3 newdb.db < out.sql`)
claw-forge export --format sql --scope all --out backup.sql

# Specific session as JSON
claw-forge export --format json --session 8d304d81-... --out session.json

# CSV split (one file per table: sessions.csv, tasks.csv, events.csv)
claw-forge export --csv-mode split --out ./out/
```

#### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--format` | choice | `csv` | `csv` / `sql` / `json` |
| `--scope` | choice | `session` | `session` (latest) or `all` (every session in DB) |
| `--csv-mode` | choice | `flat` | `flat` (one denormalized row per task) or `split` (one CSV per table) |
| `--session` | str | latest | Specific session UUID; overrides `--scope=session`'s "latest" pick |
| `--out` | path | auto | Output path (auto-generated if omitted, e.g. `taskflow-2026-04-30.csv`) |
| `--project` | path | CWD | Project root containing `.claw-forge/state.db` |

#### What it does internally
1. Opens `.claw-forge/state.db` read-only via `sqlite3`.
2. Resolves the session(s) to export from `--scope` / `--session`.
3. For each format:
   - **csv flat**: denormalized join of `sessions × tasks` columns → one row per task.
   - **csv split**: three files — `sessions.csv`, `tasks.csv`, `events.csv` — mirroring the raw schema.
   - **sql**: standard SQLite dump (`CREATE TABLE IF NOT EXISTS` + `INSERT`); round-trippable via `sqlite3 newdb.db < out.sql`.
   - **json**: nested shape — `{exported_at, claw_forge_version, scope, sessions: [{..., tasks: [...]}]}`.
4. Writes to `--out` (or auto-generated filename) and prints the path.

#### Related commands
- **Inspect interactively:** `claw-forge status` for a Rich-table summary
- **Live state:** the Kanban UI (`claw-forge ui`) for real-time activity

---

### `claw-forge export training`

#### Purpose
Emit per-task agent trajectories as JSONL for fine-tuning a smaller code-specific LLM.
Reads `.claw-forge/state.db` directly via sqlite3 — no state-service dependency, safe
to run while a session is active.

**On by default since v0.7.1** — `claw-forge init` scaffolds `claw-forge.yaml` with both
`training_traces.enabled: true` and `training_traces.acknowledged_terms: true`. Set both
to `false` in your config to disable. See [training/unsloth-recipe.md](training/unsloth-recipe.md)
for the full export → train → eval flow. Anthropic's Usage Policies prohibit using Claude
outputs to develop competing models; this feature is intended for personal/internal
distillation on your own code, and compliance with terms is the user's responsibility.

#### Usage
```bash
# Default settings (openai-tools format, both success+recovered, redact secrets+usernames)
claw-forge export training --out corpus.jsonl

# Successful tasks only — cleanest signal, smallest corpus
claw-forge export training --filter success --out clean.jsonl

# Train/val/test split into a directory (deterministic by task_id hash)
claw-forge export training --split 80/10/10 --out ./split

# Raw SDK message stream (no projection) — for custom templating downstream
claw-forge export training --format raw-jsonl

# Include failed tasks for DPO / rejection-sampling negatives
claw-forge export training --include-failed --out all.jsonl
```

#### Options

| Flag | Default | Description |
|------|---------|-------------|
| `--scope` | `all` | `all` = every session in this DB; `session` = one session |
| `--session` | latest | Override session UUID |
| `--filter` | `both` | `success` / `recovered` / `both` |
| `--include-failed` | off | Adds `outcome='failed'` records (DPO/rejection-sampling negatives) |
| `--format` | `openai-tools` | `openai-tools` / `sharegpt` / `chatml` / `raw-jsonl` |
| `--include-diff` / `--no-include-diff` | on | Attach the squash-merge diff as `final_diff` (ground truth) |
| `--include-thinking` / `--no-include-thinking` | on | Preserve `ThinkingBlock` content (non-standard ext) |
| `--min-turns` | `4` | Skip trajectories shorter than this |
| `--max-turns` | `200` | Skip trajectories longer than this |
| `--redact` | `both` | `secrets` / `usernames` / `both` / `none` — applied at export time |
| `--dedupe-by` | `both` | `prompt` / `diff` / `both` / `none` |
| `--split` | none | e.g. `80/10/10` — emits `train.jsonl` + `val.jsonl` + `test.jsonl` |
| `--out`, `-o` | stdout | Output file (or directory for `--split`) |
| `--project`, `-p` | `.` | Project directory |

#### Filter semantics

| Filter | SQL predicate | Trains the SLM to … |
|---|---|---|
| `success` | `status='completed' AND merged_to_target_branch=1 AND bugfix_retry_count=0` | Imitate clean expert trajectories |
| `recovered` | `status='completed' AND merged_to_target_branch=1 AND bugfix_retry_count>0` | Recover from failure; resume mid-task |
| `both` | union of the above | Full distribution of expert behaviour |
| `--include-failed` | adds `status='failed'` | DPO/rejection-sampling negatives |

#### Format choices

| Format | When to pick |
|---|---|
| `openai-tools` (default) | Lossless; `tool_calls` + `role:tool`. Reads natively into HF `apply_chat_template(tools=...)`. The `thinking` field is a non-standard extension most loaders silently drop — use `raw-jsonl` if you need it. |
| `sharegpt` | trl/Axolotl ShareGPT loader. Tool calls flatten to text (lossy). |
| `chatml` | Generic `<|im_start|>` template for non-tool-using models. |
| `raw-jsonl` | Direct dump of SDK messages; do your own templating downstream. |

---

### `claw-forge traces`

#### Purpose
Inspect and prune the agent_message events captured by `training_traces`. Reads
`.claw-forge/state.db` directly via sqlite3 — no state-service dependency.

#### Subcommands

| Command | Description |
|---|---|
| `traces status` | Count agent_message events and report state.db size |
| `traces prune --before <DATE>` | Delete events older than an ISO date |
| `traces prune --keep-last N` | Keep only the N newest events; delete the rest |
| `traces prune --session UUID` | Delete events for one session |
| `traces prune --all` | Delete every agent_message event |
| `traces prune --keep-completed` | Spare events from completed/merged tasks |
| `traces prune --dry-run` | Report what would be deleted without modifying the DB |

`traces prune` runs `VACUUM` automatically when reclaimable space exceeds 100 MB.

#### Auto-prune at state-service startup

When `training_traces.retention.keep_days > 0` in `claw-forge.yaml`, the state service
deletes agent_message events older than that on startup. Default `keep_days: 0` =
forever (no auto-prune).

---

### `claw-forge boundaries`

#### Purpose
Identify and refactor extension hotspots in target codebases — files where many concurrent
features are forced to edit the same lines (CLI dispatchers, parsers, route tables).
Converts those surfaces into plugin-extensible patterns so future tasks become "drop a new
file" instead of "edit the shared dispatcher."

This is a one-shot maintenance command, not part of every `claw-forge run`. Use when your
audit / log review reveals a recurring conflict choke point.

#### Subcommands
- **`audit`** — read-only; emit a ranked hotspot report
- **`apply`** — refactor hotspots one at a time, test-gated, squash-merge on green
- **`status`** — show the last audit's hotspot list

---

#### `claw-forge boundaries audit`

##### Usage
```bash
# Default: scan CWD, write boundaries_report.md
claw-forge boundaries audit

# Custom project + lower threshold
claw-forge boundaries audit --project /path/to/repo --min-score 3.0

# Custom output path
claw-forge boundaries audit --out reports/hotspots.md
```

##### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--project` | path | CWD | Project root to audit |
| `--min-score` | float | `5.0` | Minimum hotspot score to include in the report |
| `--out` | path | `<project>/boundaries_report.md` | Override the output path |

##### What it does internally
1. Walk source files via `git ls-files` (respects `.gitignore` + `boundaries.ignore_paths`).
2. Compute four signals per file:
   - **dispatch_score** — string-keyed `if/elif/match` branches (registry candidates)
   - **import_centrality** — distinct files importing this one (blast radius)
   - **recent_churn** — distinct branches that touched this file in the last 90 days
   - **function_centrality** — call-site fanout for each public top-level function
3. Composite weighted score (defaults: dispatch 0.4, churn 0.3, import 0.2, function 0.1).
4. Filter at or above `--min-score`, sort descending.
5. (Optional) classifier subagent labels each hotspot with one of four refactor patterns:
   `registry`, `split`, `extract_collaborators`, `route_table`.
6. Emit a markdown report with one section per hotspot.

##### Output example
```
Wrote /path/to/project/boundaries_report.md with 3 hotspot(s) (min score 5.0).
```

The generated `boundaries_report.md`:
```markdown
# Boundaries Audit — myapp

3 hotspot(s) identified.

## 1. cli/main.py  (score 8.7)
- signals: dispatch=10, import=6, churn=14, function=3
**Proposed pattern:** registry

## 2. parser.py  (score 6.2)
...
```

---

#### `claw-forge boundaries apply`

##### Usage
```bash
# Interactive — prompts before each hotspot
claw-forge boundaries apply

# Run only one named hotspot (recommended for first runs)
claw-forge boundaries apply --hotspot cli/main.py

# Fully autonomous — applies all hotspots in score order
claw-forge boundaries apply --auto

# Custom test command (default: `uv run pytest tests/ -q`)
claw-forge boundaries apply --test-command "npm test"
```

##### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--project` | path | CWD | Project root |
| `--test-command` | str | `uv run pytest tests/ -q` | Test command run inside each refactor's worktree |
| `--hotspot` | str | (all) | Apply only this one named hotspot path |
| `--auto` | flag | `false` | No prompts; apply all hotspots in score order |

##### What it does internally
For each hotspot in the report:

1. **`create_worktree`** → isolated branch + worktree under `.claw-forge/worktrees/`.
2. **Subagent dispatch** → claude-agent-sdk `query()` with a pattern-specific prompt (registry / split / extract / route_table). Subagent edits files inside the worktree only.
3. **Stage and commit** with `--no-verify` on the boundaries branch.
4. **Test gate** — runs `--test-command` inside the worktree so it sees the refactored code.
5. **Green** → `squash_merge` to `main` (reuses `claw-forge run`'s squash-merge plumbing); worktree + branch removed.
6. **Red** → cleanup, `main` untouched, refactor reverted.

##### Safety properties
- Reuses claw-forge's existing git plumbing (`create_worktree`, `squash_merge`, `remove_worktree`), so the v0.5.24 worktree-checkout fix and the v0.5.27 empty-squash detection apply automatically.
- Refactors run **serially** (refactor B may depend on refactor A's output); never in parallel.
- Subagents are sandboxed via the existing `make_can_use_tool` permission callback — file writes restricted to `project_dir`.
- Each hotspot's outcome is reported: `merged` / `reverted` / `skipped` (with reason).

##### First-run advice
For your first apply against a real codebase, use `--hotspot=<one_known_safe_file>` to validate the test command and the agent's behavior end-to-end before unleashing `--auto`.

---

#### `claw-forge boundaries status`

##### Usage
```bash
claw-forge boundaries status
claw-forge boundaries status --project /path/to/repo
```

Reads `boundaries_report.md` and prints the hotspot list with paths, scores, and proposed patterns. Exits 1 if no report is present (with instructions to run `audit`).

---

#### Brownfield workflow

When adding features to an existing codebase, the recommended sequence
is:

1. **`claw-forge analyze`** — generate `brownfield_manifest.json` with
   stack/conventions/test-baseline.
2. **`claw-forge boundaries audit`** — emit `boundaries_report.md`
   with extension hotspots (files where adding a feature would collide
   with existing dispatch logic).
3. **`claw-forge boundaries apply --auto`** — refactor each hotspot
   into a plugin-extensible pattern (registry / split / route-table /
   extract-collaborators).  Squash-merges to main on green tests,
   reverts on red.
4. **`/create-spec`** in Claude Code — generates `additions_spec.xml`.
   The slash command reads `boundaries_report.md` and warns about any
   un-refactored hotspots before proceeding.  Each feature is asked
   about its `shape` (plugin vs core) so the spec carries the right
   attributes for parallel-safe scheduling.
5. **`claw-forge add --spec additions_spec.xml`** — runs the
   plan-to-DB writer and starts the dispatcher.

Skipping step 3 means new features may collide with the un-refactored
hotspots; the dispatcher's pre-dispatch sync will surface those as
`resume_conflict` failures, but the agent will have already wasted time
on stale state by then.  Refactoring up front is cheaper.

---

### Related commands
- **Diagnose merge conflicts:** if features keep conflicting, run `claw-forge boundaries audit` to see whether they're all editing the same hotspot file.
- **Spec-time prevention:** `/create-spec` Phase 3.5 lets you serialize known-overlapping features at spec creation, complementing the structural fix that `boundaries apply` provides.

---

### `claw-forge worktrees`

#### Purpose
Inspect and clean up the per-task feature-branch worktrees claw-forge creates under
`.claw-forge/worktrees/`. Worktrees from terminally-failed tasks (no further retry will
land) and from completed tasks whose squash-merge itself failed are **not** auto-salvaged
at startup — `claw-forge run`'s salvage hook only fires when a prior run was *interrupted*
(`orphans_reset > 0`). This subcommand fills that gap so you can act on the residue
without resorting to manual `git worktree remove` loops.

#### Subcommands
- **`list`** — show every worktree directory with branch + commit count
- **`prune`** — squash-merge branches with commits to *target*, then remove the dirs
- **`prune --discard`** — force-remove every directory + branch without salvage

---

#### `claw-forge worktrees list`

##### Usage
```bash
# From the project directory
claw-forge worktrees list

# Different project / target / prefix
claw-forge worktrees list --project /path/to/repo --target develop --prefix feature
```

##### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--project`, `-p` | path | CWD | Project root containing `.claw-forge/worktrees/` |
| `--target` | str | auto-detected via `git symbolic-ref refs/remotes/origin/HEAD` | Branch to count commits ahead of |
| `--prefix` | str | `feat` | Feature-branch prefix used by `create_worktree` |

##### Output
For each directory under `.claw-forge/worktrees/`:
- Bold branch name + commit count when the branch has commits ahead of target
- Up to 5 commit subjects (the rest summarised as `… N more`)
- Dim `empty` row when the branch is missing or has no commits

Trailing summary line: `<N> worktree(s) total — <K> salvageable, <N-K> empty.`

---

#### `claw-forge worktrees prune`

##### Usage
```bash
# Salvage anything with commits, then drop empty dirs
claw-forge worktrees prune

# Force-remove everything; discard committed agent work
claw-forge worktrees prune --discard

# Custom project / target
claw-forge worktrees prune --project /path/to/repo --target develop

# Operate on live agents' worktrees too (only after stopping the dispatcher)
claw-forge worktrees prune --force
```

##### Options

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--project`, `-p` | path | CWD | Project root |
| `--target` | str | auto-detected | Squash-merge target branch |
| `--prefix` | str | `feat` | Feature-branch prefix |
| `--discard` | flag | off | Skip salvage; force-remove every dir + branch |
| `--force` | flag | off | Touch worktrees backing currently-running tasks too (default skips them) |

##### What it does internally

**Running-task protection (default):** before either salvage or discard, the command opens `.claw-forge/state.db` read-only via `sqlite3` and selects `category, description WHERE status = 'running'`, derives the corresponding worktree slugs via `make_branch_name`, and excludes those slugs from every subsequent step. Mirrors the read-only `state.db` access pattern used by `claw-forge export`. If the DB is missing or the read fails, no protection is applied (fail-open) — pair with `--force` only when you're certain the dispatcher is stopped.

**Default (no flag):**
1. Call `merge_orphaned_worktrees(project, prefix=prefix, target=target, skip_slugs=protected)` — for each non-protected branch with commits ahead of target, run the same `squash_merge` flow `claw-forge run` uses (auto-rebase on conflict, no-op detection on empty squash, orphan-untracked-file sidelining).
2. Call `prune_worktrees(project, skip_slugs=protected)` — `git worktree remove --force` every remaining non-protected directory and run `git worktree prune` to clean git's bookkeeping.

**`--discard`:**
1. For each non-protected directory: `git worktree remove --force <dir>` → `shutil.rmtree` fallback if needed → `git branch -D feat/<slug>`.
2. `git worktree prune` to clean residual entries in `.git/worktrees/`.

**`--force`:** disables the running-task lookup entirely; both default and `--discard` modes then operate on every worktree under `.claw-forge/worktrees/`.

##### When to use
- After upgrading past a merge-handler bug that left tasks stuck in `failed` with committed work on `feat/...` branches.
- Before re-running a session you don't intend to resume — strips stale worktrees so the next dispatch starts from a clean state.
- For triage when `claw-forge status` shows many `failed` tasks and you want to inspect (or drop) the work the agents had committed.
- **Safe to run while a `claw-forge run` is in progress** — the running-task filter leaves live agents' worktrees alone; stale ones are cleaned up.

##### Safety notes
- Default mode (no `--discard`) is non-destructive of *work*: if a branch has commits, they land on `target` before the directory is removed. The branches themselves disappear only after a successful salvage merge; merge-failed branches are preserved for manual resolution.
- `--discard` deletes *both* the worktree and the branch. Committed work on a discarded branch is gone unless you've already merged or backed it up. Use this only when you're sure the agent's output is throwaway.
- `--force` bypasses the running-task safety net. Yanking a live agent's working tree mid-run loses uncommitted work and can corrupt the shared git index — only pass `--force` after the dispatcher process has fully exited (Ctrl+C → wait for the shell prompt).

---

#### Smart-mode startup cleanup (`git.cleanup_orphan_worktrees: smart`)

The CLI command above is the *manual* cleanup surface. The same machinery is available as an *automatic* startup hook, on by default in `claw-forge.yaml`:

```yaml
git:
  merge_strategy: auto                   # required for smart cleanup to act
  cleanup_orphan_worktrees: smart        # default: smart (set to "manual" to opt out)
  llm_conflict_proposals: true           # default: true (set to false to disable advisor)
  llm_conflict_advisor_model: ""         # optional model override; blank = SDK default
```

In `smart` (default), `claw-forge run` startup walks every directory under `.claw-forge/worktrees/`, looks the corresponding task up by slug in the DB, and dispatches per the table below — preventing terminally-failed and orphaned worktrees from accumulating across runs.

In `manual`, startup only fires the salvage path when `orphans_reset > 0` — i.e. when the previous run was *interrupted* and tasks got reset. Worktrees from terminally-failed tasks and from `completed` tasks whose squash-merge itself failed accumulate until you run `claw-forge worktrees prune` by hand.

| `task.status` | branch has commits | action | rationale |
|---|---|---|---|
| `pending` | yes | **preserve** | resume substrate for `git.prefer_resumable` |
| `pending` | no | **remove** | empty branch, nothing to keep |
| `running` | any | **preserve** | the legacy `orphans_reset` path will reset & own this |
| `failed` | yes | **salvage** | terminal — no auto-retry across runs in claw-forge |
| `failed` | no | **remove** | empty branch |
| `completed` | yes | **salvage** | the v0.5.35 bug class: squash failed previously |
| `completed` | no | **remove** | bookkeeping cleanup |
| no matching task | yes | **salvage** | orphan from prior session |
| no matching task | no | **remove** | no value, no owner |

Salvage uses the same `squash_merge` plumbing as a normal task completion (catch-up rebase on stale-target divergence, no-op detection, orphan-untracked-file sidelining). On real content conflict, the worktree + branch are preserved and reported to the user — smart mode never silently writes a half-resolved merge.

When `git.llm_conflict_proposals: true`, the advisor (see below) drafts a `CONFLICT_PROPOSAL.md` inside the preserved worktree on conflict.

##### When NOT to use `smart`

- You rely on per-branch state for retry-resume beyond what survives a squash-merge to `main` (custom checkpoint files outside the worktree, agent state caches, etc.). Salvage moves the work to `main` and removes the branch; the next attempt creates a fresh worktree from `main`.
- Your `merge_strategy` is `manual`. Smart mode is a no-op in that case (it never auto-merges) — set `cleanup_orphan_worktrees: manual` to keep the existing scan-and-report behaviour.

#### Resume preference (`git.prefer_resumable` / `git.resume_stale_threshold`)

When the dispatcher picks the next task to start, two `pending` tasks at the same priority are not equivalent: one might have a feature branch with committed work from a prior interrupted run, and the other might be a fresh task with no branch yet. Resuming the first lets the agent pick up where the previous attempt left off; starting the second discards no work but redoes nothing either. The scheduler defaults to preferring the resumable one — these two knobs control that behaviour.

```yaml
git:
  prefer_resumable: true        # default true — resume work-in-progress before starting fresh
  resume_stale_threshold: 50    # default 50 — skip the preference when target has moved > N commits ahead
```

- **`prefer_resumable: true`** *(default)* — at equal priority, a task whose feature branch already has commits is dispatched before a task without commits. Higher priority still dominates: a P0 fresh task always beats a P1 resumable task. Set to `false` to force every task to start from a clean worktree off `target_branch`, regardless of any committed work from prior runs.
- **`resume_stale_threshold: 50`** *(default `50`)* — a guardrail on the preference above. When `target_branch` has moved more than N commits ahead of a candidate feature branch, the scheduler treats that branch as "too stale to resume cheaply" and falls back to no-preference behaviour. The reasoning: catching up that many commits is likely to hit conflicts, and a fresh start may be faster than fighting through a multi-file resolve. Lower the threshold for tighter codebases where 20 commits is already a lot of churn; raise it for slow-moving projects where resuming is almost always worthwhile.

These knobs influence *which* `pending` task gets picked. Once a task is dispatched, the worktree is unconditionally synced to `target_branch` via `sync_worktree_with_target` *before* the agent runs — even with `prefer_resumable: false`. That sync is independent of the preference and acts as a final guardrail: a stale resumed worktree, or one whose `target_branch` has advanced during the dispatch tick, is brought up to date before the agent sees it. If that pre-dispatch merge hits content conflicts, the autonomous merge-recovery loop (next section) kicks in.

#### Autonomous merge-conflict recovery (`git.merge_retry_attempts: 3`)

```yaml
git:
  merge_retry_attempts: 3       # default 3; 0 disables (legacy preserve-and-warn)
```

Two failure modes that previously required human intervention are now self-healing within a bounded retry budget:

1. **Post-completion squash failure** — when `apply_on_completion`'s squash to `target_branch` fails (typically alembic migration filename collision, lockfile churn, or a code conflict because another task landed first), the task is re-pended with `status='pending'` + `merge_retry_count++` + `error_message='merge_retry_<N>: <reason>'`. The dispatcher's outer wave-loop picks it up under `prefer_resumable` for the next wave.
2. **Pre-dispatch sync conflict** — when `sync_worktree_with_target` would have failed with `resume_conflict:`, the dispatcher now re-syncs with `leave_conflicts=True` (markers stay in the worktree), bumps `merge_retry_count`, and dispatches the agent into the conflict-bearing state.

Both paths inject a **Merge Conflict Recovery** section into the agent's resume preamble that explicitly lists conflicting files and resolution steps (alembic-renumber, lockfile regen, code-conflict markers, run tests). The agent uses its existing Read/Edit/Bash tools — no new resolver subsystem.

At the cap, both paths fall through to today's preserve-and-warn behaviour (`merge_failed: ... (after N attempts)` for squash, `resume_conflict:` for sync) so the irreducible escape hatch for genuinely-intractable conflicts is unchanged. Set `merge_retry_attempts: 0` to disable the autonomous loop entirely (every failure is terminal).

The validator's Gap 8 (`--strict-shape` no longer required; ERROR by default in v0.8.23+) catches the upstream cause of most squash failures — unannotated migration features that race for the same alembic revision number. Use `--allow-soft-migration-shape` during migration on-ramp on existing specs.

See `docs/superpowers/specs/2026-05-10-autonomous-merge-recovery.md` for the full design rationale.

#### LLM conflict advisor (`git.llm_conflict_proposals: true`)

When smart-mode salvage hits a content conflict, the advisor:

1. Finds the files modified on both sides since the merge-base.
2. Reads the ancestor, target, and branch versions of each.
3. Sends them to `claude_agent_sdk` (one short conversation, no tools, no MCP) with the task description and a structured-output prompt.
4. Writes the agent's draft to `<worktree>/CONFLICT_PROPOSAL.md`.

The proposal contains a per-file resolution + reasoning + a `bash` block the user can adapt to apply it. Nothing the advisor produces lands on `main` automatically — the user reviews, edits, and applies. The asymmetric cost of a silently-wrong auto-merge (regression on `main` you find out about hours later) is why this is advisory rather than authoritative.

On by default. Costs one agent call per conflicted worktree; conflicts are rare so the spend is bounded — set `llm_conflict_proposals: false` to disable if you'd rather resolve by hand or don't want the API spend.

---

### `claw-forge stash`

#### Purpose

Operator surface for the `claw-forge-*` git stash entries the harness creates automatically — separate from your personal `git stash` drawer. Three flavours land here:

| Marker prefix | Origin | When |
|---|---|---|
| `claw-forge-auto-<ts>` | Smart-cleanup at `claw-forge run` startup | Dirty-tracked files in main when the dispatcher boots — see `git.handle_uncommitted_at_startup: smart`. |
| `claw-forge-manual-<ts>` | Operator-run cleanup | Reserved for the operator's own scripted invocations of `git stash push -m "claw-forge-manual-…"` so the CLI surfaces them. |
| `claw-forge-leak-<task_id>-<ts>` | Mid-run leak detector (v0.8.16) | New dirty/untracked files appeared in main *during* an agent's execution — likely an exempt-command escape (see *Sandbox layers* below). |
| `claw-forge-boot-<ts>` | Snapshot-rollback boot baseline (v0.8.17) | Pre-existing operator dirt that smart-cleanup couldn't archive at dispatcher startup, captured so the run can enforce HEAD-clean-main as a run-lifetime invariant.  Recover after the run with `git stash apply <ref>`. |

#### `claw-forge stash list`

```bash
claw-forge stash list
claw-forge stash list --project /path/to/repo
```

| Flag | Type | Default | Purpose |
|---|---|---|---|
| `--project`, `-p` | path | CWD | Project root containing `.git/`. |

Prints all `claw-forge-*` stashes with kind tags (`auto` / `manual` / `leak`), grouped under a summary count. Operator-personal stashes (those without the marker prefix) are intentionally excluded — for those, use `git stash list` directly.

For a `leak`-kind entry, the marker embeds the suspect task ID's first 8 chars and a UTC timestamp so the operator can correlate with `claw-forge status` or `state.db` to find which task was running when the leak appeared.

#### `claw-forge stash drop <ref>`

```bash
claw-forge stash drop stash@{2}
claw-forge stash drop 2          # bare integer, sugar for stash@{2}
claw-forge stash drop stash@{0} --yes   # skip confirmation
```

| Flag / Arg | Type | Default | Purpose |
|---|---|---|---|
| `<ref>` (positional) | str | — | Stash ref to drop. Either `stash@{N}` or just `N`. |
| `--project`, `-p` | path | CWD | Project root containing `.git/`. |
| `--yes`, `-y` | bool | false | Skip the confirmation prompt. |

Refuses to drop operator-personal stashes — the CLI is scoped to harness-managed entries to prevent accidental loss of your own work. For non-harness stashes, use `git stash drop` directly.

#### Inspect a stash before dropping

```bash
git stash show -p stash@{2}     # diff
git stash apply stash@{2}       # restore into the *current* worktree (read-only on the stash entry)
```

`apply` (not `pop`) is the safer recovery flow when you're not sure where the work belongs — it leaves the stash entry intact while materialising the changes.

---

### Sandbox layers (v0.8.16)

The dispatcher hardens against the v0.8.14/15 leak class — agent writes to the *parent project's* working tree (target branch, typically `main`) instead of the agent's worktree under `.claw-forge/worktrees/<slug>/`. Three independent layers:

| Layer | Catches | Where |
|---|---|---|
| **1. File-tool path sandbox** | Accidental Write/Edit/Glob/Grep outside the worktree. | `claw_forge.agent.permissions.make_can_use_tool` (always on when `project_dir` is passed). |
| **2. Exempt-command jail check** *(v0.8.16)* | `git -C /<project_root> add foo`, `git --git-dir=/<project_root>/.git checkout`, `python /<project_root>/script.py` — paths under the parent project but outside the worktree, via dev-toolchain commands the file sandbox would otherwise exempt. | `make_can_use_tool(forbidden_jail_root=…)` — wired to `project_path` when `git_enabled`. |
| **3. Agent-prompt boundary directive** *(v0.8.16, hardened in v0.8.18)* | The long tail no static check can intercept (`python -c "open('/abs', 'w')…"`, `exec()` of literal-string paths, etc.). | The dispatcher appends a `## Workspace boundary (CRITICAL)` paragraph to the agent's system prompt.  **v0.8.18 removes the explicit parent-project path** (information-hiding) — the agent only sees its cwd as "the project root" with no observable handle to anywhere else. |
| **4. OS-level filesystem jail** *(v0.8.18 macOS, v0.8.21 Linux)* | Every escape pattern above, at the kernel level — including patterns no static analyser can see (FFI, dynamically-built paths, `python -c "exec(s)"` of remote-fetched strings).  `open(2)` outside the worktree returns `EACCES` (macOS) / `EROFS` (Linux). | `claw_forge.agent.sandbox.make_sandbox_wrapper` — generates a per-task `sandbox-exec` profile (macOS) or `bwrap` invocation (Linux: `--dev-bind / /` then `--ro-bind <project>` then `--bind <worktree>`) and points `ClaudeAgentOptions.cli_path` at a wrapper that exec's `claude` under the jail.  Falls back to behavioural-only stack with a logged warning when sandbox isn't available (Windows, BSD, sandbox binary missing). |
| **5. Container isolation** *(v0.8.19 Level 4 — opt-in)* | Everything above, plus the parent project is absent from the container's filesystem namespace entirely.  Escape paths return `ENOENT` (no such path) rather than `EACCES` (denied) — the path literally doesn't exist for the agent to target.  Strongest isolation; required for untrusted prompts or multi-tenant deployments. | `claw_forge.agent.container.make_container_wrapper` — generates a per-task `<runtime> run` wrapper script.  Opt-in via `agent.isolation: container` in `claw-forge.yaml`; needs an operator-built image (template in `docs/container-isolation.md`).  Pays ~1–3s per-task startup latency in exchange for namespace-level isolation. |

**Per-plugin sandbox fence** (`agent.sandbox.fence_to_touches_files`, opt-in, default `false`): when enabled, Layer 4's writable set for a `shape="plugin"` task is narrowed from the whole worktree down to the directories its `touches_files` declare (plus the `.claw-forge` scratch dir). An agent writing outside its declared footprint then fails with `EACCES`/`EROFS` instead of silently editing a shared file. Requires plugins to register via auto-discovery (validate-spec Gap 11 flags shared-file edits); `shape="core"` and unannotated tasks are unaffected, as are footprints that can't be safely narrowed (a leading-glob like `**/*.py` falls back to the whole worktree). Default `false` until the false-positive rate is established.

When a leak slips through all three, the **snapshot-rollback** (v0.8.17, hardened from v0.8.16's mid-run leak detector) enforces a stronger invariant: **`project_path` is HEAD-clean for the entire run's lifetime.**

- **At dispatcher startup** (after smart-cleanup): any pre-existing dirt is captured to a `claw-forge-boot-<ts>` stash so the run starts from a clean main.
- **Per-task post-agent** (in the `finally` block, BEFORE `apply_on_completion`, holding the same lock that serialises `squash_merge`): if `project_path` is dirty, stash everything as `claw-forge-leak-<task_id>-<ts>` and verify clean.  Concurrent leaks land in whichever rollback fires first — marker is best-effort attribution.
- **Recovery**: `claw-forge stash list` shows boot + leak entries; inspect with `git stash show -p <ref>`; recover with `git stash apply <ref>`.

The check is best-effort: a git failure during snapshot/stash logs at `error` level and continues — leak prevention must not become a liveness gate.

---

## Claude Slash Commands

These commands live in `.claude/commands/` and are used **inside Claude Code** (the editor),
not in the terminal. Type `/command-name` in the Claude Code chat panel to invoke them.

They are automatically scaffolded by `claw-forge init` into your project directory.

---

### `/create-spec`

#### Purpose
Guides you through an interactive conversation to generate a precise, claw-forge-compatible XML
project spec — either for a new app (greenfield) or for adding features to an existing one
(brownfield). The output becomes the input to `claw-forge plan` (greenfield) or `claw-forge add` (brownfield).

#### When to use
- Starting a brand-new project and you want to think through features systematically
- Adding a significant feature set to an existing app (Stripe, auth, notifications, etc.)
- You have a rough idea but need help turning it into 100-300 granular agent tasks
- After running `claw-forge analyze` on an existing codebase

#### Usage
In Claude Code chat panel:
```
/create-spec
```
Or with a hint:
```
/create-spec Task Manager API with FastAPI and SQLite
```

#### What it does internally
1. Checks if `brownfield_manifest.json` exists → chooses Greenfield or Brownfield flow.
2. **Greenfield:** Asks about project identity, features by category, tech stack, DB schema,
   API structure, and UI layout. Derives 100-300 granular feature bullets.
3. **Brownfield:** Loads the manifest, asks what you're adding, constraints, integration points.
4. Generates and writes `app_spec.txt` (greenfield) or `additions_spec.xml` (brownfield).
5. Also writes `claw-forge.yaml` (greenfield only).
6. Shows a summary and next steps.

#### Real-world example
You want to build a Task Manager API. In Claude Code:

```
You: /create-spec

Claude: What are you building? Give me a name and 2-3 sentence description.

You: TaskFlow API — a REST API for managing personal tasks and projects.
     Users can create projects, add tasks with due dates, assign priorities,
     and get reminded via email when deadlines approach.

Claude: Who is it for?

You: Individual developers and small teams, up to ~10 people per workspace.

Claude: Quick or Detailed spec?

You: Detailed

Claude: Let's map out the features. What happens when a user first opens the app?

You: Registration with email/password, email verification, then login.

Claude: From that, I'm generating:
  Authentication (8 bullets)
  - User can register with email and password (returns 201 with user_id)
  - System sends verification email on registration
  - User can verify email via link (sets email_verified=true)
  - User can login and receive JWT access_token + refresh_token
  - System rejects login for unverified emails with 403
  - User can refresh access token using refresh_token
  - User can logout (invalidates refresh token)
  - System rate-limits login attempts (5/minute per IP)

  Does this capture it? Anything to add?
```

#### Output example
After the conversation, Claude writes:

```
✅ Project spec created!

📊 Summary:
  Features: 59 across 6 categories
  Phases: 4 implementation steps
  Tables: 5 database tables
  Endpoints: 24 API endpoints

Files written:
  app_spec.txt     (59 feature bullets, 4 phases, full DB schema)
  claw-forge.yaml  (provider config, concurrency=5)

Next steps:
  1. Review app_spec.txt — add/remove features as needed
  2. Run: claw-forge plan app_spec.txt
  3. Run: claw-forge run --concurrency 5

💡 Tip: Each feature bullet = one agent task. More specific = better output.
```

#### Pro tips
- Be specific in each answer. "User can manage tasks" → vague. "User can create a task with
  title, description, due_date, and priority (low/medium/high)" → perfect.
- Don't worry about getting the feature list perfect — you can add more later with
  `/expand-project`.
- For brownfield, run `claw-forge analyze` first to generate `brownfield_manifest.json` —
  `/create-spec` will auto-load it and pre-fill your tech stack details.

#### Related commands
- **Before:** `claw-forge analyze` (brownfield)
- **After:** `claw-forge plan` (greenfield) or `claw-forge add` (brownfield)

---

### `/import-spec`

#### Purpose
Interactive section-by-section review of a 3rd-party harness export before writing — same
pipeline as `claw-forge import` but with approval gates at each XML section.

#### When to use
- You want to review and optionally edit each converted section before it's written
- You want to verify the extractor found the right epics and stories
- You prefer interactive control over a one-shot command

#### Usage
In Claude Code chat panel:
```
/import-spec ./bmad-output
/import-spec ./linear-export.json --model claude-sonnet-4-6
```

#### What it does internally
Steps through 5 stages — detect, extract, convert section by section (with approve/edit/skip
at each), write, suggest next steps. Each XML section is shown for review before being
committed to the output file.

#### Related commands
- **Non-interactive version:** `claw-forge import`
- **After:** `claw-forge validate-spec`, `claw-forge plan`

---

### `/expand-project`

#### Purpose
Adds new features to a running or paused claw-forge project by POSTing them atomically to the
state service — no re-running `init`, no duplicating existing features.

#### When to use
- Mid-sprint, a stakeholder requests additional functionality
- You finished Wave 1 and want to add Wave 2 features on the fly
- You realized you missed an important use case during spec creation
- You want to interactively build up features without editing XML

#### Usage
In Claude Code:
```
/expand-project
```

Claude will ask what you want to add, then handle the state service API calls automatically.

#### What it does internally
1. Queries `http://localhost:8420/sessions` to list current features and their status.
2. Shows you what exists so you don't duplicate.
3. Asks what new features to add (title, description, dependencies, priority).
4. POSTs each new feature to `/sessions/<id>/tasks` atomically.
5. On failure, rolls back successfully-created features.
6. Appends new features to `.claw-forge/app_spec.txt` to keep the spec in sync.
7. Reminds you to resume if the project is paused.

#### Real-world example
TaskFlow is 40/59 features done. Your client wants CSV export:

```
You: /expand-project

Claude: Current project: TaskFlow API (40/59 passing, 3 in-flight)

  Existing features (summary):
    Phase 1: Authentication — 8/8 ✅
    Phase 2: Task CRUD — 20/22 ✅
    Phase 3: Projects — 12/16 🔄
    Phase 4: Polish — 0/13 ⏳

  What would you like to add?

You: CSV export for tasks. User should be able to download all their tasks
     as a CSV file with columns: title, description, due_date, priority,
     status, project_name.

Claude: Creating feature:
  Title: User can export tasks as CSV
  Description: GET /tasks/export returns a CSV file with title, description,
    due_date, priority, status, project_name columns. Filters by workspace.
  Dependencies: [task-list-endpoint, project-read-endpoint]
  Priority: 6

  ✅ Created task: exp-001
  ✅ Updated .claw-forge/app_spec.txt

  The dispatcher will pick this up on the next run.
```

#### Pro tips
- Use this instead of re-running `init` — it's faster and doesn't touch existing features.
- Set `priority: 8+` for urgent additions so they jump the queue.
- After expanding, open the Kanban board (`claw-forge ui`) to see the new card appear.

#### Related commands
- **Requires:** State service running (`claw-forge state`)
- **After:** `claw-forge run` (resumes automatically if already running)

---

### `/check-code`

#### Purpose
Runs ruff (lint + format), mypy (type checking), and pytest (tests) in sequence and produces a
structured quality report — identifying exactly what's failing and why, with fix suggestions.

#### When to use
- Before creating a PR to ensure code is clean
- After a batch of agents finish to verify their output
- When CI is red and you want a fast local diagnosis
- Before running `/checkpoint` to capture only a clean state

#### Usage
In Claude Code:
```
/check-code
```

Claude runs the checks and formats the results.

#### What it does internally
1. Runs `uv run ruff check . --output-format=concise` (lint).
2. Runs `uv run ruff format --check .` (formatting).
3. Runs `uv run mypy . --ignore-missing-imports --no-error-summary` (types).
4. Runs `uv run pytest tests/ -v --tb=short --no-header` (tests).
5. Formats results into a structured report with ✅/❌ per check.
6. For failures: explains root cause and provides the exact fix command.
7. Optionally applies ruff auto-fixes if you say yes.

#### Real-world example
You've just run `claw-forge run` and 59 features are passing. You want to verify before pushing:

```
You: /check-code

Claude: Running code quality checks…
```

#### Output example
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Code Quality Report — TaskFlow API
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ✅ Ruff lint     — 0 errors, 0 warnings
  ✅ Ruff format   — All files formatted
  ❌ MyPy          — 2 type errors
  ✅ Pytest        — 59 passed, 0 failed

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

MyPy Issues:
  routers/tasks.py:87: error: Argument "due_date" has incompatible type
    "str | None"; expected "date | None"
    Fix: change annotation to Optional[date] and parse with date.fromisoformat()

  services/notifications.py:34: error: Item "None" has no attribute "email"
    Fix: add null guard → if user is None: raise HTTPException(404)

Overall: NEEDS ATTENTION (1/4 checks failing)

Quick fix:
  uv run ruff check . --fix && uv run ruff format .
  (mypy errors require manual fixes — see above)
```

#### Pro tips
- Make `/check-code` part of your pre-PR ritual: code → `/check-code` → `/checkpoint` →
  `/review-pr` → push.
- If mypy is noisy on a large codebase, run it on just the changed files:
  ask Claude to check specific modules.
- Ruff auto-fixes are safe — always accept them.

#### Related commands
- **After:** `claw-forge run`, `claw-forge fix`
- **Next:** `/checkpoint`, `/review-pr`

---

### `/checkpoint`

#### Purpose
Creates a timestamped save point: commits all changes, exports the feature state DB to a JSON
snapshot, and writes a human-readable `CHECKPOINT.md` — so you can always rewind to a known
good state.

#### When to use
- Before a risky operation (provider change, schema migration, major refactor)
- After a wave of features reaches "Passing" status
- End of day — save your progress before shutting down
- Before `/review-pr` — ensures the reviewer sees a clean, committed state

#### Usage
In Claude Code:
```
/checkpoint
```

Claude handles everything automatically.

#### What it does internally
1. Runs `uv run pytest tests/ -q` and notes pass/fail counts.
2. Creates `.claw-forge/snapshots/` if it doesn't exist.
3. Queries `http://localhost:8420/sessions` and saves the full state to
   `snapshot-YYYYMMDDTHHMMSS.json`.
4. Writes `.claw-forge/CHECKPOINT.md` with status summary, in-progress features, and known issues.
5. Runs `git add -A` and commits with a structured message including test counts and feature
   progress.
6. Reports the commit hash and snapshot file path.

#### Real-world example
Wave 2 of TaskFlow just finished — 22 more features passing. You want to save before starting
Wave 3:

```
You: /checkpoint
```

#### Output example
```
Running pytest… 59 passed, 0 failed.

Exporting state snapshot…
  ✅ Snapshot: .claw-forge/snapshots/snapshot-20250514T143022.json

Writing CHECKPOINT.md…
  ✅ .claw-forge/CHECKPOINT.md

Committing…
  [main 4a7f2e1] checkpoint: 2025-05-14 14:30:22
  Status:
  - Tests: 59 passing
  - Features: 39/59

✅ Checkpoint saved!

  Commit:   4a7f2e1
  Snapshot: .claw-forge/snapshots/snapshot-20250514T143022.json
  Summary:  .claw-forge/CHECKPOINT.md

To restore to this state:
  git checkout 4a7f2e1
```

#### Pro tips
- Run `/checkpoint` before every `claw-forge run --yolo` — if something goes wrong, you can
  revert instantly.
- The JSON snapshot captures the full task graph — use it to understand what each agent built.
- Pair with `git tag v0.1.0-checkpoint-1` for named restore points on important milestones.

#### Related commands
- **Before:** `/check-code` (verify first)
- **After:** `/review-pr`

---

### `/review-pr`

#### Purpose
Reviews the current git diff (or a specific PR) for tests, type annotations, security issues,
performance problems, and style — producing a structured APPROVE / REQUEST CHANGES / COMMENT
verdict with actionable feedback.

#### When to use
- Before merging any agent-generated code into `main`
- After `claw-forge fix` to verify the bug fix is correct
- When reviewing a teammate's PR without leaving Claude Code
- As the final step before pushing a feature branch

#### Usage
In Claude Code:
```
/review-pr
```
Or to review a specific PR number (requires `gh` CLI):
```
/review-pr 42
```

#### What it does internally
1. Gets the diff: `git diff HEAD` (uncommitted) or `gh pr diff <N>` (specific PR).
2. For each changed file, checks: tests, type annotations, docstrings, security, performance,
   style.
3. Produces a structured report with BLOCKING / SUGGESTION / LOOKS GOOD sections.
4. Optionally posts a review event to the state service.
5. Returns a clear APPROVE / REQUEST CHANGES / COMMENT verdict.

#### Real-world example
You've fixed the password-reset bug and want to verify before pushing:

```
You: /review-pr
```

#### Output example
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  PR Review — fix/password-reset-uppercase-email
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  Files changed: 2
  Lines added: +23 | Lines removed: -1

  VERDICT: ✅ APPROVE

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  🔴 BLOCKING ISSUES: none

  🟡 SUGGESTIONS:
    1. auth/service.py:142 — consider adding a comment explaining why
       .lower() is applied (non-obvious security implication)

  ✅ LOOKS GOOD:
    - Tests: new regression test covers the exact bug path
    - Types: all annotations correct
    - Security: no hardcoded secrets, parameterized queries
    - No N+1 issues introduced

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

#### Pro tips
- The security check specifically looks for shell injection, hardcoded keys, and SQL injection.
  Trust it but also scan manually for domain-specific issues the agent might miss.
- "COMMENT" verdict means the code is mergeable but has observations. Use it for stylistic
  feedback that doesn't block shipping.
- For large PRs (>500 lines), ask Claude to review file by file to get more thorough analysis.

#### Related commands
- **Before:** `/check-code`, `/checkpoint`
- **After:** `git push`, `gh pr create`

---

### `/pool-status`

#### Purpose
Shows the health of every configured provider — RPM usage, success rate, average latency, cost
today — with alerts and recommendations, so you can catch problems before they slow down your
agent run.

#### When to use
- Before starting a large `claw-forge run` to verify providers are healthy
- When agents are running slower than expected (check latency / circuit breakers)
- When you want to understand cost distribution across providers
- After adding a new provider to verify it's routing correctly

#### Usage
In Claude Code:
```
/pool-status
```

Or via CLI (raw data, no analysis):
```bash
claw-forge pool-status
```

#### What it does internally
1. Queries `http://localhost:8420/pool/status` for live health data.
2. Falls back to `claw-forge pool-status` CLI if the state service isn't running.
3. Formats provider health into a table with status indicators (🟢/🟡/🔴).
4. Shows last 5 requests with provider routing, latency, and cost.
5. Highlights circuit breaker events and approaching RPM limits.
6. Adds actionable recommendations.

#### Real-world example
Your run is slower than usual. You suspect a provider issue:

```
You: /pool-status
```

#### Output example
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Provider Pool Status — 2025-05-14 14:23:45
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  Provider           Status    RPM      Success  Latency  Cost Today
  ─────────────────────────────────────────────────────────────────
  claude-oauth       🟢 OK     12/∞     100%     1.2s     $0.00
  anthropic-direct   🟡 BUSY   58/60    99.5%    0.8s     $1.23
  groq-backup        🔴 OPEN   0/30     72%      —        $0.00

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ⚠ anthropic-direct is at 97% RPM capacity — slowdowns likely
  🔴 groq-backup circuit breaker is OPEN (5 consecutive failures)
     Auto-resets in: ~2 minutes

  Recommendations:
    - Add another provider — only 1 of 3 is fully healthy
    - groq-backup circuit breaker will auto-reset; monitor recovery
    - Consider lowering anthropic-direct priority to let claude-oauth handle more

  Total cost today: $1.23 · Active sessions: 3
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

#### Pro tips
- A 🔴 circuit breaker that auto-resets in 2 minutes is fine to wait out. A persistent one
  means your API key or endpoint is broken — fix it.
- If `anthropic-direct` is near RPM limit, add `claude-oauth` (free tier) as a load-overflow
  provider.
- Use the CLI version (`claw-forge pool-status`) for a quick table without the analysis overlay.

#### Related commands
- **Before:** `claw-forge run`
- **CLI equivalent:** `claw-forge pool-status`

---

### `/create-bug-report`

#### Purpose
Guides you through a 6-phase conversation to create a precise, structured `bug_report.md` file —
then hands it directly to `claw-forge fix` to run the TDD repair loop.

#### When to use
- A user reports a bug and you want the agent to have full context before attempting a fix
- You're tracking down a non-obvious issue and want to think through it systematically
- You want to create a reusable bug report for your issue tracker
- Before running `claw-forge fix --report` on a complex bug

#### Usage
In Claude Code:
```
/create-bug-report
```
Or with an initial hint:
```
/create-bug-report user can't reset password with uppercase email
```

#### What it does internally
1. **Phase 1** — Title & symptoms: asks what's broken, any error messages, frequency.
2. **Phase 2** — Reproduction: exact steps, every-time vs intermittent.
3. **Phase 3** — Expected vs actual behaviour.
4. **Phase 4** — Scope: runs `ls src/ lib/ app/` to suggest affected files, asks what must not
   change.
5. **Phase 5** — Writes `bug_report.md` to the project root.
6. **Phase 6** — Asks "Ready to fix?" → if yes, runs `claw-forge fix --report bug_report.md`.

#### Real-world example
A user reports they can't reset their password. In Claude Code:

```
You: /create-bug-report

Claude: Phase 1 — What's broken? Describe the symptom in one sentence.

You: Users can't reset their password if their email address has any uppercase letters.

Claude: Any other symptoms? (error messages, affected users, frequency)

You: The reset email is never sent. No error message shown to user.
     Happens to anyone with uppercase in their email (e.g. John@example.com).
     Every time, 100% reproducible.

Claude: Phase 2 — Exact reproduction steps?

You: 1. Register with email John@example.com
     2. Go to /forgot-password
     3. Enter John@example.com
     4. Check inbox — no email arrives
     5. Check DB: no password_reset_token was created

Claude: Does it happen every time?

You: Yes, every time. john@example.com (lowercase) works fine.

Claude: Phase 3 — What should happen instead?

You: The system should be case-insensitive for email lookups.
     A reset email should always be sent regardless of case.
```

#### Output example
After all 6 phases, Claude writes `bug_report.md`:

```markdown
# Bug Report: Password reset fails for emails with uppercase letters

## Symptoms
Users cannot reset their password when their email contains uppercase letters.
The reset email is never sent, no error shown to the user.
Affects: all users with uppercase in email. Frequency: 100% reproducible.

## Reproduction Steps
1. Register with email John@example.com
2. Go to /forgot-password and enter John@example.com
3. Check inbox — no reset email arrives
4. Verify in DB: no password_reset_token row created for the user

## Expected Behaviour
System is case-insensitive for email lookups. Reset email always sent.

## Actual Behaviour
Password reset silently fails for mixed-case emails.

## Affected Files (suspected)
- auth/service.py (email lookup logic)
- routers/auth.py (forgot-password endpoint)

## Constraints
- Must not break existing auth flow for lowercase emails
- All 59 existing tests must remain green
```

Then:
```
✅ bug_report.md written.

Ready to fix? (yes/no)

You: yes

Running: claw-forge fix --report bug_report.md
```

#### Pro tips
- Be specific in Phase 4 about what must NOT change — agents treat constraints as hard rules.
- If the bug is intermittent, describe the conditions that trigger it (load, timing, data state).
- You can use the generated `bug_report.md` directly in GitHub Issues for team documentation.

#### Related commands
- **After:** `claw-forge fix --report bug_report.md`
- **Then:** `/check-code`, `/review-pr`

---

---

## Middleware Reference

claw-forge ships three composable hook-based middleware layers, all activated via `claw-forge run` flags.

**Key insight:** `loop_detect_threshold=5` and `verify_on_exit=True` are **on by default**. `--edit-mode hashline` is the default for projects scaffolded by `claw-forge init` (via `agent.edit_mode: hashline` in the yaml); existing projects without that key still need to pass the flag or edit their yaml. Running `claw-forge run` on a fresh-scaffolded project gives you the full Config E stack out of the box.

---

### Hashline Edit Mode (`--edit-mode hashline`)

**What it does:** Replaces exact-text `str_replace` editing with content-addressed line references. Every file the agent reads gets annotated with 3-char SHA256 hashes; the agent references lines by hash rather than reproducing their exact text.

**The problem it solves:** `str_replace` requires the agent to reproduce an exact substring — whitespace, indentation and all. This fails constantly on indented code (Python, YAML, Rust), long sessions where the model's recall degrades, and weaker/faster models that hallucinate whitespace.

**Benchmark impact:** 6.7% → 68.3% on Grok Code Fast. On Opus 4.6, it's what enables Config E to reach 100% (vs 96.7% without it).

**When to use:**
- Weaker or faster models (Sonnet, Haiku, local models) — removes exact-match failure mode entirely
- Python/YAML/Rust heavy codebases — where indentation errors are common
- Long unattended runs (CI, overnight, `--push-after-merge`) — no edit-rejection loops at 3 AM
- Any production/evaluation run — it's strictly more reliable

**When to skip:**
- Debugging agent edit behaviour (hash annotations add log noise)
- Reviewing diffs as plain patches (hashline blocks aren't unified diff format)
- Auto-generated or minified files (annotations are noise on long lines)

**Full use-case guide:** [`docs/middleware/hashline.md`](middleware/hashline.md)

```bash
# Recommended — full Config E (loop-detect + verify-on-exit are on by default)
claw-forge run --edit-mode hashline

# Stay on str_replace (middleware still runs)
claw-forge run

# Debug mode — all middleware off
claw-forge run --no-verify-on-exit --loop-detect-threshold 0
```

---

### LoopDetectionMiddleware (`--loop-detect-threshold`)

**What it does:** Tracks how many times each file has been edited in the current agent session. When a single file exceeds the threshold, the middleware injects a structured "reconsider" prompt via the `PostToolUse` hook — breaking the agent out of doom loops before they waste tokens.

**When it fires:**
- After any `Edit` or `MultiEdit` tool use
- When `edit_count[file] >= loop_detect_threshold`

**Threshold auto-boost:** When `--edit-mode hashline` is active, the effective threshold is raised by 3 (e.g. default 5 → 8), because hashline legitimately produces more edits per file (individual line replacements).

**Disabling:** `--loop-detect-threshold 0` turns it off entirely.

**Design doc:** [`docs/middleware/loop-detection.md`](middleware/loop-detection.md)

```bash
# Use with a tighter threshold (high-risk project, big files)
claw-forge run --loop-detect-threshold 3

# Disable loop detection entirely (fast iteration mode)
claw-forge run --loop-detect-threshold 0
```

---

### PreCompletionChecklistMiddleware (`--verify-on-exit / --no-verify-on-exit`)

**What it does:** Intercepts the `Stop` event before the agent exits and injects a structured verification checklist. The agent must re-read the task spec, confirm all acceptance criteria are met, run tests, and explicitly state it has verified — before the session closes.

**Effect:** Dramatically reduces "ships passing but incomplete" — agents that claim done without actually checking.

**Disabling:** `--no-verify-on-exit` skips the checklist entirely (useful during debugging).

**Design doc:** [`docs/middleware/pre-completion-checklist.md`](middleware/pre-completion-checklist.md)

```bash
# Default — checklist runs on every exit
claw-forge run

# Disable for fast iterative runs where you'll verify manually
claw-forge run --no-verify-on-exit
```

---

### Push-After-Merge (`--push-after-merge`)

**What it does:** After every successful squash-merge into the target branch (default `main`, configurable via `git.target_branch`), pushes the target branch to its remote.  Keeps the remote in sync with merged work for collaborators and CI without polluting the remote with per-task feature branches.

**Default: disabled.** Must be explicitly opted in — never pushes without `--push-after-merge` (or `git.push_after_merge` in config).

**Behavior:**
- Fires only when a squash-merge produces a real new commit on the target branch.  No-op merges (content already reachable) are skipped to save a round-trip.
- Skipped silently if the configured remote doesn't exist (so it's safe to leave on in repos without an `origin`).
- Push failures are logged as warnings — the dispatcher continues and the next successful merge's push will catch the remote up.
- No remote feature branches are created — only the target branch is pushed.

**Replaces `--auto-push`:** the legacy per-turn auto-push (which pushed each task's feature branch to the remote, leaving zombie refs after squash-merge) has been removed.  Setting `agent.auto_push` in your config now triggers a one-line deprecation warning and is otherwise ignored.

```bash
# Push to origin/main after every merge
claw-forge run --push-after-merge

# Push to upstream/main (forked repo)
claw-forge run --push-after-merge --push-remote upstream

# Via claw-forge.yaml config
# git:
#   push_after_merge: true            # uses 'origin'
#   # push_after_merge: "upstream"    # explicit remote
```

---

### Uncommitted-State Handling at Startup (`git.handle_uncommitted_at_startup`)

**Why:** Anything in the main worktree that isn't committed to HEAD — untracked files, unstaged-modified tracked files, staged-but-not-committed files — is invisible to agent worktrees (which branch off HEAD) and silently blocks future squash-merges with three different git error signatures.  This config unifies all three under one autonomous-handling rule at run startup.

**Hard gate:** when this is enabled, no agent worktrees are created until the main worktree is clean (committed-to-HEAD).  An autonomous overnight run failing fast at this point is a *feature* — it surfaces the problem at the diagnosis-friendly moment rather than deep in a 30-task batch where the audit trail decays.

**Modes:**

| Mode | Behaviour |
|---|---|
| `ignore` | Handler doesn't run.  Legacy behaviour — uncommitted state persists and may cause future `_sideline_orphans` events or merge collisions. |
| `smart` (default) | **Fully autonomous, no human in the loop.**  Untracked files archive to `.claw-forge/orphans/`; dirty-tracked state stashes via `git stash push`.  Both primitives reversible; never aborts. |
| `abort` | Explicit fail-fast.  Refuses to start whenever any uncommitted state exists.  User must `git add`/`git commit`, `git stash`, or `rm` before re-running. |

**Smart-mode dispatch:**

| State (git status prefix) | Action | Recovery |
|---|---|---|
| Untracked (`?? `) | Archive to `.claw-forge/orphans/<startup-ts>/<path>` with sibling `PROVENANCE.json` | `cp` from archive |
| Unstaged-modified (` M `, ` D `, …) | Bundled into one `git stash push -m "claw-forge-auto-<ts>"` | `git stash list` → `git stash pop` |
| Staged-not-committed (`M  `, `A  `, …) | Same — `git stash push` captures index too | Same |

**Provenance enrichment:** each untracked file's `PROVENANCE.json` records the path, action, reason, and (if matched) the originating task's `touches_files` glob — making it trivial to trace which task produced the debris.

**Configuration:**

```yaml
git:
  handle_uncommitted_at_startup: smart        # ignore | smart | abort
```

**Console output (smart mode):**

```
[yellow]Archived 3 untracked file(s) → .claw-forge/orphans/20260509-150000/[/yellow]
   - app/scratch.py
   - app/tickets/old.py
   - migrations/wip/foo.py
[dim]Recover with: cp -r .claw-forge/orphans/.../ ./[/dim]
[yellow]Stashed 2 dirty-tracked file(s) — stash message: claw-forge-auto-20260509-150000[/yellow]
   - app/routers/auth.py
   - app/models/user.py
[dim]Recover with: git stash list  →  git stash pop[/dim]
```

**Reversibility:** every action is reversible.  Archived files: `cp` from `.claw-forge/orphans/<ts>/`.  Stashed state: `git stash pop` matching the timestamped message.  Nothing is deleted.

**Migration:** default is `smart` — claw-forge autonomously archives untracked files and stashes dirty-tracked state at startup so runs aren't blocked.  Both operations are reversible (see Reversibility above).  Set `ignore` to restore the legacy no-op behaviour, or `abort` to fail fast on any uncommitted state.

---

### Combining middleware — defaults are already Config E

`loop_detect_threshold=5` and `verify_on_exit=True` are **on by default**. You get the full middleware stack without any flags:

```bash
# This is already Config E — loop detection + verify-on-exit are on by default,
# and hashline is the default for fresh-scaffolded projects.
claw-forge run                          # fresh-scaffolded project
claw-forge run --edit-mode hashline     # legacy project without agent.edit_mode in yaml
```

For projects scaffolded by `claw-forge init`, no flag is needed — `agent.edit_mode: hashline` is written into the yaml. Legacy projects without that key need to pass `--edit-mode hashline` (or edit their yaml) to get the same stack.
To disable middleware for fast debugging:

```bash
claw-forge run --no-verify-on-exit --loop-detect-threshold 0
```

With push-after-merge for fully autonomous workflows (explicit opt-in — network write):

```bash
claw-forge run --edit-mode hashline --push-after-merge
```

**Config E** (`hashline` + `loop-detect=5` + `verify-on-exit`) achieves **100%** on claw-forge-bench (30 tasks, `claude-opus-4-6`) — and it's the default minus one flag.

See [`docs/benchmarks/results.md`](benchmarks/results.md) for full ablation results across configs A–E.

---

## See Also

- [docs/workflows.md](workflows.md) — End-to-end workflow walkthroughs
- [docs/brownfield.md](brownfield.md) — Brownfield mode deep dive
- [docs/middleware/loop-detection.md](middleware/loop-detection.md) — LoopDetectionMiddleware design
- [docs/middleware/pre-completion-checklist.md](middleware/pre-completion-checklist.md) — PreCompletionChecklistMiddleware design
- [docs/benchmarks/terminal-bench.md](benchmarks/terminal-bench.md) — Terminal Bench 2.0 eval harness
- [README.md](../README.md) — Project overview and quick start
