Skip to content

Claude Code as a delegated runtime ​

Parent: Agents and delegation.

Rho can hand a delegated agent to the installed claude binary instead of running Rho's own loop. The parent stays in Rho. The child uses Claude Code's harness and the user's Claude subscription. Model choice and runtime choice stay separate: picking an Anthropic model on the Rho runtime is not the same as runtime: claude-cli.

Subscription workaround ​

Anthropic does not allow third-party clients to sign in with Claude.ai Free/Pro/Max credentials or to route those plans through their own API stacks. Rho's Anthropic provider path is API-key billing only.

runtime: claude-cli is the supported indirect way to spend a Claude subscription from a Rho session: Rho stays the parent orchestrator, and the official claude binary owns sign-in, the child loop, and plan usage. Rho never sees or stores the subscription token. This is not a substitute for Anthropic API access inside Rho's own runtime, and it is not a root-session Claude Code mode.

When this is useful ​

Use runtime: claude-cli when you want that subscription-backed child while the main session stays on Rho:

  • Use a Claude Pro/Max plan on planning, review, or research without making Claude Code the root harness
  • Keep Rho as the orchestrator (fan-out, attach, cancel, session tree) while Claude owns the child loop and credential
  • Reuse Claude Code tool names and permission behaviour for a bounded child task
  • Open the full Claude transcript later with claude --resume <session-id> after Rho finishes the run

Skip this feature when you only need "a subagent on Opus" through Rho's normal provider path (API key or another provider). Set model: / provider: on a runtime: rho agent instead. You do not need the claude binary for that.

Claude-cli agents are delegated only. The interactive root and rho run root cannot bind runtime: claude-cli. A Rho parent must launch them through the agent tool.

How to use it ​

  1. Install the binary (Rho does not ship it):

    bash
    curl -fsSL https://claude.ai/install.sh | bash
    claude --version

    See Claude Code binary.

  2. Sign in from Rho so Claude Code stores the subscription credential:

    text
    /login claude-code

    Or open bare /login, pick Anthropic, then Claude Code (delegation only). Rho asks you to confirm, then hands the terminal to claude auth login --claudeai and never sees or stores the token. Details: Claude Code runtime sign-in.

  3. Write a delegated agent definition (there is no built-in Claude agent). Run /agents create or /create-agent for a guided questionnaire, or write a file such as ~/.rho/agents/claude-planner.md:

    markdown
    ---
    id: claude-planner
    description: Use Claude Code to plan with an Anthropic model
    runtime: claude-cli
    model: claude-opus-5
    reasoning: high
    tools: [Read, Glob, Grep]
    inherit_claude_config: false
    ---
    Produce a short plan. Prefer reading before editing.

    Notes:

    • tools: uses Claude Code names (Read, Edit, Bash(git *)), not Rho capabilities
    • Omitting tools means no tools. There is no tools: all
    • model: is a Claude model alias such as opus, or a full Claude model name. It is not a Rho @alias. In /agents, the Model row offers the aliases Rho knows (fable, opus, sonnet, haiku) plus a Claude Code default row; a definition that pins a full model name keeps its own row
    • optional reasoning: maps to Claude --effort (low/medium/high/xhigh/max); omit to inherit Claude's default; off and minimal are rejected
    • Auto and Allow edits use Claude dontAsk only when every tools: entry is a proven no-prompt Claude built-in for that Rho approval class and inherit_claude_config is false. Claude dontAsk and --allowedTools both execute without prompting, so specifiers such as Bash(git *), write/process tools, unknown Claude/plugin/MCP names, or inherited Claude settings refuse spawn. Plan and Bypass keep their Claude-native mappings. Supervised always refuses, because claude -p cannot prompt through Rho
  4. Confirm setup in the TUI:

    text
    /doctor
    /agents
    /info

    /doctor checks binary and auth health. /agents shows runtime and Claude tool lists. /info opens an overlay with Claude Code ownership wording when signed in.

  5. Delegate from a Rho root session (interactive or automation parent on runtime: rho):

    Ask the parent to call the agent tool with agent_id: claude-planner and a clear prompt. The call returns a run ID immediately, followed by an automatic completion notification.

  6. Watch, cancel, and resume:

    bash
    rho attach <run-id>

    Attach paints Claude tools with the same card grammar as native Rho tools, using Claude names (Read, Bash, Glob) plus paths, counts, and diffs when the stream provides them.

    Cancel through the agents tool or parent shutdown. When the run finishes, attach and the completion entry may show claude_session_id. Reopen the Claude-side transcript with:

    bash
    claude --resume <session-id>

    /limits probes Claude Code /usage through a PTY when you are signed in (Claude still owns the token) and falls back to last-observed windows if that probe fails.

Quick checklist ​

StepCommand or field
Installclaude on PATH
Sign in/login claude-code
Defineruntime: claude-cli + Claude tools: / model:
Permission modePlan or Bypass. Auto / Allow edits only with proven no-prompt tools: for that Rho class and inherit_claude_config: false. Unknown names fail closed
LaunchRho parent agent tool, delegated only
Inspectrho attach <id>, /agents, /limits
Full Claude transcriptclaude --resume <session-id>

Claude CLI execution details ​

A runtime: claude-cli agent runs as claude -p with stream-json output. Rho owns the parent tree node; Claude owns the child loop and credential.

