# Loom

Loom is an agent orchestration system for Claude Code. You write a plan; loom executes it — stages run in parallel across isolated git worktrees, completion is gated by checks loom runs itself rather than by the agent's own account of its work, and what each session learns is captured and distilled into a knowledge base the next session reads first.

## What Loom Solves

Autonomous agent work fails in a small number of predictable ways. Loom answers each with a mechanism, not a paragraph of prompt.

| Failure mode                            | What actually happens                                                                | Loom's answer                                                                                                                                                                                          |
| --------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **False completion**                    | Tests were never run, the module was written but never imported, the fix is a `TODO` | Loom runs the acceptance criteria itself, then checks artifacts for stubs, wiring for real integration, and dead-code patterns for orphaned work. The bypass flags need a token the agent cannot read. |
| **Instruction drift**                   | Rules decay the moment they scroll out of attention                                  | Shell hooks enforce the load-bearing rules deterministically — commit discipline, staging scope, worktree boundaries, subagent limits — outside the model's control.                                   |
| **Amnesia**                             | Every session rediscovers the same architecture and repeats the same mistakes        | A per-stage memory journal feeds a distillation stage that curates permanent, tiered knowledge; later sessions read it before touching code.                                                           |
| **Cost scaling with tokens, not value** | Expensive models doing cheap work; re-reading everything, every time                 | Judgment stays on an orchestrator; bulk implementation is delegated to cheap subagents. Signals are laid out for KV-cache reuse and knowledge is tiered, so agents load only what they need.           |
| **Context exhaustion**                  | The session degrades into an expensive compaction loop                               | Context budgets are monitored per stage; a handoff is written *before* compaction and the resumed session is re-anchored to its assignment.                                                            |
| **Lost runs**                           | A crashed or hung session takes the work with it                                     | All state is files under `.work/`. The daemon detects dead and hung sessions, classifies the failure, and retries or escalates.                                                                        |
| **Serialization**                       | Multi-stage work runs one-at-a-time, or collides on the same files                   | A dependency DAG schedules independent stages concurrently in separate worktrees, with progressive auto-merge and dedicated conflict-resolution sessions.                                              |

## Key Capabilities

### Deterministic guardrails

The rules that matter are not left to the model. Loom installs **16 Claude Code hooks** and a git `pre-commit` hook that fire regardless of what an agent intends:

