The control plane for your coding agents, however you run them.
Agent Harness sits under the Claude Code and Codex you already run, and under whatever rules library you like. It keeps your rules, skills, roles and stances in one checkout, projects them into each agent with your own primitives, enforces them with hooks, and shows you what every session did and what it cost.
git clone --branch stable \
https://github.com/JakeSelby/agent-harness.git ~/repos/agent-harness
cd ~/repos/agent-harness
bin/harness install
# Homebrew packages, VS Code + extensions, Claude Code, Codex, gh, then sync MIT licensed. One checkout, nothing hosted, and harness uninstall puts everything back. Every release names the clients it qualified and what it could not prove.
What it does for you
Guardrails that leave room for judgment
Hooks handle the few things that should be deterministic. Everything else stays the agent's call.
- Graded shell commands Every command is graded from read-only to irreversible, and your autonomy stance decides which grades stop and ask.
- Stop gate The turn doesn't end while your repo's own gate is red.
- Fresh-context review Scope is checked against the ask, then quality, by agents that never saw the code, and a framework's own review spawns are held to that whatever they call themselves.
- Secrets and personal data Lint catches tokens, keys and personal strings before they're committed.
- Untrusted tool output Text that comes back from a tool is data, never instructions.
- Sandboxing Fence the filesystem and network before you leave a loop unattended.
Settings you own, on every runtime you run
Sync keeps a journal of what it changed and refuses to overwrite what it does not own. Uninstall puts it back. The same rules then go to both runtimes.
- Reversible Sync has a dry run, diff shows drift, an ownership journal records prior and applied values, and uninstall restores what it adopted.
- Shared primitives Rules, skills, roles and workflows live in one place and sync into each runtime's native settings.
- Same policy on both A Claude Code spawn and a Codex spawn resolve to the same delegation policy.
- Declared integrations A planning framework declares itself in one descriptor. harness integration check|apply installs its overrides, and the spawn hook confines its review layers.
- Honest compatibility The catalog says which clients are qualified and where the gaps are: two runtimes today, and the headline does not claim more.
- A worktree per agent Parallel agents do not step on your checkout or on each other.
See and steer what your agents spend
A hard cap cuts an agent off after it has already spent the tokens. I'd rather tell it what things cost and let it pace itself.
- Cost postures Pick frugal, balanced or max, or write your own. One table sets model, effort and a soft budget per role.
- Model tiering Roles ask for a capability class, one of frontier, strong, standard and light, not a model name. Gathering files doesn't run on the model that reviews your code.
- Band workers A spawn that names no role gets a right-sized worker instead of your most expensive model.
- A budget in every brief Each subagent is told its expected tokens and tool calls. Finish if you're close, otherwise return what you have.
- Live usage feed The orchestrator sees what each turn and each subagent cost, and hears once when its context passes the size your stance sets. A decision log records what a hook decided.
- Lean context Always-loaded instructions are capped at 200 lines, and lint fails the commit past that. Noisy tool output is filtered before it lands in the transcript.
Answers and plans you can actually read
Most agent output is a wall of text. This puts the verdict first and the ask where you can find it.
- Voice stances Choose answer-card or scannable. Same content, shaped for how you read.
- Scannable output style Verdict first, action items in one place, and status in plain words: Fixed, Partially fixed, Not fixed, Unverified.
- Review Card plans Every plan opens with a one-screen card, rendered in the native plan pane and approved there rather than by a typed reply.
- Bounded subagent returns Subagents come back with findings and a word cap, not their whole transcript.
- Conciseness rules Explain a decision once. Comments say why, not what.
Rules you can measure, and prune
Every project in this field writes instructions and hopes. Here a rule nobody can observe is a rule nobody can prune, and lint says so before the commit lands.
- Detector or reason Every rule names a deterministic detector over the transcript, or says in one line why nothing in a transcript can decide it. Lint fails the commit otherwise.
- Hit rate per rule harness usage --rules reports how often each rule fired, grouped by repository and by the preference variant you had selected at the time.
- Cache prefix held harness usage --by prefix reports each session's cache-miss ratio and names the turn where it jumped. It measures the prefix; nothing denies a change.
- What is detected Seventeen deterministic detectors read the transcript: whole-file reads, unverified pushes, secrets in a write, banned openers, non-conventional commits.
- Caught in the act The instrument has already caught two of this repository's own shipped features doing nothing. Both are filed as issues, not hidden.
- Exports where you already look The same ledger exports over OTLP, off by default, to Langfuse, Phoenix or Opik, adding the one thing they cannot see: which rule fired.
Your preferences, as switches
Reasonable developers disagree about testing, autonomy and how much to delegate. Nine axes, each a named choice: three bind to enforcement today, the rest are prose that swaps cleanly.
- Stance dimensions and variants Autonomy, delegation, testing, cost, voice, commits, planning, licensing and build versus buy.
- User, project, session Set a default, override it for one repo, override that for one session.
- Write your own A new stance dimension is a folder of Markdown files. No fork needed.
- See one switch end to end The demo flips delegation and shows what changes in both runtimes.
- Autonomy stances Execute, confirm-writes or ask. The choice sets which shell-command grade stops and asks; it is enforced, not advised.
- Judgment stays local by default An external judgment provider is off at every decision point until you turn it on, sends only the fields you list, and one file switches every call off.
You choose the behavior
Make preferences explicit and switch them as your work changes.
Switch a policy, keep one source
Compare the delegation variants and inspect their resolved behavior.
Extend what the harness can express
Author your own stance dimensions, skills, roles and workflows.
How it loads
One shared primitive authority, projected through runtime adapters. User defaults, explicit project choices and session overrides have documented precedence.
- Your preferencesExplicit stance selectionsuser → project → session
- Shared primitivesRules · skills · roles · workflowsone authoring authority
- Runtime adaptersNative instructions and controlscapability differences stay visible
- Claude Code · CodexCLI · editor · desktopqualification is per client and platform
Owned configuration is reconciled with your files; conflicts stay visible. Read the sync model before adopting an existing setup.
What you get
The ritual, in 7 keystrokes
Read-only gatherers fan out for one digest; a Review Card stops at the build gate; the build lands in its own worktree and opens the pull request; two fresh contexts review scope then quality; the handoff file is what the next session reads.
A stance switch, in practice
Show one stance switch, end to end
Nine stance axes ship, and three of them bind to enforcement: autonomy decides which
shell-command grade stops and asks, delegation routes a spawn, and cost resolves a class, an
effort and a budget per role. The other six are prose that swaps cleanly in both projections. The
switch demonstrated below is delegation, one of the three.
The demonstration describes deterministic adapter behavior. It is not a native client qualification result; use the catalog for that evidence.
harness config set stances.delegation off
harness stances --json
harness sync
The resolved source is primitives/stances/delegation/off.md. Claude’s selected rule link and
Codex’s generated instructions carry that same policy. With native hooks active, a Claude Agent
event and a Codex spawn_agent event normalize to the same shared spawn policy: ask before the
spawn, so only an explicit user request permits it. tests/test_lifecycle.py exercises both native
envelopes.
harness config set stances.delegation tiered
harness stances --json
harness sync
Both projections now carry primitives/stances/delegation/tiered.md: bounded gathering is allowed;
judgment stays with the session. Each shared role names a capability class and each adapter’s
tiers table maps the classes to its own native models, so neither adapter interprets the
other’s names. Both map all four. A class an adapter leaves out resolves upward or inherits the
session model, and a role_bindings override of model to inherit does the same per role.
For communication, switch stances.voice from answer-card to scannable: the resolved text
changes from the answer/why/catch contract to verdict-first sections and explicit status labels.
The same source drives both projections, but only native behavioral tests can measure compliance.
Author a switch of your own
Create stances/feedback/direct.md and stances/feedback/gentle.md in an external primitive root:
# Feedback stance: direct
Lead with the conclusion. Name the evidence and the next useful action.
# Feedback stance: gentle
Explain the observation first, then suggest one concrete next action.
Register the absolute root in primitive_roots, select stances.feedback=direct, inspect with
harness stances --json, then sync. Switching to gentle changes both projections without a
provider-specific copy. A new prose stance is advisory in both adapters; it does not acquire
new enforced controls by its name. The authoring contract covers project
and session precedence, invalid selections, duplicate authorities and conflict constraints.
The CLI
Show every subcommand
- install
- full setup on a fresh machine, then sync
- sync
- project shared primitives into selected runtimes and merge owned settings
- catalog
- emit the shared primitive catalog as JSON
- generate
- regenerate native source projections from shared primitives
- stances
- show resolved personal stance switches and their behavior
- decide
- ask the selected decision provider about one action class
- diff
- report drift between checkout, last sync and live files
- doctor
- versions, logins, links, drift
- uninstall
- remove links and owned settings, restore adopted files
- lint
- scan for personal-data shapes, lint terms, secret patterns, and the context cap
- usage
- summarize recorded session tokens and cache hit rate
- keychain
- give a disposable HOME its own default keychain before a client is launched under it (macOS)
- trust
- let the stop-gate hook run a repository's `## Gate` block (default: the current repo)
- workspace
- create a multi-root workspace with a shared session store
- worktree
- create and manage task checkouts under a dedicated root
- remote-control
- keep a Claude Code Remote Control server running per configured folder (macOS)
- init
- write the config file by answering questions
- config
- read or write one config value, e.g. `config get identity.name`
- import
- read an existing CLAUDE.md, AGENTS.md or .cursorrules into
- integrations
- inspect or register interchangeable implementation adapters
- viewer
- invoke the selected viewer; existing sessions retain their adapter
- integration
- check or apply a declared framework integration's override templates in a repository (default: the current repo)
- bmad
- alias for `harness integration check|apply bmad`
- compatibility
- show versioned native qualification and adapter gaps
- freeze
- show runtime source drift from the frozen release commit
- task
- save or inspect a shared task continuation contract
- role
- run a constrained shared role in an isolated CLI worker, or inspect worker status
- decisions
- evaluate a decision provider against the recorded decision log
- tiers
- check the adapters' class-to-model tables against their providers' model catalogs
It keeps itself honest
CLAUDE.md plus the rules plus the longest variant of every stance may never exceed the cap. harness lint fails the commit if they do.
harness diff shows anything that drifted.
~/.config/agent-harness/config.json; lint checks source for personal-data shapes and secrets.
Known limits
Claude Code Auto Mode depends on native runtime and provider access; model unavailability is a visible limitation, not a passing qualification result.
Direct native Codex role defaults can inherit parent permissions; constrained harness roles use isolated CLI workers instead.
Planner publication is mediated by the harness after constrained workers return result data.
The architecture-viewer integration is a preview for a separately installed implementation. A local protocol 1 candidate passed process-level harness acceptance; no viewer is bundled, and native viewer interaction and distribution/license clearance remain unverified.
The usage feed is a Claude Code capability: Codex raises none of UserPromptSubmit, SubagentStart or SubagentStop, so turn spend, the fresh-session nudge, in-flight width and finished-subagent spend are not fed back there and no such event is registered.
Cursor and Grok integration, hosted agents and native memory merging are planned or deferred.
BMad review confinement is requested in the routed layer text rather than enforced at the spawn hook: a client can run a review layer as an unnamed native subagent, unconfined, and still report a result. Observed on Claude Code; a confined run writes isolated-worker state. Tracked in #291.
On Codex, output-filter rewrites are never applied: a rewrite travels only with an allow, and the filtered commands are not auto-allowed. Tracked in #292.
Under Codex auto permissions an isolated role worker launched from inside a sandboxed turn has no network access and stalls until its deadline; it completes under an acknowledged bypass. Tracked in #293.
harness sync links user-level stance selections only; a HARNESS_STANCE_ variable or a project selection changes what harness stances and the hooks resolve, not the linked stance text. Tracked in #276 and #294.
The 0.11.1 spawn guards refuse a constrained role's brief re-issued verbatim under another name, or carrying a `harness-role:` line; a client that paraphrases the brief and names no role is not caught, so BMad review confinement still depends on the client following the routed instructions. Tracked in #291 and #300.
No third-party framework's own workflow is exercised natively in a release qualification round. Framework layering is qualified through a synthetic recipe driven at the spawn hook; that a given framework's workflow completes on a given client is not claimed by a release. The BMad Method integration is exercised by an optional suite whose last result is recorded separately, at the harness version, framework version and client stated there.
Constrained-role confinement is enforced at the spawn hook only for a framework a declared descriptor covers. From 0.13.0 the hook classifies a spawn against the descriptors in policy/integrations/, so a covered recipe layer is refused whatever the client named it, and the two entries above describe 0.11.1 through 0.12.0 and stop applying at that release. What remains: recognition needs one of the framework's own layer names as the spawn type, or two sentences of its prompt text, or one of those sentences beside a path out of its routed text, so a brief rewritten with none of that, or a framework or a release no descriptor covers, still runs as an unnamed native subagent, unconfined, and can still report a result. Observed on the Claude Code CLI on Linux, where one confined run required five attempts; a confined run writes isolated-worker state. In the 0.13.0 and 0.13.1 qualification rounds a brief the client wrote in its own words kept the layer's prompt file, the layer's agent name and the framework's name, quoted none of the descriptor's phrases, and was not refused; step 9 of the qualification procedure records that as the observed limit. Tracked in #291 and #739.
Codex CLI is not in the 0.13.0 or 0.13.1 stable contract: FR-12 admits it only once a scripted qualification round agrees with a hand-driven one, and the acceptance runner cannot drive Codex until #612; codex-cli-macos carries hand evidence only (#700).
gate-invalidation, in the 0.13.0 and 0.13.1 qualifications of both Claude Code CLI targets, delivered its Stop events to the harness coordinator directly, not through client turns: no client turn ran the trusted gate's pass, reuse, rerun or block-then-release loop. The only Stop event observed from a client turn is hook-composition's untrusted skip.
No Codex client ran in the 0.13.0 and 0.13.1 qualifications of the two Claude Code CLI targets. The Claude to Codex continuation was not observed, because a Claude session read a Claude save, and the Codex to Claude record was written by `harness task save --runtime codex`; step 7's re-established permissions were observed in neither direction. The Codex targets are not required for this release, so no round covers these.
In the 0.13.0 and 0.13.1 qualifications the eleven scripted cases other than permission-controls were judged only by the case driver and the assessment of its observation text; the hand comparison owed on each case's first live round (0.13.0's) was not made and is still owed. Tracked in #741.
In the 0.13.0 and 0.13.1 qualifications a band worker's effort was read from the installed worker definition, not from the subagent's transcript; its model, the budget sentence in its brief, the usage feed and the usage row were observed from the run.
With a token-only login (`CLAUDE_CODE_OAUTH_TOKEN`, as in CI and containers, including the Linux target image), an isolated role worker that a Claude Code session launches cannot authenticate: the client strips the token from its tool subprocesses, and the worker reports that it is not logged in. A client whose confined layers cannot run may then do their work in its own context, unconfined, as the 0.13.0 BMad integration suite observed. Qualification rounds launch their workers from the runner rather than from a client session, so they do not exercise this path. Tracked in #759.
In the 0.13.0 and 0.13.1 qualifications cost-posture compared each role the cost variant does not change by its content, byte for byte, rather than by its link, so a role replaced by an identical copy would also pass; step 8 asks that every other role keeps its link. Tracked in #742.
The compatibility catalog identifies qualified clients and capability gaps.
This page is generated from the v0.13.1 tag of the repository. Every count, description and CLI line above is read from the checkout at build time.
On the way
Planned, not promised.
- Grok and Cursor adapters Six runtimes at equal depth is the target, after the measurement loop closes. Cursor and Grok are the next two.
- Close the loop Jev becomes the controller between measured rules and autonomy: detector generation from rule prose, stance drift, adaptive cost.