Multi-agent coordination for AI coding agents — Claude Code, Cursor, and Codex.
⚠️ Pre-1.0. API surface is still settling. Pin a specific minor version (harnery@^0.7.0) and read the CHANGELOG before each upgrade.
harnery keeps multiple AI coding agents from stepping on each other in a shared checkout. It was extracted from years of running several Claude Code / Cursor / Codex sessions at once against the same monorepo:
- Multi-agent coordination: per-agent heartbeats in
.harnery/active/, claim-time and commit-time guards, the canonical event stream, councils, a decision docket, per-agent scratchpads, and harness adapters for Claude Code / Cursor / Codex. - Cross-machine presence: sessions on every machine that shares a repo see each other, labeled by machine. Zero-config over the repo's own git remote (presence refs), with an optional live-socket upgrade via an end-to-end-encrypted relay — the public
relay.harnery.com, or self-host withharn relay serve/ the bundled Cloudflare Worker (relay/worker/). The relay sees only ciphertext in opaquely-named rooms. - Coordination-aware workflows:
harn workflow run <script>executes bounded, schema-gated multi-subagent workflow scripts — plain JS stages fanning out to headless harness-CLI subagents that are born coordination-registered (heartbeats, events, claim guards), with deterministic code deciding the routing between stages. An optional host-owned policy gates dispatch and declared external mutations withALLOW,ASK, andDENY; CLIASKrequests park durably for an explicit approve/deny and same-run resume, while library callers remain fail-closed by default. - Durable work above attempts:
harn workpreserves an objective across bounded workflow attempts, dependencies, approval parks, failures, and review. Its one-shot reconciler derives state from append-only local evidence and reports the next explicit action without silently spawning, retrying, or accepting work. - Standalone web UI:
harn web upboots a local Next.js dashboard for the coord layer, councils, per-project state, and a local coding-agent status view (Claude Code / Codex / Cursor usage, backed byharn devtools). Ships with the git clone, not the npm package (see Install). - Backup + sync:
harn backupsnapshots.harnery/via restic;harn synckeeps a curated subset live across machines via rclone (Google Drive or any rclone remote).
The CLI also ships batteries: portable utility commands (tokens, eml, env, grep — parallel, ripgrep-accelerated monorepo search — docs, browse, fetch, read, devtools, and more) plus the library toolkit they're built from. Useful, cross-platform, dependency-light — and deliberately not the headline. Coordination is why harnery exists; the toolkit exists because the CLI needed it (see Public surface tiers).
curl -fsSL https://harnery.com/install.sh | bashOne line, no clone: it installs the harn CLI globally (npm preferred, Bun fallback), puts it on your PATH, and verifies it. Or drive your package manager directly — npm install -g harnery / bun add -g harnery (or npm install harnery for a project dep). Then wire a project:
harn init # creates .harnery/ + registers the harness hooks
harn doctor # optional: one-time runtime + dependency checkFrom a git clone? Cloning for the
web/dashboard or to contribute?./scripts/setup.shdoes the clone setup in one shot: installs deps, buildsdist/on a Bun-free host, runsharn init, and links the bins onto yourPATH.
npm gives you the engine + CLI. The
web/dashboard and thedocs/site live in the git repo, not the npm package (which is the CLI + coord engine:bin,dist,src,schemas). To run the dashboard,git clonethe repo,bun install, andharn web upfrom there, pointing it at your project with--coord-root <dir>(or just run it from inside the project).harn web upprints these exact steps if you invoke it without the clone present.
Two layers. Unwire a project (keeps .harnery/ history by default; on a terminal it asks before deleting it):
harn deinit # unwire the harness hooks
harn deinit --purge-state # also delete .harnery/ (destructive)Remove the CLI with the hosted one-liner (npm rm -g harnery / bun remove -g harnery work too):
curl -fsSL https://harnery.com/uninstall.sh | bashFrom a git clone, ./scripts/teardown.sh is the mirror of ./scripts/setup.sh: it runs harn deinit, removes the PATH symlinks, and — on a terminal — asks whether to also delete this project's .harnery/ history and the clone itself. Both default to no; pre-answer with --purge-state and --remove-clone for unattended runs.
Project-specific CLIs compose Harnery's command tree and add their own commands on top:
// mycli/src/program.ts
import { createHarneryProgram } from 'harnery/commander';
import { deployCommand, dbCommand } from './commands';
const program = createHarneryProgram({
binName: 'mycli',
context: { projectName: 'my-monorepo' },
});
program.addCommand(deployCommand);
program.addCommand(dbCommand);
await program.parseAsync(process.argv);mycli agents status then resolves to the same code as harn agents status, loaded as a library. See examples/extending-with-commander.ts for the full pattern.
The exports map draws the line between what harnery is and what it ships with:
- Product tier —
harnery,harnery/commander,harnery/core/*: the coordination layer and CLI composition. This is the API to build against, and the reason to install harnery. - Toolkit tier — every
harnery/lib/*subpath (http,cookies,format,readability,browser,machine, …): the supporting utilities harnery's own CLI is built from, exposed for embedding hosts that want to lean on them. Supported, but secondary: it can evolve faster than the product tier, and it isn't a reason to adopt harnery on its own.
The boundary is enforced, not aspirational: CI verifies that no harnery/lib/* export imports the coordination core, directly or transitively (scripts/check-layering.ts), so pulling a toolkit module never drags in coordination state. Details: Embedding + surface tiers.
Full docs at harnery.com:
See CONTRIBUTING.md. Bug reports and feature requests via GitHub Issues.
MIT © Ryan Kelly