- `commit-guard.sh` blocks a session from ending with uncommitted work or a stage still `Executing`
- `git-add-guard.sh` blocks `git add -A` / `git add .`; `git-pre-commit-hook.sh` blocks commits containing `.work` or `.worktrees`
- `worktree-isolation.sh` / `worktree-file-guard.sh` block cross-worktree writes, reads, and path traversal
- `commit-filter.sh` blocks subagent git operations (a subagent commit loses the main agent's work) and blocks AI attribution in commit messages
- `subagent-verify-guard.sh` blocks subagents from running project-wide build/test/lint suites, so verification stays with the one agent that can see the whole tree — with `integration-verify` stages carved out, and no opt-out environment variable
- `pre-compact.sh` blocks compaction, writes a handoff, then allows it; `session-start.sh` re-anchors the resumed agent to its signal file
- `plans-path-guard.sh` keeps plans in `doc/plans/` where loom and git can see them

Subagent detection is a live process-tree ancestry check, not a PPID comparison. See [Verification Is the Main Agent's Job](#verification-is-the-main-agents-job).

### Verification that outlives the agent's opinion

`loom stage complete` is not a self-report. Loom executes the stage's acceptance criteria in-process and refuses completion on failure, leaving the stage `Executing` so the agent must fix and retry. On top of that, goal-backward verification asks whether the *outcome* exists:

- **`artifacts`** — files exist and contain real implementation (stub detection rejects `TODO`, `FIXME`, `unimplemented!`, `todo!`, `pass`, `NotImplementedError`)
- **`wiring`** — regex proof that new code is actually referenced: module registered, route mounted, component rendered
- **`wiring_tests`** — runtime commands proving the integration behaves
- **`dead_code_check`** — command output patterns catching code that exists but is never called
- **`before_stage` / `after_stage`** — pre-spawn and post-acceptance gates; a failed pre-check blocks the stage before a session is even spawned

The escape hatches (`--no-verify`, `--force-unsafe`, `--assume-merged`) require the daemon's `.work/admin.token`, which the generated sandbox explicitly denies agents read access to. An agent cannot authorize its own bypass.

### Knowledge capture and distillation

Loom treats what agents learn as a first-class artifact with a pipeline, not a scratch file.

1. **Capture** — during execution, agents record to a per-stage journal: `loom memory note` (gotchas, mistakes-with-prevention), `decision` (with rationale), `change`, `question`. The journal is injected into the *recitation* section at the end of the next signal, where model attention is highest.
2. **Distill** — a `knowledge-distill` stage runs at the end of a plan, reads every stage memory, and curates it into permanent knowledge — mistakes rewritten as actionable prevention rules, decisions with their rationale, reusable patterns and conventions.
3. **Retrieve** — the result is a **tiered** base under `doc/loom/knowledge/`: a generated `INDEX.md`, seven tier-1 summaries, and tier-2 topic files. Agents read the index, then the summary for their area, then only the topics they touch — so the base can grow without every session paying to load it.

`loom knowledge check` reports coverage, `audit` reports structural rot (oversized sections, broken links, orphans), `gc` restructures, and `loom map` seeds the base from static analysis. Details: [Knowledge System](#knowledge-system).

### Cost control by construction

Loom's savings come from **delegation, not downgrade**:

- **Orchestration is always Opus at `xhigh` effort.** Every stage's main agent plans, decomposes, verifies, and commits — the judgment-heavy work that is worst to economize on.
- **Implementation is always delegated** to the cheapest subagent that can do the job (Haiku for trivial mechanical edits, Sonnet for the common case, Opus only for genuinely hard work), spawned by agent type so the choice is explicit rather than inherited.
- **Signals are built for cache reuse.** Each signal is a four-section layout with a per-stage-type stable prefix that is byte-identical across sessions, so the large doctrine block is a cache hit rather than a re-read.
- **Context budgets prevent compaction**, which is the expensive failure: an uncached re-read that costs more and produces worse work.
- **Tiered knowledge and a skill index** keep the working set small — at most 5 matched skills are injected per stage, out of 61 installed.
- **Orchestrated sessions are interactive**, billing against your Claude subscription. The handful of headless `claude -p` paths are opt-in flags, off by default (see the Billing note below).

Per-stage `model`, `reasoning_effort`, and `ultracode` fields let you override any of this explicitly.

### Parallel execution and progressive merge

Stages form a dependency DAG; everything independent runs at once, each in its own worktree (`.worktrees/<stage-id>`, branch `loom/<stage-id>`). Completed stages merge back progressively under a file lock, and a real conflict spawns a dedicated resolution session rather than stalling the run.

### Crash recovery and liveness

All orchestration state is plain files in `.work/`, so nothing is lost when a process dies. The daemon polls every 5s, tracks PID liveness and per-session heartbeats, flags hung sessions after 300s, and classifies failures across ten types into retryable (exponential backoff) and needs-diagnosis. Tool-call telemetry drives a stuck-session signal when a session's recent calls are overwhelmingly failures. Orphaned sessions are recovered on daemon restart.

### Sandboxing and plan hardening

Plan-level defaults and per-stage overrides control filesystem reads/writes, network domains, and permission mode ([Sandbox Configuration](#sandbox-configuration)). Before you spend anything, `loom plan verify` validates a plan with no side effects, and `loom pressure` hardens it through adversarial review rounds run by two different model families.

### Human-in-the-loop where it matters

Thirteen stage states make "needs a person" a first-class outcome rather than a hang: `WaitingForInput` (raised automatically when an agent asks a question), `NeedsHumanReview`, `Blocked`, `MergeConflict`. Operators get `loom stage hold/release/skip/retry/human-review`, and an agent that believes a criterion is wrong can escalate with `loom stage dispute-criteria` instead of quietly weakening it.

## Platform Support

- Linux: primary development and full CI test runs
- macOS: supported for build/terminal integration, CI does build-only verification
- Windows: not supported (WSL may work but is best-effort)

## Quick Start

Loom is under active development and not yet published to GitHub Releases. You need to build locally with the Rust toolchain installed.

### 1. Install Loom

```bash
git clone https://github.com/cosmix/loom.git
cd loom
bash ./dev-install.sh
```

`dev-install.sh` builds the release binary (`cargo build --release`) and runs `install.sh`, which installs `loom-*` prefixed agents and skills (non-destructively, preserving user customizations), hooks, and configuration into `~/.claude/` and the CLI binary to `~/.local/bin/loom`. Orchestration rules are written directly to `~/.claude/CLAUDE.md` (existing file is backed up).

### 2. Write a Plan

Plans are how loom knows what to build. Open Claude Code in your target project and use the `/loom-plan-writer` skill to create one:

```bash
cd /path/to/project
claude  # start Claude Code CLI
```

Inside the Claude Code session:

1. Enter plan mode (`/plan`)
2. Load the plan-writing skill by typing `/loom-plan-writer`
3. Describe what you want to build and discuss with Claude
4. Claude will write the plan to `doc/plans/PLAN-<name>.md`

To validate the draft before running it:

```bash
loom plan verify doc/plans/PLAN-<name>.md
```

### 3. Run Loom

Once your plan is written:

```bash
loom init doc/plans/PLAN-<name>.md
loom run
loom status --live
loom stop
```

`loom init` parses the plan, creates stage state, and installs/configures project hook wiring automatically. For an existing repo that is missing Claude Code hook setup, run `loom repair --fix`.

### What Gets Installed

| Location                     | Contents                                                  |
| ---------------------------- | --------------------------------------------------------- |
| `~/.claude/agents/loom-*.md` | 4 specialized subagents (per-item, non-destructive)       |
| `~/.claude/skills/loom-*/`   | 61 domain knowledge modules (per-item, non-destructive)   |
| `~/.claude/commands/*.md`    | Loom slash commands (`/pressure`, `/address`, `/distill`) |
| `~/.claude/hooks/loom/`      | 16 lifecycle and guardrail hooks + shared library         |
| `~/.claude/CLAUDE.md`        | Orchestration rules                                       |
| `~/.codex/skills/pressure/`  | Codex pressure-testing skill (`$pressure`)                |
| `~/.local/bin/loom`          | Loom CLI                                                  |

> The `~/.claude/commands/` and `~/.codex/skills/pressure/` entries are installed only by the local `install.sh` (cloned repo); the `curl | bash` install does not ship them yet.

## Core Workflow

1. Open Claude Code, enter plan mode (`/plan`), and use `/loom-plan-writer` to write a plan to `doc/plans/`.
2. Run `loom init <plan-path>` to parse metadata and create stage state.
3. Run `loom run` to start daemon + orchestrator.
4. Track progress with `loom status --live`.
5. Recover, verify, merge, or retry stages as needed.

### Stage Lifecycle

```text
WaitingForDeps → Queued → Executing → Completed
```

Everything else is an explicit, inspectable outcome rather than a hang:

| State                   | Meaning                                                                |
| ----------------------- | ---------------------------------------------------------------------- |
| `Blocked`               | A `before_stage` check or an explicit block stopped the stage          |
| `NeedsHandoff`          | Context budget exceeded; a handoff was written                         |
| `WaitingForInput`       | The agent asked a question (raised automatically by the AskUser hooks) |
| `MergeConflict`         | Auto-merge hit a real conflict; a resolution session is spawned        |
| `MergeBlocked`          | Merge cannot proceed (e.g. another merge is in progress)               |
| `CompletedWithFailures` | Work finished but acceptance did not pass                              |
| `NeedsHumanReview`      | Escalated to a person                                                  |
| `NeedsAdjudication`     | A disputed acceptance criterion is awaiting a verdict                  |
| `Skipped`               | Explicitly skipped                                                     |

## CLI Reference

### Primary Commands

```bash
loom init <plan-path> [--clean]
loom run [--manual] [--max-parallel N] [--foreground] [--watch] [--no-merge]
loom status [--live] [--compact] [--verbose]
loom stop
loom resume <stage-id>
loom check <stage-id> [--suggest]
loom diagnose <stage-id>
loom pressure <plan-path> [--rounds N] [--dry-run]
```

`loom pressure` hardens a plan before you run it by combining two external agents over `--rounds` rounds (default 2). Each round runs both pressure-tests in parallel: Claude `/pressure` edits the plan in place in the foreground (you watch it live), while Codex `$pressure` writes an independent review next to it (`codex-<plan>.md`) in the background (its output is captured to a temp log to keep the terminal clean). Once both finish, Claude `/address` folds the review back in. Claude stays interactive (subscription billing) and auto-closes when done; Codex runs from the repo root. Requires both the `claude` and `codex` CLIs on PATH. `--dry-run` prints the exact commands without spawning anything.

### Plan Commands

```bash
loom plan verify <plan-path> [--strict] [--json] [--no-color]
```

`loom plan verify` validates a plan file without touching `.work/` or requiring a git repo. It runs the same fatal validation as `loom init` (schema errors, duplicate IDs, unknown dependencies, path safety) plus advisory warnings (structural issues, missing knowledge-bootstrap stage, sandbox gaps). Exits 0 on success, non-zero on fatal errors; `--strict` promotes warnings to errors.

### Stage Commands

```bash
loom stage complete <stage-id> [--session <id>] [--no-verify] [--force-unsafe --assume-merged]
loom stage block <stage-id> <reason>
loom stage reset <stage-id> [--hard] [--kill-session]
loom stage waiting <stage-id>
loom stage resume <stage-id>
loom stage hold <stage-id>
loom stage release <stage-id>
loom stage skip <stage-id> [--reason <text>]
loom stage retry <stage-id> [--force] [--context <message>]
loom stage merge [stage-id] [--resolved]
loom stage verify <stage-id> [--no-reload] [--dry-run]
loom stage human-review <stage-id> [--approve|--force-complete|--reject <reason>]
loom stage dispute-criteria <stage-id> --criterion-index N --reason <text> [--evidence-commit <sha>] [--failure-output <path>]
```

`loom stage dispute-criteria` is the sanctioned way for an agent to challenge a criterion it believes is wrong or impossible, instead of quietly weakening it. The daemon writes `request.md` and moves the stage to `NeedsAdjudication`; the verdict is daemon-written and never authored by the agent.

### Stage Outputs

```bash
loom stage output set <stage-id> <key> <value> [--description <text>]
loom stage output get <stage-id> <key>
loom stage output list <stage-id>
loom stage output remove <stage-id> <key>
```

### Knowledge / Memory

```bash
loom knowledge show [target]                 # target: a tier-1 file, or <category>/<slug>; no arg shows INDEX.md
loom knowledge update <target> <content>     # e.g. `patterns` (tier 1) or `architecture/merge-flow` (tier 2)
loom knowledge init
loom knowledge index                                                         # Regenerate INDEX.md (creates it on a flat dir)
loom knowledge list
loom knowledge check [--min-coverage N] [--src-path <path>] [--quiet]
loom knowledge audit [--max-file-lines N] [--max-topic-lines N] [--quiet]   # Report structural issues (oversized sections, broken links, orphans)
loom knowledge gc [--model NAME] [--dry-run] [--quick]                       # Spawn Claude to restructure (extract, dedupe, relink)
loom knowledge bootstrap [--model <name>] [--skip-map] [--quick]             # --quick uses headless `claude -p` (see Billing note)

loom memory note <text> [--stage <id>]
loom memory decision <text> [--context <why>] [--stage <id>]
loom memory change <text> [--stage <id>]
loom memory question <text> [--stage <id>]
loom memory query <search> [--stage <id>]
loom memory list [--stage <id>] [--entry-type <type>]
loom memory show [--stage <id>] [--all]
```

See [Knowledge System](#knowledge-system) for how these fit together.

### Other Commands

```bash
loom review [--ai-summary]                                                   # Generate a code-review doc from stage memories; --ai-summary uses headless `claude -p` (see Billing note)
loom sessions list
loom sessions kill <session-id...> | --stage <stage-id>
loom worktree list
loom worktree remove <stage-id>
loom graph
loom map [--deep] [--focus <area>] [--overwrite]
loom repair [--fix]
loom clean [--all|--worktrees|--sessions|--state]
loom self-update
loom completions [<shell>] [--install] [--migrate]
```

### ⚠️ Billing: headless `claude -p` flags

Loom runs every orchestrated stage as a normal **interactive** Claude Code session, which bills against your Claude subscription exactly like launching `claude` yourself. A few **opt-in** flags instead invoke Claude in headless print mode (`claude -p`):

| Command                    | Flag           | Behavior without the flag                                       |
| -------------------------- | -------------- | --------------------------------------------------------------- |
| `loom knowledge bootstrap` | `--quick`      | Runs an interactive bootstrap session instead                   |
| `loom knowledge gc`        | `--quick`      | Runs an interactive compaction session instead                  |
| `loom review`              | `--ai-summary` | Uses the plan's first paragraph as the summary (no Claude call) |

Headless `claude -p` usage may be billed **separately from (and in addition to) your Claude subscription** as API/extra charges, depending on your account and auth setup. These flags are **off by default** so loom never silently incurs those charges — only pass them when you knowingly accept the headless billing.

## Plan Format

Plans live in `doc/plans/` with metadata in fenced YAML between loom markers.

````markdown
# PLAN-0001: Feature Name

<!-- loom METADATA -->

```yaml
loom:
  version: 1
  sandbox:
    enabled: true
  stages:
    - id: implement-api
      name: Implement API
      description: Add endpoint + tests
      working_dir: "."
      stage_type: standard
      dependencies: []
      acceptance:
        - "cargo test"
        - command: "cargo test api_integration::returns_200"
          stdout_contains: ["test result: ok"]
      files:
        - "loom/src/**/*.rs"
      artifacts:
        - "loom/src/api/*.rs"
      wiring:
        - source: "loom/src/main.rs"
          pattern: "mod api;"
          description: "API module registered"
      execution_mode: team

    - id: integration-verify
      name: Integration Verify
      working_dir: "."
      stage_type: integration-verify
      dependencies: ["implement-api"]
      acceptance:
        - "cargo test --all-targets"
        - command: "cargo test api_integration::returns_200"
          stdout_contains: ["test result: ok"]
```

<!-- END loom METADATA -->
````

### Stage Fields

| Field                              | Required               | Notes                                                                                                                                      |
| ---------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `id`                               | Yes                    | Stage identifier                                                                                                                           |
| `name`                             | Yes                    | Human-readable title                                                                                                                       |
| `working_dir`                      | Yes                    | Relative execution directory (`.` allowed)                                                                                                 |
| `description`                      | No                     | Optional summary                                                                                                                           |
| `dependencies`                     | No                     | Upstream stage IDs                                                                                                                         |
| `acceptance`                       | Conditionally required | Shell criteria (strings or extended objects with stdout_contains etc.)                                                                     |
| `setup`                            | No                     | Setup commands                                                                                                                             |
| `files`                            | No                     | File glob scope                                                                                                                            |
| `stage_type`                       | No                     | `standard` (default), `knowledge`, `integration-verify`, `knowledge-distill`                                                               |
| `artifacts` / `wiring`             | Conditionally required | Required for `standard` and `integration-verify` (acceptance OR goal-backward)                                                             |
| `wiring_tests` / `dead_code_check` | No                     | Extended verification                                                                                                                      |
| `before_stage`                     | No                     | Pre-spawn checks (TruthCheck list); stage → Blocked if any fail                                                                            |
| `after_stage`                      | No                     | Post-acceptance checks (TruthCheck list); completion fails if any fail                                                                     |
| `code_review`                      | No                     | `integration-verify` only: `dimensions` (string list) and `require_all` (bool); rendered as checklist in agent signal                      |
| `model`                            | No                     | Model for this stage's main agent (default `opus` for every stage type)                                                                    |
| `reasoning_effort`                 | No                     | `low`, `medium`, `high`, `xhigh`, `max` (default `xhigh` on opus, `high` otherwise)                                                        |
| `ultracode`                        | No                     | License this stage for large multi-agent fan-out; per-stage opt-in (default `false`)                                                       |
| `context_budget`                   | No                     | Context threshold (%) for handoff (default 65%, hard maximum 75%)                                                                          |
| `sandbox`                          | No                     | Per-stage sandbox override                                                                                                                 |
| `sandbox.permission_mode`          | No                     | `auto` (default), `accept-edits`, `plan`, `default` — resolves stage > plan > stage-type default; `bypass-permissions` is rejected at init |
| `execution_mode`                   | No                     | `single` (default) or `team` hint                                                                                                          |

### Stage Type Behavior

- `knowledge`: knowledge/bootstrap work, different verification expectations
- `standard`: implementation stage; must define goal-backward checks
- `integration-verify`: final quality gate combining code review and functional verification; must define goal-backward checks. Define `code_review.dimensions` to render a checklist of review dimensions in the agent's signal.
- `knowledge-distill`: final stage; curates stage memories into permanent knowledge files

## Verification Model

`loom check <stage-id>` validates outcomes, not just compilation/tests:

- `acceptance`: shell criteria (simple strings or extended objects with `stdout_contains`, `exit_code`, etc.)
- `artifacts`: real implementation files exist
- `wiring`: critical integration links exist
- `wiring_tests`: runtime integration checks
- `dead_code_check`: detect unused code via command output patterns

For `standard` and `integration-verify` stages, acceptance criteria or at least one goal-backward check must be defined.

### Verification Is Enforced, Not Self-Reported

`loom stage complete` is the only way a stage finishes, and it runs the acceptance criteria itself before doing anything else. If they fail, the stage stays `Executing` — the agent must fix the work and re-run, and `fix_attempts` is incremented so repeated failures surface rather than accumulate silently. `after_stage` checks then run post-acceptance, and goal-backward verification runs before the progressive merge.

Artifact verification treats a stub as a failure: a file that exists but contains `TODO`, `FIXME`, `unimplemented!`, `todo!`, a bare `pass`, or `raise NotImplementedError` does not count as delivered.

The three bypass flags — `--no-verify`, `--force-unsafe`, `--assume-merged` — are gated on the daemon's admin capability, which requires reading `.work/admin.token`. The generated sandbox settings deny agents read access to that file, so an agent cannot authorize its own bypass; a human operating outside the sandbox can.

An agent that genuinely believes a criterion is wrong or impossible has a sanctioned path — `loom stage dispute-criteria` — rather than an incentive to weaken it.

### Verification Is the Main Agent's Job

Subagents do not verify. A subagent may run **at most one narrowly-scoped check** covering the files it just changed; project-wide builds, full test suites, and repo-wide lint or typecheck runs belong to the main agent — the only party that can see the whole tree and act on the result.

This is enforced, not just advised: `hooks/subagent-verify-guard.sh` (a `PreToolUse:Bash` hook) blocks project-wide runners — `cargo build`, `cargo test`, `make test`, `tsc`, `go build` and friends — when the caller is detected as a subagent. Scoped invocations pass, quoted mentions are ignored, and unrecognised commands are always allowed: a false block would strand a subagent mid-task.

Two things worth knowing:

- **`integration-verify` stages are carved out.** That stage type exists to run the complete suite, so its subagents may. The carve-out is read from the stage file and fails safe — an ambiguous or missing stage file means no relaxation.
- **There is deliberately no opt-out environment variable.** The main agent is never affected, so an escape hatch would only serve to defeat the rule.

## Knowledge System

Loom's answer to "every session starts from zero" is a three-stage pipeline: capture during execution, distill at the end of a plan, retrieve cheaply forever after.

### 1. Capture — session memory

While a stage runs, its agent journals to `.work/memory/<session>.md`:

```bash
loom memory note "gotcha: worktree exclude lives at <worktree>/.git/info/exclude, not <dir>/.git/..."
loom memory decision "centralized plan lookup in plan/parser" --context "avoids an orchestrator→commands layering violation"
```

Entries are typed (`note`, `decision`, `change`, `question`). The most recent are embedded in the *recitation* section at the end of the next signal — the position with the highest model attention — so a later stage inherits an earlier stage's hard-won detail instead of rediscovering it.

Memory is deliberately cheap and disposable. It is a working journal, not the deliverable.

### 2. Distill — memories become knowledge

A `knowledge-distill` stage runs at the end of a plan and performs the reduce step: it reads every stage memory, dedupes, and curates the survivors into permanent knowledge. Mistakes are rewritten as actionable prevention rules rather than anecdotes:

```markdown
## [Short description]

**What happened:** ...
**Why:** [root cause]
**Prevention:** [how to detect it earlier]
**Fix:** [what to do instead]
```

Procedural noise ("spawned agents", "ran tests") and anything recoverable from git history is dropped. `loom review` turns the same memories into a human-readable code-review document.

### 3. Retrieve — a tiered base agents can afford to read

Knowledge lives in `doc/loom/knowledge/` and is **tiered**: a generated `INDEX.md` (tier 0) maps the seven curated summary files (tier 1), which link out to per-category topic files (tier 2, e.g. `architecture/merge-flow.md`). Tier-1 files stay navigable summaries; detail lives in topics. The index is regenerated automatically on every knowledge write, and by `loom knowledge index`.

**Reading protocol** — read the index first, then the tier-1 summary for the area you are working in, then only the tier-2 topics you actually touch. Loading the whole base defeats the point of tiering.

**Writing protocol** — when a tier-1 section grows past roughly 40 lines, move its body into a topic with `loom knowledge update <category>/<slug>` and leave a 2-4 line summary plus a relative link behind. Write the link as `[Title](category/slug.md)` in a tier-1 file: that is the one form `loom knowledge audit` accepts for both its orphan check and its broken-link check.

There is **no aggregate line budget** across the knowledge base — `loom knowledge audit` prints the total for information only. The limits that matter are per-file (`--max-file-lines`, default 250) and per-topic (`--max-topic-lines`, default 500), because structure is what degrades retrieval, not size.

### Bootstrapping and maintenance

| Command                    | Role                                                                                            |
| -------------------------- | ----------------------------------------------------------------------------------------------- |
| `loom map [--deep]`        | Static analysis pass — project type, dependencies, entry points, structure — with no agent cost |
| `loom knowledge bootstrap` | Claude-driven exploration that populates the base (runs a deep `loom map` first by default)     |
| `loom knowledge check`     | Coverage of `src/` by the knowledge base                                                        |
| `loom knowledge audit`     | Structural rot: oversized sections, broken links, orphaned topics                               |
| `loom knowledge gc`        | A Claude session that extracts oversized sections into topics and relinks them                  |
| `loom knowledge index`     | Regenerate `INDEX.md` — always the last step after knowledge writes                             |

Knowledge directories created before the hierarchy existed stay **flat** and keep working unchanged — nothing migrates them behind your back. `loom knowledge audit` will advise it, and `loom knowledge index` (structure only) or `loom knowledge gc` performs the opt-in upgrade.

Knowledge writes are protected by the sandbox defaults: agents update knowledge through `loom knowledge ...`, never by editing the files directly.

## Model Allocation

Every stage's main agent is an **orchestrator**, and orchestration is never economized:

| Stage type           | Default model | Default effort |
| -------------------- | ------------- | -------------- |
| `standard`           | `opus`        | `xhigh`        |
| `knowledge`          | `opus`        | `xhigh`        |
| `integration-verify` | `opus`        | `xhigh`        |
| `knowledge-distill`  | `opus`        | `xhigh`        |

The orchestrator decomposes the work, hands each subagent full context, then verifies and commits. It does not implement. Implementation is delegated to as few subagents as the work allows, each spawned **by agent type** so the model choice is explicit:

| Agent                           | Model  | Use for                                                                    |
| ------------------------------- | ------ | -------------------------------------------------------------------------- |
| `loom-software-engineer`        | Sonnet | The common case: implementation to detailed instructions, tests, refactors |
| `loom-senior-software-engineer` | Opus   | Architecture, complex debugging, security-sensitive or cross-cutting work  |
| `loom-code-reviewer`            | Opus   | Read-only code, security, and architecture review                          |
| `loom-advisor`                  | Fable  | Diagnosis after a repeated failure — advice returned, nothing written      |

This is why savings come from delegation rather than downgrade: an untyped subagent silently inherits the stage's Opus model, making every worker expensive. Two failures on the same task should produce a `loom-advisor` diagnosis, not a blind retry at a larger model.

Override per stage with `model` and `reasoning_effort` (`low`, `medium`, `high`, `xhigh`, `max`). `ultracode: true` licenses a stage for large multi-agent fan-out; it is per-stage opt-in so the cost decision stays explicit.

## Sandbox Configuration

Loom supports plan-level defaults plus stage-level overrides.

```yaml
loom:
  version: 1
  sandbox:
    enabled: true
    auto_allow: true
    excluded_commands: ["loom"]
    filesystem:
      deny_read:
        - "~/.ssh/**"
        - "~/.aws/**"
        - "../../**"
        - "../.worktrees/**"
      deny_write:
        - "../../**"
        - "doc/loom/knowledge/**"
      allow_write:
        - "src/**"
    network:
      allowed_domains: ["github.com", "crates.io"]
      additional_domains: []
      allow_local_binding: false
      allow_unix_sockets: []
```

Note: knowledge file writes are intentionally protected by sandbox defaults; knowledge updates should be done via `loom knowledge ...` commands.

### Permission Mode

All stages default to `auto` (agents auto-accept any action their heuristics deem safe, since loom stages run autonomously with no human to answer prompts; the sandbox deny/allow rules are the safety boundary). Override per-plan or per-stage to tighten control:

```yaml
loom:
  version: 1
  sandbox:
    permission_mode: accept-edits # plan-level override

  stages:
    - id: my-stage
      sandbox:
        permission_mode: plan # stage-level override (takes precedence)
```

Valid values: `auto` (default), `accept-edits`, `plan`, `default`. `bypass-permissions` is rejected at init time.

### Remote Control

Claude Code's `--remote-control` flag lets the loom orchestrator drive spawned Claude sessions programmatically. Loom enables it automatically when prerequisites are met — no configuration required.

**Prerequisites (preflight check):**

- **Claude version** ≥ 2.1.51
- **Auth**: claude.ai login — `~/.claude/.credentials.json` must be present and none of these env vars may be set: `ANTHROPIC_API_KEY`, `CLAUDE_CODE_OAUTH_TOKEN`, `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, `CLAUDE_CODE_USE_FOUNDRY`

The flag exits non-zero when its prerequisites are not met, so loom never passes it blindly. When preflight fails, loom falls back silently to standard mode and prints a one-line advisory at orchestrator startup (e.g. `⚠ Remote Control disabled: <reason>`).

**Configuration** — the `[remote_control]` section of `.work/config.toml` carries a single switch:

```toml
# .work/config.toml
[remote_control]
mode = "auto"   # default: enable whenever preflight passes
# mode = "off"  # never enable, regardless of preflight
```

Toggling `mode` takes effect on the next session spawn — no daemon restart needed.

**Mid-run fallback** — if a session crashes within 15 seconds of spawn while Remote Control is active, loom writes a `.work/remote_control-unsupported` marker, then respawns and omits the flag for the rest of the run.

## Agent Teams (Experimental)

Loom enables agent teams in spawned sessions (`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`) and injects team-usage guidance into stage signals.

Use teams when work needs coordination/discussion across agents (multi-dimension review, exploratory analysis). Use subagents for independent, concrete file-level tasks.

## State Layout

```text
project/
├── .work/
│   ├── config.toml
│   ├── stages/
│   ├── sessions/
│   ├── signals/
│   └── handoffs/
├── .worktrees/
├── doc/plans/
└── doc/loom/knowledge/
    ├── INDEX.md            # generated tier-0 map
    ├── architecture.md     # tier-1 summaries
    ├── patterns.md
    ├── ...
    └── architecture/       # tier-2 topics, one directory per category
        └── merge-flow.md
```

## Shell Completions

Loom provides context-aware tab completions for all commands, subcommands, flags, and dynamic values (stage IDs, plan files, session IDs, knowledge files).

### Quick Install

```bash
loom completions --install
```

Auto-detects your shell from `$SHELL` and writes completions to the standard location:

| Shell | Install Path                                      |
| ----- | ------------------------------------------------- |
| Bash  | `~/.local/share/bash-completion/completions/loom` |
| Zsh   | `~/.zfunc/_loom`                                  |
| Fish  | `~/.config/fish/completions/loom.fish`            |

Follow the printed post-install instructions to activate (e.g., for zsh, ensure `fpath=(~/.zfunc $fpath)` appears before `compinit` in `~/.zshrc`).

### Manual Setup

You can also write the completion script to a file yourself:

```bash
# bash
loom completions bash > ~/.local/share/bash-completion/completions/loom

# zsh — ensure ~/.zfunc is in fpath (add before compinit in ~/.zshrc):
#   fpath=(~/.zfunc $fpath)
#   autoload -Uz compinit && compinit
mkdir -p ~/.zfunc
loom completions zsh > ~/.zfunc/_loom

# fish
loom completions fish > ~/.config/fish/completions/loom.fish
```

### Migrating from Older Versions

Older versions of loom used `clap_complete` and required an `eval` line in your shell RC file that ran a subprocess on every shell startup. The new system writes a static script to disk and only calls `loom` at actual tab-completion time, which means faster shell startup and completions that work even before `loom` is in your `PATH`.

To check whether you need to migrate:

```bash
loom completions --migrate
```

This scans for two things:

1. **`eval` lines** in RC files (`.bashrc`, `.zshrc`, etc.) like `eval "$(loom completions zsh)"` — these should be removed
2. **Stale completion files** containing old `clap_complete` markers — these need to be regenerated

If issues are found, follow the printed instructions. Typically: remove the `eval` line from your RC file, then run `loom completions --install` to write the new file-based completion script.

### What's Completed

- Commands and subcommands (`loom stage <TAB>` shows all stage subcommands)
- Flags (`loom run --<TAB>` shows available flags)
- Stage IDs with smart filtering (`loom stage complete <TAB>` shows only executing stages)
- Plan files, session IDs, knowledge files (including aliases like `deps`, `tech`)
- Model names, trigger types, and more

## License

MIT
