systemctlfor your agents.
Harness is a client-server TUI for supervising, attaching to, and hopping
between long-running coding agents — Claude Code, Crush, Codex, and the other
agents agent-trace can read — built
in Go on the Charmbracelet ecosystem. The
successor to zsh-harnessd.
Harness is bound to agent-trace: every run is recorded as the agent's normalized trace, so it supervises only agents agent-trace supports. It is not a general process manager. Run arbitrary processes under your init system (systemd, launchd).
A single harness binary has two faces:
harness daemon— long-lived supervisor. Owns every harness: the process, its PTY, daemon-side scrollback, restart policy, and state. A stream-json one-shot (claude -p) runs on pipes instead of a PTY, and its output is kept per run as JSON lines.harness— thin client. Open the keyboard-driven dashboard with no arguments, or run one-shot verbs (list,start,logs, ...) to script it. Locally over a Unix socket, or remotely over SSH (Wish).
Think tmux + systemctl + an agent-ops dashboard in one Go binary.
Documentation: https://stump-wtf.github.io/harness/
- Getting started — the 0-to-1 path: install, run the daemon as a service, supervise your first agent, scheduled sweeps, push events with MCP channels, observability, and how Harness fits with Switchboard and Cairn.
- Usage — the reference: every verb, config key, and flag.
The site also publishes this project's architecture decisions and
specifications. Source for the docs lives in docs/ and docs-site/ in this
repo.
brew install stump-wtf/tap/harnessInstalling by the fully qualified name is a one-liner and the only form that
works out of the box: since Homebrew 6.0.0
non-official taps require explicit trust, and a fully qualified name trusts just
that one formula rather than the tap and everything it may ever contain. The old
brew tap stump-wtf/tap + brew install harness form now fails because the
short name needs the tap loaded and the tap is untrusted.
That installs the latest tagged release. To build unreleased work from main
instead, add --HEAD:
brew install --HEAD stump-wtf/tap/harnessRequires Go 1.26+ (older Go toolchains download it automatically).
git clone https://github.com/stump-wtf/harness.git
cd harness
go install ./cmd/harnessharness daemon # run the supervisor (or run it as a service)
harness # open the TUI dashboard
harness list # see every harness and its state
harness attach foo # attach to harness "foo" as a live terminalDefine what to supervise in ~/.config/harness/harness.toml:
[harness.crush]
harness = "crush"
workdir = "~/src/my-project"
enabled = trueharness is required and names the kind. crush, claude-code, codex,
pi and omp are agent CLIs with adapters of their own, and agent-trace reads
the sessions of every one of them. agent-trace also reads OpenCode, which has
no kind here yet. command runs any
other program, with no shell: its argv array is the whole process, so each
element reaches the program as one byte-identical argument. A command
harness that hand-builds an agent's argv can set transcripts to that agent's
kind to be observed as it.
The generic kind, which ran an arbitrary sh command, is deprecated and is
being removed (ADR-0033); a harness must be an agent agent-trace can read.
command is what replaces it for a program that is not an agent —
harness.toml.example has the details, including why a command harness has
no args, and how it runs on a schedule or triggers with its argv
templated over the run.
Then harness doctor verifies config, daemon, and state. The full config
reference and every verb are in the docs above.
To run someone else's agent instead of writing one, install it from a stable, a git repository of agent packages:
harness stable add stump-wtf https://github.com/stump-wtf/harness-stable.git
harness agent install stump-wtf/pr-reviewerInstall pins the package at an exact commit, scans it, and asks before it
writes a [harness.pr-reviewer] table. You add the schedule and the workdir.
See Install shared agents from a stable.
Alpha — and self-hosting. Harness supervises real work daily; the latest
version is on the releases page.
Everything in the docs is implemented and exercised on main, but the TOML
schema and daemon protocol can still change before v1.
Development happens on a private Gitea instance, which is the origin of truth; github.com/stump-wtf/harness is its public copy, updated on every push.
- Found a bug or want something?
Open a GitHub issue.
Issues there are read and triaged onto the canonical tracker. The bug form
asks for what we need to reproduce it:
harness --version, how you installed it, your OS and agent CLI, the relevantharness.tomltable, andharness doctoroutput. - Have a fix? Open an issue describing it and link your branch or fork. Pull requests can't be merged on GitHub, because each sync from the canonical repository overwrites it, so a maintainer carries the change across and credits you.
- Security issue? Don't open a public issue; see SECURITY.md.
make check # fmt + vet + test + race + fuzz (the CI gate)
make test # go test ./...
make lint # fmt + vet
make fuzz # fuzz targets for FUZZTIME each (default 30s)