Getting started
This page gets you from zero to a running, copy-paste-complete example, then routes you by goal. The mental model behind it all is in What is DotBoxD? - a two-minute read.
Prerequisites
Section titled “Prerequisites”- .NET SDK 10.0.2xx (the repository pins it in
global.json). The test suite also exercises the .NET 8 and .NET 9 runtimes, so install those runtimes if you intend to run all tests. - Any OS: Windows, Linux, macOS.
First win: a typed RPC call in five minutes
Section titled “First win: a typed RPC call in five minutes”Mode 1 (call the host - Services/RPC) gives the fastest end-to-end result: one console project, one file, a real named-pipe round-trip. Scaffold it:
dotnet new console -n CatalogQuickstartcd CatalogQuickstartdotnet add package DotBoxD --prerelease
--prereleaseis required while the net10.0 stack is in preview; drop it once a stable tag ships. Building for Unity / netstandard2.1 instead? InstallDotBoxD.Services.Alland see Tutorial 1 for the transport-explicit setup; the package tables in the root README list every individual package.
Replace the generated Program.cs with this complete file:
using DotBoxD.Pushdown.Services; // RpcMessagePackIpc helperusing DotBoxD.Services.Attributes; // [RpcService]using DotBoxD.Services.Generated; // generated ProvideCatalogService / Get<T>
// A unique pipe name, so parallel runs never collide.var pipeName = $"dotboxd-quickstart-{Guid.NewGuid():N}";var prices = new Dictionary<string, int> { ["sword"] = 120, ["shield"] = 80 };
// Host: turn every accepted connection into a peer that serves the contract.await using var host = RpcMessagePackIpc.ListenNamedPipe( pipeName, peer => peer.ProvideCatalogService(new CatalogService(prices)));await host.StartAsync();
// Client: connect and call the generated typed proxy. The client lives in the// same process here to keep the demo to one file; the call still crosses the// named pipe exactly like an out-of-process client would.await using var connection = await RpcMessagePackIpc.ConnectNamedPipeAsync(pipeName);var catalog = connection.Get<ICatalogService>();
var price = await catalog.GetUnitPriceAsync("sword");Console.WriteLine($"sword costs {price}");
// The contract: one attribute, no base classes, no marshaling code.[RpcService]public interface ICatalogService{ ValueTask<int> GetUnitPriceAsync(string itemId, CancellationToken cancellationToken = default);}
// The host-side implementation is plain C#.public sealed class CatalogService(Dictionary<string, int> prices) : ICatalogService{ public ValueTask<int> GetUnitPriceAsync(string itemId, CancellationToken cancellationToken = default) => ValueTask.FromResult(prices[itemId]);}Run it:
dotnet runExpected output:
sword costs 120What just happened: [RpcService] drove a source generator that emitted a typed proxy, a
dispatcher, and the ProvideCatalogService / Get<ICatalogService>() wiring at compile time,
and the call crossed a real named pipe. No hand-written marshaling, no runtime reflection on the
hot path. Host and client share a process here only to keep the demo to one file - split them
into a host app, a client app, and a shared contract project and nothing about the API changes.
That split, plus MessagePack DTOs, the generated pieces, diagnostics, and the explicit
netstandard2.1/Unity setup, is Tutorial 1: your first Service.
Prefer a ready-made project? The repository ships
dotnet new templates
(dotboxd-service, dotboxd-sidecar, dotboxd-kernel-host) you can install from a checkout.
See the whole system run
Section titled “See the whole system run”The maintained GameServer sample ties everything together: service IPC, event kernels, live settings, host bindings, policy-gated execution, server extensions (Pushdown), and unload-on-disconnect. It lives in the repo, not the NuGet package - clone and run from the repo root:
git clone https://github.com/JKamsker/DotBoxDcd DotBoxDdotnet run -c Release --project samples/GameServer/Examples.GameServer.Server/Examples.GameServer.Server.csprojYou should see three phases print - a baseline run, a with-plugins run, and a summary confirming the plugin’s kernels unloaded on disconnect. For the annotated output, see What the run prints. Features no longer covered by maintained samples are listed in coverage gaps.
Pick your journey
Section titled “Pick your journey”| Your journey | Start here | Then |
|---|---|---|
| RPC & Unity - typed request/response between processes | Tutorial 1: your first Service (from scratch) | The RPC & transports deep dive: transports, Unity integration, performance. |
| Plugin author - extend an existing DotBoxD host | Run the GameServer baseline, then walkthrough 2: event pipelines (clone the repo - it builds on the sample) | Walkthrough 3: Pushdown server extension, plus the event pipelines and Pushdown concepts. |
| Host integrator - you own the host and want to accept plugins | The GameServer walkthrough server side, then host bindings (what you expose) | Kernel runtime (policies, fuel, quotas), then sandbox caveats for production isolation. |
| Sandbox & tooling author - hand-written IR, other languages, custom fluent APIs | The kernels concept (includes the smallest end-to-end SandboxHost), a real JSON-IR example | Walkthrough 4: hand-written IR and the schemas. |
| Security reviewer - decide whether to run untrusted plugins | Sandbox caveats - the three trust postures and what is and isn’t a boundary | The kernel runtime for fuel, quotas, and capabilities. |
Unsure which interaction mode fits a call site? Use the decision table in Choosing a mode.
Words you’ll keep meeting
Section titled “Words you’ll keep meeting”Kernel (the sandboxed unit of plugin logic), IR (the restricted instruction format kernels are written in), lowering (compiling your C# down to IR), fuel (the execution budget), capability (permission for a kernel to touch a host binding), terminal (the last stage of an event pipeline - where the reaction runs). All defined with links in the glossary.
Next steps
Section titled “Next steps”Ready to go deeper? Work through the tutorials & walkthroughs - one per interaction mode, in order.