Claude Code provides TypeScript and Python SDKs for programmatic access, enabling integration into applications, scripts, and automated workflows.
Comprehensive TypeScript SDK for Node.js applications and scripts.
// Installation
npm install @anthropic-ai/claude-code
// Basic setup
import { ClaudeCodeSDK } from '@anthropic-ai/claude-code';
const sdk = new ClaudeCodeSDK({
apiKey: process.env.ANTHROPIC_API_KEY,
workingDirectory: '/path/to/project'
});interface ClaudeCodeSDK {
// Session management
createSession(options?: SessionOptions): Promise<Session>;
// Permission management
canUseTool(toolName: string): boolean;
getPermissions(): ToolPermissions;
// Event handling
onUserInput(callback: (input: string) => void): void;
onToolExecution(callback: (tool: string, input: any) => void): void;
onError(callback: (error: Error) => void): void;
// Request management
cancelRequest(requestId: string): void;
getActiveRequests(): string[];
}
interface SessionOptions {
apiKey?: string;
model?: string;
workingDirectory?: string;
permissions?: ToolPermissions;
hooks?: HookConfiguration;
maxTokens?: number;
temperature?: number;
}
interface Session {
// Messaging
sendMessage(message: string): Promise<Response>;
sendMessageStream(message: string): AsyncIterable<ResponseChunk>;
// Custom tools
addCustomTool(name: string, callback: ToolCallback): void;
removeCustomTool(name: string): void;
listCustomTools(): string[];
// Session state
getConversationHistory(): ConversationMessage[];
clearHistory(): void;
saveSession(path: string): Promise<void>;
loadSession(path: string): Promise<void>;
// Configuration
updatePermissions(permissions: ToolPermissions): void;
getConfiguration(): SessionConfiguration;
}// Simple message exchange
const session = await sdk.createSession();
const response = await session.sendMessage("Fix the bug in auth.js");
console.log(response.content);
// Streaming responses
const session = await sdk.createSession();
for await (const chunk of session.sendMessageStream("Explain this codebase")) {
process.stdout.write(chunk.content);
}
// Custom tool integration
session.addCustomTool('custom-linter', async (input) => {
const { filePath } = input;
const results = await runCustomLinter(filePath);
return { results, success: true };
});
// Permission-controlled session
const session = await sdk.createSession({
permissions: {
allowedTools: ['Read(*)', 'Write(src/**/*.ts)'],
blockedTools: ['Bash(rm *)']
}
});// Automated code review
async function performCodeReview(files: string[]) {
const session = await sdk.createSession({
model: 'claude-3-opus-20240229',
permissions: {
allowedTools: [`Read(${files.join('|')})`]
}
});
const reviews = [];
for (const file of files) {
const response = await session.sendMessage(`Review code quality in ${file}`);
reviews.push({ file, review: response.content });
}
return reviews;
}
// Batch processing with error handling
async function batchProcess(tasks: string[]) {
const session = await sdk.createSession();
const results = [];
for (const task of tasks) {
try {
const response = await session.sendMessage(task);
results.push({ task, success: true, result: response.content });
} catch (error) {
results.push({ task, success: false, error: error.message });
}
}
return results;
}
// Custom hook integration
const session = await sdk.createSession({
hooks: {
PreToolUse: [
{
matcher: 'Write',
hooks: [
{
type: 'command',
command: 'node backup-file.js'
}
]
}
]
}
});Full-featured Python SDK for Python applications and automation scripts.
# Installation
pip install claude-code-sdk
# Basic setup
from claude_code_sdk import ClaudeCodeSDK
sdk = ClaudeCodeSDK(
api_key=os.getenv('ANTHROPIC_API_KEY'),
working_directory='/path/to/project'
)class ClaudeCodeSDK:
def __init__(self, api_key: str, working_directory: str = None):
"""Initialize SDK with API key and optional working directory"""
async def create_session(self, options: SessionOptions = None) -> Session:
"""Create a new Claude Code session"""
def can_use_tool(self, tool_name: str) -> bool:
"""Check if tool is permitted"""
def get_permissions(self) -> ToolPermissions:
"""Get current tool permissions"""
def on_user_input(self, callback: Callable[[str], None]):
"""Register callback for user input events"""
def cancel_request(self, request_id: str):
"""Cancel active request"""
class Session:
async def send_message(self, message: str) -> Response:
"""Send message and get response"""
async def send_message_stream(self, message: str) -> AsyncIterator[ResponseChunk]:
"""Send message and get streaming response"""
def add_custom_tool(self, name: str, callback: Callable):
"""Add custom tool with callback"""
def get_conversation_history(self) -> List[ConversationMessage]:
"""Get conversation history"""
async def save_session(self, path: str):
"""Save session to file"""
async def load_session(self, path: str):
"""Load session from file"""import asyncio
from claude_code_sdk import ClaudeCodeSDK
# Basic usage
async def main():
sdk = ClaudeCodeSDK(api_key="your-api-key")
session = await sdk.create_session()
response = await session.send_message("Fix the bug in auth.py")
print(response.content)
# Streaming responses
async def stream_example():
session = await sdk.create_session()
async for chunk in session.send_message_stream("Explain this codebase"):
print(chunk.content, end='')
# Custom tool integration
def custom_formatter(input_data):
file_path = input_data.get('file_path')
# Custom formatting logic
return {'formatted': True, 'path': file_path}
session.add_custom_tool('format-code', custom_formatter)
# Batch processing
async def batch_code_review(files):
session = await sdk.create_session(
options={'model': 'claude-3-opus-20240229'}
)
reviews = []
for file in files:
response = await session.send_message(f"Review {file}")
reviews.append({'file': file, 'review': response.content})
return reviews// Express.js API endpoint
app.post('/api/code-review', async (req, res) => {
try {
const { files } = req.body;
const session = await sdk.createSession({
permissions: {
allowedTools: files.map(f => `Read(${f})`)
}
});
const results = [];
for (const file of files) {
const response = await session.sendMessage(`Review ${file}`);
results.push({ file, review: response.content });
}
res.json({ success: true, results });
} catch (error) {
res.status(500).json({ error: error.message });
}
});# Python CLI tool
import click
from claude_code_sdk import ClaudeCodeSDK
@click.command()
@click.argument('task')
@click.option('--files', multiple=True)
async def claude_cli(task, files):
"""Claude Code CLI wrapper"""
sdk = ClaudeCodeSDK(api_key=os.getenv('ANTHROPIC_API_KEY'))
session = await sdk.create_session()
if files:
for file in files:
await session.send_message(f"Read {file}")
response = await session.send_message(task)
click.echo(response.content)
if __name__ == '__main__':
asyncio.run(claude_cli())// GitHub Actions workflow integration
async function runCodeReview() {
const sdk = new ClaudeCodeSDK({
apiKey: process.env.ANTHROPIC_API_KEY
});
const session = await sdk.createSession({
permissions: {
allowedTools: ['Read(*)', 'Bash(git diff *)']
}
});
// Get changed files
const changedFiles = await session.sendMessage("git diff --name-only HEAD~1");
// Review each file
const review = await session.sendMessage(
`Review the code changes in: ${changedFiles.content}`
);
// Post review as PR comment
await postPRComment(review.content);
}try {
const response = await session.sendMessage("Complex task");
console.log(response.content);
} catch (error) {
if (error instanceof PermissionError) {
console.error('Permission denied:', error.message);
} else if (error instanceof RateLimitError) {
console.error('Rate limit exceeded:', error.retryAfter);
} else if (error instanceof NetworkError) {
console.error('Network error:', error.message);
} else {
console.error('Unknown error:', error);
}
}
// Event-based error handling
sdk.onError((error) => {
console.error('SDK Error:', error);
// Log to monitoring service
monitor.logError(error);
});from claude_code_sdk import ClaudeCodeSDK, PermissionError, RateLimitError
try:
response = await session.send_message("Complex task")
print(response.content)
except PermissionError as e:
print(f"Permission denied: {e}")
except RateLimitError as e:
print(f"Rate limit exceeded. Retry after: {e.retry_after}")
except Exception as e:
print(f"Unexpected error: {e}")// Jest test example
import { ClaudeCodeSDK } from '@anthropic-ai/claude-code';
describe('Claude Code Integration', () => {
let sdk: ClaudeCodeSDK;
beforeEach(() => {
sdk = new ClaudeCodeSDK({
apiKey: 'test-key',
baseURL: 'http://test-server'
});
});
test('should create session', async () => {
const session = await sdk.createSession();
expect(session).toBeDefined();
});
test('should handle custom tools', async () => {
const session = await sdk.createSession();
session.addCustomTool('test-tool', (input) => {
return { result: 'test-result' };
});
const response = await session.sendMessage('Use test-tool');
expect(response.content).toContain('test-result');
});
});// Enable debug logging
const sdk = new ClaudeCodeSDK({
apiKey: 'your-key',
debug: true,
logLevel: 'verbose'
});
// Custom logging
sdk.onToolExecution((tool, input) => {
console.log(`Tool executed: ${tool}`, input);
});
sdk.onUserInput((input) => {
console.log(`User input: ${input}`);
});
// Performance monitoring
const startTime = Date.now();
const response = await session.sendMessage("task");
const duration = Date.now() - startTime;
console.log(`Request completed in ${duration}ms`);// Reuse sessions for better performance
class ClaudeCodeManager {
private sessions = new Map<string, Session>();
async getSession(key: string): Promise<Session> {
if (!this.sessions.has(key)) {
const session = await this.sdk.createSession();
this.sessions.set(key, session);
}
return this.sessions.get(key)!;
}
async closeSession(key: string) {
const session = this.sessions.get(key);
if (session) {
await session.close();
this.sessions.delete(key);
}
}
}# Efficient batch processing
async def batch_process_files(files: List[str]):
session = await sdk.create_session()
# Load all files first
for file in files:
await session.send_message(f"Read {file}")
# Process in batch
file_list = ', '.join(files)
response = await session.send_message(f"Analyze these files: {file_list}")
return response.content