Model or dataset
HarnessRouter/harnessrouter avatar
HarnessRouter/harnessrouter

HarnessRouter Community Edition: one API in front of Codex, Claude Code and Hermes

HarnessRouter Community Edition: the self-hosted, Apache-2.0 edition of the unified interface for agent harnesses. Run Codex, Claude Code, Hermes, PI, DSH, and more through one API, with sessions, streaming, files, cancellation, and failure handling. Implements the Unified Harness Protocol (UHP), an open standard. Your keys, your infrastructure.

2,796 stars289 forksPythonApache-2.0

At a glance

What is it?
The Apache-2.0 edition of HarnessRouter packages a Console, a Gateway and a Runner in a single Docker container and speaks the Unified Harness Protocol to several agent harnesses. Its real cost is that harness CLIs are installed on first launch, not baked into the image.
Who is it for?
Adopt HarnessRouter Community Edition if you already run more than one coding agent and want a single OpenAI Responses-compatible surface with sessions, streaming, files and cancellation, and if you are willing to keep the container on loopback until the default credentials are changed.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The N times M integration problem HarnessRouter collapses

If your product runs more than one agent harness, you own a matrix. Each harness has its own CLI, its own session model, its own way of streaming output, and its own failure surface. Adding a second harness means writing a second backend adapter; switching harnesses later means writing a third. The README frames the project as "the world's first unified interface for agent harnesses" and says the goal is to add or switch harnesses "without redesigning your product backend." That is the problem statement, and it is a real one for anyone shipping an agent feature rather than a demo.

The intended audience is a team that self-hosts and brings its own provider keys. The README is explicit that no HarnessRouter account is required for Community Edition and that keys, state and files stay on infrastructure you control. The supported harnesses named in the README are Codex, Claude Code, Hermes, DeepSeek Harness and PI, with the Dockerfile listing a wider default set of backends. This is infrastructure for people building on top of agents, not an agent you use directly.

Console, Gateway and Runner in one container

The architecture is visible in the repository layout: gateway/, runner/, ui/ and protocol/ sit side by side at the top level. The Dockerfile describes one container running the whole product, with the three processes supervised by a small entrypoint, and it gives the reason: the gateway talks to the runner over loopback, so there is no service discovery, no connection pool and no cloud identity to configure. The README calls the packaged pieces the Console, Gateway and Runner.

State is deliberately boring. The Dockerfile says state is SQLite and files on one mounted volume, and the compose file repeats that SQLite databases, blobs and the secret store all live in /data. The protocol/ directory is where the Unified Harness Protocol lives, and the README describes Community Edition as the Apache 2.0 reference implementation of UHP, with a conformance badge in the project header. The interface your product talks to is OpenAI Responses-compatible, and the README lists what it handles: tasks and runs, sessions, streaming, files, artifacts, cancellation, recovery, structured errors and traces.

One design choice is worth flagging. The Dockerfile says the console is the same one the hosted product runs, and that surfaces with no self-hosted backend (billing, marketplace, analytics, sign-in) are hidden by an edition flag rather than removed, so the two stay one codebase. That keeps the editions from drifting apart, but it also means the image you self-host carries UI code paths you will never exercise.

Installing HarnessRouter Community Edition with docker run

The README's quickstart needs Docker, about 4 GB of disk space and an API key from a supported model provider. The first command starts the container, publishes the console on loopback and attaches a named volume.

bash
 docker run -d --name harnessrouter \
  -p 127.0.0.1:3000:3000 \
  -v harnessrouter:/data \
  harnessrouter/harnessrouter

Docker pulls the image if it is not present. The volume keeps the database, files, installed harness CLIs and workspaces across restarts. If port 3000 is taken, the README suggests publishing 3100 instead while keeping the loopback binding, and it warns against adding --user, because the container starts as root to establish per-session users before dropping privileges. The README does not document a rollback path for a failed upgrade, so treat the volume as the thing you back up.

The first launch is slow because the enabled harness CLIs are installed then, not baked in. Follow the logs until the ready line appears.

