Skip to content

Harness

Harness is an agent runtime: a daemon (kernel and sessions) and client shells that share one session document. The TUI in the Harness checkout is one of those shells. This page is how to install that checkout and finish a first useful session. It is an operator guide, not the product spec.

Browse the Harness source reference — published current documentation from the Harness checkout. Proposed and design documents are excluded pending review.

The checkout is self-contained. You do not need sibling Arrival, Plexus, Commons, or Foundation repositories.

You need Node.js 22 or newer and pnpm 10.33. From the Harness repository root:

Terminal window
corepack enable
pnpm install --frozen-lockfile
pnpm build
pnpm --filter @inhuman.tools/harness dev

corepack enable supplies the pinned pnpm. The last command builds the TUI package and opens it.

The kernel directory defaults to ~/.harness. Pass --kernel PATH for a separate one. Connections live in <kernel>/config.json (so ~/.harness/config.json unless you moved the kernel).

pnpm verify is the full local release gate: build, typecheck, lint, logic tests, process tests, TUI visual tests, and a smoke test of the packed server tarball. You do not need it to start a session.

You need one completion connection and a model. MCP servers, plugins, web search, and a command-line model override are optional. They are listed in the next section so they stay off this path.

In the TUI:

  1. /connect — adopt one built-in completion provider and finish its sign-in or API-key step. Secrets stay on the daemon.
  2. /model — pick an advertised model on that live connection, or type an invocation id.

/connect is the connection inventory (adopt, rename, remove). Choosing a completion wire also sets this session’s model to the last-used id, otherwise the highest-version live id, and remembers both. The next session mints that same pair.

/model sets the session model and, when you pick a model on a wire, the connection. It remembers that pair too. It does not adopt or drop connections — use /connect for that. --model / --connection, a subagent, or any other bare session write changes only the current session.

  1. Type the first prompt in the composer and press Enter.

When nothing is running, that nonempty draft starts a turn. An empty Enter does nothing until a turn exists. While a turn is already running, Enter queues the draft instead of starting a second one. Slash commands such as /connect and /model are app tools; they do not replace that prompt.

Driver Sign-in In /connect
chatgpt ChatGPT subscription (OIDC) add-by-default: picking the driver can adopt on its own
openrouter PKCE key exchange add-by-default
grok Grok subscription (OIDC) add-by-default. Also a web-search driver if you pin it; chat does not need that
nous Nous Portal (device-code OAuth) add-by-default
openai-compat OpenAI-compatible endpoint add-as-secondary: /connect collects config, then adopts

add-by-default means adopt can finish from the driver row. add-as-secondary means a nested step collects config first. oidc/ is an internal base class, not a picker row. Hermes is an OAuth client of Nous Portal, not a driver id.

MCP. mcp-stdio (a spawned server) and mcp-http (Streamable HTTP) are add-as-secondary. Add them later from /connect or /mcp. /mcp is health, authenticate, add or drop, and a session disable. Connecting is not a grant: tools that remain still run policy.yaml. Hiding a name removes it from the next turn’s catalog; it is not a license, and calling the hidden wire name still fails. The durable cut is the tools globs on that connection in config.json (toolSeverity and alwaysAllow are optional overlays).

Plugins. Optional. Plugins do not register drivers, and plugin manifests are not how drivers are loaded. New capability is a connection on a driver that already exists, a pack tool, or a .scm command.

Web search and extract. Not required for a first completion. web-keyless is the built-in keyless ring (Exa, then Parallel, Firecrawl, Keenable, Tavily). exa, parallel, firecrawl, keenable, and tavily are add-as-secondary (API key, or a self-hosted URL for Firecrawl). web-nous is not adopted and holds no second secret; it is projected only when a nous connection exists. When more than one search path exists, pick order is: pin, then a file BYOK dedicated driver, then that Nous intern, then keyless.

Model flags. --model and --connection are optional and apply only to this session. They do not replace /connect.

/model is empty. Models are invocation ids on a live connection. Adopt a completion provider with /connect first.

A new provider did not stick, or MCP stole the chat model. /model never adopts. /connect on a completion wire does set the session model. MCP tool visibility is the tools list on that MCP connection (/mcp), not the chat model.

Every tool asks, or a block survives yolo. Permission mode is manual, auto, or yolo. Shift-Tab cycles manual → auto → yolo and does not change session mode (act / plan). A new session uses the project default policy, else the kernel default, else manual. All three modes run policy.yaml. A floor block stays a block in auto and yolo. Attaching to an existing session does not re-seed the mode.

Logs. Daemon and TUI are one process. They append ~/.harness/harness.log, or <kernel>/harness.log when you passed --kernel. Override the file with HARNESS_LOG=/path/to/file. A nonempty DEBUG also mirrors that chatter to stderr before the full-screen UI. The documented dev script sets DEBUG=*, so noisy stderr on first launch is expected.

The steps above are condensed from the sibling Harness checkout (../harness during local development):

  • README.md — install, first run, and what is optional
  • docs/README.md — operator path is docs/client/operate.md
  • docs/client/operate.md — /connect, /mcp, /model, permission mode, logs
  • docs/runtime/drivers.md — driver roster, multiplicity, and the plugin rule

Those files stay authoritative. Approval key chords, MCP glob syntax, and pack authoring are left there on purpose.