# OpenHarness: every coding agent, every machine, one tmux window

> OpenHarness runs a daemon per machine, gives every agent CLI its own tmux pane, and moves terminal text between a laptop, a home server and a GPU box over a sealed channel. It streams bytes rather than pixels, and it never wraps the agent it is running.

**autonomous-ai/openharness** — The ultimate harness for coding agents and beyond. All your agents. All your machines. One command center. Start with code, then follow your curiosity and build across disciplines: CAD, circuits, robots, games and music.

- Repository: https://github.com/autonomous-ai/openharness
- Website: https://www.autonomous.ai/harness
- Stars: 1,037 · Forks: 88
- Language: Dart
- License: MIT
- Published: 2026-09-30 · Updated: 2026-09-30 · Language: en
- Canonical page: https://hysenlabs.com/projects/autonomous-ai-openharness

## Every agent CLI gets a pane and a worktree of its own

The demo shows four agents working at once in one window, each pane labelled with its machine, project and branch. The supported set reads like a roll call of coding CLIs: Claude Code, Codex, Cursor, OpenCode, Devin, Amp and Copilot, plus seven more. The rule underneath is that an agent runs untouched. Harness never wraps a CLI; it reads transcripts and uses each vendor's own hooks, so what you get in the pane is the vendor's own interface.

Two consequences follow. A worktree per harness means an agent can be started on its own branch while your working copy stays clean. And because panes are driven by keys rather than mouse hunting, the Command-O shortcut opens any session on any machine, Shift-Command-I jumps to the agent waiting on you, and Command-D splits. Every binding lives in one JSONC file, reloaded on save, with chords up to four strokes. Local weights are a first-class option too, through Grid, Ollama, MLX-LM and vLLM.

## One daemon per machine, dialing out rather than listening

The architecture diagram is small enough to read in one glance. On the laptop the app talks to its own daemon over loopback, and that daemon owns tmux panes running Claude Code and Codex. On the GPU box a second daemon owns a separate set of panes, shown holding OpenCode and Hermes. A Harness device reaches the laptop's daemon over USB. The dashed line between the two daemons is a direct WebRTC path; the solid lines down to the relay carry ciphertext.

The detail that shapes everything else is direction. The daemon initiates, so no machine opens a listening port, which is why linking needs nothing more than a password: no SSH keys, no Tailscale, no port forwarding. Because the panes live in tmux under the daemon rather than under the window, closing the app leaves the agents working, and scrollback, colours and key handling stay tmux's own. docs/architecture.md holds the rest of the detail.

## Direct WebRTC, Cloudflare TURN, and a relay with no keys

Three paths, one sealing scheme. The direct path is a WebRTC channel between two of your machines with no server in it. When a firewall blocks that, the same encrypted channel runs over Cloudflare's TURN network, and the client keeps retrying for a direct path rather than settling for the slower one. A relay of the project's own is the third option, held back as a fallback while WebRTC negotiates, carrying the session over a WebSocket.

Sealing is identical on all three: ChaCha20-Poly1305 for the bytes, X25519 session keys, pinned Ed25519 identities. The relay holds no keys, so it forwards bytes it cannot read. The encryption demo makes the claim checkable: on one side an agent rotates a secret and redeploys, and on the other the relay's view is numbered frames of ciphertext. Workloads, slow tails and connection failures for each route are written up in docs/performance/2026-09-23-transport-routes.md, which is the file to read before trusting the direct path through your own firewall.

## Linking a second machine with four commands

Grab the app for macOS or Linux first. To bring another machine in, you run four commands on it and then pick Machines and Link Machine in the app:

```bash
curl -fsSL https://harness.autonomous.ai/cli/install.sh | bash
harness login
harness remote-password set
harness start
```

The install line fetches the CLI from harness.autonomous.ai. `harness login` authenticates the machine, `harness remote-password set` chooses the password the app will link it with, and `harness start` brings the daemon up. The daemon then dials out to the app; there is no port to forward and no key to copy.

If you would rather stay in a terminal, the same line also installs `hn`, which keeps tmux's own keys and your `~/.tmux.conf` while listing every harness on every machine. Its first run signs in and connects the computer:

```bash
curl -fsSL https://harness.autonomous.ai/cli/install.sh | bash
hn
```

Building from source wants Node.js 20+, tmux, Xcode and Flutter 3.47+ with Dart 3.13+:

```bash
git clone https://github.com/autonomous-ai/openharness.git
cd openharness
(cd cli && npm ci)
make install-cli
cd desktop
flutter config --enable-swift-package-manager
flutter pub get
flutter run -d macos
```

`make install-cli` installs this checkout's CLI and restarts the local daemon, which is what lets a patched build take over the panes. The development guide at docs/development.md covers the rest of the workflow.

## Idle latency on an M2 Max, and what the 304 MiB leaves out

The idle figures are published with their conditions attached, which is more than most projects bother to do. On an M2 Max, the Command-N, Command-O and Command-T UI paths run at 11 to 13 ms median and 15 to 18 ms at p95. Local terminal echo sits at 1.1 ms median and 7.2 ms p95 with UI rendering excluded. Desktop resources come to about 0.1 percent of one CPU core and 304 MiB.

Two caveats are printed next to those numbers. The memory figure covers terminal rendering and scrollback but excludes the agent CLIs and the daemon, so the true cost of a box running eight agents is higher than 304 MiB. And the fixture is fixed: a Release build with 16 terminals and 1,000 scrollback lines each, not a full day of work. The app being native rather than Electron is the plausible reason the numbers look like this at all. Workloads and slow tails live in docs/performance/2026-09-23-core-experiences.md.

## Against tmux over SSH, and against a remote desktop