Before spawn, Rho checks claude auth status. If the binary is missing or the user is signed out, the run fails immediately with a message pointing at /login claude-code. Rho never stores Claude tokens.

Spawn flags are fixed and deliberate:

FlagBehaviour
--output-format stream-json --verbose --include-partial-messagesNDJSON event stream with partial text
--input-format stream-jsonNDJSON user turns on stdin so the parent can course-correct a live child
--permission-modeAlways set from a Claude-native mode. Delegated runs map Rho Plan to Claude plan and Rho Bypass to Claude bypassPermissions (just run; not Claude classifier auto). Rho Auto / Allow edits map to Claude dontAsk only when every declared tool is a proven no-prompt Claude built-in for that Rho approval class and inherit_claude_config is false. Claude dontAsk also auto-approves read-only Bash and PreToolUse hooks, and --allowedTools runs listed tools without prompting, so a specifier such as Bash(git *) (emitted as --tools Bash), write/process tools, unknown Claude/plugin/MCP names, or inherited settings refuse spawn rather than over-claim a deny-closed --allowedTools fence. Advisor one-shots set Claude dontAsk directly, with no tools. Supervised refuses before spawn.
--disallowedTools Task,AgentBlocks Claude nested subagents (legacy Task and current Agent) so fan-out stays under Rho
--toolsRestricts built-in tool availability to the base Claude tool names from tools:. A specifier such as Bash(git *) still lists Bash, and unknown names have no proven Rho class, which is why Auto / Allow edits refuse those shapes under dontAsk. Empty allowlist still sets --tools "" so ambient tools are not inherited
--allowedToolsEvery declared non-nested-agent tool entry from tools: as separate argv values (bare names such as Read and patterns such as Bash(git *)). Task and Agent are never listed here
--setting-sourcesEmpty for Claude dontAsk so user, project, and local hooks and allow rules cannot widen the child. Org-managed Claude policy still applies. Otherwise project by default, or user,project,local when inherit_claude_config: true
--strict-mcp-configMCP servers only from what the spawn passes
--system-prompt-file / --append-system-prompt-fileFrom the agent definition body plus the delegated-child communication contract. prompt: replace writes a private run-dir file and passes --system-prompt-file; prompt: extend uses --append-system-prompt-file, even when the definition body is empty, because the contract is always included. Prompt body bytes never appear on argv
--modelFrom the agent model: field when set, passed through unchanged. Omitted when the definition inherits Claude's model. Parent provider/model updates do not overwrite Claude agents
--effortFrom agent reasoning: when set (low, medium, high, xhigh, max). Omitted when unset so Claude keeps its default. off and minimal never reach spawn
--max-turnsExact configured step/turn cap from the bound launch data. If the installed binary rejects the flag, the run fails with a clear error
--no-session-persistenceDelegated agent runs omit it, so claude --resume <session-id> works. Rho's own one-shot calls, such as a Claude Code advisor, set it and leave no session behind
cwdExplicit project directory
promptFirst stream-json user turn on stdin, not argv

Parents can message a running Claude-cli child with the agents action message. Rho keeps stdin open, writes each body as another stream-json user turn (Claude queues it until the current turn ends), and closes stdin after the terminal result when no parent messages remain. Each parent message counts against --max-turns. Claude children do not get message_parent yet.

Stderr goes to log.txt in the run directory. Cancel kills the child. Terminal success or failure comes from the stream result message (subtype / is_error), not exit code alone.

Usage, limits, and resume ​

Per-run usage (turns, tokens, cost) comes from Claude's terminal result and is stored on result.json. Cache read/write token fields stay separate on attachment usage events; input_tokens on the status file is the total input including cache so attach metrics stay consistent.

/limits probes the signed-in claude TUI /usage panel over a PTY and shows remaining percentages when the panel includes them. Rho never reads Claude's credential files. If the probe fails, /limits keeps last-observed windows from a prior claude-cli run.

The probe forces classic rendering in its child environment so inherited fullscreen preferences or Claude's automatic renderer fallback do not change the panel layout. Your normal Claude renderer settings are unchanged.

Percentages shown while Claude is still refreshing are not treated as live usage. The probe waits for refresh completion and reads the completed panel. A refresh timeout, load error, or last-known/partial-data fallback leaves the previous observations unchanged rather than stamping cached percentages as newly fetched. The probe does not retry a failed refresh automatically.

When a run finishes, result.json may include claude_session_id. Attach and the parent completion entry show it so you can reopen the full Claude transcript with:

bash
claude --resume <session-id>

Default concurrency is one global pool of 10 delegated runs (behavior.agent_concurrency in config). RHO_AGENT_CONCURRENCY is no longer read. /config → Agent behavior → Concurrent agents changes the live cap immediately. Claude-cli runs also take a nested Claude permit capped at 2 by default (RHO_CLAUDE_AGENT_CONCURRENCY overrides that nested cap). The Claude pool is always min(total, claude_cap), so the nested env cannot open a 2N fan-out window and Claude never exceeds the global total. The named max is 64.

Auth ownership ​

ActionOwner
Sign inClaude Code via /login claude-code (terminal handoff to claude auth login --claudeai)
Sign outClaude Code via /logout claude-code or claude auth logout (global, not Rho-only)
Credential storageClaude binary only. Rho never sees or stores the token