A modern .NET library for interacting with the Claude Code CLI, providing both a simple one-shot QueryAsync() API and a full bidirectional client with control-protocol support.
Disclaimer: This is an independent, unofficial port and is not affiliated with or endorsed by Anthropic, PBC.
- Simple
Claude.QueryAsync()API for one-shot requests ClaudeSDKClientfor multi-turn, bidirectional conversations- Control protocol support (interrupts, modes, dynamic model switching)
- Hook system (PreToolUse, PostToolUse, UserPromptSubmit)
- Tool permission callbacks with allow/deny control
- In-process MCP server support (tools, prompts, resources)
- Cross-platform: Windows, Linux, macOS
- Source-generated JSON models for message types
- Well-tested: 109 tests (90 unit + 19 integration; integration tests are disabled by default)
- .NET 8.0 or .NET 9.0
- Claude Code CLI >= 2.0.0:
npm install -g @anthropic-ai/claude-code
The SDK discovers the Claude Code CLI in this order:
ClaudeAgentOptions.CliPath(explicit path)CLAUDE_CLI_PATHenvironment variablePATHsearch forclaude(orclaude.cmdon Windows)
using Claude.AgentSdk;
await foreach (var msg in Claude.QueryAsync("What is 2+2?"))
{
if (msg is AssistantMessage am)
foreach (var block in am.Content)
if (block is TextBlock tb)
Console.Write(tb.Text);
}using Claude.AgentSdk;
await using var client = new ClaudeSDKClient();
await client.ConnectAsync();
await client.QueryAsync("Write a Python hello world");
await foreach (var msg in client.ReceiveResponseAsync())
{
if (msg is AssistantMessage am)
foreach (var block in am.Content)
if (block is TextBlock tb)
Console.Write(tb.Text);
}var options = Claude.Options()
.SystemPrompt("You are a helpful coding assistant.")
.MaxTurns(5)
.Model("claude-sonnet-4-20250514")
.AcceptEdits()
.Build();
await foreach (var msg in Claude.QueryAsync("Explain async/await", options))
{
// handle messages
}var options = Claude.Options()
.CanUseTool(async (toolName, input, context, ct) =>
{
if (toolName == "Bash" && input.GetProperty("command").GetString()?.Contains("rm") == true)
return new PermissionResultDeny("Destructive commands not allowed");
return new PermissionResultAllow();
})
.Build();var options = Claude.Options()
.AllowTools("Bash")
.Hooks(h => h
.PreToolUse("Bash", (input, toolUseId, ctx, ct) =>
{
Console.WriteLine($"[Hook] Bash: {input}");
return Task.FromResult(new HookOutput { Continue = true });
}))
.Build();using Claude.AgentSdk;
using Claude.AgentSdk.Mcp;
var options = Claude.Options()
.McpServers(m => m.AddSdk("calculator", s => s
.Tool("add", (double a, double b) => a + b, "Add two numbers")))
.AllowAllTools()
.Build();var options = Claude.Options()
.Agents(a => a
.Add("reviewer", "Reviews code", "You are a code reviewer.", "Read", "Grep")
.Add("writer", "Writes code", "You are a clean coder.", tools: ["Read", "Write"]))
.Build();var options = Claude.Options()
.Sandbox(s => s
.Enable()
.AutoAllowBash()
.ExcludeCommands("rm", "sudo")
.Network(n => n.AllowLocalBinding()))
.Build();ClaudeAgentOptions mirrors the Python SDK's options:
| Property | Type | Description |
|---|---|---|
SystemPrompt |
string? |
Custom system prompt |
MaxTurns |
int? |
Maximum conversation turns |
MaxBudgetUsd |
decimal? |
Spending limit in USD |
Model |
string? |
Model to use |
FallbackModel |
string? |
Fallback model |
PermissionMode |
PermissionMode? |
Default, AcceptEdits, BypassPermissions |
McpServers |
object? |
MCP server configurations |
CanUseTool |
CanUseToolCallback? |
Tool permission callback |
Hooks |
IReadOnlyDictionary<...>? |
Event hooks |
AllowedTools |
IReadOnlyList<string> |
Whitelist tools |
DisallowedTools |
IReadOnlyList<string> |
Blacklist tools |
Cwd |
string? |
Working directory |
CliPath |
string? |
Explicit CLI path |
AssistantMessage- Claude's response withContentblocksUserMessage- User inputSystemMessage- System notificationsResultMessage- Query completion with cost/duration info
TextBlock- Text contentThinkingBlock- Extended thinking (with signature)ToolUseBlock- Tool invocationToolResultBlock- Tool output
See the examples/ directory:
| Example | Description |
|---|---|
BasicQuery |
Simple one-shot query |
StreamingMode |
Interactive bidirectional client |
SystemPrompt |
Custom system prompts |
McpCalculator |
In-process MCP tools |
McpPrompts |
MCP prompt templates |
Hooks |
Pre/post tool use hooks |
ToolPermissionCallback |
Permission control |
Agents |
Agent configurations |
MaxBudget |
Spending limits |
- Current version: 0.1.0
- Status: Preview (API and behavior may change)
- Parity: Designed to match the Python Claude Agent SDK API, behavior, and ergonomics
- Tests: 109 tests (90 unit + 19 integration; integration tests are disabled by default)
control_cancel_requestis currently ignored (cancellation of in-flight control requests is not implemented yet; matches Python SDK TODO).
Integration tests require a working Claude Code CLI and are disabled by default.
- Enable them with:
CLAUDE_AGENT_SDK_RUN_INTEGRATION_TESTS=1 dotnet test
Canonical rule: The Python claude-agent-sdk is the canonical reference. This .NET port tracks its behavior and API.
dotnet add package Claude.AgentSdkgit clone https://github.com/anthropics/claude-agent-sdk-dotnet.git
cd claude-agent-sdk-dotnet
dotnet build| Project | Language | Description |
|---|---|---|
| claude-agent-sdk-python | Python | Official Python SDK (canonical reference) |
| claude-agent-sdk-cpp | C++ | C++ port with full feature parity |
Licensed under the MIT License. See LICENSE for details.
This is a .NET port of claude-agent-sdk-python by Anthropic, PBC.
- Issues: Use the GitHub issue tracker
- Examples: See
examples/ - Tests: See
tests/