bash
docker logs -f harnessrouter

You are waiting for the line the README shows as [harnessrouter] ready on :3000. Then open http://localhost:3000 and sign in with the initial local credentials, username harnessrouter and password harnessrouter, and change the password from Profile. Saving that restarts the Console and signs out other browsers. If you set HR_AUTH_USER or HR_AUTH_PASSWORD, those credentials apply instead.

Before any task can run you need a provider. The .env.example defines a connection as one JSON value naming a provider and its credential, and it shows the Anthropic shape for the claude-code backend. Copy .env.example to .env and put your own key in it.

bash
HR_SECRET_GLOBAL_HARNESS_CONN_ANTHROPIC={"name":"anthropic","provider":"anthropic","api_key":"sk-ant-REPLACE_ME"}

A second variable decides which connection a backend uses, for example HR_SECRET_GLOBAL_HARNESS_POLICY_CLAUDE={"chain":["anthropic"]}. The .env.example notes that env is read before disk, so a key exported there is used but not persisted. The README also says connections can be added in the console under Integrations, Add Integration, which is the path most people will take. Once a provider is connected, its models appear in the Console, and you can open Agent harnesses, pick a harness and select New task.

Harness CLIs are installed at first run, and that is a licensing decision

The most consequential thing about this image is not in the quickstart. The Dockerfile states that agent CLIs are installed on first run rather than baked in, and it gives the reason plainly: Claude Code ships under Anthropic's own terms and hermes-agent declares no license at all, so neither may be redistributed inside a public image. Installing at first start means you install them under their terms, as if you had run npm or pip yourself, and the image stays redistributable.

That is a defensible call, and it changes how you operate the container. The install happens once per volume, which the Dockerfile notes explicitly, but it happens on the first start of every fresh volume. In an environment that recreates volumes, that cost recurs. It also means the first launch depends on network access to package sources, so an air-gapped deployment needs a plan the README does not describe. A cold start on a new volume will not be ready in seconds; the README tells you to wait for the ready line rather than assume a fixed delay.

The backend set is chosen at run time. The Dockerfile gives the default as claude,codex,hermes,pi,dsh,opencode,qwen,gemini,cline,omp and shows a lean alternative of opencode alone, both through the HR_BACKENDS environment variable. Narrowing that list is the obvious lever if you want a smaller first-run install, and it is the one place where the image's footprint is under your control rather than the maintainers'.

Where HarnessRouter Community Edition is the wrong tool

If you run exactly one harness, the router is a layer you do not need. You would be adding a container, a volume, a console with its own credentials and an extra network hop between your product and a CLI you could call directly. The value here comes from the second and third harness, not the first.

Docker is a hard requirement. The README's quickstart is a docker run and the compose file assumes the same, so a deployment model that cannot run containers, or a platform where you cannot mount a persistent volume at /data, is out of scope.

There is no bundled model access. The README says there is no bundled model or trial key and that a compatible provider must be connected before a task can run, so the project cannot be evaluated end to end without your own provider credential and whatever that provider charges. The .env.example adds a warning worth reading before you pick a provider: it notes that a Google AI Studio free-tier key's content may be reviewed or used for training, and advises a billing-linked key for anything private.

Finally, the security posture of the default install is temporary by design. The README tells you to keep the instance local until the default password is changed, and the docker run example binds to 127.0.0.1 for that reason. Anyone who publishes port 3000 before rotating credentials is running a known-credential console on the public internet. The README is clear about this; the failure mode is an operator who skips step three.

How this differs from calling a harness CLI yourself

The alternative most teams already have is a thin wrapper: invoke the harness CLI from their own backend, parse its output, and manage sessions in their own database. That approach has no extra moving parts and no new protocol to learn, and for a single harness it is usually the right answer. What it does not give you is a stable contract. When the CLI changes its flags or its output format, your wrapper breaks, and every harness you add multiplies that maintenance.

