Start it
omp --mode rpc --no-session # headless: events out, commands in
omp --mode rpc-ui --no-session # adds tool-card / selector UI framesOn startup omp writes {"type":"ready"}, then reads one JSON object per line on stdin and writes one per line on stdout. Mode flags are documented alongside every other CLI option on the CLI reference. Pass --no-session to keep the run out of ~/.omp/agent/sessions/; omit it to persist and later resume, fork, or branch through the same channels you’d use interactively (Sessions).
--mode rpc is fully headless. --mode rpc-ui layers the TUI’s interactive surfaces on top of the same wire: tool-execution cards, selectors, permission prompts arrive as extension_ui_request frames the embedder MUST answer with a matching extension_ui_response.
Message shape
Every command may carry an id; the matching response echoes it back with {"type":"response","command":"…","success":bool}. prompt and abort_and_prompt ack immediately — the turn itself streams as agent_start, message_update, tool_execution_*, and finishes with agent_end.
Commands
| Command | Payload | Returns |
| -------------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------- | ---------- | --------------------------------------------------- |
| prompt | message, images? | ack; streams agent_start → deltas → agent_end |
| steer | message, images? | ack; inserted into the running turn |
| follow_up | message, images? | ack; queued after the current turn |
| abort | — | ack; the active turn ends with agent_end |
| abort_and_prompt | message, images? | ack; aborts then starts a new turn |
| new_session / switch_session / branch | session targets | session-tree transitions |
| handoff | customInstructions? | { savedPath } \\ | null |
| get_state / get_messages / get_session_stats | — | session snapshot |
| set_model / cycle_model / set_thinking_level | model selectors | set_model / cycle_model return the selected model; thinking changes emit a thinking_level_changed event |
| compact / set_auto_compaction | compaction controls | ack / CompactionResult |
| bash / abort_bash | command | BashResult |
| set_host_tools | tools: RpcHostToolDefinition[] | host-side tools surface as host_tool_call frames; reply with host_tool_result |
| extension_ui_response | id, value \\ | confirmed \\ | cancelled | answers a previously emitted extension_ui_request |
| get_login_providers / login | provider id | OAuth URLs arrive as extension_ui_request with method: "open_url" |
| export_html | outputPath? | { path } |
Event stream
-
message_update— assistant output.assistantMessageEvent.typeselects betweentext_delta,thinking_delta,tool_call_start,tool_call_delta, andtool_result. -
message_start/message_end— message boundaries inside a turn. -
tool_execution_start/_update/_end— tool lifecycle; carrytoolCallId,toolName, and intent labell. -
agent_start/agent_end— turn boundaries.agent_endcarries the stop reason a single prompt waits on. -
auto_compaction_start/_end,auto_retry_start/_end— mid-stream housekeeping. -
available_commands_update— the current slash-command surface; emitted once at startup and again whenever command metadata changes. Session-tree transitions (new_session/switch_session/branch) are observed through their command responses. -
extension_ui_request— the agent needs UI: a selector, a confirm, an input, or an OAuth URL. Reply withextension_ui_responseusing the sameid. Tool-execution cards and permission prompts only arrive under--mode rpc-ui.
Shell example
One prompt in, text deltas out, exit on agent_end. No language binding required.
#!/usr/bin/env bash
set -euo pipefail
prompt='Say "ok" and nothing else.'
jq -nc --arg m "$prompt" '{id:"s1",type:"prompt",message:$m}' \
| omp --mode rpc --no-session \
| while IFS= read -r line; do
t=$(jq -r '.type' <<<"$line")
[["$t" == "message_update"]] && \
jq -r '.assistantMessageEvent.delta // empty' <<<"$line"
[["$t" == "agent_end"]] && exit 0
doneJSON event stream mode
--mode json is the print-mode variant of the same wire. It accepts a prompt from argv (or -p), writes the same event objects to stdout, then exits. Use it for CI captures, golden-file tests, or piping into the HTML exporter without keeping a subprocess alive.
omp --mode json --no-session "Audit src/ for unused exports" > run.jsonl
omp --export run.jsonl audit.htmlSame framing, same event types, same renderer. The difference is purely lifecycle: --mode rpc is a long-running pipe you keep feeding; --mode json is one prompt, one stream, exit.\n