Operate
Source:
harness/docs/client/operate.mdStatus: current
Operate
Section titled “Operate”Day-to-day use of the harness TUI. Named actions, need-human keys, permission
mode, /connect / /mcp / /model.
Not here: pack authoring (author/), PEW/Proposal law
(../canon/proposals.md), approval mechanism
(../runtime/approval.md), shell duties and empty-draft
law (shell.md), tape grammar (transcript.md).
What you are doing
Section titled “What you are doing”You evaluate named actions on the session socket (turn, kv/set,
connect/adopt, …), write PEW/Proposals (cancel / Question), and write
approved on a pending Approvable leaf. The daemon writes Job and PEW bodies.
Permission mode is manual / auto / yolo. Session mode (act /
plan) is not that join. Slash commands are app tools; they do not replace the
agent loop. Law: ../runtime/approval.md.
Permission mode
Section titled “Permission mode”| Axis | Values | When |
|---|---|---|
| Permission mode | manual, auto, yolo |
All three run policy.yaml. Remainder ask: cover / classifier / allow. Floor block holds in all three. |
Shift-Tab cycles manual → auto → yolo → manual. It does not cycle
session mode. Active permission mode is SessionRoot.currentPolicy. The same
write is last-choice backing: session policy/set also stores
ProjectRoot.defaultPolicy and kernel config.json defaultPolicy (not a
kv key). A new session mints project.defaultPolicy if set, else kernel,
else manual. Attach does not re-seed. evalSpec overlays the turn and
does not write last-choice.
A currentPolicy change re-runs still-null ApprovableJobs (not mid-evaluate),
including rows already asked. In-flight evaluation does not rebind.
Need-human keys
Section titled “Need-human keys”When policy asks, you write approved on that leaf (approvalQueueHead). You
do not mint a second “approval” unit. Ask chrome shadows the composer — the
prompt you were typing stays. Confirm chords write only while the cover is
armed; a mount over a nonempty draft waits
KernelRoot.approvalAskThrottleMs (default 2s, 0 = off). No y / n / a /
Space grants. Implementer face: shell.md. Extra-root folder
offer: ../runtime/approval.md.
Persist modifier is ⌃ (config.json superKey, default ctrl; cmd is ⌘).
Super is not inferred from the OS — terminals often do not forward it.
| You press / mean | What happens |
|---|---|
| Allow (empty cover, ⏎) | approved = true on the leaf. A file read also stores that path on SessionRoot.readAllowlist — later reads of it (and descendants) this session do not ask. Writes still ask. |
| Allow this folder (empty cover, extra-root read, suggested parent, persist-mod ⏎) | same, plus readAllowlist for that parent. Offered when a same-parent sibling was allowed or is in-flight. Not Always. Not auto. |
This session in auto (empty cover, auto remainder ask of a grantable cluster, persist-mod ⏎) |
same, plus SessionRoot.autoAllow[cluster] = true. Hatch / extra-root deny / MCP cousin: unpainted. |
| Always in auto (empty cover, same leaf, persist-mod ⇧ ⏎) | same, plus kernel config/auto-allow (config.json autoAllow) |
| Allow this session (empty cover, MCP look-up in manual, persist-mod ⏎) | same, plus SessionRoot.toolAllowlist for that connection+tool |
| Always allow (empty cover, MCP look-up in manual, persist-mod ⇧ ⏎) | same, plus kernel connect/always-allow (connection alwaysAllow) |
| Deny (empty cover, Esc) | approved = false on the leaf. The Job seals with no BODY — it still happened on the tree |
| Deny this session (empty cover, MCP cousin, persist-mod Esc) | same, plus SessionRoot.toolBlocklist |
| Deny forever (empty cover, MCP cousin, persist-mod ⇧ Esc) | same, plus kernel connect/exclude-tool (!name on connection tools). There is no alwaysDeny bag. |
| Allow / deny with comment (cover has text, persist-mod ⏎ / persist-mod Esc) | writes approvalComment too. Persist and folder-widen do not fire from a comment. Shift+Enter is a newline. |
| Esc (open head, nothing need-human) | empty Esc arms, then turn/cancel. Nonempty Esc is draft-clear (same arm). |
| Choice row (Question) | propose a choice. Actor considers. Not UAC. |
Policy-written allow/deny does not raise the cover; it is a chip on the tool
row (policyResult / judgeResult). Persist does not cross the floor — a
look-up cannot be banned from the card, a cousin cannot be remembered as a
read. Folder-widen is not Always and does not fire on a lone file.
/connect
Section titled “/connect”Connection inventory only. Source of truth is ~/.harness/config.json;
KernelReflector projects it onto the kernel CRDT. Picker: rename / remove /
adopt. Class/instance = driver/connection. Esc and back are host navigation,
not menu rows. Secrets stay local to the daemon.
Selecting a wire also sets that session’s model (last-used, else the
highest-version live id) and remembers both as the default. MCP catalog cut
is tools on that row — /mcp.
MCP connections in the same ~/.harness/config.json. /mcp is health,
authenticate, add/drop, and session disable (kv/set mcp-disabled:{id} —
not a file write). The durable catalog cut is tools on the connection;
toolSeverity overlays auto-class on leftovers. Always-as-read names land on
alwaysAllow via kernel connect/always-allow. Deny forever appends !name to
tools via kernel connect/exclude-tool. Session remember / hide live on
SessionRoot.toolAllowlist / toolBlocklist. The kernel rewrites config.json
the same way connect/adopt does.
Hide is not a license. Remaining tools still run policy.yaml. Connecting
is not a grant. A hidden name is absent from the next turn’s catalog; calling it
by wire name still fails.
Ordered globs on the server tool name (get_issue, merge_pull_request) —
not the wire mcp__github__…. * any run of characters; ? one character.
Match is case-sensitive. ! in front removes matches. Rules apply in listed
order, so a later include can put a name back. A list of only excludes
behaves as if * were written first. Omit the field (or a non-array) to keep
every tool the server lists. [] keeps none.
Write it on settings.tools, or as a sibling tools on the connection object
(lifted into that bag):
{ "connections": { "github": { "driver": "mcp-stdio", "name": "GitHub", "settings": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "tools": ["!merge_*", "!delete_*"] } }, "mail": { "driver": "mcp-http", "settings": { "url": "https://mcp.example/mcp", "tools": ["get_*", "list_*", "!get_secret"] } } }}github keeps everything except merge_* / delete_*. mail starts empty,
adds get_* and list_*, then drops get_secret. /mcp row counts are the
server’s listed tools.
toolSeverity
Section titled “toolSeverity”Optional overlay when auto-class is the wrong pole. Keys are serverToolName
globs; last match wins. Same placement as tools. Values: view → catalog
read; effect → effect (auto cannot say this); irreversible-effect →
write. Omit to keep auto-class. A bad value is skipped. Not a license and not
readOnlyHint.
"toolSeverity": { "mark_all_notifications_read": "effect", "merge_*": "irreversible-effect", "get_issue": "view"}alwaysAllow
Section titled “alwaysAllow”Exact serverToolName strings remembered by Always allow. Kernel
connect/always-allow writes the same bag as tools. The read floor still
applies — a veto or one-word name on this list does not skip ask. A new name
still knocks.
"alwaysAllow": ["get_issue", "list_issues"]/model
Section titled “/model”Session model, and the default. Models are invocation ids on a live connection
((:models (:live c))), plus free-type id. Sets the session KV key model
(and the connection when you pick a model on a wire) with remember: "1", so the
next session mints the same pair. A bare kv/set — a subagent, or
--model / --connection — changes only this session.
Does not adopt or drop connections — use /connect.
Daemon and TUI are one process; it appends ~/.harness/harness.log (or
<kernel>/harness.log if you passed --kernel). Override with
HARNESS_LOG=/path/to/file. Nonempty DEBUG also mirrors chatter to stderr
before the alt-screen.
See also
Section titled “See also”| Doc | Role |
|---|---|
shell.md |
Client shell duties, empty-draft law, unattended eval |
transcript.md |
Live tape: identity, liveness, ask pin, follow-tail |
../canon/proposals.md |
PEW/Proposal shapes |
../canon/standard-toolkit.md |
Default FS tools |
author/ |
Pack / command authoring |