HarnessRouter's difference is that the contract is a published protocol rather than a CLI. Community Edition is described as the Apache 2.0 reference implementation of the Unified Harness Protocol, and the repository carries a protocol/ directory with a conformance suite. Your product talks to an OpenAI Responses-compatible interface and gets sessions, streaming, files, artifacts, cancellation, recovery, structured errors and traces from the router rather than from each CLI. The trade is a new dependency and a new abstraction in exchange for not owning the adapter matrix.

A second, smaller difference is where the state lives. A hand-rolled wrapper typically keeps session state in your application database. Here it sits in SQLite and files under the /data volume, which the compose file describes as holding the databases, blobs and the secret store. That is convenient and it makes the volume the unit of backup and migration, but it also means your agent session history is not in the same store as the rest of your application data.

Licence, releases and what an upgrade actually costs

Community Edition is Apache-2.0, and the repository carries both a LICENSE and a NOTICE file, which is the normal pairing when a project wants attribution preserved. The licence covers HarnessRouter's own code. It does not cover the harness CLIs the container installs at first run, and the Dockerfile is explicit that at least two of them carry their own terms or none at all. That separation is the reason the install-at-first-run design exists, and it is the thing to check before redistributing an image built from this Dockerfile. This is not legal advice; read the terms of each harness you enable.

On releases, the version tags in the repository are frequent and tightly spaced. Three releases landed on 2026-09-10 alone, v0.15.8, v0.15.9 and v0.15.10, and the last push to the default branch was on 2026-09-10. The project is at 0.x, and a cadence of three patch releases in a day is a signal about how fast the surface is still moving. Pin a version for anything you depend on. The README points to a setup and operations guide for version pinning and Docker Compose, which is where that detail lives rather than in the README itself.

The upgrade cost is mostly the volume. Because the harness CLIs land in /data and the secret store reads env before disk, a container swap keeps your installed backends and your data, while a fresh volume pays the first-run install again. The README does not document rollback, so the practical upgrade procedure is to snapshot the volume before pulling a new tag.

Editorial conclusion

Adopt HarnessRouter Community Edition if you already run more than one coding agent and want a single OpenAI Responses-compatible surface with sessions, streaming, files and cancellation, and if you are willing to keep the container on loopback until the default credentials are changed. Skip it if you need one harness only, if you cannot run Docker, or if you expect a bundled model key, because the README states there is no trial key and an integration must be connected before any task runs. Verify first that your chosen harness is in HR_BACKENDS, that your provider connection JSON names a provider the policy chain expects, and that the first launch reaches the ready line before you point real traffic at it.

Frequently asked questions

What is HarnessRouter Community Edition used for?

It gives a product one OpenAI Responses-compatible interface for running supported agent harnesses such as Codex, Claude Code, Hermes and DeepSeek Harness, handling tasks and runs, sessions, streaming, files, artifacts, cancellation, recovery, structured errors and traces. The README describes it as the Apache 2.0 reference implementation of the Unified Harness Protocol, self-hosted with your own provider keys.

How do I install HarnessRouter Community Edition?

The README's quickstart is a single docker run that publishes port 3000 on loopback and mounts a named volume at /data, after which you wait for the log line [harnessrouter] ready on :3000. Docker, about 4 GB of disk space and an API key from a supported model provider are the stated requirements, and no HarnessRouter account is needed.

Does HarnessRouter Community Edition include a model or a trial API key?

No. The README states there is no bundled model or trial key, and that a compatible provider must be connected before a task can run. Connections are added in the console under Integrations, or defined in .env as a JSON value naming a provider and its credential.

Where does HarnessRouter Community Edition store its data?

In the mounted volume. The compose file says everything durable lives there, including SQLite databases, blobs and the secret store, and the Dockerfile describes state as SQLite and files on one mounted volume. The README notes the same volume keeps installed harness CLIs and workspaces between restarts.

Official sources

  1. HarnessRouter/harnessrouter on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/harnessrouter-harnessrouter.svg)](https://hysenlabs.com/projects/harnessrouter-harnessrouter)