### Install Agent SDK Backend Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Install the required Node.js package and verify the installation. ```bash # Install the Claude Agent SDK globally npm install -g @anthropic-ai/claude-agent-sdk # Verify installation node -e "import('@anthropic-ai/claude-agent-sdk').then(() => console.log('✓ Installed'))" ``` -------------------------------- ### Test Headless Backend Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Commands to install the Claude CLI and configure the environment for the headless backend. ```bash # 1. Install Claude CLI npm install -g @anthropic-ai/claude-code # 2. Set API key export ANTHROPIC_API_KEY="your-key" # 3. Run your Swift app with default config # Should use headless backend automatically ``` -------------------------------- ### Test Agent SDK Backend Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Commands to install the Agent SDK and configure the environment for the agent-based backend. ```bash # 1. Install Agent SDK npm install -g @anthropic-ai/claude-agent-sdk # 2. Set API key export ANTHROPIC_API_KEY="your-key" # 3. Configure your Swift app to use .agentSDK backend # Should use Agent SDK automatically ``` -------------------------------- ### Check SDK Availability Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Verify if Node.js is installed and if the Agent SDK is available in the environment. This is useful for ensuring the SDK can run correctly. ```swift import ClaudeCodeSDK // Check if Node.js is available if let nodePath = NodePathDetector.detectNodePath() { print("Node.js found at: \(nodePath)") } // Check if Agent SDK is installed if NodePathDetector.isAgentSDKInstalled() { print("✓ Agent SDK is installed") } else { print("ℹ Agent SDK not found, using headless backend") } ``` -------------------------------- ### Custom MCP Configuration for Filesystem and GitHub Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/Example/ClaudeCodeSDKExample/README.md Create custom MCP configurations for different servers like filesystem access or GitHub integration. For GitHub, replace 'your-github-token' with your actual token and ensure the '@modelcontextprotocol/server-github' package is installed. ```json { "mcpServers": { "filesystem": { "command": "npx", "args": [ "-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files" ] }, "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "your-github-token" } } } } ``` -------------------------------- ### Using Native Storage with ClaudeCodeClient Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Example of resuming a conversation using data from native session storage with the ClaudeCodeClient. ```APIDOC ## Using Native Storage with ClaudeCodeClient ### Description Demonstrates how to retrieve a past session from native storage and use it to resume a conversation with the `ClaudeCodeClient`. ### Method Various (primarily asynchronous methods) ### Endpoint N/A (SDK internal usage) ### Parameters None directly for this integration example, relies on `ClaudeNativeSessionStorage` and `ClaudeCodeClient` methods. ### Request Example ```swift let storage = ClaudeNativeSessionStorage() let client = ClaudeCodeClient() let projectPath = "/path/to/your/project" // Find a session to resume if let session = try await storage.getMostRecentSession(for: projectPath) { // Resume that specific session let result = try await client.resumeConversation( sessionId: session.id, prompt: "Continue where we left off", outputFormat: .text, options: nil ) print("Conversation resumed: \(result)") } else { print("No previous session found to resume.") } ``` ### Response #### Success Response (200) - **result** (ClaudeCodeResult) - The result of resuming the conversation. The exact structure depends on the `outputFormat` specified. #### Response Example ```json { "type": "text", "value": "Okay, continuing the conversation..." } ``` ### Error Handling - Throws an error if `getMostRecentSession` fails or if `resumeConversation` encounters an issue. ``` -------------------------------- ### Define NodePathDetector Utility Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Provides methods for auto-detecting Node.js, npm, and the Agent SDK installation paths. ```swift public struct NodePathDetector { public static func detectNodePath() -> String? public static func detectNpmPath() -> String? public static func isAgentSDKInstalled() -> Bool public static func getAgentSDKPath() -> String? } ``` -------------------------------- ### Example MCP Configuration for XcodeBuildMCP Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/Example/ClaudeCodeSDKExample/README.md This JSON configuration enables Claude Code to interact with Xcode build tools via the XcodeBuildMCP server. Ensure the 'npx' command is available in your environment. ```json { "mcpServers": { "XcodeBuildMCP": { "command": "npx", "args": [ "-y", "xcodebuildmcp@latest" ] } } } ``` -------------------------------- ### Detect Node.js and Agent SDK Paths Source: https://context7.com/jamesrochabrun/claudecodesdk/llms.txt Use NodePathDetector to locate Node.js, npm, and the Claude Agent SDK, or to verify installation status with custom configurations. ```swift import ClaudeCodeSDK // Detect Node.js executable path if let nodePath = NodePathDetector.detectNodePath() { print("Node.js found at: \(nodePath)") } else { print("Node.js not found") } // Detect npm executable path if let npmPath = NodePathDetector.detectNpmPath() { print("npm found at: \(npmPath)") } // Detect npm global bin directory if let globalPath = NodePathDetector.detectNpmGlobalPath() { print("npm global bin: \(globalPath)") } // Check if Agent SDK is installed if NodePathDetector.isAgentSDKInstalled() { print("Claude Agent SDK is installed") if let sdkPath = NodePathDetector.getAgentSDKPath() { print("SDK location: \(sdkPath)") } } else { print("Agent SDK not found. Install with:") print("npm install -g @anthropic-ai/claude-agent-sdk") } // Check with specific configuration var config = ClaudeCodeConfiguration.default config.nodeExecutable = "/custom/path/to/node" if NodePathDetector.isAgentSDKInstalled(configuration: config) { print("SDK available for configured node") } // Auto-configure backend based on availability var autoConfig = ClaudeCodeConfiguration.default autoConfig.backend = NodePathDetector.isAgentSDKInstalled() ? .agentSDK : .headless print("Using backend: \(autoConfig.backend.rawValue)") let client = try ClaudeCodeClient(configuration: autoConfig) ``` -------------------------------- ### Automatic NVM Path Detection with ClaudeCodeSDK Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Utilize the `NvmPathDetector` utility to automatically find and append nvm paths to the SDK's configuration, simplifying setup for Node.js projects managed by nvm. ```swift // Automatic nvm detection var config = ClaudeCodeConfiguration.default if let nvmPath = NvmPathDetector.detectNvmPath() { config.additionalPaths.append(nvmPath) } // Or use the convenience initializer let config = ClaudeCodeConfiguration.withNvmSupport() ``` -------------------------------- ### Resume Conversation using Native Storage and ClaudeCodeClient Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Integrates native session storage with the ClaudeCodeClient to resume past conversations. This example shows how to retrieve the most recent session and use its ID to continue the conversation with a new prompt. ```swift let storage = ClaudeNativeSessionStorage() let client = ClaudeCodeClient() // Find a session to resume if let session = try await storage.getMostRecentSession(for: projectPath) { // Resume that specific session let result = try await client.resumeConversation( sessionId: session.id, prompt: "Continue where we left off", outputFormat: .text, options: nil ) } ``` -------------------------------- ### Switch Backend at Runtime Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Demonstrates changing the backend configuration after client initialization with automatic validation and fallback. ```swift let client = try ClaudeCodeClient() // Starts with headless // Switch to Agent SDK (validates requirements first) client.configuration.backend = .agentSDK // If validation fails, automatically reverts to previous backend // No crashes, graceful degradation! ``` -------------------------------- ### ClaudeCodeClient Initialization - After Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Demonstrates the client initialization syntax after adopting the throwing initializer. This requires using `try` and provides immediate error handling for configuration issues. ```swift // After let client = try ClaudeCodeClient() ``` -------------------------------- ### Initialize ClaudeCodeClient Source: https://context7.com/jamesrochabrun/claudecodesdk/llms.txt Demonstrates basic client initialization, debug logging, custom configuration with the Agent SDK, and backend auto-detection. ```swift import ClaudeCodeSDK // Basic initialization with default configuration (headless backend) let client = try ClaudeCodeClient() // Initialize with debug logging enabled let debugClient = try ClaudeCodeClient(workingDirectory: "/path/to/project", debug: true) // Custom configuration with Agent SDK backend var config = ClaudeCodeConfiguration( backend: .agentSDK, command: "claude", workingDirectory: "/path/to/project", environment: ["API_KEY": "your-key"], enableDebugLogging: true, additionalPaths: [ "/usr/local/bin", "/opt/homebrew/bin", "\(NSHomeDirectory())/.nvm/versions/node/v22.11.0/bin" ], commandSuffix: nil ) let customClient = try ClaudeCodeClient(configuration: config) // Auto-detect best backend config.backend = NodePathDetector.isAgentSDKInstalled() ? .agentSDK : .headless let autoClient = try ClaudeCodeClient(configuration: config) ``` -------------------------------- ### Configure Execution Backends Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Select between headless and Agent SDK backends, or use auto-detection to choose the best available option. ```swift // Explicitly use headless backend (though it's the default) var config = ClaudeCodeConfiguration.default config.backend = .headless let client = ClaudeCodeClient(configuration: config) ``` ```swift // Use the new Agent SDK backend var config = ClaudeCodeConfiguration.default config.backend = .agentSDK let client = ClaudeCodeClient(configuration: config) ``` ```swift // Detects if Agent SDK is installed, falls back to headless var config = ClaudeCodeConfiguration.default config.backend = NodePathDetector.isAgentSDKInstalled() ? .agentSDK : .headless let client = ClaudeCodeClient(configuration: config) ``` -------------------------------- ### Run Quick Test Tool Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Executes the built-in test tool to verify configuration and backend availability. ```bash # Run the built-in test tool swift run QuickTest ``` -------------------------------- ### ClaudeCodeClient Initialization - Before Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Illustrates the client initialization syntax before the introduction of the throwing initializer, which did not provide immediate error feedback on configuration. ```swift // Before let client = ClaudeCodeClient() ``` -------------------------------- ### Initialize SDK with MCP Configuration File Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Load an external MCP configuration file into ClaudeCodeOptions. ```swift var options = ClaudeCodeOptions() options.mcpConfigPath = "/path/to/mcp-config.json" // MCP tools are automatically added with the format: mcp__serverName__toolName // The SDK will automatically allow tools like: // - mcp__filesystem__read_file // - mcp__filesystem__list_directory // - mcp__github__* let result = try await client.runSinglePrompt( prompt: "List all files in the project", outputFormat: .text, options: options ) ``` -------------------------------- ### Implement New Backend Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Steps to extend the SDK by creating a new backend class, registering it in the enum, and updating the factory. ```swift final class MyBackend: ClaudeCodeBackend { // Implement all protocol methods } ``` ```swift public enum BackendType { case headless case agentSDK case myBackend // Add new case } ``` ```swift case .myBackend: return MyBackend(configuration: config) ``` -------------------------------- ### Add Invalid Configuration Error Case to ClaudeCodeError Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Introduces a new error case `invalidConfiguration` to the `ClaudeCodeError` enum to handle specific configuration issues. This allows for more granular error reporting related to setup problems. ```swift public enum ClaudeCodeError: Error { // ... existing cases case invalidConfiguration(String) // NEW public var localizedDescription: String { // ... existing cases case .invalidConfiguration(let message): return "Invalid configuration: \(message)" } } ``` -------------------------------- ### Initialize and Run Claude Code Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Create a client instance and execute a single prompt using the SDK. ```swift import ClaudeCodeSDK // Initialize the client let client = ClaudeCodeClient(debug: true) // Run a simple prompt Task { do { let result = try await client.runSinglePrompt( prompt: "Write a function to calculate Fibonacci numbers", outputFormat: .text, options: nil ) switch result { case .text(let content): print("Response: \(content)") default: break } } catch { print("Error: \(error)") } } ``` -------------------------------- ### Initialize Headless Backend Client Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Initializes the ClaudeCodeClient using the default headless backend. ```swift import ClaudeCodeSDK // Default uses headless backend let client = try ClaudeCodeClient() let result = try await client.runSinglePrompt( prompt: "Write a hello world function", outputFormat: .json, options: nil ) ``` -------------------------------- ### Configure Permission Prompts Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Set permission mode and approval tool for non-interactive environments. ```swift var options = ClaudeCodeOptions() options.mcpConfigPath = "/path/to/mcp-config.json" options.permissionMode = .auto options.permissionPromptToolName = "mcp__permissions__approve" ``` -------------------------------- ### Run Single Prompt with Different Output Formats Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Execute a single prompt and retrieve the response in various formats: plain text, JSON with metadata, or as a stream of JSON chunks. ```swift // Get plain text let textResult = try await client.runSinglePrompt( prompt: "Write a sorting algorithm", outputFormat: .text, options: nil ) ``` ```swift // Get JSON with metadata let jsonResult = try await client.runSinglePrompt( prompt: "Explain big O notation", outputFormat: .json, options: nil ) ``` ```swift // Stream responses as they arrive let streamResult = try await client.runSinglePrompt( prompt: "Create a React component", outputFormat: .streamJson, options: nil ) ``` -------------------------------- ### HeadlessBackend Key Methods Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Defines the core methods for the HeadlessBackend, responsible for CLI logic. Supports various output formats and streaming. ```swift final class HeadlessBackend: ClaudeCodeBackend { func runSinglePrompt(...) -> ClaudeCodeResult func runWithStdin(...) -> ClaudeCodeResult func continueConversation(...) -> ClaudeCodeResult func resumeConversation(...) -> ClaudeCodeResult func listSessions() -> [SessionInfo] func validateSetup() -> Bool } ``` -------------------------------- ### Execute Single Prompts Source: https://context7.com/jamesrochabrun/claudecodesdk/llms.txt Shows how to run single prompts using text, JSON, and streaming output formats with the ClaudeCodeClient. ```swift import ClaudeCodeSDK let client = try ClaudeCodeClient(debug: true) // Text output format let textResult = try await client.runSinglePrompt( prompt: "Write a function to calculate Fibonacci numbers in Swift", outputFormat: .text, options: nil ) switch textResult { case .text(let content): print("Response: \(content)") case .json(let resultMessage): print("Session ID: \(resultMessage.sessionId ?? "none")") case .stream(let publisher): print("Received stream publisher") } // JSON output format with metadata let jsonResult = try await client.runSinglePrompt( prompt: "Explain big O notation", outputFormat: .json, options: nil ) if case .json(let result) = jsonResult { print("Session: \(result.sessionId ?? "unknown")") } // Streaming JSON output for real-time responses import Combine var cancellables = Set() let streamResult = try await client.runSinglePrompt( prompt: "Create a REST API endpoint in Swift", outputFormat: .streamJson, options: nil ) if case .stream(let publisher) = streamResult { publisher.sink( receiveCompletion: { completion in switch completion { case .finished: print("Stream completed") case .failure(let error): print("Stream error: \(error)") } }, receiveValue: { chunk in print("Received chunk: \(chunk)") } ) .store(in: &cancellables) } ``` -------------------------------- ### Configure Claude Code Options Source: https://context7.com/jamesrochabrun/claudecodesdk/llms.txt Sets up behavior parameters including models, system prompts, tool permissions, and session management for a single prompt execution. ```swift import ClaudeCodeSDK var options = ClaudeCodeOptions() // Basic options options.verbose = true options.maxTurns = 10 options.timeout = 300 // 5 minute timeout options.model = "claude-sonnet-4-20250514" options.fallbackModel = "claude-3-haiku-20240307" // System prompt configuration options.systemPrompt = "You are a senior Swift developer specializing in iOS applications." options.appendSystemPrompt = "Always include unit tests with your code examples." // Tool permissions options.allowedTools = ["Read", "Write", "Bash", "Glob", "Grep"] options.disallowedTools = ["Delete", "WebFetch"] // Permission modes: .default, .acceptEdits, .bypassPermissions, .plan options.permissionMode = .acceptEdits // Session management options.sessionId = "550e8400-e29b-41d4-a716-446655440000" options.forkSession = true // Create new session ID when resuming // Agent configuration options.agent = "code-reviewer" options.additionalDirectories = ["/shared/libs", "/common/utils"] // Execute with options let client = try ClaudeCodeClient() let result = try await client.runSinglePrompt( prompt: "Refactor this code for better performance", outputFormat: .json, options: options ) ``` -------------------------------- ### Configure MCP Servers Source: https://context7.com/jamesrochabrun/claudecodesdk/llms.txt Defines Model Context Protocol servers either via a configuration file or programmatically to extend agent capabilities. ```swift import ClaudeCodeSDK var options = ClaudeCodeOptions() // Option 1: Use a configuration file options.mcpConfigPath = "/path/to/mcp-config.json" // Option 2: Programmatic configuration options.mcpServers = [ "XcodeBuildMCP": .stdio(McpStdioServerConfig( command: "npx", args: ["-y", "xcodebuildmcp@latest"] )), "filesystem": .stdio(McpStdioServerConfig( command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"], env: ["NODE_ENV": "production"] )), "github": .stdio(McpStdioServerConfig( command: "npx", args: ["-y", "@modelcontextprotocol/server-github"], env: ["GITHUB_TOKEN": "ghp_xxxxxxxxxxxx"] )) ] // Allow specific MCP tools (format: mcp__serverName__toolName) options.allowedTools = [ "mcp__filesystem__read_file", "mcp__filesystem__write_file", "mcp__github__search_repositories", "mcp__XcodeBuildMCP__*" // Wildcard for all tools from a server ] options.strictMcpConfig = true // Only use MCP servers from config let client = try ClaudeCodeClient() let result = try await client.runSinglePrompt( prompt: "Build the iOS app and list all source files", outputFormat: .streamJson, options: options ) ``` -------------------------------- ### Initialize Agent SDK Backend Client Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Configures and initializes the ClaudeCodeClient to use the Agent SDK backend. ```swift import ClaudeCodeSDK // Configure for Agent SDK var config = ClaudeCodeConfiguration.default config.backend = .agentSDK let client = try ClaudeCodeClient(configuration: config) let result = try await client.runSinglePrompt( prompt: "Write a hello world function", outputFormat: .streamJson, // SDK only supports streaming options: nil ) ``` -------------------------------- ### Create Custom Client Configuration Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Initialize the Claude Code client with a custom configuration, specifying the command, working directory, environment variables, debug logging, additional paths, and command suffix. ```swift // Create a custom configuration var configuration = ClaudeCodeConfiguration( command: "claude", // Command to execute (default: "claude") workingDirectory: "/path/to/project", // Set working directory environment: ["API_KEY": "value"], // Additional environment variables enableDebugLogging: true, // Enable debug logs additionalPaths: ["/custom/bin"], // Additional PATH directories commandSuffix: "--" // Optional suffix after command (e.g., "claude --") ) // Initialize client with custom configuration let client = ClaudeCodeClient(configuration: configuration) // Or modify configuration at runtime client.configuration.enableDebugLogging = false client.configuration.workingDirectory = "/new/path" client.configuration.commandSuffix = "--" // Add suffix for commands like "claude -- -p --verbose" ``` -------------------------------- ### Execute Quick Test Tool Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Command to run the QuickTest executable, which is a tool for verifying various configurations and functionalities of the Claude Code SDK. ```bash swift run QuickTest ``` -------------------------------- ### ClaudeCodeClient Initialization Source: https://context7.com/jamesrochabrun/claudecodesdk/llms.txt Initialize the ClaudeCodeClient with various configuration options, including backend selection (headless CLI or Agent SDK), working directory, debug logging, and environment variables. ```APIDOC ## ClaudeCodeClient Initialization The main client for interacting with Claude Code. Supports both headless CLI backend and Agent SDK backend with configurable options. ### Description Initializes the `ClaudeCodeClient` for interacting with Claude Code. It supports both a traditional headless CLI mode and the newer Agent SDK backend, offering flexibility in integration. ### Initialization Examples **Basic initialization with default configuration (headless backend):** ```swift import ClaudeCodeSDK let client = try ClaudeCodeClient() ``` **Initialize with debug logging enabled:** ```swift let debugClient = try ClaudeCodeClient(workingDirectory: "/path/to/project", debug: true) ``` **Custom configuration with Agent SDK backend:** ```swift import ClaudeCodeSDK var config = ClaudeCodeConfiguration( backend: .agentSDK, command: "claude", workingDirectory: "/path/to/project", environment: ["API_KEY": "your-key"], enableDebugLogging: true, additionalPaths: [ "/usr/local/bin", "/opt/homebrew/bin", "\(NSHomeDirectory())" + ".nvm/versions/node/v22.11.0/bin" ], commandSuffix: nil ) let customClient = try ClaudeCodeClient(configuration: config) ``` **Auto-detect best backend:** ```swift config.backend = NodePathDetector.isAgentSDKInstalled() ? .agentSDK : .headless let autoClient = try ClaudeCodeClient(configuration: config) ``` ### Parameters `workingDirectory` (String?): The working directory for the Claude Code process. Defaults to the current directory. `debug` (Bool): Enables debug logging. Defaults to `false`. `configuration` (ClaudeCodeConfiguration): A custom configuration object for the client. ``` -------------------------------- ### ClaudeCodeClient Initialization and Backend Switching Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md The refactored ClaudeCodeClient acts as a lightweight wrapper. It initializes with a backend and supports runtime switching, with graceful fallback on failure. ```swift public final class ClaudeCodeClient: ClaudeCode { private var backend: ClaudeCodeBackend public var configuration: ClaudeCodeConfiguration { didSet { // Recreate backend if type changed if oldValue.backend != self.configuration.backend { do { backend = try BackendFactory.createBackend(for: self.configuration) logger?.info("Backend switched to: \(self.configuration.backend.rawValue)") } catch { // Gracefully revert on failure configuration = oldValue } } } } public init(configuration: ClaudeCodeConfiguration = .default) throws { self.configuration = configuration self.backend = try BackendFactory.createBackend(for: configuration) } // All methods delegate to backend public func runSinglePrompt(...) async throws -> ClaudeCodeResult { try await backend.runSinglePrompt(...) } // ... etc } ``` -------------------------------- ### Implement Node.js SDK Wrapper Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Executable script that bridges Swift to the TypeScript Agent SDK, outputting JSONL for compatibility. ```javascript #!/usr/bin/env node import { query } from '@anthropic-ai/claude-agent-sdk'; async function main() { const configJson = process.argv[2]; const config = JSON.parse(configJson); const { prompt, options = {} } = config; const sdkOptions = mapOptions(options); const result = query({ prompt, options: sdkOptions }); // Stream JSONL output compatible with headless mode for await (const message of result) { console.log(JSON.stringify(message)); } } ``` -------------------------------- ### runSinglePrompt - Execute Single Prompt Source: https://context7.com/jamesrochabrun/claudecodesdk/llms.txt Execute a single prompt to Claude Code and receive the response in various formats: plain text, JSON, or a streaming JSON publisher. ```APIDOC ## runSinglePrompt - Execute Single Prompt Runs a single prompt and returns the result in the specified format. This is the primary method for one-off queries to Claude Code. ### Description Executes a single prompt against the Claude Code model and returns the result. This method is suitable for straightforward, non-conversational requests. ### Method `runSinglePrompt` ### Parameters - **prompt** (String) - Required - The user's prompt to send to Claude Code. - **outputFormat** (OutputFormat) - Required - Specifies the desired format of the output. Options include `.text`, `.json`, and `.streamJson`. - **options** (PromptOptions?) - Optional - Additional options for the prompt execution, such as `maxTokens` or `temperature`. ### Output Formats - **`.text`**: Returns a plain text string. - **`.json`**: Returns a `ResultMessage` object containing structured JSON data and session information. - **`.streamJson`**: Returns a `Combine` publisher that emits chunks of JSON data as they become available. ### Request Example (Swift) ```swift import ClaudeCodeSDK import Combine let client = try ClaudeCodeClient(debug: true) var cancellables = Set() // Example 1: Text output let textResult = try await client.runSinglePrompt( prompt: "Write a function to calculate Fibonacci numbers in Swift", outputFormat: .text, options: nil ) if case .text(let content) = textResult { print("Response: \(content)") } // Example 2: JSON output with metadata let jsonResult = try await client.runSinglePrompt( prompt: "Explain big O notation", outputFormat: .json, options: nil ) if case .json(let result) = jsonResult { print("Session: \(result.sessionId ?? "unknown")") } // Example 3: Streaming JSON output let streamResult = try await client.runSinglePrompt( prompt: "Create a REST API endpoint in Swift", outputFormat: .streamJson, options: nil ) if case .stream(let publisher) = streamResult { publisher.sink( receiveCompletion: { switch $0 { case .finished: print("Stream completed") case .failure(let error): print("Stream error: \(error)") } }, receiveValue: { print("Received chunk: \($0)") } ) .store(in: &cancellables) } ``` ### Response The response is a `Result` enum that can be one of the following: - **`.text(String)`**: For `.text` output format. - **`.json(ResultMessage)`**: For `.json` output format. `ResultMessage` contains session ID and other metadata. - **`.stream(AnyPublisher)`**: For `.streamJson` output format. Provides a Combine publisher for streaming JSON chunks. #### Success Response Example (Conceptual) **For `.text`:** ``` "func fibonacci(_ n: Int) -> Int { if n <= 1 { return n } else { return fibonacci(n - 1) + fibonacci(n - 2) } }" ``` **For `.json`:** ```json { "sessionId": "some-session-id", "content": "Big O notation is a mathematical notation that describes the limiting behavior of a function when the argument tends towards a particular value or infinity. It is a type of asymptotic notation, providing a useful approximation for complex functions in computer science." } ``` **For `.streamJson`:** (Each chunk would be a JSON object, potentially partial) ```json { "sessionId": "another-session-id", "partialContent": "Big O notation is a mathematical notation..." } ``` ``` -------------------------------- ### Advanced Debugging: PATH and Environment Access Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Demonstrates how to access and utilize the PATH and environment variables from the last executed command for advanced debugging. ```APIDOC ## Advanced Debugging: PATH and Environment ### Description Accessing the `lastExecutedCommandInfo` property to retrieve and inspect the runtime PATH and environment variables is crucial for diagnosing issues like "command not found" errors or verifying environment variable configurations. ### Method Accessing the `lastExecutedCommandInfo` property on the SDK client. ### Example Usage (Swift) ```swift if let commandInfo = client.lastExecutedCommandInfo { // Debug "command not found" errors by checking the actual PATH used print("Actual PATH used:") commandInfo.pathEnvironment.split(separator: ":").forEach { path in print(" - \(path)") } // Check if specific environment variables were set if let nodeEnv = commandInfo.environment["NODE_ENV"] { print("NODE_ENV was set to: \(nodeEnv)") } // See what nvm version was actually used if let nvmPath = commandInfo.pathEnvironment.split(separator: ":").first(where: { $0.contains(".nvm") }) { print("Using nvm path: \(nvmPath)") } } ``` ### Key Information Extracted - **PATH Debugging**: Inspecting `pathEnvironment` to resolve "command not found" errors. - **Environment Variable Verification**: Checking specific variables within the `environment` dictionary. ``` -------------------------------- ### MCP Configuration Mapping to SDK Format Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Converts Swift MCP configuration to the SDK format for AgentSDKBackend. Handles both stdio and sse configurations. ```swift // Converts Swift MCP config to SDK format switch mcpServerConfig { case .stdio(let config): serverConfig = [ "command": config.command, "args": config.args, "env": config.env ] case .sse(let config): serverConfig = [ "type": "sse", "url": config.url, "headers": config.headers ] } ``` -------------------------------- ### Manage Multi-turn Conversations Source: https://context7.com/jamesrochabrun/claudecodesdk/llms.txt Demonstrates how to continue existing conversations or resume specific sessions using session IDs and branching via session forking. ```swift import ClaudeCodeSDK let client = try ClaudeCodeClient() // Start a conversation let firstResult = try await client.runSinglePrompt( prompt: "Create a User model in Swift with name, email, and age properties", outputFormat: .json, options: nil ) // Get session ID for later use let sessionId = firstResult.sessionId // Continue the most recent conversation let continuationResult = try await client.continueConversation( prompt: "Now add validation to ensure email is valid and age is positive", outputFormat: .text, options: nil ) // Resume a specific session by ID if let sessionId = sessionId { let resumeResult = try await client.resumeConversation( sessionId: sessionId, prompt: "Add a computed property for full display name", outputFormat: .text, options: nil ) if case .text(let content) = resumeResult { print("Resumed response: \(content)") } } // Fork a session to create a new branch var forkOptions = ClaudeCodeOptions() forkOptions.forkSession = true let forkedResult = try await client.resumeConversation( sessionId: sessionId!, prompt: "Try a different approach using Codable", outputFormat: .json, options: forkOptions ) ``` -------------------------------- ### Implement Retry Policies Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Execute prompts with default or custom exponential backoff retry strategies. ```swift // Simple retry with default policy let result = try await client.runSinglePromptWithRetry( prompt: "Generate code", outputFormat: .json, retryPolicy: .default // 3 attempts with exponential backoff ) // Custom retry policy let conservativePolicy = RetryPolicy( maxAttempts: 5, initialDelay: 5.0, maxDelay: 300.0, backoffMultiplier: 2.0, useJitter: true ) let result = try await client.runSinglePromptWithRetry( prompt: "Complex analysis", outputFormat: .json, retryPolicy: conservativePolicy ) ``` -------------------------------- ### Add Swift Package Dependency Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Include the SDK in your Package.swift file to manage dependencies. ```swift dependencies: [ .package(url: "https://github.com/jamesrochabrun/ClaudeCodeSDK", from: "1.0.0") ] ``` -------------------------------- ### AgentSDKBackend Key Methods Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Defines the core methods for the AgentSDKBackend, which uses a Node.js wrapper for the Claude Agent SDK. Supports only streamJson output. ```swift final class AgentSDKBackend: ClaudeCodeBackend { func runSinglePrompt(...) -> ClaudeCodeResult func runWithStdin(...) -> ClaudeCodeResult func continueConversation(...) -> ClaudeCodeResult func resumeConversation(...) -> ClaudeCodeResult func validateSetup() -> Bool } ``` -------------------------------- ### Configure ClaudeCodeConfiguration Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Extends the configuration struct to include backend selection and path properties for the Agent SDK. ```swift public struct ClaudeCodeConfiguration { public var backend: BackendType // NEW: Select backend public var command: String // For headless backend public var nodeExecutable: String? // NEW: For Agent SDK public var sdkWrapperPath: String? // NEW: Path to wrapper script // ... existing properties } ``` -------------------------------- ### Configure MCP Servers Programmatically Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Define MCP servers directly within Swift code using McpStdioServerConfig. ```swift var options = ClaudeCodeOptions() // Define MCP servers in code options.mcpServers = [ "XcodeBuildMCP": .stdio(McpStdioServerConfig( command: "npx", args: ["-y", "xcodebuildmcp@latest"] )), "filesystem": .stdio(McpStdioServerConfig( command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"] )) ] // The SDK creates a temporary configuration file automatically let result = try await client.runSinglePrompt( prompt: "Build the iOS app", outputFormat: .streamJson, options: options ) ``` -------------------------------- ### Debug PATH and Environment Variables in Swift Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Access `lastExecutedCommandInfo` to debug 'command not found' errors by printing the actual PATH used. Verify specific environment variables like NODE_ENV and identify the nvm path if applicable. ```swift if let commandInfo = client.lastExecutedCommandInfo { // Debug "command not found" errors by checking the actual PATH used print("Actual PATH used:") commandInfo.pathEnvironment.split(separator: ":").forEach { path in print(" - \(path)") } // Check if specific environment variables were set if let nodeEnv = commandInfo.environment["NODE_ENV"] { print("NODE_ENV was set to: \(nodeEnv)") } // See what nvm version was actually used if let nvmPath = commandInfo.pathEnvironment.split(separator: ":").first(where: { $0.contains(".nvm") }) { print("Using nvm path: \(nvmPath)") } } ``` -------------------------------- ### BackendFactory Create Backend Logic Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Factory method to create the appropriate ClaudeCodeBackend based on configuration. Includes validation for Node.js and Agent SDK. ```swift struct BackendFactory { static func createBackend(for config: ClaudeCodeConfiguration) throws -> ClaudeCodeBackend { switch config.backend { case .headless: return HeadlessBackend(configuration: config) case .agentSDK: // Validate Node.js availability guard NodePathDetector.detectNodePath() != nil else { throw ClaudeCodeError.invalidConfiguration("Node.js not found...") } // Validate Agent SDK installation guard NodePathDetector.isAgentSDKInstalled() else { throw ClaudeCodeError.invalidConfiguration("Agent SDK not installed...") } return AgentSDKBackend(configuration: config) } } static func validateConfiguration(_ config: ClaudeCodeConfiguration) -> Bool static func getConfigurationError(_ config: ClaudeCodeConfiguration) -> String? } ``` -------------------------------- ### Reproducing ClaudeCodeSDK Commands in Terminal Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Generate a terminal-ready command string from `lastExecutedCommandInfo` to easily reproduce and debug issues directly in your terminal. This includes setting the working directory and piping stdin if they were used. ```swift if let commandInfo = client.lastExecutedCommandInfo { var terminalCommand = "" // Add working directory if present if let workingDir = commandInfo.workingDirectory { terminalCommand += "cd \"\(workingDir)\" && " } // Add stdin if present if let stdin = commandInfo.stdinContent { terminalCommand += "echo \"\(stdin)\" | " } // Add the command terminalCommand += commandInfo.commandString print("Run this in Terminal:") print(terminalCommand) // Copy to clipboard if needed NSPasteboard.general.clearContents() NSPasteboard.general.setString(terminalCommand, forType: .string) } ``` -------------------------------- ### Configure Additional Paths for ClaudeCodeSDK Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md When subprocesses launched by ClaudeCodeSDK don't find executables (e.g., npm via nvm), add necessary paths to `additionalPaths` in the configuration. This ensures the SDK can locate tools in custom or nvm-managed directories. ```swift var config = ClaudeCodeConfiguration.default config.additionalPaths = [ "/usr/local/bin", "/opt/homebrew/bin", "/usr/bin", "\(NSHomeDirectory())/.nvm/versions/node/v22.11.0/bin", // Replace with your version ] ``` ```swift // For Homebrew on Apple Silicon config.additionalPaths.append("/opt/homebrew/bin") // For Homebrew on Intel Macs config.additionalPaths.append("/usr/local/bin") // For custom tools config.additionalPaths.append("/path/to/your/tools/bin") ``` -------------------------------- ### Display Migration Statistics Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Summary of file changes and line insertions/deletions for Phase 1. ```text 11 files changed 2,194 insertions(+) 18 deletions(-) ``` -------------------------------- ### Use Cases for Executed Command Information Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Outlines the various scenarios where the detailed information from `ExecutedCommandInfo` is beneficial. ```APIDOC ## Use Cases for Executed Command Information ### Description The detailed information captured by `ExecutedCommandInfo` is invaluable for a range of development and support activities. ### Applications - **Bug Reports**: Including exact command details ensures reproducibility and clarity. - **Terminal Reproduction**: Copy-pasting commands directly to the terminal for debugging. - **Support Tickets**: Providing precise command information to support teams for efficient issue resolution. - **Command Verification**: Confirming that commands are constructed and executed as intended. - **Debugging Failures**: Understanding the specifics of a failed command to identify the root cause. - **PATH Debugging**: Analyzing the runtime PATH to troubleshoot "command not found" errors. - **Environment Debugging**: Verifying that environment variables are correctly set and utilized at runtime. ``` -------------------------------- ### Quick Test Tool Execution Status Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Shows the passing status of all tests executed by the `swift run QuickTest` command, confirming the SDK's functionality across different scenarios. ```text ✅ swift run QuickTest - All tests pass! ``` -------------------------------- ### Access Claude CLI Session Storage Source: https://context7.com/jamesrochabrun/claudecodesdk/llms.txt Provides methods to interact with Claude CLI's native session storage, allowing you to list projects, retrieve specific sessions, and access conversation messages. Useful for analyzing past interactions or resuming conversations. ```swift import ClaudeCodeSDK // Initialize with default path (~/.claude/projects/) let storage = ClaudeNativeSessionStorage() // Or specify custom path let customStorage = ClaudeNativeSessionStorage(basePath: "/custom/path/to/sessions") // List all projects with sessions let projects = try await storage.listProjects() print("Projects with Claude sessions:") for project in projects { print(" - \(project)") } // Get all sessions for a specific project let projectPath = "/Users/me/projects/myapp" let sessions = try await storage.getSessions(for: projectPath) for session in sessions { print("Session: \(session.id)") print(" Created: \(session.createdAt)") print(" Last accessed: \(session.lastAccessedAt)") print(" Summary: \(session.summary ?? "No summary")") print(" Git branch: \(session.gitBranch ?? "unknown")") print(" Messages: \(session.messages.count)") } // Get most recent session for a project if let recentSession = try await storage.getMostRecentSession(for: projectPath) { print("Most recent session: \(recentSession.id)") // Access conversation messages for message in recentSession.messages { print("[\(message.role.rawValue)] \(message.content.prefix(100))...") print(" Timestamp: \(message.timestamp)") print(" Working dir: \(message.cwd ?? "unknown")") } } // Get a specific session by ID let sessionId = "550e8400-e29b-41d4-a716-446655440000" if let session = try await storage.getSession(id: sessionId, projectPath: projectPath) { print("Found session: \(session.summary ?? session.id)") } // Get all sessions across all projects let allSessions = try await storage.getAllSessions() print("Total sessions across all projects: \(allSessions.count)") // Get messages for a specific session let messages = try await storage.getMessages(sessionId: sessionId, projectPath: projectPath) for message in messages { print("\(message.role): \(message.content)") } // Use with ClaudeCodeClient to resume sessions let client = try ClaudeCodeClient() if let session = try await storage.getMostRecentSession(for: projectPath) { let result = try await client.resumeConversation( sessionId: session.id, prompt: "Continue where we left off", outputFormat: .text, options: nil ) } ``` -------------------------------- ### Apply Rate Limiting Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Wrap the client in a RateLimitedClaudeCode instance to control request frequency. ```swift // Create a rate-limited client let rateLimitedClient = RateLimitedClaudeCode( wrapped: client, requestsPerMinute: 10, burstCapacity: 3 // Allow 3 requests in burst ) // All requests are automatically rate-limited let result = try await rateLimitedClient.runSinglePrompt( prompt: "Task", outputFormat: .json, options: nil ) ``` -------------------------------- ### Handle SDK Errors Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Implement recovery logic for retryable, rate-limited, or permission-denied errors. ```swift // Enhanced error handling do { let result = try await client.runSinglePrompt( prompt: "Complex task", outputFormat: .json, options: options ) } catch let error as ClaudeCodeError { if error.isRetryable { // Error can be retried if let delay = error.suggestedRetryDelay { // Wait and retry } } else if error.isRateLimitError { print("Rate limited") } else if error.isTimeoutError { print("Request timed out") } else if error.isPermissionError { print("Permission denied") } } ``` -------------------------------- ### Swift Build Status Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/MIGRATION.md Indicates the successful completion of the Swift build process for the project. ```text ✅ swift build - Complete! ``` -------------------------------- ### Manage MCP Tool Permissions Source: https://github.com/jamesrochabrun/claudecodesdk/blob/main/README.md Control access to specific MCP tools using explicit names or wildcards. ```swift // Explicitly allow specific MCP tools options.allowedTools = [ "mcp__filesystem__read_file", "mcp__filesystem__write_file", "mcp__github__search_repositories" ] // Or use wildcards to allow all tools from a server options.allowedTools = ["mcp__filesystem__*", "mcp__github__*"] ```