ClaudeCodeSdk 10.4.0
dotnet add package ClaudeCodeSdk --version 10.4.0
NuGet\Install-Package ClaudeCodeSdk -Version 10.4.0
<PackageReference Include="ClaudeCodeSdk" Version="10.4.0" />
<PackageVersion Include="ClaudeCodeSdk" Version="10.4.0" />
<PackageReference Include="ClaudeCodeSdk" />
paket add ClaudeCodeSdk --version 10.4.0
#r "nuget: ClaudeCodeSdk, 10.4.0"
#:package ClaudeCodeSdk@10.4.0
#addin nuget:?package=ClaudeCodeSdk&version=10.4.0
#tool nuget:?package=ClaudeCodeSdk&version=10.4.0
Claude Code SDK for C#
A .NET SDK for interacting with Claude through the Claude Code CLI, providing both one-shot queries and interactive client sessions with full Microsoft Agent Framework (MAF) integration.
Status & Version
Package versions use the format x.y.z and may include a -preview suffix for prerelease builds.
xfollows the target .NET version.yis incremented when the library introduces breaking changes or updates its Microsoft Agent Framework dependency.zis incremented for library patch releases.
Features
- ✅ One-shot Queries - Simple request/response pattern via
ClaudeQuery.QueryAsync - ✅ Interactive Client - Bidirectional communication with
ClaudeSdkClient - ✅ Streaming Support - Real-time response streaming via
IAsyncEnumerable<T> - ✅ Partial Messages - Optional token-level text, thinking, and Tool Call streaming
- ✅ Microsoft Agent Framework Integration - Use Claude as an
AIAgent(ClaudeCodeSdk.MAF) - ✅ Session Management - Multi-turn conversations with session support and automatic session lifecycle management
- ✅ Session Persistence - Serialize/deserialize conversation sessions for storage
- ✅ Tool Integration - Full support for Claude Code tools and MCP servers
- ✅ Human Input Callbacks - Handle permissions and
AskUserQuestionthrough the stdio control protocol - ✅ Thinking Blocks - Extended reasoning with configurable thinking tokens
- ✅ Usage Tracking - Token usage and cost monitoring
- ✅ .NET 10.0 - Targets
net10.0 - ✅ Modern Async/Await - Full
IAsyncDisposablesupport with proper resource management
Installation
Core SDK
Install via NuGet:
dotnet add package ClaudeCodeSdk
Microsoft Agent Framework Integration (Optional)
For Microsoft Agent Framework support:
dotnet add package ClaudeCodeSdk.MAF
Prerequisites
- .NET 10.0 SDK
- Claude Code CLI available on
PATH. For example, install it via npm:npm install -g @anthropic-ai/claude-code - API Key: Set
ANTHROPIC_AUTH_TOKENenvironment variable with your Anthropic API key
Quick Start
One-shot Query
using ClaudeCodeSdk;
using ClaudeCodeSdk.Types;
await foreach (var message in ClaudeQuery.QueryAsync("What is the capital of France?"))
{
if (message is AssistantMessage assistantMessage)
{
foreach (var text in assistantMessage.Content.OfType<TextBlock>())
{
Console.WriteLine(text.Text);
}
}
}
Interactive Client
using ClaudeCodeSdk;
using ClaudeCodeSdk.Types;
await using var client = new ClaudeSdkClient();
await client.ConnectAsync();
await client.QueryAsync("Hello Claude!");
await foreach (var message in client.ReceiveResponseAsync())
{
if (message is AssistantMessage assistantMsg)
{
foreach (var text in assistantMsg.Content.OfType<TextBlock>())
{
Console.WriteLine($"Claude: {text.Text}");
}
}
}
Microsoft Agent Framework Integration
using ClaudeCodeSdk.MAF;
using Microsoft.Extensions.AI;
// Create Claude as an AIAgent
await using var agent = new ClaudeCodeAIAgent();
// Simple query
var response = await agent.RunAsync("Explain async/await in C#");
Console.WriteLine(response.Text);
// Multi-turn conversation with session
var session = await agent.CreateSessionAsync();
var response1 = await agent.RunAsync(
[new ChatMessage(ChatRole.User, "What is dependency injection?")],
session: session
);
// Context is automatically preserved across turns
var response2 = await agent.RunAsync(
[new ChatMessage(ChatRole.User, "Show me an example in C#")],
session: session
);
// Streaming with real-time updates
await foreach (var update in agent.RunStreamingAsync("Tell me a story", session: session))
{
if (update.Contents != null)
{
foreach (var content in update.Contents)
{
if (content is TextContent text)
{
Console.Write(text.Text);
}
}
}
}
See ClaudeCodeSdk.MAF README for complete MAF integration documentation.
MAF forwards text and image DataContent from the first user message. If you need a global instruction, configure ClaudeCodeAIAgentOptions.SystemPrompt (or AppendSystemPrompt) instead of relying on per-request ChatRole.System messages.
For long-running conversations backed by your own storage, configure ClaudeCodeAIAgentOptions.ChatHistoryProvider to observe each request and save new messages after each response. Claude Code resumes model history through the supplied AgentSession ID rather than resending stored messages as prompt input.
Architecture
The SDK implements a simplified dual-pattern architecture for Claude Code interactions:
Core Components
ClaudeProcess - Unified subprocess manager
- Direct subprocess communication with Claude Code CLI
- JSON-based message protocol with strongly-typed parsing
- Automatic CLI discovery and process lifecycle management
- Shared by both
ClaudeQueryandClaudeSdkClient
ClaudeQuery - One-shot query API
- Fire-and-forget pattern for simple queries
- Streams responses as
IAsyncEnumerable<IMessage> - Automatically handles connection lifecycle
- Ideal for single-request scenarios
ClaudeSdkClient - Interactive client API
- Long-lived bidirectional communication
- Manual connection control via
ConnectAsync/DisconnectAsync - Session management with multi-turn conversations
- Interrupt support and resource cleanup
Message Types
All messages implement IMessage:
AssistantMessage- Claude's responses with content blocksUserMessage- User inputSystemMessage- System notifications and metadataResultMessage- End-of-conversation marker with cost/usage dataStreamEvent- Raw partial-message event emitted whenIncludePartialMessagesis enabled
Content Blocks
All content blocks implement IContentBlock:
TextBlock- Plain text contentThinkingBlock- Claude's reasoning (when extended thinking is enabled)ToolUseBlock- Tool invocationsToolResultBlock- Tool execution resultsErrorContentBlock- Error information
Exception Hierarchy
Custom exceptions inherit from ClaudeSDKException:
CLINotFoundException- Claude Code CLI not foundCLIConnectionException- Transport connection issuesProcessException- Subprocess execution failuresCLIJsonDecodeException- Message parsing errorsMessageParseException- Type conversion failures
Microsoft Agent Framework Integration
The MAF integration (ClaudeCodeSdk.MAF) provides:
ClaudeCodeAIAgent
- Full
AIAgentimplementation from Microsoft.Agents.AI - Streaming and non-streaming execution modes
- Session-based conversation management
- Automatic session persistence via
ClaudeSdkClientManager - System prompt extraction and configuration
ClaudeCodeAgentSession
- Session serialization/deserialization for persistence
- Session ID management for conversation continuity
- Compatible with MAF's
AIConversationState
ClaudeSdkClientManager
- Automatic client lifecycle management
- Disposes old clients when switching sessions
- Session-safe with proper async resource management
- Optimizes resource usage across multiple sessions
Configuration
Environment Variables
The SDK automatically configures these environment variables for the Claude Code CLI:
ANTHROPIC_AUTH_TOKEN- API authentication (fromClaudeCodeOptions.ApiKeyor environment)ANTHROPIC_BASE_URL- Custom API endpoint (fromClaudeCodeOptions.BaseUrl)CLAUDE_CODE_ENTRYPOINT- SDK identifier (always "sdk-csharp")
ClaudeCodeOptions
Key configuration options:
var options = new ClaudeCodeOptions
{
ApiKey = "sk-ant-...", // Anthropic API key
BaseUrl = "https://api.anthropic.com", // Custom API endpoint
MaxThinkingTokens = 10000, // Extended thinking budget
SystemPrompt = "You are a helpful assistant",
Model = "sonnet", // Stable alias for the latest Sonnet model
IncludePartialMessages = true, // Emit raw StreamEvent messages
PermissionMode = PermissionMode.acceptEdits, // Tool approval mode
WorkingDirectory = "/path/to/project",
MaxTurns = 10,
EnvironmentVariables = new Dictionary<string, string?>
{
{ "HTTP_PROXY", "http://proxy:1080" }
}
};
Streaming partial messages
Set IncludePartialMessages to receive raw Claude Code StreamEvent messages before each complete
AssistantMessage. Each event preserves the CLI's original JSON payload so callers can handle new event types without
waiting for an SDK update.
ClaudeCodeSdk.MAF translates supported partial events into standard AgentResponseUpdate chunks. Text and thinking
deltas are emitted immediately with a stable ResponseId and MessageId; Tool Use JSON is accumulated internally and
emitted as a complete FunctionCallContent when its content block ends. The later complete AssistantMessage is used
only as a fallback for content that was not already streamed.
When a MAF ChatHistoryProvider is configured together with partial messages, deltas are emitted as they arrive. Each
logical Assistant message is persisted after both its message_stop event and complete AssistantMessage arrive, before
the corresponding processed message is yielded.
The SDK combines that message's updates with ToAgentResponse(), so a run containing multiple Tool Use rounds can persist
multiple completed history batches. Tool results are carried into the next completed Assistant batch. On normal completion,
failure, cancellation, source exception, or early consumer disposal, the SDK also persists any remaining buffered updates in
their original order, including incomplete Assistant text and tool fragments. Final persistence ignores the run cancellation
token; if both the stream and persistence fail, the stream failure remains primary.
Without partial events, the SDK retains the compatible end-of-run aggregation fallback.
Handling tool permissions and questions
Set CanUseTool to handle Claude Code permission requests without a terminal. The SDK automatically configures
--permission-prompt-tool stdio; the callback can remain pending while your application collects user input.
var options = new ClaudeCodeOptions
{
CanUseTool = async (toolName, input, context, cancellationToken) =>
{
if (toolName != "AskUserQuestion")
{
return new PermissionResultDeny($"Unsupported request: {toolName}");
}
var updatedInput = await CollectAnswersAsync(input, cancellationToken);
return new PermissionResultAllow(updatedInput);
}
};
PermissionResultAllow preserves the original input when UpdatedInput is omitted. For AskUserQuestion, return the
original questions plus an answers object. Cancelling the query also cancels the pending callback.
Development
Building
# Build the entire solution
dotnet build
# Build specific project
dotnet build src/ClaudeCodeSdk/ClaudeCodeSdk.csproj
Testing
# Run all tests
dotnet test
# Run with verbose output
dotnet test --verbosity normal
# Run specific test
dotnet test --filter "FullyQualifiedName~ExceptionsTests"
Running Examples
# Run all examples
dotnet run --project examples/ClaudeCodeSdk.Examples.csproj
# Run specific example class
dotnet run --project examples/ClaudeCodeSdk.Examples.csproj -- --example QuickStart
Packaging NuGet Packages
# Pack both SDK and MAF packages
dotnet pack src/ClaudeCodeSdk/ClaudeCodeSdk.csproj -c Release
dotnet pack src/ClaudeCodeSdk.MAF/ClaudeCodeSdk.MAF.csproj -c Release
# Pack with symbols
dotnet pack src/ClaudeCodeSdk/ClaudeCodeSdk.csproj -c Release -p:IncludeSymbols=true
Examples
The examples/ folder contains complete working examples:
- QuickStartExamples - Basic one-shot queries and interactive client usage
- StreamingExamples - Real-time response streaming patterns
- MafExample - Microsoft Agent Framework integration examples
Running Examples
Make sure you have:
- Installed Claude Code CLI:
npm install -g @anthropic-ai/claude-code - Set
ANTHROPIC_AUTH_TOKENenvironment variable
Then run:
dotnet run --project examples/ClaudeCodeSdk.Examples.csproj
Key Behaviors
Message Streaming and Termination
ClaudeProcess.ReceiveAsync()automatically terminates when receiving aResultMessage- Both
ClaudeQueryandClaudeSdkClientrely on this automatic termination ClaudeSdkClient.ReceiveResponseAsync()provides convenience method that yields until ResultMessage
JSON Serialization
- Uses
snake_case_lowernaming policy viaJsonUtilfor Claude Code CLI compatibility - Consistent serialization across all message exchanges
Resource Management
- All process-managing classes implement
IAsyncDisposable ClaudeProcesshandles subprocess lifecycle (start, kill, cleanup)- Use
await usingfor automatic cleanup
MAF Session Management
ClaudeSdkClientManagerautomatically handles client creation/disposal when switching sessions- Agent session IDs are sent as
session_idon user messages for conversation continuity - Session state persists via the session's
SessionId
Troubleshooting
"Claude Code CLI not found"
Ensure Claude Code CLI is installed globally:
npm install -g @anthropic-ai/claude-code
Authentication Errors
Set your API key:
# macOS/Linux
export ANTHROPIC_AUTH_TOKEN="your-api-key"
# Windows PowerShell
$env:ANTHROPIC_AUTH_TOKEN="your-api-key"
# Windows Command Prompt
set ANTHROPIC_AUTH_TOKEN=your-api-key
Or pass it via options:
var options = new ClaudeCodeOptions { ApiKey = "your-api-key" };
Process Lifecycle Issues
Always dispose of SDK objects properly:
await using var client = new ClaudeSdkClient();
await client.ConnectAsync();
// ... use client
// Automatic disposal on scope exit
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see LICENSE.txt for details
Links
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ClaudeCodeSdk:
| Package | Downloads |
|---|---|
|
ClaudeCodeSdk.MAF
.NET SDK for Claude Code |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.4.0 | 358 | 8/31/2026 |
| 10.4.0-preview.7 | 197 | 8/29/2026 |
| 10.4.0-preview.6 | 64 | 8/29/2026 |
| 10.4.0-preview.4 | 74 | 8/24/2026 |
| 10.4.0-preview.3 | 68 | 8/23/2026 |
| 10.4.0-preview.2 | 67 | 8/22/2026 |
| 10.4.0-preview.1 | 152 | 8/20/2026 |
| 10.3.2 | 123 | 8/7/2026 |
| 10.3.2-preview.1 | 334 | 8/7/2026 |
| 10.3.1 | 117 | 8/5/2026 |
| 10.3.1-preview.1 | 103 | 7/27/2026 |
| 10.3.0 | 135 | 7/27/2026 |
| 10.3.0-preview.2 | 180 | 7/16/2026 |
| 10.3.0-preview.1 | 70 | 7/16/2026 |
| 10.2.0 | 145 | 7/3/2026 |
| 10.2.0-preview.2 | 92 | 7/1/2026 |
| 10.2.0-preview.1 | 80 | 6/15/2026 |
| 10.1.0 | 193 | 5/4/2026 |