Quick answer

What is the Autohand RPC Mode integration?

Autohand RPC Mode exposes a newline-delimited JSON protocol over stdin and stdout. A parent process can start the CLI, send prompts and control messages, and consume structured events without parsing the interactive terminal interface.

Status
Available
Requires
A local process that can manage Autohand stdin, stdout, lifecycle, and any model-provider credentials.
Configure with
Start Autohand in RPC mode, send one JSON message per line, and keep stdout reserved for protocol events as documented below.
Best for
Custom interfaces, scripts, test harnesses, and process-level automation.

Know before you start: The host application owns process supervision, message ordering, secret injection, error handling, and protocol-version compatibility.

Overview

RPC mode enables headless operation of the Autohand CLI via a JSON-RPC protocol. This allows external applications to:

  • Send prompts and receive streaming responses
  • Monitor tool execution in real-time
  • Handle permission requests programmatically
  • Control auto-mode, plan mode, and YOLO mode
  • Manage skills and MCP servers
  • Build custom UIs and IDE extensions
  • Create automated pipelines with full agent control

Looking for session-managed connections? If you need persistent sessions, model switching, and editor-style integration, see ACP Mode instead.

Getting Started

Start RPC Mode

Launch Autohand in RPC mode:

# Basic RPC mode
autohand --mode rpc

# With options
autohand --mode rpc --model nvidia/nemotron-3-super-120b-a12b:free --ephemeral

# All options
autohand --mode rpc \
  --model <model-id> \
  --ephemeral \
  --thinking <level> \
  --config <path>

Protocol Basics

The protocol uses newline-delimited JSON (JSON Lines):

  • Commands: JSON objects sent to stdin, one per line
  • Responses: JSON objects with type: "response"
  • Events: JSON objects streamed during agent operation

Correlation IDs: Include an optional id field in commands. The corresponding response will include the same id for matching.

Core Commands

prompt

Send an instruction to the agent:

{"type": "prompt", "message": "Create a hello.ts file", "id": "1"}

// With file context
{"type": "prompt", "message": "Review this file", "mentions": ["src/index.ts"]}

abort

Cancel the current operation:

{"type": "abort"}

reset

Clear conversation context:

{"type": "reset"}

get_state

Get current agent state:

{"type": "get_state"}

// Response
{
  "type": "response",
  "command": "get_state",
  "success": true,
  "data": {
    "model": "nvidia/nemotron-3-super-120b-a12b:free",
    "provider": "openrouter",
    "workspace": "/path/to/project",
    "isProcessing": false,
    "contextPercent": 85,
    "messageCount": 5
  }
}

get_messages

Get conversation history:

{"type": "get_messages"}

get_history

Get the full session history including tool calls and results:

{"type": "get_history"}

// Response
{
  "type": "response",
  "command": "get_history",
  "success": true,
  "data": {
    "messages": [...],
    "toolCalls": [...],
    "totalTokens": 12500
  }
}

permission_response

Respond to a permission request:

{"type": "permission_response", "requestId": "perm-123", "approve": true}

Auto-Mode Commands

Control the autonomous execution mode programmatically. Auto-mode lets the agent work through tasks without requiring manual prompt-by-prompt interaction.

automode_start

Start auto-mode with an initial instruction:

{"type": "automode_start", "message": "Refactor the auth module", "id": "am-1"}

// Response
{
  "type": "response",
  "command": "automode_start",
  "success": true,
  "data": {"status": "running"}
}

automode_status

Check the current auto-mode status:

{"type": "automode_status"}

// Response
{
  "type": "response",
  "command": "automode_status",
  "success": true,
  "data": {
    "active": true,
    "paused": false,
    "turnsCompleted": 3,
    "turnsRemaining": 7
  }
}

automode_pause

Pause a running auto-mode session:

{"type": "automode_pause"}

automode_resume

Resume a paused auto-mode session:

{"type": "automode_resume"}

automode_cancel

Cancel auto-mode entirely:

{"type": "automode_cancel"}

automode_get_log

Get the auto-mode execution log:

{"type": "automode_get_log"}

// Response
{
  "type": "response",
  "command": "automode_get_log",
  "success": true,
  "data": {
    "entries": [
      {"turn": 1, "action": "Read file src/auth.ts", "timestamp": "..."},
      {"turn": 2, "action": "Edited src/auth.ts", "timestamp": "..."}
    ]
  }
}

Skill Commands

Manage the agent's skill registry programmatically.

get_skills_registry

List all available skills:

{"type": "get_skills_registry"}

// Response
{
  "type": "response",
  "command": "get_skills_registry",
  "success": true,
  "data": {
    "skills": [
      {
        "name": "commit",
        "description": "Create a git commit",
        "source": "builtin"
      },
      {
        "name": "review-pr",
        "description": "Review a pull request",
        "source": "plugin:code-review"
      }
    ]
  }
}

install_skill

Install a skill from a registry or path:

{
  "type": "install_skill",
  "source": "npm:@autohand/skill-tdd",
  "id": "sk-1"
}

// Response
{
  "type": "response",
  "command": "install_skill",
  "success": true,
  "data": {"name": "tdd", "installed": true}
}

MCP Commands

Manage Model Context Protocol servers and tools.

mcp_list_servers

List configured MCP servers:

{"type": "mcp_list_servers"}

// Response
{
  "type": "response",
  "command": "mcp_list_servers",
  "success": true,
  "data": {
    "servers": [
      {"name": "context7", "status": "connected", "tools": 2},
      {"name": "brave-search", "status": "connected", "tools": 1}
    ]
  }
}

mcp_list_tools

List all available MCP tools across servers:

{"type": "mcp_list_tools"}

// Response
{
  "type": "response",
  "command": "mcp_list_tools",
  "success": true,
  "data": {
    "tools": [
      {"name": "query-docs", "server": "context7"},
      {"name": "brave_web_search", "server": "brave-search"}
    ]
  }
}

mcp_get_server_configs

Get the full configuration for all MCP servers:

{"type": "mcp_get_server_configs"}

// Response
{
  "type": "response",
  "command": "mcp_get_server_configs",
  "success": true,
  "data": {
    "configs": {
      "context7": {
        "command": "npx",
        "args": ["-y", "@upstash/context7-mcp@latest"]
      }
    }
  }
}

mcp_set_vscode_tools

Configure MCP tools for VS Code integration. This syncs tool availability between the CLI and VS Code extension:

{
  "type": "mcp_set_vscode_tools",
  "tools": ["query-docs", "brave_web_search"]
}

mcp_invoke_response

Send the result of an MCP tool invocation back to the agent. Used when the host application handles tool execution:

{
  "type": "mcp_invoke_response",
  "toolCallId": "call_abc123",
  "result": {"content": "Search results..."}
}

Mode Commands

Control agent operation modes.

plan_mode_set

Toggle plan mode on or off. In plan mode, the agent designs an approach before making changes:

// Enable plan mode
{"type": "plan_mode_set", "enabled": true}

// Disable plan mode
{"type": "plan_mode_set", "enabled": false}

// Response
{
  "type": "response",
  "command": "plan_mode_set",
  "success": true,
  "data": {"planMode": true}
}

yolo_set

Toggle YOLO mode. When enabled, the agent auto-approves all tool executions without permission prompts:

// Enable YOLO mode
{"type": "yolo_set", "enabled": true}

// With specific patterns
{"type": "yolo_set", "enabled": true, "patterns": ["npm *", "git *"]}

// Response
{
  "type": "response",
  "command": "yolo_set",
  "success": true,
  "data": {"yolo": true}
}

Use YOLO mode with care: Auto-approving all operations can lead to unwanted changes. Consider using patterns to limit which commands are auto-approved.

File Change Commands

changes_decision

Accept or reject file changes proposed by the agent. When the agent writes or edits files, you can review and decide on each change:

// Accept changes
{
  "type": "changes_decision",
  "changeId": "chg-456",
  "decision": "accept"
}

// Reject changes
{
  "type": "changes_decision",
  "changeId": "chg-456",
  "decision": "reject"
}

// Response
{
  "type": "response",
  "command": "changes_decision",
  "success": true,
  "data": {"applied": true}
}

Events

Events are streamed to stdout during agent operation:

Event Description
agent_start Agent ready to accept commands
agent_end Agent shutting down
turn_start Started processing a prompt
turn_end Finished processing a prompt
message_start LLM response started
message_update Streaming content delta
message_end LLM response completed
tool_execution_start Tool execution started
tool_execution_update Tool output chunk
tool_execution_end Tool execution completed
permission_request Awaiting approval for action
automode_turn Auto-mode completed a turn
automode_complete Auto-mode finished all turns
file_change File was created, modified, or deleted
error Error occurred

Event Examples

// Turn lifecycle
{"type": "turn_start", "timestamp": "...", "data": {"instruction": "Create a file"}}
{"type": "turn_end", "timestamp": "...", "data": {"success": true}}

// Message streaming
{"type": "message_update", "timestamp": "...", "data": {"delta": "I'll create "}}

// Tool execution
{"type": "tool_execution_start", "timestamp": "...", "data": {
  "toolName": "write_file",
  "toolCallId": "call_abc",
  "args": {"path": "hello.ts"}
}}
{"type": "tool_execution_end", "timestamp": "...", "data": {
  "toolName": "write_file",
  "toolCallId": "call_abc",
  "success": true,
  "duration": 150
}}

// Permission request
{"type": "permission_request", "timestamp": "...", "data": {
  "requestId": "perm-123",
  "tool": "run_command",
  "message": "Execute: npm install?"
}}

