The Agent Harness is the local feedback loop for coding agents. It watches what your agent edits, runs shipmoor scan against those edits, and routes the findings back into the agent’s context so the agent fixes its own mistakes during the session, not after a human catches them in review.
Where Agent Skills tell an agent how to behave, the harness is the runtime that drives the loop mechanically: lifecycle hooks, wrappers, and watchers that fire on every edit whether or not the agent remembered its instructions. It ships inside the shipmoor binary and is invoked as shipmoor harness <cmd>, bundled since 0.5.0, the same way shipmoor skills is. The harness is generally available (it ran as a preview through the 0.4.x line and is now stable).
The mental model
Shipmoor keeps four roles cleanly separated, and the harness sits squarely on the runtime side:
- CLI: source of truth.
shipmoor scan,shipmoor capabilities --json, andshipmoor whoami --jsonown detection, auth, and entitlement state. - Harness: runtime. Hooks, wrappers, and watchers that invoke the CLI against agent edits and feed findings back. It contains no detection logic; it is a client of the CLI’s JSON contracts.
- Skill: behavior. Static, agent-readable instructions the agent follows (Agent Skills).
- IDE: visualization. The same CLI-backed state, rendered in your editor (IDE Extension).
The harness and skills install side by side. Each writes its own marker-wrapped managed block, and neither ever touches the other’s bytes: the skill tells the agent to scan; the harness makes sure it happens.
How it works
Two small pieces do the work:
- The scanner is the only CLI-aware module. It locates the binary on
PATH, then falls back to~/.shipmoor/bin/shipmoor(SHIPMOOR_BINoverrides both), checks the version, runsscan --changed|--staged|--diff|--patch --json, and parses the stablescan.v1JSON contract. Human output is never scraped. - The orchestrator folds a scan result into a decision: a mode (
observe/feedback/block) plus deterministic, severity-ordered feedback text formatted from the parsed findings.
Per-agent adapters then deliver that decision the way each agent natively understands: a Claude Code hook response, a Cursor hook (followup_message), an Aider lint failure, or a Codex re-prompt. See Agent support, and the worked setups for Claude Code and Cursor.
Exit-code posture
The harness reads the CLI’s exit codes the way you should. Exit 1 means findings met the gate, a signal it parses normally, not an error. Only 2 (usage) and 3 (scan failed) are treated as errors, and a missing or failing CLI degrades to a no-op. The result: your agent is never broken by a tooling problem. Worst case, the loop quietly does nothing that session.
The command surface
Every subcommand takes --dir DIR (the project root; default .).
| Command | Purpose |
|---|---|
status [--json] | CLI / capabilities / mode / adapters / watch / entitlement state |
mode observe|feedback|block | How intrusive the loop is |
install <agent> / uninstall <agent> | Wire the loop into Claude Code, Aider, Codex, or Cursor (or all) |
scan | One-shot: scan the current change-set, record the report, and exit. The primitive a hook calls. |
watch [--emit json|file] | Debounced scan-on-change with a privacy-safe event stream |
codex -- <args> | Run Codex wrapped in the feedback loop |
inbox | Drain editor “send finding to agent” payloads into the repair loop |
hook <agent> <event> | The Claude Code / Cursor hook handlers (payload on stdin) |
The standalone
shipmoor-harnessscript is a recognized legacy alias for from-source installs; on a released binary use the bundledshipmoor harness <cmd>form everywhere.
Entitlement
The harness is gated by the agent_harness entitlement (IC plan), enforced once at install in the install plumbing. The per-agent adapters never read account state; they only deliver decisions the CLI already produced. Without the entitlement, install prints an upgrade message instead of wiring anything in.
Next
- Install & modes: wiring it in and choosing observe / feedback / block.
- With Claude Code: the native hook setup.
- With Cursor: native hooks and the soft fallback.
- The self-correction loop: a real catch → fix → clear cycle.