claude-code
The claude-code worker exposes the Claude Code API as iii functions. One
claude::run call executes one headless Claude Code turn — the same agent
the user runs in their terminal, with the same login, filesystem, and
permission model — in a chosen working directory, and returns the final
result, token usage, and cost. The worker is a pure pass-through: named
payload fields cover the common path, the options field forwards any Agent
SDK option verbatim, and every message Claude Code emits mirrors untouched
onto the claude::events stream. A translated AgentEvent view lands on
agent::events, which is what the iii console and the acp worker render.
Requires the claude CLI on the host with an existing login or
ANTHROPIC_API_KEY in the worker environment. When a turn needs a
capability beyond Claude Code itself, add another iii worker to the bus
instead of bolting anything onto this one.
When to Use
- Delegate a whole coding task ("add an endpoint and run the tests") in one
call, instead of orchestrating individual
coder::* / shell::* calls
yourself: claude::run with prompt and cwd.
- Continue a conversation across calls: pass the same
session_id again and
the worker resumes the underlying Claude Code session with full context.
- Run long jobs without holding the call open:
claude::start returns
{session_id, started} immediately; follow claude::events (group_id =
session_id) for raw progress or agent::events for the rendered view;
interrupt with claude::stop.
- Act on the whole backend: turns carry the iii runtime context by default,
so the agent discovers and calls any registered function through the iii
CLI (engine::functions::list,
iii trigger <fn> --help) with the
matching Bash allow rule pre-set; disable per turn with
iii_context: false.
- Plan before touching anything:
permission_mode: "plan" runs Claude
Code's native plan mode (read-only, returns the plan as the result);
then send "implement the plan" on the same session_id with
permission_mode: "acceptEdits".
- Reach past the named payload fields: anything the Agent SDK accepts goes
through
options unchanged — {"options": {"forkSession": true, "includePartialMessages": true}} — and includePartialMessages puts
token-level stream_event frames on claude::events.
Boundaries
- Spawns the host
claude CLI per turn — needs Claude Code installed and
authenticated; not available inside a bare container without it.
- Function execution happens inside Claude Code's own permission model
(
permission_mode, allowed_tools, disallowed_tools), not the
engine's; set approval_gate: true to route every call through
policy::check_permissions (fail-closed, needs the harness worker).
- One turn per session at a time: check
claude::status (live: true)
before sending another claude::run for the same session_id; parallel
runs against one session race on the underlying Claude Code resume.
agent::events carries whole-message frames (message_complete,
function_execution_start/end, turn_end, agent_end); token deltas
exist only on claude::events and only when includePartialMessages is
set.
Functions
claude::run — run one Claude Code turn and wait; accepts prompt (or a
messages array whose last user entry becomes the prompt), plus model,
cwd, permission_mode, allowed_tools, disallowed_tools,
max_turns, system_prompt, append_system_prompt, and raw options;
returns {session_id, claude_session_id, result, stop_reason, usage, total_cost_usd}.
claude::start — same payload, returns {session_id, started}
immediately; progress arrives on the streams.
claude::stop — interrupt the live run for a session.
claude::status — point-in-time session view: live flag, status, turns,
usage, cost.
claude::sessions::list — every session this worker has run.
run::start_and_wait — alias for claude::run under the entrypoint the
console and acp worker drive, so both run Claude Code with no changes.
The terminal half
The same worker also runs Claude Code as a terminal page on the console: it
installs the CLI on the terminal host (the shell worker's), equips a
workspace with the iii skills and engine notes, and opens Claude in a
shell::pty session. A person opens it; the session's turns stream onto
agent::events with the same frames a claude::run turn produces, so both
halves render alike. Use it when an operator wants to talk to Claude Code
interactively — with login handled in the terminal — or wants an agent that
can scaffold and register new iii workers from inside the engine. pi
is the same terminal shape with the pi agent.
Boundaries:
claude::terminal::describe, claude::terminal::activity, and
claude::ui-content are console plumbing, flagged internal. Do not call
them; a terminal is opened by a person, from the page.
- The command is fixed to Claude Code. Use the
shell worker for anything
else — including shell::pty::sessions to see what a terminal is doing.
- The workspace must be reachable by the
shell worker: it owns the session.
claude::auth::status reports which plan a terminal session spends
(subscription vs API key, and an API key silently outranks a subscription
login). The page shows it in the status bar; agents are denied it.
1---2name: claude-code3description: Run headless Claude Code turns over the iii bus — file edits, shell, and web against any host directory — with verbatim message streaming, session resume, and full Agent SDK option pass-through. Also serves Claude Code as an interactive terminal page on the console.4---56# claude-code78The claude-code worker exposes the Claude Code API as iii functions. One9`claude::run` call executes one headless Claude Code turn — the same agent10the user runs in their terminal, with the same login, filesystem, and11permission model — in a chosen working directory, and returns the final12result, token usage, and cost. The worker is a pure pass-through: named13payload fields cover the common path, the `options` field forwards any Agent14SDK option verbatim, and every message Claude Code emits mirrors untouched15onto the `claude::events` stream. A translated AgentEvent view lands on16`agent::events`, which is what the iii console and the acp worker render.1718Requires the `claude` CLI on the host with an existing login or19`ANTHROPIC_API_KEY` in the worker environment. When a turn needs a20capability beyond Claude Code itself, add another iii worker to the bus21instead of bolting anything onto this one.2223## When to Use2425- Delegate a whole coding task ("add an endpoint and run the tests") in one26 call, instead of orchestrating individual `coder::*` / `shell::*` calls27 yourself: `claude::run` with `prompt` and `cwd`.28- Continue a conversation across calls: pass the same `session_id` again and29 the worker resumes the underlying Claude Code session with full context.30- Run long jobs without holding the call open: `claude::start` returns31 `{session_id, started}` immediately; follow `claude::events` (group_id =32 session_id) for raw progress or `agent::events` for the rendered view;33 interrupt with `claude::stop`.34- Act on the whole backend: turns carry the iii runtime context by default,35 so the agent discovers and calls any registered function through the iii36 CLI (engine::functions::list, `iii trigger <fn> --help`) with the37 matching Bash allow rule pre-set; disable per turn with38 `iii_context: false`.39- Plan before touching anything: `permission_mode: "plan"` runs Claude40 Code's native plan mode (read-only, returns the plan as the result);41 then send "implement the plan" on the same `session_id` with42 `permission_mode: "acceptEdits"`.43- Reach past the named payload fields: anything the Agent SDK accepts goes44 through `options` unchanged — `{"options": {"forkSession": true,45 "includePartialMessages": true}}` — and `includePartialMessages` puts46 token-level `stream_event` frames on `claude::events`.4748## Boundaries4950- Spawns the host `claude` CLI per turn — needs Claude Code installed and51 authenticated; not available inside a bare container without it.52- Function execution happens inside Claude Code's own permission model53 (`permission_mode`, `allowed_tools`, `disallowed_tools`), not the54 engine's; set `approval_gate: true` to route every call through55 `policy::check_permissions` (fail-closed, needs the harness worker).56- One turn per session at a time: check `claude::status` (`live: true`)57 before sending another `claude::run` for the same `session_id`; parallel58 runs against one session race on the underlying Claude Code resume.59- `agent::events` carries whole-message frames (`message_complete`,60 `function_execution_start/end`, `turn_end`, `agent_end`); token deltas61 exist only on `claude::events` and only when `includePartialMessages` is62 set.6364## Functions6566- `claude::run` — run one Claude Code turn and wait; accepts `prompt` (or a67 `messages` array whose last user entry becomes the prompt), plus `model`,68 `cwd`, `permission_mode`, `allowed_tools`, `disallowed_tools`,69 `max_turns`, `system_prompt`, `append_system_prompt`, and raw `options`;70 returns `{session_id, claude_session_id, result, stop_reason, usage,71 total_cost_usd}`.72- `claude::start` — same payload, returns `{session_id, started}`73 immediately; progress arrives on the streams.74- `claude::stop` — interrupt the live run for a session.75- `claude::status` — point-in-time session view: live flag, status, turns,76 usage, cost.77- `claude::sessions::list` — every session this worker has run.78- `run::start_and_wait` — alias for `claude::run` under the entrypoint the79 console and acp worker drive, so both run Claude Code with no changes.8081## The terminal half8283The same worker also runs Claude Code as a terminal page on the console: it84installs the CLI on the terminal host (the `shell` worker's), equips a85workspace with the iii skills and engine notes, and opens Claude in a86`shell::pty` session. A person opens it; the session's turns stream onto87`agent::events` with the same frames a `claude::run` turn produces, so both88halves render alike. Use it when an operator wants to talk to Claude Code89interactively — with login handled in the terminal — or wants an agent that90can scaffold and register new iii workers from inside the engine. `pi`91is the same terminal shape with the pi agent.9293Boundaries:9495- `claude::terminal::describe`, `claude::terminal::activity`, and96 `claude::ui-content` are console plumbing, flagged internal. Do not call97 them; a terminal is opened by a person, from the page.98- The command is fixed to Claude Code. Use the `shell` worker for anything99 else — including `shell::pty::sessions` to see what a terminal is doing.100- The workspace must be reachable by the `shell` worker: it owns the session.101- `claude::auth::status` reports which plan a terminal session spends102 (subscription vs API key, and an API key silently outranks a subscription103 login). The page shows it in the status bar; agents are denied it.