mirror of
https://github.com/anthropics/claude-code-sdk-python.git
synced 2025-12-23 09:19:52 +00:00
No description
## Summary This PR implements control protocol support in the Python SDK, aligning it with the TypeScript implementation pattern. The refactor introduces a Query + Transport separation to enable bidirectional communication between the SDK and CLI. ## Motivation The previous Python SDK implementation used a high-level abstraction in the Transport ABC (`send_request`/`receive_messages`) that couldn't handle bidirectional communication. This prevented support for: - Control messages from CLI to SDK that need responses - Hooks implementation - Dynamic permission mode changes - SDK MCP servers ## Changes ### Core Architecture Refactor 1. **New Query Class** (`src/claude_code_sdk/_internal/query.py`) - Manages control protocol on top of Transport - Handles control request/response routing - Manages initialization handshake with timeout - Supports hook callbacks and tool permission callbacks - Implements message streaming 2. **Refactored Transport ABC** (`src/claude_code_sdk/_internal/transport/__init__.py`) - Changed from high-level (`send_request`/`receive_messages`) to low-level (`write`/`read_messages`) interface - Now handles raw I/O instead of protocol logic - Aligns with TypeScript ProcessTransport pattern 3. **Updated SubprocessCLITransport** (`src/claude_code_sdk/_internal/transport/subprocess_cli.py`) - Simplified to focus on raw message streaming - Removed protocol logic (moved to Query) - Improved cleanup and error handling 4. **Enhanced ClaudeSDKClient** (`src/claude_code_sdk/client.py`) - Now uses Query for control protocol - Supports initialization messages - Better error handling for control protocol failures ### Control Protocol Features - **Initialization handshake**: SDK sends initialize request, CLI responds with supported commands - **Control message types**: - `initialize`: Establish bidirectional connection - `interrupt`: Cancel ongoing operations - `set_permission_mode`: Change permission mode dynamically - **Timeout handling**: 60-second timeout for initialization to handle CLI versions without control support ### Examples Updated `examples/streaming_mode.py` to demonstrate control protocol initialization and error handling. ## Testing - Tested with current CLI (no control protocol support yet) - gracefully falls back - Verified backward compatibility with existing `query()` function - Tested initialization timeout handling - Verified proper cleanup on errors ## Design Alignment This implementation closely follows the TypeScript reference: - `src/core/Query.ts` → `src/claude_code_sdk/_internal/query.py` - `src/transport/ProcessTransport.ts` → `src/claude_code_sdk/_internal/transport/subprocess_cli.py` - `src/entrypoints/sdk.ts` → `src/claude_code_sdk/client.py` ## Next Steps Once the CLI implements the control protocol handler, this will enable: - Hooks support - Dynamic permission mode changes - SDK MCP servers - Improved error recovery 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Ashwin Bhat <ashwin@anthropic.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Kashyap Murali <kashyap@anthropic.com> |
||
|---|---|---|
| .github/workflows | ||
| examples | ||
| scripts | ||
| src/claude_code_sdk | ||
| tests | ||
| .gitignore | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
Claude Code SDK for Python
Python SDK for Claude Code. See the Claude Code SDK documentation for more information.
Installation
pip install claude-code-sdk
Prerequisites:
- Python 3.10+
- Node.js
- Claude Code:
npm install -g @anthropic-ai/claude-code
Quick Start
import anyio
from claude_code_sdk import query
async def main():
async for message in query(prompt="What is 2 + 2?"):
print(message)
anyio.run(main)
Usage
Basic Query
from claude_code_sdk import query, ClaudeCodeOptions, AssistantMessage, TextBlock
# Simple query
async for message in query(prompt="Hello Claude"):
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text)
# With options
options = ClaudeCodeOptions(
system_prompt="You are a helpful assistant",
max_turns=1
)
async for message in query(prompt="Tell me a joke", options=options):
print(message)
Using Tools
options = ClaudeCodeOptions(
allowed_tools=["Read", "Write", "Bash"],
permission_mode='acceptEdits' # auto-accept file edits
)
async for message in query(
prompt="Create a hello.py file",
options=options
):
# Process tool use and results
pass
Working Directory
from pathlib import Path
options = ClaudeCodeOptions(
cwd="/path/to/project" # or Path("/path/to/project")
)
API Reference
query(prompt, options=None)
Main async function for querying Claude.
Parameters:
prompt(str): The prompt to send to Claudeoptions(ClaudeCodeOptions): Optional configuration
Returns: AsyncIterator[Message] - Stream of response messages
Types
See src/claude_code_sdk/types.py for complete type definitions:
ClaudeCodeOptions- Configuration optionsAssistantMessage,UserMessage,SystemMessage,ResultMessage- Message typesTextBlock,ToolUseBlock,ToolResultBlock- Content blocks
Error Handling
from claude_code_sdk import (
ClaudeSDKError, # Base error
CLINotFoundError, # Claude Code not installed
CLIConnectionError, # Connection issues
ProcessError, # Process failed
CLIJSONDecodeError, # JSON parsing issues
)
try:
async for message in query(prompt="Hello"):
pass
except CLINotFoundError:
print("Please install Claude Code")
except ProcessError as e:
print(f"Process failed with exit code: {e.exit_code}")
except CLIJSONDecodeError as e:
print(f"Failed to parse response: {e}")
See src/claude_code_sdk/_errors.py for all error types.
Available Tools
See the Claude Code documentation for a complete list of available tools.
Examples
See examples/quick_start.py for a complete working example.
License
MIT