NSprites 0.6.0
dotnet add package NSprites --version 0.6.0
NuGet\Install-Package NSprites -Version 0.6.0
<PackageReference Include="NSprites" Version="0.6.0" />
<PackageVersion Include="NSprites" Version="0.6.0" />
<PackageReference Include="NSprites" />
paket add NSprites --version 0.6.0
#r "nuget: NSprites, 0.6.0"
#:package NSprites@0.6.0
#addin nuget:?package=NSprites&version=0.6.0
#tool nuget:?package=NSprites&version=0.6.0
NSprites
A .NET client library for the Sprites.dev API.
Features
- Full REST API Support: Create, manage, and delete sprites
- Checkpoint Management: Create and restore filesystem snapshots
- Command Execution: Run commands with streaming output
- Port Tunneling: Forward local ports to sprite containers
- Async/Await: Modern async API throughout
- Strongly Typed: Full type safety with records and enums
- Testable: Dependency injection friendly with mocked HTTP clients
Installation
dotnet add package NSprites
Quick Start
using NSprites;
// Create a client with your token
var client = new SpritesClient("your-sprites-token");
// Create a new sprite
var sprite = await client.CreateSpriteAsync(new CreateSpriteRequest("my-sprite"));
Console.WriteLine($"Created sprite: {sprite.Url}");
// Get an existing sprite client
var mySprite = client.Sprite("my-sprite");
// Run a command
var result = await mySprite.Exec.RunCommandAsync(
new ExecuteRequest(new[] { "echo", "Hello, World!" }));
Console.WriteLine(result.Stdout); // "Hello, World!\n"
// Create a checkpoint
await foreach (var @event in mySprite.Checkpoints.CreateAsync("Before deployment"))
{
Console.WriteLine($"Checkpoint: {@event.Data}");
}
// List checkpoints
var checkpoints = await mySprite.Checkpoints.ListAsync();
foreach (var cp in checkpoints)
{
Console.WriteLine($"Checkpoint: {cp.Id} - {cp.Comment}");
}
// Create a port tunnel
var tunnel = await mySprite.Proxy.CreateTunnelAsync(
remotePort: 3000,
localPort: 8080
);
API Overview
Sprites
// List all sprites
var sprites = await client.ListSpritesAsync();
// Create a sprite
var sprite = await client.CreateSpriteAsync(new CreateSpriteRequest("my-app"));
// Get sprite details
var details = await client.Sprite("my-app").GetAsync();
// Update URL settings
await client.Sprite("my-app").UpdateUrlSettingsAsync("public");
// Delete a sprite
await client.Sprite("my-app").DeleteAsync();
Checkpoints
var checkpoints = client.Sprite("my-app").Checkpoints;
// Create a checkpoint with streaming events
await foreach (var @event in checkpoints.CreateAsync("Backup before deploy"))
{
Console.WriteLine($"{@event.Type}: {@event.Data}");
}
// List checkpoints
var list = await checkpoints.ListAsync();
// Get specific checkpoint
var cp = await checkpoints.GetAsync("v1");
// Restore to a checkpoint
await foreach (var @event in checkpoints.RestoreAsync("v1"))
{
Console.WriteLine($"{@event.Type}: {@event.Data}");
}
Command Execution
var exec = client.Sprite("my-app").Exec;
// Run a simple command
var result = await exec.RunCommandAsync(
new ExecuteRequest(new[] { "python", "-c", "print(42)" }));
Console.WriteLine($"Exit code: {result.ExitCode}");
Console.WriteLine($"Output: {result.Stdout}");
// Run with environment variables
var result = await exec.RunCommandAsync(new ExecuteRequest(
Command: new[] { "env" },
Env: new[] { "MY_VAR=test" },
Dir: "/tmp"
));
// List active sessions
var sessions = await exec.ListSessionsAsync();
// Kill a session
await foreach (var @event in exec.KillSessionAsync(123))
{
Console.WriteLine($"{@event.Type}: {@event.Message}");
}
WebSocket Command Execution
For real-time streaming and interactive sessions, use the WebSocket exec client:
var wssExec = client.Sprite("my-app").WssExec;
// Start an interactive bash session
using var session = await wssExec.ExecuteAsync(new WssExecOptions(
["bash"],
Tty: true,
Stdin: true,
Timeout: TimeSpan.FromMinutes(5)
));
// Send input
await session.Stdin.WriteAsync(Encoding.UTF8.GetBytes("echo Hello\n"));
await session.Stdin.FlushAsync();
// Stream stdout as it arrives (recommended for real-time processing)
await foreach (var data in session.GetStdoutAsync(cancellationToken))
{
var text = Encoding.UTF8.GetString(data);
Console.WriteLine($"Output: {text}");
// Stop when you see what you're looking for
if (text.Contains("Hello"))
{
await session.Stdin.WriteAsync(Encoding.UTF8.GetBytes("exit\n"));
await session.Stdin.FlushAsync();
break;
}
}
// Wait for command to complete
var exitMessage = await session.ExitTask;
Console.WriteLine($"Exit code: {exitMessage.ExitCode}");
Benefits of streaming API:
- No race conditions - thread-safe by design
- Real-time data consumption as it arrives
- Modern, idiomatic C# API with
await foreach - Multiple concurrent readers supported
Alternative approaches:
- Event callbacks: Subscribe to
OnStdoutData/OnStderrDataevents - Buffered stream access: Read from
Stdout/Stderrstreams afterExitTaskcompletes
Note: Subscribe to events before calling ExecuteAsync() to avoid missing early data.
Port Tunneling
var proxy = client.Sprite("my-app").Proxy;
// Create a tunnel from local port 8080 to remote port 3000
var tunnel = await proxy.CreateTunnelAsync(
remotePort: 3000,
localPort: 8080,
host: "localhost"
);
// Each local connection to localhost:8080 creates a new WebSocket to the sprite's port 3000
// The tunnel listener stays alive to handle multiple sequential connections
using var httpClient = new HttpClient();
var response = await httpClient.GetAsync("http://localhost:8080");
// When done, dispose the tunnel
tunnel.Dispose();
Each TCP connection creates its own WebSocket connection to the sprite for that specific session, making it suitable for testing web services, databases, or any networked applications running in sprites.
Running the Demo
See the NSprites.Demo project for a complete working example:
# Set your API token
export SPRITES_TOKEN=your-sprites-token
# Run the interactive bash demo
dotnet run --project NSprites.Demo <sprite-name>
Error Handling
All API errors are wrapped in SpritesApiException:
try
{
var sprite = await client.Sprite("nonexistent").GetAsync();
}
catch (SpritesApiException ex)
{
Console.WriteLine($"API Error: {ex.ErrorCode} - {ex.Message}");
// ErrorCode: NotFound, StatusCode: 404
}
Available error codes:
Unauthorized- Authentication requiredForbidden- Access deniedNotFound- Resource not foundConflict- Resource conflictValidationError- Invalid request dataRateLimited- Too many requestsInternalServerError- Server error
Testing
Solid Test Coverage
See the test files for examples of mocking HTTP responses.
Requirements
- .NET 10.0+
- Sprites.dev account and API token
License
MIT
| 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.Configuration (>= 10.0.3)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.3)
- Microsoft.Extensions.Http (>= 10.0.3)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on NSprites:
| Package | Downloads |
|---|---|
|
MonumentalSystems.Sprites
A Semantic Kernel plugin for Sprites containerized development environment integration. Provides tools for managing sprites, executing commands, creating checkpoints, and establishing port forwarding tunnels. |
GitHub repositories
This package is not used by any popular GitHub repositories.