claude_code Extension

claude_code Extension

This extension spawns the Claude Code CLI as a subprocess and exposes it to rill scripts. Scripts send prompts, invoke skills like /commit, and run named commands. The extension handles process lifecycle, timeout enforcement, and NDJSON stream parsing.

Each call returns a dict with the response text, token usage breakdown, cost in USD, exit code, and duration in ms. Typical uses: automated code review, commit generation, and PR workflows.

Quick Start

import { createRuntimeContext, prefixFunctions } from '@rcrsr/rill';
import { createClaudeCodeExtension } from '@rcrsr/rill-ext-claude-code';

const ext = createClaudeCodeExtension({ defaultTimeout: 60000 });
const functions = prefixFunctions('claude_code', ext);
const ctx = createRuntimeContext({ functions });

// Script: claude_code::prompt("Explain TCP handshakes")

Prerequisites

The extension requires two external dependencies:

  • node-pty (peer dependency) — Requires native compilation during install
  • claude binary — Must be in $PATH before factory call

The factory validates both requirements eagerly and throws on missing dependencies.

Configuration

import { createClaudeCodeExtension } from '@rcrsr/rill-ext-claude-code';

const ext = createClaudeCodeExtension({
  binaryPath: '/usr/local/bin/claude',  // default: 'claude'
  defaultTimeout: 60000,                // default: 1800000 (30 min)
  dangerouslySkipPermissions: true,     // default: true
  settingSources: '',                   // default: ''
});
ParameterTypeDefaultDescription
binaryPathstring'claude'Path to Claude CLI binary
defaultTimeoutnumber1800000Timeout in ms (max: 3600000)
dangerouslySkipPermissionsbooleantrueSkip permission checks
settingSourcesstring''Settings to load at startup

settingSources Values

Controls which Claude Code settings load before execution.

ValueEffect
'' (default)No settings. Disables plugins, MCP servers, slash commands.
'user'Load user settings (~/.claude/settings.json) including plugins.
'project'Load project settings (.claude/settings.json).
'user,project'Load both user and project settings.

Functions

prompt(text, options?) — Execute a Claude Code prompt:

claude_code::prompt("Explain TCP handshakes") => $result
$result.result       # Response text
$result.tokens       # Token usage breakdown
$result.cost         # Cost in USD
$result.duration     # Execution time in ms

skill(name, args?) — Execute a Claude Code skill:

claude_code::skill("commit", [message: "fix: resolve timeout bug"]) => $result
$result.result

command(name, args?) — Execute a Claude Code command:

claude_code::command("review-pr", [pr: "123"]) => $result
$result.result

All functions accept an options dict as the second parameter.

PromptOptions

Override timeout per call via options dict:

claude_code::prompt("Long task", [timeout: 300000]) => $result
OptionTypeDescription
timeoutnumberOverride defaultTimeout for this call

Result Dict

All 3 functions return the same structure:

FieldTypeDescription
resultstringCombined text output
tokensdictToken usage breakdown
tokens.promptnumberNon-cached prompt tokens
tokens.cacheWrite5mnumber5-minute cache write tokens
tokens.cacheWrite1hnumber1-hour cache write tokens
tokens.cacheReadnumberCache read tokens
tokens.outputnumberOutput tokens
costnumberTotal cost in USD
exitCodenumberCLI exit code (0 = success)
durationnumberExecution time in ms

Error Behavior

The extension validates inputs and process state at runtime.

Validation errors (empty input):

  • Empty prompt text throws RuntimeError RILL-R004: prompt text cannot be empty
  • Empty skill name throws RuntimeError RILL-R004: skill name cannot be empty
  • Empty command name throws RuntimeError RILL-R004: command name cannot be empty

Process errors:

  • Binary not found throws RuntimeError RILL-R004: claude binary not found
  • Timeout throws RuntimeError RILL-R004: Claude CLI timeout after Xms
  • Non-zero exit throws RuntimeError RILL-R004: Claude CLI exited with code X

Events

EventEmitted When
claude-code:promptPrompt completes
claude-code:skillSkill completes
claude-code:commandCommand completes
claude-code:errorAny operation fails

Test Host

A runnable example at packages/ext/claude-code/examples/test-host.ts demonstrates integration:

# Built-in demo
pnpm exec tsx examples/test-host.ts

# Inline expression
pnpm exec tsx examples/test-host.ts -e 'claude_code::prompt("Tell me a joke") -> log'

# Script file
pnpm exec tsx examples/test-host.ts script.rill

The test host wires the extension to the rill runtime with logging callbacks.

Low-Level Exports

Advanced use cases can import low-level utilities:

  • createStreamParser() — Parse NDJSON stream from Claude CLI
  • spawnClaudeCli() — Spawn process with timeout enforcement
  • extractResult() — Aggregate messages into result dict

See package source for implementation details.

See Also