All docs

Harnesses

Harness matrix

Which harnesses the crew runs on, and what's coming next.

The installer builds payloads for seven harnesses. Only one has been run for real — the rest are format-verified against each harness's own parsing source and first-party docs, but not exercised against a running harness.

The matrix

HarnessStatusTracking epic
claude-codeRuntime-verified
opencodeBuilds, not runtime-verified#31, #32
antigravityBuilds, not runtime-verified
github-copilotBuilds, not runtime-verifiedQuickstart
codexBuilds, not runtime-verified#46, #47
cursorBuilds (skills only)
windsurfBuilds (skills only)

Runtime-verified means the payload is compiled from neutral canonical sources, byte-compared against its committed reference digest, and the harness is one Shipmates has actually been run on. Only claude-code meets all of that.

Builds, not runtime-verified is every other harness. shipmates install --harness <name> produces the payload, and each format was verified against the harness's own parsing source and first-party docs. None has been exercised against a running harness — whether agents resolve, whether argument passing behaves, and whether /ship-issue completes end to end are open questions, tracked for opencode in #31 and #32. Nothing on this site should be read as “tested on <harness>” until those close.

GitHub Copilot has a dedicated quickstart with its payload checks, safe smoke-test command, and the current /ship-issue Tier B boundary.

Builds (skills only) marks harnesses where the crew has nowhere to go and only the thirteen skills land. That is now cursor and windsurf, and for two different reasons. cursor is unconfirmed rather than absent: .cursor/agents/*.md is widely reported and Cursor describes delegating to named subagents, but no first-party page documents the frontmatter schema, so emitting one would be guesswork. windsurf is under review — Windsurf became Devin Desktop in June 2026 and that target may no longer address a live product. Each harness now carries its evidence and the date it was checked in tools/harness_matrix.json.

Why only one runtime-verified?

Building a payload is the easy half — the format is documented and the CLI validates each target's output against a committed reference digest on every build. Verifying it works means installing into a running harness and exercising /ship-issue end to end: subagents resolve, argument passing behaves, worktrees, CI gates, the review board. That is real work per harness, and it hasn't been done yet for any of the six.

Until it has, treat every non-Claude payload as format-correct-but-unproven. The tracking for the harnesses we plan to exercise first lives in the issue list; opencode's is #31 and #32.

How opencode cleared the guard

opencode has no disable-model-invocation equivalent either. It cleared the guard a different way — by using a directory where the property holds structurally.

The thirteen install as commands, not skills. opencode has both, and they are different things. Its skills are model-invoked: the model loads one on demand through a native skill tool, and disable-model-invocation is not among the frontmatter keys a SKILL.md recognises there — declaring it would be silently dropped rather than rejected. So the thirteen go to .opencode/commands/<name>.md, which is /-invoked only. The captain still decides when a run starts, and that now rests on the directory rather than on a key the target ignores.

Least privilege survived, by inversion. Claude Code's permission model is an allowlist, so naming the tools a role needs is enough. opencode's defaults are permissive — effectively "*": "allow" — so an allow list alone would restrict nothing. Every generated opencode agent instead writes a "*": deny catch-all first and its specific allows after; opencode resolves permissions last-match-wins, so that ordering is what makes it hold. The result is marginally stronger than the Claude posture: a tool a wildcard denies is hidden from the model entirely rather than refused when it is called.

Role-level refinements survive the translation too. art-director declares web-scopes: search once in the canonical sources, and gets WebSearch without WebFetch on Claude Code, and websearch: allow without webfetch on opencode.

opencode receives subagents at .opencode/agents/<name>.md, each with mode: subagent. Four other harnesses also take the full crew: antigravity (.agents/agents/<name>.md), codex (.codex/agents/<name>.toml — the one target whose agent format is TOML rather than Markdown), github-copilot (.github/agents/<name>.agent.md, note the double extension), and Claude Code itself.

One caveat on Codex, worth knowing before you install it. Every other crew-bearing harness restricts each specialist to the tools its role declares — the architect reviews and cannot edit, the art-director can search the web but not fetch. Codex documents no per-agent tool allowlist, so there is nothing for the adapter to write: its twelve subagents inherit whatever the session itself can do. That is a real gap, not an oversight — emitting an invented tools key would be ignored at best and rejected at worst, and claiming a boundary we do not enforce would be worse than saying plainly that we cannot. If per-agent least privilege matters to you, prefer a harness that supports it.

Codex quickstart

Validate compiled payload and install layout; optionally run one safe headless skill.

# Run from a Shipmates checkout
SANDBOX="$(mktemp -d)"
trap 'rm -rf "$SANDBOX"' EXIT
printf '# Codex smoke sandbox\n' > "$SANDBOX/README.md"
printf '# Project instructions\n' > "$SANDBOX/AGENTS.md"

CODEX_PROJECT="$SANDBOX" bash tests/test_codex_smoke.sh
# Optional live Codex check; requires authenticated `codex`:
CODEX_PROJECT="$SANDBOX" CODEX_SMOKE=1 bash tests/test_codex_smoke.sh

Codex skills follow the open Agent Skills layout at .agents/skills/<name>/SKILL.md. Named crew are Codex-native TOML files at .codex/agents/<name>.toml. The default smoke is explicitly a golden/layout-install check: it verifies all twelve skills, all twelve TOML agents, the committed Codex digest, and the install diagnosis. It does not invoke Codex.

Fidelity and caveats. Skills use the shared neutral payload, while crew instructions are rendered for Codex. Codex has no documented per-agent tool allowlist, so crew inherit the session's tools. Agent Skills vendor keys such as disable-model-invocation are not emitted. The optional live path invokes the installed harden skill in read-only report mode; that bounded exercise does not make Codex runtime-verified.

Tier C status. The current adapter emits the files above, but the external orchestrator in #13 is not implemented here. Therefore a real issue → reviewed PR with CI polling and a bounded remediation loop has not been demonstrated on Codex; flagship validation remains tracked in #46.

opencode quickstart

Install the native payload, inspect the crew, then try a report-mode order.

shipmates install --harness opencode --dir /path/to/project --with-tools none
cd /path/to/project
ls .opencode/agents .opencode/commands
opencode agent list
opencode run --command shipmates-harden --format json \
  "Review this project in report mode. Do not modify files."

The install places twelve Markdown subagents under .opencode/agents/ and fifteen user-invoked commands under .opencode/commands/. agent list should include all twelve Shipmates roles; the report-only shipmates-harden order is a narrow manual probe of command loading. Keep --auto off.

CI runs deterministic install-fidelity checks without network or model credentials: it builds against the committed opencode golden file, installs from the embedded payload into a temporary directory, checks all twelve crew files and thirteen commands, and verifies the report-only /shipmates-harden rendering. This proves exporter and installer fidelity, not opencode runtime behaviour.

Fidelity caveat. The current status remains Builds, not runtime-verified. These checks do not prove all twelve agents spawn, argument substitution, permission enforcement, parallel acceptance-board subagents, CI polling, or the full /ship-issue workflow. Those remain the explicit follow-up for #31 and #32.

Where a tool lands

A tool is the model-invoked sibling of a command: the crew reach for it implicitly, never by typing a slash. Where a command targets each harness's user-invoked surface, a tool targets its agent-invoked one — grounded, like everything else here, in each harness's own first-party docs.

opencode is the one harness with a genuine tool primitive — a code tool at .opencode/tools/<name>.ts the model calls directly, never a slash command. Everywhere else the closest native fit is a model-invoked Agent Skill. Claude Code can pin one agent-only with user-invocable: false — model-invoked, hidden from the / menu — which is exactly “never a command.” The other five auto-select a skill by its description as intended, but their docs offer no way to hide it from a manual @// mention, so on those a tool is agent-invoked yet still technically typeable. That is recorded here rather than papered over.

Tools ship with a plain install. Use `--with-tools none` for crew-only — see Tools on the install reference.