Olbrasoft.OpenCode.DotnetClient 1.0.0

dotnet add package Olbrasoft.OpenCode.DotnetClient --version 1.0.0
                    
NuGet\Install-Package Olbrasoft.OpenCode.DotnetClient -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Olbrasoft.OpenCode.DotnetClient" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Olbrasoft.OpenCode.DotnetClient" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Olbrasoft.OpenCode.DotnetClient" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Olbrasoft.OpenCode.DotnetClient --version 1.0.0
                    
#r "nuget: Olbrasoft.OpenCode.DotnetClient, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Olbrasoft.OpenCode.DotnetClient@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Olbrasoft.OpenCode.DotnetClient&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Olbrasoft.OpenCode.DotnetClient&version=1.0.0
                    
Install as a Cake Tool

OpenCode.DotnetClient

Build Publish NuGet NuGet NuGet Downloads .NET License

A simple .NET client library for the OpenCode API, enabling easy integration of OpenCode's AI coding capabilities into C# applications.

๐Ÿ“‹ Overview

This is a Proof of Concept (POC) .NET client for OpenCode API, built with:

  • Refit for type-safe HTTP client
  • System.Text.Json for JSON serialization
  • xUnit for testing

๐Ÿš€ Features

  • โœ… Session Management: create, get, list, delete sessions
  • โœ… Prompt Sending: send prompts to AI models (sync + async)
  • โœ… Message Retrieval: fetch messages from sessions
  • โœ… Todo Support: get todo lists for sessions
  • โœ… Event Streaming: real-time SSE event streaming with robust error handling
  • โœ… Type-Safe API: Refit-based type-safe HTTP calls
  • โœ… Async/Await: full async support with cancellation tokens
  • โœ… Dependency Injection: proper HttpClient management with IHttpClientFactory support
  • โœ… Error Handling: custom exception types for different error scenarios
  • โœ… Configuration: flexible options for timeouts, base URL, and default model settings
  • โœ… Comprehensive Tests: unit + integration tests
  • โœ… Production-Ready: follows .NET best practices and clean code principles

๐Ÿ“ฆ Installation

NuGet Package

dotnet add package Olbrasoft.OpenCode.DotnetClient

Or via Package Manager Console:

Install-Package Olbrasoft.OpenCode.DotnetClient