The honest baseline is tmux plus a few scripts of your own, and this project knows it. tmux alone gives you panes, scrollback and a session that survives your terminal closing, on one machine. Reaching a second machine means SSH in, or an SSH tunnel, or port forwarding, and the panes stay in separate terminals unless you build the glue yourself. `hn` sits close to that baseline for people who never open the window: tmux keys, your own config, every harness listed.

The other baseline is a remote desktop, and here the difference is a stated refusal. The project's line is bytes, not pixels: remote terminals stream text peer to peer, so nothing in the transport depends on a framebuffer. That choice has a price. Anything graphical inside a session, a mouse-driven TUI or a browser preview, does not survive a text-only stream. Vendor CLIs in separate terminal windows are the third option, and the worktree-per-harness rule exists precisely to make running several of them less messy than a row of windows.

## Transcript parsing and vendor hooks are the load-bearing part

This is where the design is exposed. The rule that an agent is never wrapped sounds like restraint, but it means OpenHarness sits outside each CLI, reading transcripts and calling whatever hooks the vendor exposes. It therefore inherits two things it does not control: the shape of each agent's output, and the stability of each agent's hook points. A vendor that changes either breaks pane features for everyone running that agent, and the README does not document a degraded mode for an agent whose hooks are missing.

Platform coverage is narrow by choice. The download covers macOS and Linux, and the source build asks for Xcode, so there is no Windows path in anything documented. tmux is a hard requirement on every linked machine, since owning panes is the daemon's whole job. And the relay is framed as a fallback while WebRTC negotiates, so on a network where negotiation never finishes, the direct path never arrives and latency becomes whatever the relay costs. If you run one agent on one box, all of this buys you nothing.

## Per-component release tags, an MIT licence, and a 2026-09-28 push

Versions here do not move as one number. The Makefile tags per component. `release-cli` tags this commit vX.Y.Z_cli and pushes it, after which CI bundles the CLI, publishes it to GCS and cuts the GitHub Release. The published version comes from the larger of the last git tag and the live metadata.json cli key; the `_cli` suffix is only a tag-trigger marker and never appears in the published version. `release-backend` tags vX.Y.Z_backend and CI builds the backend's Docker image and rolls it out, with ARGS=minor|major|X.Y.Z choosing the bump. `release-desktop` tags vX.Y.Z_desktop and builds both macOS builds and both Linux architectures. Extra arguments pass through ARGS, so `make install-cli ARGS="--no-restart"` and `make release-cli ARGS="--dry-run"` both work. The test target is one line:

```bash
cd cli && npx tsc --noEmit && npx vitest run
```

The licence field reads MIT, and the scope is stated plainly: the app, CLI, daemon, relay and device are all in this repository. Two things to weigh. A deploy means running a Docker image of the backend built by backend/scripts/release-be.sh, and the hosting question is left open. The top level also carries artifacts/, output/, work/, HANDOFF.md and claude_research.md next to the source directories, an in-flight repository layout rather than a curated one. The project is not archived, and its last push was on 2026-09-28, with three web releases, v1.3.1_web, v1.3.2_web and v1.3.3_web, cut on that same day.

## Conclusion

Adopt OpenHarness when you already run several agent CLIs across a laptop, a home server and a GPU box and have grown tired of SSH windows; it swaps those for tmux panes and a sealed peer-to-peer stream. Leave it alone if one agent on one machine is your workflow, if you need Windows, or if you cannot accept that it reads vendor transcripts and hooks. Check docs/architecture.md and docs/performance/2026-09-23-transport-routes.md first, and link one machine with `harness remote-password set` before you migrate anything.

## FAQ

### What does OpenHarness add that plain tmux does not?

tmux gives you panes and scrollback on one machine. OpenHarness puts a daemon on every machine, has it dial out instead of opening a port, and streams terminal text between machines over a channel sealed with ChaCha20-Poly1305 and X25519 keys, using a direct WebRTC path, Cloudflare TURN, or its own keyless relay.

### How do I install OpenHarness and link a second machine?

Download the app for macOS or Linux, then run the install script on the machine you want to add, followed by `harness login`, `harness remote-password set` and `harness start`. Finish with Machines and Link Machine in the app. The same install line also gives you `hn` for a terminal-only workflow.

### Does OpenHarness ever open a port or need SSH keys?

No. One daemon per machine runs the agents in tmux and dials out, so no machine opens a listening port, and each machine is linked with a password instead of SSH keys, Tailscale or port forwarding.

### Can the OpenHarness relay read my code or my keystrokes?

The project states the relay holds no keys and forwards ciphertext, with ChaCha20-Poly1305, X25519 session keys and pinned Ed25519 identities sealing all three paths, whether traffic goes direct, through Cloudflare TURN or through the relay.

### What does OpenHarness need in order to build from source?

Node.js 20+, tmux, Xcode and Flutter 3.47+ with Dart 3.13+. After running `npm ci` in the cli directory, `make install-cli` installs that checkout's CLI and restarts the local daemon, and `flutter run -d macos` starts the desktop app.

### Does OpenHarness work with local models?

Yes. It names Grid, Ollama, MLX-LM and vLLM for running open-weight models on your own machines, and because it never wraps an agent CLI, the model server stays your choice.

## Sources

- [autonomous-ai/openharness on GitHub](https://github.com/autonomous-ai/openharness)
- [License: MIT](https://github.com/autonomous-ai/openharness/blob/main/LICENSE)
- [Project website](https://www.autonomous.ai/harness)
- [README](https://github.com/autonomous-ai/openharness/blob/main/README.md)
- [Releases](https://github.com/autonomous-ai/openharness/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/autonomous-ai-openharness
