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.
{"type":"user","message":{"role":"user","content":"What does this project do?"}}| Field | Type | Description |
|---|---|---|
type | "user" | Message type |
message.role | "user" | Always "user" |
message.content | string | The message text |
With createMessage:
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.
{"type":"approve","tool_use_id":"toolu_abc123"}| Field | Type | Description |
|---|---|---|
type | "approve" | Approval type |
tool_use_id | string | The id from the tool_use content block |
With createMessage:
claude.stdin.write(createMessage.approve('toolu_abc123'))Tool Denial
Deny a pending tool execution.
{"type":"deny","tool_use_id":"toolu_abc123"}With createMessage:
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.
{"type":"tool_result","tool_use_id":"toolu_abc123","content":"The user selected option B"}| Field | Type | Description |
|---|---|---|
type | "tool_result" | Result type |
tool_use_id | string | The id from the tool_use content block |
content | string | The result content |
With createMessage:
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.
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)
│ │