ClaudeCode.Net
0.2.3
See the version list below for details.
dotnet add package ClaudeCode.Net --version 0.2.3
NuGet\Install-Package ClaudeCode.Net -Version 0.2.3
<PackageReference Include="ClaudeCode.Net" Version="0.2.3" />
<PackageVersion Include="ClaudeCode.Net" Version="0.2.3" />
<PackageReference Include="ClaudeCode.Net" />
paket add ClaudeCode.Net --version 0.2.3
#r "nuget: ClaudeCode.Net, 0.2.3"
#:package ClaudeCode.Net@0.2.3
#addin nuget:?package=ClaudeCode.Net&version=0.2.3
#tool nuget:?package=ClaudeCode.Net&version=0.2.3
ClaudeCode.NET
Drive Claude Code sessions from .NET.
The Claude Agent SDK ships for TypeScript and Python. .NET developers who want to orchestrate Claude Code sessions end up hand-rolling the same plumbing every time: find the CLI, spawn the process, escape the arguments, pump stream-json output, parse events, capture the session ID for resume. This library is that plumbing, done once and tested.
- Typed event stream —
IAsyncEnumerable<ClaudeStreamEvent>over the CLI's stream-json output: assistant text, tool calls, tool results, session stats, rate-limit signals - Safe argument handling — prompts pass through
ProcessStartInfo.ArgumentList, so newlines, quotes, and backslashes arrive verbatim (no shell-escaping bugs) - Session chaining — capture
SessionIdfrom one run, pass it asResumeSessionIdto the next - Clean cancellation — cancelling the token kills the entire CLI process tree; no orphaned
claudeprocesses - Max plan friendly — uses the CLI's
claude loginauth; no API key required - No logging opinion — takes an optional
Microsoft.Extensions.Logging.ILogger; silent by default
Parsing is verified against real CLI output, not guessed from docs.
Requirements
.NET 8.0 or later
Install the Claude Code CLI (native installer, auto-updates):
# Windows (PowerShell) irm https://claude.ai/install.ps1 | iex# macOS / Linux / WSL curl -fsSL https://claude.ai/install.sh | bashThen authenticate: run
claudeand follow the login prompts.
Quick start
using ClaudeCode;
var session = new ClaudeSession();
var options = new ClaudeSessionOptions
{
WorkingDirectory = "/path/to/repo",
Model = "claude-sonnet-5", // optional; omit for the CLI default
MaxTurns = 50
};
// Streaming: react to events as they arrive
await foreach (var evt in session.StreamAsync("Fix the failing test in FooTests", options))
{
switch (evt.Kind)
{
case ClaudeStreamEventKind.AssistantText: Console.WriteLine(evt.Text); break;
case ClaudeStreamEventKind.ToolUse: Console.WriteLine($"-> {evt.ToolName}"); break;
case ClaudeStreamEventKind.Result: Console.WriteLine($"done in {evt.NumTurns} turns"); break;
}
}
// Or aggregate: one call, one result
var result = await session.RunAsync("Summarize this repo's architecture", options);
Console.WriteLine(result.AssistantText);
Console.WriteLine($"session {result.SessionId}, {result.NumTurns} turns");
Session chaining
Each --print invocation is a fresh session, but you can resume the previous one so Claude keeps its context:
var first = await session.RunAsync("Implement feature A", options);
var chained = options with { ResumeSessionId = first.SessionId };
var second = await session.RunAsync("Now implement feature B", chained);
Rate limits
ClaudeRunResult.RateLimitDetected is true when the CLI reports a rate limit (via its
rate_limit_event stream event or recognizable error text) — poll-and-retry policies
are yours to choose; the library just gives you a reliable signal.
Unattended tool use
SkipPermissions defaults to true (--dangerously-skip-permissions), because non-interactive
sessions can't answer permission prompts — without it, any Bash/Write tool call fails.
Only run unattended sessions in a workspace you trust Claude to modify.
Cookbook
Commit messages from your staged diff (pure text generation - one turn, no tools):
var diff = /* output of: git diff --cached */;
var result = await session.RunAsync(
$"Write a conventional commit message for this diff. Reply with ONLY the message.\n\n{diff}",
new ClaudeSessionOptions { WorkingDirectory = repoDir, MaxTurns = 1, SkipPermissions = false });
Console.WriteLine(result.ResultText);
Live progress display - render what the agent is doing as it works:
await foreach (var evt in session.StreamAsync(prompt, options))
{
var line = evt.Kind switch
{
ClaudeStreamEventKind.ToolUse => $" [tool] {evt.ToolName}",
ClaudeStreamEventKind.AssistantText => $" {evt.Text}",
ClaudeStreamEventKind.Result => $" [done: {evt.NumTurns} turns]",
_ => null
};
if (line is not null) Console.WriteLine(line);
}
Unattended runs: check the result honestly. A session can "complete" while having failed - always look at the whole outcome, not just the text:
var result = await session.RunAsync(prompt, options);
if (result.RateLimitDetected && result.IsError)
/* back off and retry later */ ;
else if (result.IsError || result.ExitCode != 0)
logger.LogError("Session failed: {Text}", result.ResultText);
else
/* trust - then verify: run your tests before accepting the changes */ ;
Timeouts - cancellation kills the entire CLI process tree, no orphans:
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(20));
var result = await session.RunAsync(prompt, options, cts.Token);
Samples
Runnable projects in samples/:
CommitMessageBot- staged diff in, conventional commit message out (~40 lines)ChainedRefactor- two sessions where the second resumes the first and provably builds on its contextHelloAgent- minimal event-stream walkthrough
Status
Early (0.1.0). Extracted from SharpCoder (a private project — an AI application generator), where this code drives multi-hour autonomous build sessions. API may move before 1.0.
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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 (>= 8.0.2)
-
net8.0
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.