Skip to content

Commands — app program invocation

Source: harness/docs/plugins/commands.md
Status: current. Staged verbatim for documentation ingestion.

Commands are not PEW/Work. They are app-managed programs: a Client Scheme (Arrival) half for pickers and projections, and a commit of name+args as a JSON-RPC action on the session socket.

Grain: ../canon/grain.md (Command = app program).
Surfaces ladder: plugins/tldr.md.
Inventory grounding: ../runtime/drivers.md (drivers[] is still projected; it is not the behavior surface).

The Client Scheme does not implement a mini-app UI framework. It declares session-hub projections (catalog, faces, commands) into a unified choice / action surface. The Client owns navigation, search, chrome, and rebuild.

Registration is extensions.tools.inhuman.commands — { description, importPath } to a Scheme file. File-driven so require works. polish.md.


Half Where Role
Sandbox Client Scheme file (Arrival); read session-hub projections; fast local UX
Commit Session socket name+args as a JSON-RPC action

Commit holds { type, args } — programs never await (../runtime/control-effects.md).


Command declares Client owns
Content Choice rows over DriverSpecs + ConnectionSpecs + faces Fuzzy, arrows, focus, multi-rep (TUI / remote / voice)
Primary action (commit) or nested choice (drill) Enter / default activate
Additional actions list (manage ops on the same subject) Bind chrome; optional hotkeys
Hotkeys Optional triggers on action/choice — never the behavior itself Keymap
Navigation — Esc / back / stack / cleanup
Inventory Read driver + connection faces only Re-interpret whole surface when atoms change (v0 all-or-nothing)
Product knowledge Never invent package-form import paths, whitelist entries, badges, doors, Back rows Chrome, empty states, session-attached gate
World Current is immutable (reads / provenance) Next via commit of kv/set / named actions

One verb, one concern.

Verb Owns Must not
/connect ConnectionSpec registry: list wires, adopt/drop, set current wire (+ last-used model on that wire) Model catalog / free model pick as primary product
/model Models from connection faces; free model id; set session model Adopt/drop drivers/connections
/mcp ConnectionSpecs whose can includes mcp: health, tool count, session disable, authenticate, add/drop Completion wires / model catalog

Selecting a connection is kv/set connection (then last-used model on that wire) — not a special “use pipeline.” Selecting a model is kv/set connection, then model, then last-used on that wire. Reactivity does the rest. Adopted offers are omitted. Unused add-by-default drivers adopt from the driver row. OpenRouter opens a PKCE key-exchange URL. ChatGPT and Grok park an OIDC browser sign-in and store a refreshable session. /model lists faces with fewer than 20 ids first; catalogs of 20 or more sit below.

Packs may register extra operator verbs through extensions.tools.inhuman.commands. Those commands are absent from the model tool catalog.


choice = { kind: "choice", rows }
row = title, description?, state?
primary: InhumanAction.ref(args) | choice | input
actions: list of { label, hotkeys?, action }
action = name + args → { type, args } issued as JSON-RPC
hotkeys?: optional triggers only

Same grammar can be lensed to TUI, remote UI, or voice — the command does not care.

{
title: "…",
description: "…",
state: "warning",
primary: selectConnection.ref({ id: c.id }),
actions: [
{ label: "disconnect", hotkeys: ["control-x"], action: dropConnection.ref({ id: c.id }) },
],
}

Missing adopt settings (base URL) are a harness/input callback form from connect/adopt, not a nested input dict in the command program. openai-compat’s OpenAI-compatible door is an adoptable offer with empty settings: Enter parks Base URL, then an optional secret API key (empty skips). The written wire is named by a well-known catalog when the host matches (Groq, Fireworks, OpenRouter, …), else the URL’s eTLD+1, so many custom endpoints coexist. The door is never hidden after adopt.

/mcp is the same grammar over can: ["mcp"]. Rows have no primary select (not a completion wire). Add is mcp-server/adopt, not connect/adopt: remainder on the root action is the dropped URL or stdio command (:input); Enter on the Add MCP row parks. HTTP remainder that 401s with Protected Resource Metadata parks the same PKCE harness/open-url as connect/login; otherwise an optional token. Session disable is kv/set mcp-disabled:{id}, not config.json. Row tool counts are live.tools (what the server listed). The durable catalog cut is tools on the connection; toolSeverity overlays auto-class — ../client/operate.md § /mcp.

