Skip to content

Input Messages (stdin)

Undocumented Protocol

The --input-format stream-json stdin protocol is officially undocumented. The following is reverse-engineered from working implementations. It may change without notice.

These NDJSON messages are written to Claude Code's stdin when using --input-format stream-json. Each message is a single JSON object followed by a newline (\n).

User Message

Send a chat message to Claude.

json
{"type":"user","message":{"role":"user","content":"What does this project do?"}}
FieldTypeDescription
type"user"Message type
message.role"user"Always "user"
message.contentstringThe message text

With createMessage:

typescript
claude.stdin.write(createMessage.user('What does this project do?'))

Tool Approval

Approve a pending tool execution. Send this after receiving a tool_use event.

json
{"type":"approve","tool_use_id":"toolu_abc123"}
FieldTypeDescription
type"approve"Approval type
tool_use_idstringThe id from the tool_use content block

With createMessage:

typescript
claude.stdin.write(createMessage.approve('toolu_abc123'))

Tool Denial

Deny a pending tool execution.

json
{"type":"deny","tool_use_id":"toolu_abc123"}

With createMessage:

typescript
claude.stdin.write(createMessage.deny('toolu_abc123'))

Tool Result with Content

Send a tool result with user-provided content. Used for interactive tools like AskUserQuestion.

json
{"type":"tool_result","tool_use_id":"toolu_abc123","content":"The user selected option B"}
FieldTypeDescription
type"tool_result"Result type
tool_use_idstringThe id from the tool_use content block
contentstringThe result content

With createMessage:

typescript
claude.stdin.write(createMessage.toolResult('toolu_abc123', 'The user selected option B'))

Abort (Mid-Turn)

Mid-turn abort is not done via stdin — it requires sending SIGINT to the Claude Code process.

typescript
import { kill } from 'process'

// Send SIGINT to abort the current turn
kill(claude.pid!, 'SIGINT')

WARNING

SIGINT aborts the current turn but does not kill the process. Claude Code handles it gracefully and waits for the next stdin message.

Message Flow Example

YOUR CODE                           CLAUDE CODE
   │                                     │
   │  user message ──────────────────>   │
   │                                     │  ← processes, starts thinking
   │   <──────────────── system/init     │
   │   <──────────────── assistant       │  (thinking)
   │   <──────────────── assistant       │  (thinking + text)
   │   <──────────────── assistant       │  (thinking + text + tool_use)
   │                                     │
   │  approve ───────────────────────>   │
   │                                     │  ← executes tool
   │   <──────────────── user            │  (tool_result)
   │   <──────────────── assistant       │  (new text)
   │   <──────────────── result          │  (turn complete)
   │                                     │

Not affiliated with or endorsed by Anthropic.