{"id":51083118,"url":"https://github.com/managedcode/claudecodesharpsdk","last_synced_at":"2026-06-23T20:01:40.928Z","repository":{"id":342431814,"uuid":"1173906216","full_name":"managedcode/ClaudeCodeSharpSDK","owner":"managedcode","description":"CLI-first .NET / C# SDK for Claude Code CLI with typed thread API, streamed JSONL events, structured outputs","archived":false,"fork":false,"pushed_at":"2026-04-09T19:26:21.000Z","size":255,"stargazers_count":1,"open_issues_count":69,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-08T16:36:16.122Z","etag":null,"topics":["claude-code","claude-code-sdk","csharp","sdk","sdk-dotnet"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/managedcode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-05T21:50:50.000Z","updated_at":"2026-04-09T19:25:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/managedcode/ClaudeCodeSharpSDK","commit_stats":null,"previous_names":["managedcode/claudecodesharpsdk"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/managedcode/ClaudeCodeSharpSDK","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/managedcode%2FClaudeCodeSharpSDK","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/managedcode%2FClaudeCodeSharpSDK/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/managedcode%2FClaudeCodeSharpSDK/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/managedcode%2FClaudeCodeSharpSDK/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/managedcode","download_url":"https://codeload.github.com/managedcode/ClaudeCodeSharpSDK/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/managedcode%2FClaudeCodeSharpSDK/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34704748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["claude-code","claude-code-sdk","csharp","sdk","sdk-dotnet"],"created_at":"2026-06-23T20:01:34.761Z","updated_at":"2026-06-23T20:01:40.921Z","avatar_url":"https://github.com/managedcode.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ManagedCode.ClaudeCodeSharpSDK\n\n[![CI](https://github.com/managedcode/ClaudeCodeSharpSDK/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/managedcode/ClaudeCodeSharpSDK/actions/workflows/ci.yml)\n[![Release](https://github.com/managedcode/ClaudeCodeSharpSDK/actions/workflows/release.yml/badge.svg?branch=main)](https://github.com/managedcode/ClaudeCodeSharpSDK/actions/workflows/release.yml)\n[![CodeQL](https://github.com/managedcode/ClaudeCodeSharpSDK/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/managedcode/ClaudeCodeSharpSDK/actions/workflows/codeql.yml)\n[![NuGet](https://img.shields.io/nuget/v/ManagedCode.ClaudeCodeSharpSDK.svg)](https://www.nuget.org/packages/ManagedCode.ClaudeCodeSharpSDK)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\n`ManagedCode.ClaudeCodeSharpSDK` is a .NET SDK for driving the Claude Code CLI from C#.\n\nIt is intentionally CLI-first. The library does not reimplement Anthropic APIs or invent its own transport. It wraps the local `claude` binary, runs Claude Code in print mode, and maps the emitted protocol into typed C# models.\n\n## What You Get\n\n- `ClaudeClient` / `ClaudeThread` API for start, resume, run, and stream workflows\n- real Claude Code print-mode transport via `claude -p`\n- typed parsing for `stream-json` events\n- structured output with `StructuredOutputSchema`\n- optional `Microsoft.Extensions.AI` adapter package\n- optional Microsoft Agent Framework adapter package\n- repository automation that tracks upstream changes in `anthropics/claude-code`\n\n## Source Of Truth\n\nThis SDK follows the real Claude Code CLI contract in print mode:\n\n- `claude -p --output-format json`\n- `claude -p --output-format stream-json --verbose`\n- upstream reference repository: [anthropics/claude-code](https://github.com/anthropics/claude-code)\n\nIf the docs in this repository and the observed CLI behavior ever diverge, the observed CLI behavior wins and the SDK should be updated to match.\n\nUpstream tracking is built into the repo:\n\n- reference submodule: [`submodules/anthropic-claude-code`](submodules/anthropic-claude-code)\n- sync workflow: [`.github/workflows/claude-cli-watch.yml`](.github/workflows/claude-cli-watch.yml)\n\n## Packages\n\nCore SDK:\n\n```bash\ndotnet add package ManagedCode.ClaudeCodeSharpSDK\n```\n\nOptional `Microsoft.Extensions.AI` adapter:\n\n```bash\ndotnet add package ManagedCode.ClaudeCodeSharpSDK.Extensions.AI\n```\n\nOptional Microsoft Agent Framework adapter:\n\n```bash\ndotnet add package ManagedCode.ClaudeCodeSharpSDK.Extensions.AgentFramework --prerelease\n```\n\n## Prerequisites\n\nBefore using the SDK, you need:\n\n- `claude` installed and available in `PATH`, or configured via `ClaudeOptions.ClaudeExecutablePath`\n- an authenticated local Claude Code session for real runs\n\nQuick sanity check:\n\n```bash\nclaude --version\nclaude --help\nclaude -p --output-format json --dangerously-skip-permissions --no-session-persistence \"Reply with ok only.\"\n```\n\n## Quickstart\n\n```csharp\nusing ManagedCode.ClaudeCodeSharpSDK.Client;\n\nusing var client = new ClaudeClient();\nusing var thread = client.StartThread();\n\nvar result = await thread.RunAsync(\"Diagnose failing tests and propose a fix.\");\n\nConsole.WriteLine(result.FinalResponse);\nConsole.WriteLine($\"Items: {result.Items.Count}\");\n```\n\n`ClaudeClient` auto-starts by default. If you want explicit lifecycle control, create it with `AutoStart = false` and call `StartAsync()` yourself.\n\n## Core Concepts\n\n### Client\n\n`ClaudeClient` owns executable discovery, lifecycle, and metadata queries:\n\n- `StartThread()`\n- `ResumeThread(sessionId)`\n- `GetCliMetadata()`\n- `GetCliUpdateStatus()`\n\n### Thread\n\n`ClaudeThread` represents one Claude Code conversation/session:\n\n- turns are serialized per thread instance\n- `RunAsync(...)` returns the final response plus collected items\n- `RunStreamedAsync(...)` exposes the parsed event stream\n\n### Transport\n\nAt runtime the SDK executes Claude Code in print mode and parses `stream-json` output. It does not maintain a separate protocol implementation.\n\n## Streaming\n\n```csharp\nusing ManagedCode.ClaudeCodeSharpSDK.Client;\nusing ManagedCode.ClaudeCodeSharpSDK.Models;\n\nusing var client = new ClaudeClient();\nusing var thread = client.StartThread();\n\nvar streamed = await thread.RunStreamedAsync(\"Implement the fix.\");\n\nawait foreach (var evt in streamed.Events)\n{\n    switch (evt)\n    {\n        case ItemCompletedEvent completed:\n            Console.WriteLine($\"Item: {completed.Item.Type}\");\n            break;\n\n        case TurnCompletedEvent done:\n            Console.WriteLine(done.Result);\n            Console.WriteLine($\"Output tokens: {done.Usage.OutputTokens}\");\n            break;\n    }\n}\n```\n\n## Structured Output\n\n```csharp\nusing System.Text.Json.Serialization;\nusing ManagedCode.ClaudeCodeSharpSDK.Client;\nusing ManagedCode.ClaudeCodeSharpSDK.Models;\n\npublic sealed record RepositorySummary(string Summary, string Status);\n\n[JsonSerializable(typeof(RepositorySummary))]\ninternal sealed partial class AppJsonContext : JsonSerializerContext;\n\nvar schema = StructuredOutputSchema.Map\u003cRepositorySummary\u003e(\n    additionalProperties: false,\n    (response =\u003e response.Summary, StructuredOutputSchema.PlainText()),\n    (response =\u003e response.Status, StructuredOutputSchema.PlainText()));\n\nusing var client = new ClaudeClient();\nusing var thread = client.StartThread();\n\nvar result = await thread.RunAsync(\n    \"Summarize the repository status as JSON.\",\n    schema,\n    AppJsonContext.Default.RepositorySummary);\n\nConsole.WriteLine(result.TypedResponse.Status);\nConsole.WriteLine(result.TypedResponse.Summary);\n```\n\nIf you want full turn control, use `TurnOptions`:\n\n```csharp\nusing var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(30));\n\nvar result = await thread.RunAsync(\n    \"Summarize the repository status as JSON.\",\n    AppJsonContext.Default.RepositorySummary,\n    new TurnOptions\n    {\n        OutputSchema = schema,\n        CancellationToken = timeout.Token,\n    });\n```\n\nNotes:\n\n- typed runs require `TurnOptions.OutputSchema` or a direct `outputSchema` overload\n- the `JsonTypeInfo\u003cT\u003e` overloads are the AOT-safe path\n- reflection-based typed overloads are intentionally marked as AOT-unsafe\n\n## Resume An Existing Session\n\n```csharp\nusing ManagedCode.ClaudeCodeSharpSDK.Client;\n\nusing var client = new ClaudeClient();\nusing var thread = client.ResumeThread(\"existing-session-id\");\n\nvar result = await thread.RunAsync(\"Continue from the previous plan.\");\nConsole.WriteLine(result.FinalResponse);\n```\n\nClaude Code persists SDK print-mode sessions by default. Unless you set `NoSessionPersistence = true`, the session transcript is written under `~/.claude/projects/.../\u003csession-id\u003e.jsonl` and can be resumed later by session id.\n\n```bash\nclaude --resume \u003csession-id\u003e\n```\n\nClaude stores those sessions in project-scoped directories derived from the working directory, so external CLI/App resume should use the same `WorkingDirectory` or project that created the session. The SDK guarantees persistence and resume-by-id; whether a non-interactive `-p` session is shown in the default Claude history/resume picker is controlled by the Claude CLI/App itself.\n\n## Microsoft Agent Framework\n\n`ManagedCode.ClaudeCodeSharpSDK.Extensions.AgentFramework` is a thin Microsoft Agent Framework package over the existing `ClaudeChatClient`.\nIt is currently published as a prerelease package because the upstream `Microsoft.Agents.AI` dependency is still prerelease.\n\n```csharp\nusing ManagedCode.ClaudeCodeSharpSDK.Extensions.AI;\nusing Microsoft.Agents.AI;\nusing Microsoft.Extensions.AI;\n\nIChatClient chatClient = new ClaudeChatClient();\n\nAIAgent agent = chatClient.AsAIAgent(\n    name: \"ClaudeAssistant\",\n    instructions: \"You are a concise coding assistant.\");\n\nvar response = await agent.RunAsync(\"What changed in this repository?\");\nConsole.WriteLine(response.Text);\n```\n\nDI registration:\n\n```csharp\nusing ManagedCode.ClaudeCodeSharpSDK.Extensions.AgentFramework.Extensions;\nusing Microsoft.Agents.AI;\nusing Microsoft.Extensions.AI;\n\nbuilder.Services.AddClaudeCodeAgent(\n    configureAgent: options =\u003e\n    {\n        options.Name = \"ClaudeAssistant\";\n        options.ChatOptions = new ChatOptions\n        {\n            Instructions = \"You are a concise coding assistant.\"\n        };\n    });\n\napp.MapGet(\"/agent\", async (AIAgent agent) =\u003e\n{\n    var response = await agent.RunAsync(\"Summarize the repository\");\n    return response.ToString();\n});\n```\n\nKeyed DI registration:\n\n```csharp\nusing ManagedCode.ClaudeCodeSharpSDK.Extensions.AgentFramework.Extensions;\nusing Microsoft.Agents.AI;\nusing Microsoft.Extensions.AI;\nusing Microsoft.Extensions.DependencyInjection;\n\nvar services = new ServiceCollection();\nservices.AddKeyedClaudeCodeAgent(\n    \"claude-main\",\n    configureAgent: options =\u003e\n    {\n        options.Name = \"ClaudeAssistant\";\n        options.ChatOptions = new ChatOptions\n        {\n            Instructions = \"You are a concise coding assistant.\"\n        };\n    });\n\nusing var provider = services.BuildServiceProvider();\nvar keyedAgent = provider.GetRequiredKeyedService\u003cAIAgent\u003e(\"claude-main\");\n```\n\nThis package builds on the existing `IChatClient` adapter, so the canonical MAF path remains `IChatClient.AsAIAgent(...)`; the Claude-specific package adds a supported package boundary and DI convenience methods.\n\nCurrent limitations are the same as the underlying `ClaudeChatClient` adapter:\n\n- message input is text-first in the current runtime surface\n- Claude CLI-managed tools are not exposed as provider-specific MAF callbacks by this SDK\n- streaming behavior follows `ClaudeChatClient` updates rather than token-level deltas\n\n## Thread Options\n\n`ThreadOptions` maps the Claude Code flags currently supported by this SDK.\n\n```csharp\nusing ManagedCode.ClaudeCodeSharpSDK.Client;\nusing ManagedCode.ClaudeCodeSharpSDK.Models;\n\nvar options = new ThreadOptions\n{\n    Model = ClaudeModels.ClaudeOpus45,\n    PermissionMode = PermissionMode.AcceptEdits,\n    AllowedTools = [\"Read\", \"Write\", \"Edit\"],\n    DisallowedTools = [\"Bash\"],\n    AdditionalDirectories = [\"/workspace\", \"/tmp\"],\n    SystemPrompt = \"Be concise and explicit about risk.\",\n    AppendSystemPrompt = \"Prefer concrete file paths in explanations.\",\n    MaxBudgetUsd = 0.50m,\n    NoSessionPersistence = true,\n    AdditionalCliArguments = [\"--some-future-flag\", \"custom-value\"],\n};\n\nusing var thread = client.StartThread(options);\n```\n\nNot every flag in the upstream CLI is necessarily surfaced yet, but unsupported future non-transport flags can still be passed through `AdditionalCliArguments`. SDK-managed transport flags such as `--print`, `--output-format`, `--input-format`, and `--json-schema` are reserved and rejected if passed through manually.\n\n## Metadata And Update Checks\n\n```csharp\nusing System.Linq;\nusing ManagedCode.ClaudeCodeSharpSDK.Client;\n\nusing var client = new ClaudeClient();\n\nvar metadata = client.GetCliMetadata();\nConsole.WriteLine($\"Installed Claude Code: {metadata.InstalledVersion}\");\nConsole.WriteLine($\"Default model: {metadata.DefaultModel}\");\n\nforeach (var model in metadata.Models.Where(model =\u003e model.IsListed))\n{\n    Console.WriteLine(model.Slug);\n}\n\nvar update = client.GetCliUpdateStatus();\nif (update.IsUpdateAvailable)\n{\n    Console.WriteLine(update.UpdateMessage);\n    Console.WriteLine(update.UpdateCommand);\n}\n```\n\nCurrent metadata support includes:\n\n- installed CLI version from `claude --version`\n- default model discovery from Claude settings files with SDK fallback to `sonnet`\n- SDK-known model aliases/constants\n- upstream tag comparison against `anthropics/claude-code`\n\n## Logging\n\n```csharp\nusing ManagedCode.ClaudeCodeSharpSDK.Client;\nusing ManagedCode.ClaudeCodeSharpSDK.Configuration;\nusing Microsoft.Extensions.Logging;\n\npublic sealed class ConsoleClaudeLogger : ILogger\n{\n    public IDisposable BeginScope\u003cTState\u003e(TState state) where TState : notnull =\u003e NullScope.Instance;\n    public bool IsEnabled(LogLevel logLevel) =\u003e true;\n\n    public void Log\u003cTState\u003e(\n        LogLevel logLevel,\n        EventId eventId,\n        TState state,\n        Exception? exception,\n        Func\u003cTState, Exception?, string\u003e formatter)\n    {\n        Console.WriteLine($\"[{logLevel}] {formatter(state, exception)}\");\n        if (exception is not null)\n        {\n            Console.WriteLine(exception);\n        }\n    }\n\n    private sealed class NullScope : IDisposable\n    {\n        public static NullScope Instance { get; } = new();\n        public void Dispose() { }\n    }\n}\n\nusing var client = new ClaudeClient(new ClaudeOptions\n{\n    Logger = new ConsoleClaudeLogger(),\n});\n```\n\n## Current Limitations\n\n- the current SDK transport is print-mode only\n- `LocalImageInput` exists in the model layer but is rejected in the current Claude print-mode implementation\n- `TurnOptions.ReplayUserMessages` is reserved for future stream-json input support and currently throws\n- the `Microsoft.Extensions.AI` adapter is text-first and does not expose custom Claude internal item types\n- `ChatOptions.Tools` is ignored because Claude Code manages tools internally\n- authenticated end-to-end behavior depends on the local Claude Code session available on the machine\n\n## Microsoft.Extensions.AI Adapter\n\n```csharp\nusing Microsoft.Extensions.AI;\nusing ManagedCode.ClaudeCodeSharpSDK.Extensions.AI;\n\nIChatClient client = new ClaudeChatClient();\n\nvar response = await client.GetResponseAsync(\n[\n    new ChatMessage(ChatRole.User, \"Summarize the repository.\"),\n]);\n\nConsole.WriteLine(response.Text);\n```\n\nStreaming:\n\n```csharp\nawait foreach (var update in client.GetStreamingResponseAsync(\n[\n    new ChatMessage(ChatRole.User, \"Implement the fix.\"),\n]))\n{\n    Console.Write(update.Text);\n}\n```\n\nClaude-specific options flow through `ChatOptions.AdditionalProperties`:\n\n```csharp\nusing ManagedCode.ClaudeCodeSharpSDK.Client;\nusing Microsoft.Extensions.AI;\n\nvar options = new ChatOptions\n{\n    AdditionalProperties = new AdditionalPropertiesDictionary\n    {\n        [\"claude:working_directory\"] = \"/workspace\",\n        [\"claude:permission_mode\"] = PermissionMode.AcceptEdits,\n        [\"claude:allowed_tools\"] = new[] { \"Read\", \"Write\" },\n        [\"claude:max_budget_usd\"] = 0.25m,\n    },\n};\n```\n\nSee:\n\n- [docs/Features/meai-integration.md](docs/Features/meai-integration.md)\n- [docs/ADR/003-microsoft-extensions-ai-integration.md](docs/ADR/003-microsoft-extensions-ai-integration.md)\n\n## Development\n\nClone with submodules:\n\n```bash\ngit clone https://github.com/managedcode/ClaudeCodeSharpSDK.git\ncd ClaudeCodeSharpSDK\ngit submodule update --init --recursive\n```\n\nBuild and test:\n\n```bash\ndotnet build ManagedCode.ClaudeCodeSharpSDK.slnx -c Release -warnaserror\ndotnet test --solution ManagedCode.ClaudeCodeSharpSDK.slnx -c Release\n```\n\nSmoke-only subset:\n\n```bash\ndotnet test --project ClaudeCodeSharpSDK.Tests/ClaudeCodeSharpSDK.Tests.csproj -c Release --no-build -- --treenode-filter \"/*/*/*/ClaudeCli_Smoke_*\"\n```\n\n## Documentation Map\n\n- architecture: [docs/Architecture/Overview.md](docs/Architecture/Overview.md)\n- thread execution: [docs/Features/thread-run-flow.md](docs/Features/thread-run-flow.md)\n- CLI metadata: [docs/Features/cli-metadata.md](docs/Features/cli-metadata.md)\n- M.E.AI adapter: [docs/Features/meai-integration.md](docs/Features/meai-integration.md)\n- automation and upstream sync: [docs/Features/release-and-sync-automation.md](docs/Features/release-and-sync-automation.md)\n- ADRs: [docs/ADR](docs/ADR)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanagedcode%2Fclaudecodesharpsdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmanagedcode%2Fclaudecodesharpsdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanagedcode%2Fclaudecodesharpsdk/lists"}