No kind: "pick" ceremony if the host treats every row as choosable context. Free model id is remainder-as-:input on kv/set.

/goal and /plan are pack command files (plugins/inhuman-plugin-goal/tools/inhuman/commands/goal.scm, plugins/inhuman-plugin-fusion/tools/inhuman/commands/plan.scm). They call call/method and harness/action-with-choices. The client Arrival interpreter does not evaluate those forms, and the behavior capability does not either.


Subject of each define must match the name (connections vs drivers):

Projection Meaning
prompt-drivers DriverSpecs whose pre-load can includes completion
used-connections ConnectionSpecs whose DriverSpec is prompt-capable. Titles prefer live.catalogName over the config.json name. Dim annotation (user · $balance / displayName) and tertiary hint (key mask / plan caption) are client-composed from live.account / live.identity / live.keyMask. Adopted rows do not show the URL
offers class-bootstrap offers on those drivers, minus already-adopted. openai-compat names loopback catalogs by port (Ollama, LM Studio, …) and seeds remote catalogs on load
unused-drivers prompt DriverSpecs with no ConnectionSpec and no offers

Rebuild: whole connect-surface re-runs when Spec inventory/faces change — not per-define fine-grained computeds (v0).


"commands": {
"connect": {
"description": "Manage provider connections",
"importPath": "./commands/connect.scm"
}
}

On extensions.tools.inhuman.commands. The Scheme file is loaded file-driven (Arrival require against that path). The plugin JS module does not load on the Client. Dual ambient (manifest vs Client eval): lifecycle.md.


(harness/kernel/…) reads KernelRoot.drivers / KernelRoot.connections — live entities, not view dicts. (harness/action 'kv/set :params …) is a named RPC, not a Scheme mutate of the kernel. The operation is the first positional argument. A branded host instance is opaque identity: (:id c) doors. Field reads are (:field entity).

(harness/kernel/drivers :can 'completion) ; DriverSpec list
(harness/kernel/connections) ; ConnectionSpec list
(harness/kernel/offers d) ; class-bootstrap connection construction
(:models (:live c)) ; openai-compat invocation ids on spec.live
(harness/session/get-current key) ; immutable current
(harness/action 'kv/set :params (dict :key "connection" :value (:id c) :remember "1"))
(harness/action 'connect/adopt :params (dict :driver (:name d) :name n :settings s))
(harness/action 'connect/drop :name "Remove connection" :hotkey "control-x" :params (dict :id (:id c)))
(harness/action 'mcp-server/adopt :name "Add MCP" :params (dict :input ""))
Entity Field reads ((:field entity))
connection (ConnectionSpec) id, name, driver, issue, error, configuration, live
driver (DriverSpec) name, description, can (Expectation model names), multiplicity
offer name, description, adoptable, settings

connect/adopt takes driver name + offer name + settings. can is readable before ensure; broken connections surface sticky failure messages, not silent absence. add-by-default unused drivers adopt from the driver row. Secrets stay in process-local secrets.json, never config.json.


  1. Session attached (session-hub catalog present).
  2. Interpret surface → choice/action tree; fuzzy + arrows.
  3. Primary activate / additional actions / hotkeys as triggers.
  4. Esc / back / dismiss — never command rows.
  5. Re-interpret on reactive projection change.
  6. Commit InhumanAction.ref(args) / host { type, args }.

Surface System
Slash command picker declarative choice/action + DriverSpec / ConnectionSpec faces
Behavior guards and hooks critical path and parallel notes (lifecycle.md)
Chat completion PEW + ensure → PEWConnection.resolve → ExpectationActor

Listing connections/models = observation. Running a completion = work.


  • ../packages/harness-server/src/defaults/commands/connect.scm
  • ../packages/harness-server/src/defaults/commands/model.scm
  • ../packages/harness-server/src/defaults/commands/mcp.scm
  • ../runtime/drivers.md (internal — drivers[] is still projected)