Claude Code API

repository·main·Indexed 41 days ago

https://github.com/zhanghandong/claude-code-api-rs

A high-performance Rust-based gateway and SDK (cc-sdk v0.8) that provides an OpenAI-compatible RESTful API for the Claude Code CLI. It enables developers to use their Claude Code subscription as a direct LLM proxy or a full-featured agent, supporting stateful conversations via InteractiveClient, one-shot queries, and programmatic tool permission control through the CanUseTool trait.

Tokens
84.8K
Snippets
228
Records
319
Agent score
73%

What's inside Claude Code API

  1. Handle Agent Hook Events

    main

    The SDK supports several hook events that allow you to react to the agent's lifecycle and internal processes. Key events include:

    • SubagentStart / SubagentStop: Triggered when a subagent begins or finishes a task.
    • PreCompact: Triggered before context compaction (manual or auto).
    • Notification: Triggered when the agent sends a notification (includes message, title, and notification_type).
    • PermissionRequest: Triggered when the agent requests permission to use a tool (includes tool_name, tool_input, and permission_suggestions).
  2. How Interactive Sessions work

    main

    The Interactive Session feature allows the Claude Code API to reuse the same Claude process for multiple requests within the same conversation. This improves performance by avoiding the overhead of creating new processes for each request.

    Key Benefits:

    • Faster Response Times: Subsequent requests in a conversation typically take 1-3 seconds compared to 5-15 seconds for new processes.
    • Context Preservation: The Claude process maintains context between requests, enabling multi-turn conversations.
    • Resource Efficiency: Reuses existing processes instead of spawning new ones.

    Lifecycle:

    1. A request is sent with a conversation_id.
    2. If a session exists for that ID, the message is sent to the existing process.
    3. If no session exists, a new process is started and associated with that ID.
    4. Sessions are automatically cleaned up after 30 minutes of inactivity.
    # First request - creates a new session
    curl -X POST http://localhost:8000/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{ "model": "claude-3-5-sonnet-20241022", "conversation_id": "my-session-123", "messages": [{ "role": "user", "content": "Hello!" }] }'
    
    # Second request - reuses the same session
    curl -X POST http://localhost:8000/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{ "model": "claude-3-5-sonnet-20241022", "conversation_id": "my-session-123", "messages": [{ "role": "user", "content": "What did I just say?" }] }'
  3. How account authentication works in cc-sdk

    main

    The cc-sdk uses the same account that the Claude CLI is currently logged in with at the system level.

    • Authentication is stored in system-wide config directories (e.g., ~/.config/claude/).
    • All terminal sessions share this authentication; it is not per-session or per-terminal.
    • To switch accounts, you must use Claude CLI commands (like claude followed by /login or logging out/in), not cc-sdk specific commands.
  4. Use OpenAI Tool Calling with Claude Code API

    main

    The Claude Code API supports the modern OpenAI tools format for AI tool integrations. It does not support the deprecated functions format.

    When you include a tools parameter in your request, the API analyzes Claude's response for JSON content (via direct parsing, markdown code blocks, or embedded objects) and converts matching JSON into an OpenAI-compatible tool_calls response.

    Note: The API does not execute the tools itself; it only handles the formatting of the tool call request from the model.

    {
      "model": "claude-3-5-haiku-20241022",
      "messages": [
        {
          "role": "user",
          "content": "Please preview this URL: https://example.com"
        }
      ],
      "tools": [
        {
          "type": "function",
          "function": {
            "name": "url_preview",
            "description": "Preview a URL and extract its content",
            "parameters": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string",
                  "description": "The URL to preview"
                }
              },
              "required": ["url"]
            }
          }
        }
      ],
      "tool_choice": "auto"
    }
  5. Understand the Unified Agent Abstraction Layer

    main

    The Claude Code SDK is designed with a unified abstraction layer that allows developers to interact with multiple AI agent backends (such as Claude Code CLI, Codex, or Direct APIs) through a single, consistent interface. This architecture enables dynamic provider switching based on specific task requirements.

    Core Design Principles

    • Multi-Backend Support: Seamlessly switch between different agent systems.
    • Dynamic Routing: Route tasks to specific providers based on their capabilities.
    • Unified Interface: Use a single API for all agent interactions, regardless of the underlying backend.
    • Extensibility: Easily add new providers (e.g., custom agents or Direct APIs) without changing the consumer-facing code.
  6. Understand Claude Code permission modes

    main

    The SDK supports different permission modes that control how Claude interacts with your system (e.g., file operations or tool usage):

    • Default: The CLI will prompt you for permission before performing dangerous operations. This mode is primarily used in interactive mode.
    • AcceptEdits: Automatically accepts edit prompts but still performs permission checks for other operations.
    • BypassPermissions: Bypasses all permission checks. Warning: Use with extreme caution; never use this in production or untrusted environments.

    Note on Query Mode vs Interactive Mode:

    • In query mode (using query()), file operations are not supported by default. To allow them, you must use BypassPermissions.
    • For interactive permission prompts, use ClaudeSDKClient.
  7. Advanced subagent patterns: Factory functions and Type Safety

    main

    To manage complex agent definitions in Rust, use these patterns:

    Type-Safe Tool Lists

    Avoid string typos by defining tool sets as constants:

    const READONLY_TOOLS: &[&str] = &["Read", "Grep", "Glob"];

    Agent Builder Pattern

    Implement a custom AgentBuilder struct to provide a fluent API for creating AgentDefinition objects. This encapsulates default values (like model: "sonnet") and provides helper methods for common tool configurations (e.g., .readonly_tools() or .editor_tools()).

    Model Selection Strategy

    Map task complexity to specific models to optimize cost and performance:

    • Simple tasks: haiku
    • Medium tasks: sonnet
    • Complex tasks: opus
    // Example of an Agent Builder pattern
    struct AgentBuilder {
        name: String,
        description: String,
        prompt: String,
        tools: Vec<String>,
        model: String,
    }
    
    impl AgentBuilder {
        fn new(name: impl Into<String>) -> Self {
            Self {
                name: name.into(),
                description: String::new(),
                prompt: String::new(),
                tools: Vec::new(),
                model: "sonnet".to_string(),
            }
        }
    
        fn readonly_tools(mut self) -> Self {
            self.tools = vec!["Read".into(), "Grep".into(), "Glob".into()];
            self
        }
    
        fn build(self) -> (String, AgentDefinition) {
            ( 
                self.name.clone(), 
                AgentDefinition { 
                    description: self.description, 
                    prompt: self.prompt, 
                    tools: Some(self.tools), 
                    model: Some(self.model) 
                } 
            )
        }
    }
  8. How to choose the right Claude model

    main

    Select a model based on your application's requirements for reasoning, speed, and cost:

    RequirementRecommended Model
    Complex reasoning, advanced coding, or agent/computer useOpus 4.5
    Balanced performance, general programming, or interactive chatSonnet 4.5
    General use with a focus on cost-effectivenessSonnet 4
    High-volume, simple queries, or minimal latencyHaiku 3.5
  9. Choose a subagent definition method

    main

    The Rust SDK provides three ways to define subagents, allowing you to balance flexibility, portability, and type safety:

    1. Programmatic Definition (agents()): Define agents directly in your Rust code using AgentDefinition.

      • Pros: Dynamic generation, no file dependencies, version-controlled in code, type-safe.
      • Cons: Cannot be shared across projects or used directly in the CLI.
      • Best for: CI/CD, automated testing, or session-specific agents.
    2. File System Definition (.claude/agents/): Define agents in Markdown files within the .claude/agents/ directory.

      • Pros: Team sharing, CLI compatibility, highly reusable.
      • Cons: Requires configuring setting_sources and introduces file dependencies.
      • Best for: Team collaboration and cross-project reuse.
    3. Hybrid Approach: Combine both programmatic and file-system definitions.

      • Pros: Maximum flexibility.
      • Cons: Increased management complexity.
      • Best for: Large-scale projects.
  10. How to create a custom MCP Server

    main

    You can extend Claude's capabilities by building your own MCP server. A custom server must implement the following interface:

    1. List Tools: Returns a list of available tools.
    2. Execute Tool: Executes a specific tool call.
    3. List Resources (Optional): Returns available resources.
    4. Read Resource (Optional): Reads a specific resource.

    Example configuration for a Python-based custom server:

    {
      "my-custom-server": {
        "command": "python",
        "args": ["/path/to/my_mcp_server.py"],
        "env": {
          "API_KEY": "your-api-key"
        }
      }
    }
  11. Understand the Core Trait Hierarchy for Agent Abstraction

    main

    The SDK uses a hierarchical trait system to provide a unified interface across different AI providers (like Claude Code or Codex).

    • AgentProvider: The top-level abstraction used to discover capabilities, estimate costs, and create sessions. It identifies the ProviderType (e.g., ClaudeCode, Codex, DirectAPI, or Custom).
    • AgentSession: The interface for interacting with an active agent. It allows sending UserInput, receiving a stream of AgentEvents, interrupting tasks, and retrieving usage statistics.

    This abstraction allows you to write code that works with any agent provider without knowing the underlying implementation details.

    #[async_trait]
    pub trait AgentProvider: Send + Sync {
        fn provider_type(&self) -> ProviderType;
        async fn create_session(&self, config: SessionConfig) -> Result<Box<dyn AgentSession>>;
        fn capabilities(&self) -> ProviderCapabilities;
        fn can_handle_task(&self, task: &TaskDescriptor) -> bool;
        async fn estimate_cost(&self, task: &TaskDescriptor) -> Result<CostEstimate>;
    }
    
    #[async_trait]
    pub trait AgentSession: Send + Sync {
        async fn send_input(&mut self, input: UserInput) -> Result<()>;
        fn receive_events(&mut self) -> Pin<Box<dyn Stream<Item = Result<AgentEvent>> + Send + '_>>;
        async fn interrupt(&mut self) -> Result<()>;
        async fn get_usage(&self) -> UsageStats;
        fn metadata(&self) -> &SessionMetadata;
        async fn close(self: Box<Self>) -> Result<()>;
    }
  12. What are Claude Code hooks and how do they work

    main

    Claude Code hooks are user-defined shell commands that execute at specific points in the Claude Code lifecycle. They provide deterministic control over the agent's behavior, allowing you to enforce rules (like formatting or security) through code rather than relying on LLM prompting.

    Key Use Cases:

    • Notifications: Trigger alerts when Claude is awaiting input.
    • Automatic formatting: Run tools like prettier or gofmt after file edits.
    • Logging: Track executed commands for compliance.
    • Feedback: Provide automated feedback on code quality.
    • Custom permissions: Block modifications to sensitive files or directories.

    Security Warning: Hooks run automatically during the agent loop using your current environment's credentials. Malicious hooks can exfiltrate data. Always review hook implementations before registering them.