Prerequisites

  • .NET 10.0 SDK or later
  • Running OpenCode server (default: http://localhost:4096)

Building from Source

git clone https://github.com/Olbrasoft/OpenCode.DotnetClient.git
cd OpenCode.DotnetClient
dotnet build

Running Tests

dotnet test

Note: Integration tests require a running OpenCode server at http://localhost:4096.

๐Ÿ“– Usage

Basic Example

using OpenCode.DotnetClient;

// Create client
using var client = new OpenCodeClient("http://localhost:4096");

// Create a new session
var session = await client.CreateSessionAsync("My AI Session");
Console.WriteLine($"Session created: {session.Id}");

// Send a prompt
var response = await client.SendPromptAsync(
    session.Id,
    "Write a hello world function in C#",
    providerId: "anthropic",
    modelId: "claude-3-5-sonnet-20241022"
);

// Get the response
foreach (var part in response.Parts)
{
    if (part.Type == "text")
    {
        Console.WriteLine(part.Text);
    }
}

// List messages in session
var messages = await client.GetMessagesAsync(session.Id);
Console.WriteLine($"Total messages: {messages.Count}");

// Cleanup
await client.DeleteSessionAsync(session.Id);

Event Streaming

Listen to real-time events from OpenCode server:

using var eventStream = client.CreateEventStream();

await foreach (var globalEvent in eventStream.StreamGlobalEventsAsync())
{
    Console.WriteLine($"[{globalEvent.Payload.Type}] in {globalEvent.Directory}");

    // Handle specific event types
    switch (globalEvent.Payload.Type)
    {
        case "session.status":
            Console.WriteLine("Session status changed");
            break;
        case "message.updated":
            Console.WriteLine("Message was updated");
            break;
        case "todo.updated":
            Console.WriteLine("Todo list changed");
            break;
        case "file.edited":
            Console.WriteLine("File was edited");
            break;
    }
}

Todos

Get todos for a session:

var todos = await client.GetTodosAsync(session.Id);

foreach (var todo in todos)
{
    Console.WriteLine($"[{todo.Status}] {todo.Content} (Priority: {todo.Priority})");
}

Advanced Usage

Configuration Options
// Create client with custom configuration
var options = new OpenCodeClientOptions
{
    BaseUrl = "http://localhost:4096",
    Timeout = TimeSpan.FromMinutes(10),
    DefaultProviderId = "anthropic",
    DefaultModelId = "claude-3-5-sonnet-20241022",
    ThrowOnError = true
};

using var client = new OpenCodeClient(options);
Dependency Injection (ASP.NET Core)

Recommended approach for production applications to avoid socket exhaustion:

// In Program.cs or Startup.cs
builder.Services.AddHttpClient<OpenCodeClient>((serviceProvider, httpClient) =>
{
    httpClient.BaseAddress = new Uri("http://localhost:4096");
    httpClient.Timeout = TimeSpan.FromMinutes(5);
});

// Or with IHttpClientFactory
builder.Services.AddHttpClient("OpenCodeApi", client =>
{
    client.BaseAddress = new Uri("http://localhost:4096");
    client.Timeout = TimeSpan.FromMinutes(5);
});

builder.Services.AddScoped<OpenCodeClient>(sp =>
{
    var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>();
    var httpClient = httpClientFactory.CreateClient("OpenCodeApi");
    return new OpenCodeClient(httpClient);
});

// Usage in controllers
public class MyController : ControllerBase
{
    private readonly OpenCodeClient _openCodeClient;

    public MyController(OpenCodeClient openCodeClient)
    {
        _openCodeClient = openCodeClient;
    }
}
Custom HttpClient (Simple Usage)

For console applications or simple scenarios:

var httpClient = new HttpClient
{
    BaseAddress = new Uri("http://localhost:4096"),
    Timeout = TimeSpan.FromMinutes(5)
};

using var client = new OpenCodeClient(httpClient);
Error Handling

The client includes custom exception types for better error handling:

try
{
    var session = await client.CreateSessionAsync("My Session");
    var response = await client.SendPromptAsync(
        session.Id,
        "Write a hello world function"
    );
}
catch (OpenCodeConnectionException ex)
{
    // Connection failures (server unreachable, timeout)
    Console.WriteLine($"Connection failed: {ex.Message}");
}
catch (OpenCodeApiException ex)
{
    // API errors (4xx, 5xx responses)
    Console.WriteLine($"API error {ex.StatusCode}: {ex.Message}");
    Console.WriteLine($"Response: {ex.ResponseContent}");
}
catch (OpenCodeException ex)
{
    // Other OpenCode errors
    Console.WriteLine($"OpenCode error: {ex.Message}");
}
Cancellation Support

All async methods support cancellation tokens:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

try
{
    var sessions = await client.GetSessionsAsync(
        cancellationToken: cts.Token
    );

    var response = await client.SendPromptAsync(
        sessionId: "ses_abc123",
        prompt: "Long-running task...",
        cancellationToken: cts.Token
    );
}
catch (OperationCanceledException)
{
    Console.WriteLine("Operation was cancelled");
}
Working with Sessions
// List all sessions
var sessions = await client.GetSessionsAsync();

// Get specific session
var session = await client.GetSessionAsync("ses_abc123");

// Create session with title and parent
var childSession = await client.CreateSessionAsync(
    title: "Feature Development",
    parentId: session.Id
);

// Delete session
await client.DeleteSessionAsync(session.Id);
Sending Prompts
// Simple text prompt
var response = await client.SendPromptAsync(
    sessionId: "ses_abc123",
    prompt: "Explain SOLID principles",
    providerId: "anthropic",
    modelId: "claude-3-5-sonnet-20241022"
);

// Async prompt (fire and forget)
await client.SendPromptAsyncAsync(
    sessionId: "ses_abc123",
    prompt: "Generate documentation"
);

๐Ÿ—๏ธ Architecture

OpenCode.DotnetClient/
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ OpenCode.DotnetClient/
โ”‚       โ”œโ”€โ”€ Models/                       # DTOs for API requests/responses
โ”‚       โ”‚   โ”œโ”€โ”€ Session.cs
โ”‚       โ”‚   โ”œโ”€โ”€ Message.cs
โ”‚       โ”‚   โ”œโ”€โ”€ PromptRequest.cs
โ”‚       โ”‚   โ”œโ”€โ”€ PromptResponse.cs
โ”‚       โ”‚   โ”œโ”€โ”€ Todo.cs
โ”‚       โ”‚   โ””โ”€โ”€ OpenCodeEvent.cs          # Event models
โ”‚       โ”œโ”€โ”€ IOpenCodeApi.cs               # Refit API interface
โ”‚       โ”œโ”€โ”€ OpenCodeClient.cs             # Main client wrapper
โ”‚       โ”œโ”€โ”€ OpenCodeClientOptions.cs      # Configuration options
โ”‚       โ”œโ”€โ”€ OpenCodeException.cs          # Custom exception types
โ”‚       โ””โ”€โ”€ OpenCodeEventStream.cs        # SSE event streaming
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ OpenCode.DotnetClient.Tests/
โ”‚       โ”œโ”€โ”€ OpenCodeClientTests.cs        # Integration tests
โ”‚       โ””โ”€โ”€ OpenCodeClientUnitTests.cs    # Unit tests
โ””โ”€โ”€ examples/
    โ””โ”€โ”€ OpenCode.DotnetClient.Example/  # Example console app
        โ””โ”€โ”€ Program.cs                  # Interactive example

๐Ÿ”ง API Reference

OpenCodeClient

Constructor
  • OpenCodeClient(string baseUrl = "http://localhost:4096")
  • OpenCodeClient(HttpClient httpClient)
Methods

Session Management

  • Task<List<Session>> GetSessionsAsync(string? directory = null)
  • Task<Session> CreateSessionAsync(string? title = null, string? parentId = null, string? directory = null)
  • Task<Session> GetSessionAsync(string sessionId, string? directory = null)
  • Task<bool> DeleteSessionAsync(string sessionId, string? directory = null)

Messaging

  • Task<PromptResponse> SendPromptAsync(string sessionId, string prompt, string providerId = "anthropic", string modelId = "claude-3-5-sonnet-20241022", string? directory = null)
  • Task SendPromptAsyncAsync(string sessionId, string prompt, string providerId = "anthropic", string modelId = "claude-3-5-sonnet-20241022", string? directory = null)
  • Task<List<MessageWithParts>> GetMessagesAsync(string sessionId, int? limit = null, string? directory = null)

Session Control

  • Task<bool> AbortSessionAsync(string sessionId, string? directory = null)

Todos

  • Task<List<Todo>> GetTodosAsync(string sessionId, string? directory = null)

Event Streaming

  • OpenCodeEventStream CreateEventStream()

๐Ÿงช Testing

The project includes comprehensive tests:

  • Unit Tests (4): Basic client functionality, constructors, disposal
  • Integration Tests (6): Real API calls requiring running OpenCode server

Run tests:

# All tests
dotnet test

# Only unit tests (no server required)
dotnet test --filter "FullyQualifiedName~UnitTests"

# Only integration tests
dotnet test --filter "FullyQualifiedName~OpenCodeClientTests"

๐Ÿ› ๏ธ Development

Project Structure

This is a .NET solution with two projects:

  • OpenCode.DotnetClient: Class library (.NET 10)
  • OpenCode.DotnetClient.Tests: Test project with xUnit

Dependencies

  • Refit - Type-safe REST client
  • xUnit - Testing framework
  • Moq - Mocking framework

Building

dotnet build

Running OpenCode Server

Before running integration tests, start the OpenCode server:

opencode serve --port 4096

Running the Example

An interactive example application is included in the examples directory:

cd examples/OpenCode.DotnetClient.Example
dotnet run

The example demonstrates:

  • Event Streaming: Real-time monitoring of all OpenCode events
  • Interactive Sessions: Chat with AI through the console
  • Session Management: List and manage active sessions
  • Color-coded Output: Beautiful terminal UI with ANSI colors

See examples/README.md for detailed usage instructions.

๐Ÿ“ Requirements

  • .NET 10.0 or later
  • OpenCode Server running on http://localhost:4096 (for integration tests)

๐ŸŽฏ Supported Events

The client supports real-time streaming of these OpenCode events:

Session Events

  • session.status - Session status changes (running, idle, etc.)
  • session.idle - Session becomes idle

Message Events

  • message.updated - Message content updated
  • message.removed - Message deleted

Todo Events

  • todo.updated - Todo list changes (new todos, status updates)

File Events

  • file.edited - File was edited by AI
  • file.watcher.updated - File system watcher detected changes

Other Events

  • server.instance.disposed - Server instance cleanup
  • lsp.client.diagnostics - LSP diagnostics from language servers
  • command.executed - Command execution notifications
  • installation.updated - Installation updates
  • installation.update-available - New version available

๐ŸŽฏ Future Enhancements

Possible improvements for future versions:

  • โœ… Error Handling: Implemented - Custom exception types with detailed error information
  • โœ… Configuration: Implemented - Strongly-typed OpenCodeClientOptions
  • Retry Policies: Add automatic retry with exponential backoff using Polly
  • NuGet Package: Publish as reusable package to nuget.org
  • Additional Endpoints: Support for more OpenCode API features (file operations, providers, models list, etc.)
  • CLI Tool: Command-line interface for quick operations
  • Logging: Integrate with ILogger for production-grade logging
  • Metrics: Add telemetry and metrics collection
  • Connection Pooling: Advanced HttpClient configuration for high-throughput scenarios

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

๐Ÿ“ง Contact

For questions or issues, please open an issue on GitHub.

๐Ÿ™ Acknowledgments

  • OpenCode - The AI coding assistant
  • Refit - For the excellent HTTP client library

Note: This is a Proof of Concept (POC) implementation. For production use, additional error handling, logging, and configuration options should be added.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 345 12/5/2025

Version 1.0.0: Initial release with session management, prompt sending, message retrieval, todo support, and SSE event streaming.