Ship harnesses
2 min read
Ship harnesses
Ship is the control plane, not the agent. The loop that edits the tree sits behind one interface, and a run's harness is recorded in its input at enqueue:
SHIP_HARNESS=native # default: Ship's own loop — no binary needed, air-gapped
SHIP_HARNESS=claude-code # `claude -p`, headless, inside the sandbox
SHIP_HARNESS=opencode # `opencode run`, headless, inside the sandbox
SHIP_HARNESS_ATTEMPTS=native,claude-code # every harness tries; the critic picksPer repo, the harness is the harness field on the Projects page.
Declaring and installing are separate acts
The harness binary is baked into the sandbox image:
images/build.sh --harness claude-code go # pinned in images/versions.jsonNever installed per run. A run-time install would need the sandbox egress that default-deny exists to close, and would let the binary drift under a running worker — a run replays only under the harness version its log recorded.
What Ship owns regardless
Whichever harness runs, intake, approvals, the publish gate, the evidence legs, spend and audit are Ship's. A harness fed by a subscription is counted as an unpriced run rather than shown as $0. The native loop stays the default and the measured baseline.
The CLI contracts, forwarded credentials and cost-honesty rules for each
adapter are in docs/adapters.md in the repository.