SDK overview
Embed Claude Code in your own tools using the stdin/stdout control protocol. Reference for the SDK session API, message types, and output formats.
The Claude Code SDK is a control protocol for embedding Claude Code in other applications — IDEs, automation scripts, CI/CD pipelines, or any host that can spawn a subprocess and communicate over stdin/stdout.
Rather than exposing a library API directly, the SDK communicates with a running claude process over a structured JSON message stream. The host process sends user messages and control requests; the CLI process streams back assistant messages, tool progress events, and result payloads.
Note: The TypeScript types described on this page are exported from
@anthropic-ai/claude-codeunder theagentSdkTypesentry point. Control protocol types (prefixedSDKControl) are@alphaand subject to change.
How it works
1. Spawn a Claude Code process
Start claude with --output-format stream-json and --print (non-interactive mode). Pipe its stdin and stdout into your host process.
```bash
claude --output-format stream-json --print --verbose
```
For a persistent session that accepts multiple prompts over time, omit `--print` and instead send `SDKUserMessage` objects to stdin after the session initializes.
2. Send an initialize request
Write a control_request with subtype: "initialize" to stdin. The CLI responds with an SDKControlInitializeResponse containing available commands, models, agents, and account information.
```json
{
"type": "control_request",
"request_id": "init-1",
"request": {
"subtype": "initialize",
"systemPrompt": "You are a code reviewer.",
"appendSystemPrompt": "Always suggest tests."
}
}
```
3. Stream messages from stdout
Read newline-delimited JSON from stdout. Each line is one of the SDKMessage union types — assistant turns, tool progress, system events, and result summaries.
4. Send user messages
Write SDKUserMessage objects to stdin to continue the conversation. Each message contains an Anthropic API-compatible message payload.
Output formats
Pass --output-format to control what Claude Code writes to stdout.
| Format | Description |
|---|---|
text | Plain text responses only. Default for interactive mode. |
json | Single JSON object written at completion. Suitable for one-shot scripts. |
stream-json | Newline-delimited JSON stream. One message per line, emitted as events occur. Required for SDK use. |
Tip: Use
stream-jsonwhen you need to render progress incrementally or handle tool events. Usejsonwhen you only care about the final result.
Control protocol messages
The control protocol uses two top-level envelope types that flow bidirectionally over stdin/stdout.
SDKControlRequest
Sent to the CLI process to configure the session or issue commands.
{
"type": "control_request",
"request_id": "<unique-string>",
"request": { "subtype": "...", ...payload }
}
-
type(literal: 'control_request') — Always"control_request". -
request_id(string) — Unique identifier for this request. The CLI echoes it back in the correspondingcontrol_response. -
request(SDKControlRequestInner) — The request payload.subtypeidentifies which operation to perform.
SDKControlResponse
Emitted from the CLI process in response to a control_request.
{
"type": "control_response",
"response": {
"subtype": "success",
"request_id": "<echoed-id>",
"response": { ...payload }
}
}
On error, subtype is "error" and the error field contains a human-readable message.
Initialize request and response
The initialize request is the first control message you must send. It configures the session and returns available capabilities.
SDKControlInitializeRequest
{
"type": "control_request",
"request_id": "init-1",
"request": {
"subtype": "initialize",
"systemPrompt": "You are a CI automation agent.",
"appendSystemPrompt": "Always add test coverage.",
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hookCallbackIds": ["my-hook-id"]
}
]
},
"agents": {
"CodeReviewer": {
"description": "Reviews code for quality and security.",
"prompt": "You are an expert code reviewer...",
"model": "opus"
}
}
}
}
-
subtype(literal: 'initialize') — Identifies this as an initialize request. -
systemPrompt(string) — Replaces the default system prompt for this session. -
appendSystemPrompt(string) — Appended to the system prompt without replacing it. Use this to add context while keeping the default behavior. -
hooks(Record) — Registers SDK-side hook callbacks. The CLI calls back into the SDK process when hook events fire. See Hooks reference. -
sdkMcpServers(string[]) — Names of in-process SDK MCP servers (created withcreateSdkMcpServer) to connect to this session. -
agents(Record<string, AgentDefinition>) — Custom subagent definitions available to theAgenttool during this session.Natural language description of when Claude should invoke this agent.
-
prompt(string) — System prompt for this agent. -
model(string) — Model alias ("sonnet","opus","haiku") or full model ID. Defaults to inheriting the parent model. -
tools(string[]) — Allow-list of tool names. When omitted, the agent inherits all tools. -
disallowedTools(string[]) — Tools explicitly blocked for this agent. -
maxTurns(number) — Maximum agentic turns before the agent stops. -
permissionMode(PermissionMode) — Override permission mode for this agent. See Permissions API.
SDKControlInitializeResponse -
The CLI responds with the session's current capabilities.
{
"type": "control_response",
"response": {
"subtype": "success",
"request_id": "init-1",
"response": {
"commands": [...],
"agents": [...],
"output_style": "stream-json",
"available_output_styles": ["text", "json", "stream-json"],
"models": [...],
"account": {
"email": "user@example.com",
"organization": "Acme Corp",
"apiProvider": "firstParty"
}
}
}
}
-
commands(SlashCommand[]) — Available slash commands (e.g.,/compact,/cost). Each entry hasname,description, andargumentHint. -
agents(AgentInfo[]) — Available subagent types. Each hasname,description, and an optionalmodel. -
output_style(string) — The active output format ("stream-json","json","text"). -
models(ModelInfo[]) — Available models for this account.Model identifier for API calls (e.g.,
"claude-sonnet-4-6").-
displayName(string) — Human-readable name (e.g.,"Claude Sonnet 4.6"). -
supportsEffort(boolean) — Whether this model supports effort levels. -
supportsAdaptiveThinking(boolean) — Whether this model supports adaptive thinking (Claude decides when and how much to think). -
account(AccountInfo) — Logged-in account details.
Account email address.
-
organization(string) — Organization name. -
subscriptionType(string) — Subscription tier. -
apiProvider('firstParty' | 'bedrock' | 'vertex' | 'foundry') — Active API backend. Anthropic OAuth only applies when"firstParty".
-
User messages
Send user messages to stdin to drive the conversation forward.
SDKUserMessage
{
"type": "user",
"message": {
"role": "user",
"content": "Refactor this function to use async/await."
},
"parent_tool_use_id": null
}
-
type(literal: 'user') — Always"user". -
message(APIUserMessage) — An Anthropic API-compatible user message.contentcan be a string or a content block array (for images and other media). -
parent_tool_use_id(string | null) — Tool use ID this message is responding to, ornullfor top-level user messages. -
uuid(string) — Optional UUID to track this message. Echoed back in related events. -
priority('now' | 'next' | 'later') — Scheduling hint for async message queuing.
SDK message stream types
Claude Code emits a stream of JSON messages to stdout. The type field identifies each message.
system — session initialization
Emitted once at session start with subtype: "init". Contains the active model, tool list, MCP server statuses, permission mode, and session ID.
```json
{
"type": "system",
"subtype": "init",
"model": "claude-sonnet-4-6",
"tools": ["Bash", "Read", "Write", "Edit", "Glob", "Grep"],
"mcp_servers": [],
"permissionMode": "default",
"session_id": "abc123",
"uuid": "..."
}
```
assistant — model response
Emitted when the model produces a turn. Contains the full Anthropic API response object, including any tool_use blocks.
```json
{
"type": "assistant",
"message": { "role": "assistant", "content": [...] },
"parent_tool_use_id": null,
"uuid": "...",
"session_id": "abc123"
}
```
stream_event — partial streaming tokens
Emitted during streaming with RawMessageStreamEvent payloads. Use these to render incremental output.
tool_progress — long-running tool status
Emitted periodically for tools that take more than a few seconds (e.g., Bash commands). Contains tool_name, tool_use_id, and elapsed time.
result — final turn summary
Emitted at the end of each turn. subtype is "success" or one of the error subtypes.
```json
{
"type": "result",
"subtype": "success",
"result": "The function has been refactored.",
"duration_ms": 4200,
"total_cost_usd": 0.0042,
"num_turns": 3,
"is_error": false,
"stop_reason": "end_turn",
"session_id": "abc123",
"uuid": "..."
}
```
Error subtypes: `"error_during_execution"`, `"error_max_turns"`, `"error_max_budget_usd"`, `"error_max_structured_output_retries"`.
system — status updates
Emitted with subtype: "status" when the permission mode or session status changes (e.g., "compacting").
Other control requests
Beyond initialize, the control protocol exposes these operations.
subtype | Direction | Description |
|---|---|---|
interrupt | host → CLI | Interrupt the current turn. |
set_permission_mode | host → CLI | Change the active permission mode. |
set_model | host → CLI | Switch to a different model mid-session. |
can_use_tool | CLI → host | Permission request for a tool call (requires SDK permission handler). |
mcp_status | host → CLI | Get MCP server connection statuses. |
mcp_set_servers | host → CLI | Replace dynamically managed MCP servers. |
get_context_usage | host → CLI | Get context window usage breakdown. |
get_settings | host → CLI | Read the effective merged settings. |
apply_flag_settings | host → CLI | Merge settings into the flag settings layer. |
rewind_files | host → CLI | Revert file changes made since a given message. |
hook_callback | CLI → host | Deliver a hook event for an SDK-registered hook callback. |
reload_plugins | host → CLI | Reload plugins from disk. |
Session management API
For scripting scenarios, the SDK exports functions that operate on saved session transcripts stored in ~/.claude/.
import {
query,
listSessions,
getSessionInfo,
getSessionMessages,
forkSession,
renameSession,
tagSession,
} from '@anthropic-ai/claude-code'
query — run a prompt
The primary SDK entry point. Accepts a prompt string or AsyncIterable and returns an async iterable of SDKMessage.
```typescript
for await (const message of query({
prompt: 'What files are in this directory?',
options: { cwd: '/my/project' }
})) {
if (message.type === 'result') {
console.log(message.result)
}
}
```
listSessions — list saved sessions
Returns session metadata for a project directory. Pass dir to scope to a specific project, or omit to list all sessions.
```typescript
const sessions = await listSessions({ dir: '/my/project', limit: 50 })
```
getSessionMessages — read a transcript
Parses the JSONL transcript file for a session and returns messages in chronological order.
```typescript
const messages = await getSessionMessages(sessionId, {
dir: '/my/project',
includeSystemMessages: false,
})
```
forkSession — branch a conversation
Copies a session's transcript into a new session with remapped UUIDs. Supports upToMessageId to fork from a specific point.
```typescript
const { sessionId: newId } = await forkSession(originalSessionId, {
upToMessageId: 'msg-uuid',
title: 'Experimental branch',
})
```
renameSession and tagSession
await renameSession(sessionId, 'My refactor session')
await tagSession(sessionId, 'needs-review')
await tagSession(sessionId, null) // clear tag
```
***
## Use cases
#### IDE integration
IDEs can spawn a persistent Claude Code process and route messages through the control protocol. Send the `initialize` request with a custom `systemPrompt` that describes the IDE context, then forward user messages from the editor's chat panel. Use `PreToolUse` hook callbacks to intercept file edits and display diffs in the IDE's native UI before they are applied.
#### CI/CD automation
In CI pipelines, use `--output-format json` and `--print` for one-shot tasks:
```bash
result=$(echo "Review the diff and output pass/fail" | \
claude --output-format json --print \
--permission-mode bypassPermissions)
```
Parse the `result` field from the JSON output to extract the agent's response programmatically.
#### Headless agents
For long-running background agents, use `query()` from the TypeScript SDK with a streaming output format. Combine with `watchScheduledTasks` (internal) to fire tasks on cron schedules while keeping a persistent daemon process that maintains the WebSocket connection to claude.ai.