// Auto-mode events
{"type": "automode_turn", "timestamp": "...", "data": {
  "turn": 3,
  "total": 10,
  "action": "Edited src/auth.ts"
}}
{"type": "automode_complete", "timestamp": "...", "data": {
  "turnsCompleted": 5,
  "success": true
}}

// File change
{"type": "file_change", "timestamp": "...", "data": {
  "path": "src/hello.ts",
  "action": "created",
  "changeId": "chg-456"
}}

Examples

Python Client

import subprocess
import json

proc = subprocess.Popen(
    ["autohand", "--mode", "rpc", "--ephemeral"],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    text=True
)

def send(cmd):
    proc.stdin.write(json.dumps(cmd) + "\n")
    proc.stdin.flush()

def read_events():
    for line in proc.stdout:
        yield json.loads(line)

# Wait for ready
for event in read_events():
    if event.get("type") == "agent_start":
        break

# Send prompt
send({"type": "prompt", "message": "Hello!", "id": "1"})

# Process events
for event in read_events():
    if event.get("type") == "message_update":
        print(event["data"]["delta"], end="", flush=True)

    if event.get("type") == "permission_request":
        # Handle permission
        send({
            "type": "permission_response",
            "requestId": event["data"]["requestId"],
            "approve": True
        })

    if event.get("type") == "turn_end":
        print()
        break

proc.terminate()

Node.js Client

const { spawn } = require("child_process");
const readline = require("readline");

const agent = spawn("autohand", ["--mode", "rpc", "--ephemeral"]);

const rl = readline.createInterface({ input: agent.stdout });

rl.on("line", (line) => {
    const event = JSON.parse(line);

    if (event.type === "message_update") {
        process.stdout.write(event.data.delta);
    }

    if (event.type === "permission_request") {
        agent.stdin.write(JSON.stringify({
            type: "permission_response",
            requestId: event.data.requestId,
            approve: true
        }) + "\n");
    }

    if (event.type === "turn_end") {
        console.log("\n--- Done ---");
    }
});

// Send prompt after ready
setTimeout(() => {
    agent.stdin.write(JSON.stringify({
        type: "prompt",
        message: "List files in current directory"
    }) + "\n");
}, 1000);

process.on("SIGINT", () => {
    agent.stdin.write(JSON.stringify({ type: "abort" }) + "\n");
    agent.kill();
});

Auto-Mode Example

import subprocess
import json

proc = subprocess.Popen(
    ["autohand", "--mode", "rpc"],
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    text=True
)

def send(cmd):
    proc.stdin.write(json.dumps(cmd) + "\n")
    proc.stdin.flush()

def read_events():
    for line in proc.stdout:
        yield json.loads(line)

# Wait for ready
for event in read_events():
    if event.get("type") == "agent_start":
        break

# Enable YOLO mode for auto-approval
send({"type": "yolo_set", "enabled": True, "patterns": ["git *"]})

# Start auto-mode
send({
    "type": "automode_start",
    "message": "Add unit tests for the auth module"
})

# Monitor progress
for event in read_events():
    if event.get("type") == "automode_turn":
        d = event["data"]
        print(f"Turn {d['turn']}/{d['total']}: {d['action']}")

    if event.get("type") == "automode_complete":
        print("Auto-mode finished!")
        break

proc.terminate()

Use Cases

IDE Extensions

Build VS Code, JetBrains, or Zed extensions that embed Autohand:

  • Spawn RPC process on extension activation
  • Send file context with mentions
  • Display streaming responses in editor panels
  • Handle permission requests via UI dialogs

Custom Web UIs

Create browser-based interfaces:

  • Backend spawns RPC process
  • WebSocket bridges JSON events to browser
  • React/Vue components render streaming output
  • Users approve/deny via web interface

CI/CD Integration

Programmatic control in pipelines:

  • Auto-approve safe operations with YOLO patterns
  • Use auto-mode for multi-step tasks
  • Collect structured output for reports
  • Chain multiple prompts in sequence

Error Handling

Failed commands return responses with success: false:

{
  "type": "response",
  "command": "prompt",
  "success": false,
  "error": "Agent is already processing a request"
}

// Parse errors
{
  "type": "response",
  "command": "parse",
  "success": false,
  "error": "Invalid JSON: Unexpected token..."
}

Always handle errors: Check success field in responses and listen for error events to handle failures gracefully.

Future Commands

These commands are planned for future releases:

  • Model: set_model, cycle_model, get_available_models
  • Thinking: set_thinking_level, cycle_thinking_level
  • Compaction: compact, set_auto_compaction

Common questions

RPC Mode integration FAQ

How do I configure the Autohand RPC Mode integration?

Start Autohand in RPC mode, send one JSON message per line, and keep stdout reserved for protocol events as documented below.

What does the Autohand RPC Mode integration require?

A local process that can manage Autohand stdin, stdout, lifecycle, and any model-provider credentials.

What limitations should I know about?

The host application owns process supervision, message ordering, secret injection, error handling, and protocol-version compatibility.