fissionplane crate connects your Rust applications to a self-hosted FissionPlane installation. The client is fully async, built on Tokio, and gives you typed access to sandboxes, commands, file operations, port exposure, and template builds. Every network call returns fissionplane::Error, making error handling straightforward to pattern-match.
Requirements
Before you add the crate, make sure you have:- Rust 1.97 or later
- A Tokio runtime
- A running FissionPlane control plane and its URL
- An API key or OIDC bearer token
- A template alias or template artifact ID to use when creating sandboxes
Installation
Add the crate to your project:Configuration
Set your control plane URL and API key as environment variables soClientOptions::new() picks them up automatically:
ClientOptions::access_token() instead of api_key() when authenticating with an OIDC bearer token. When you set both, api_key() takes precedence. The constructor rejects an empty credential or one that contains whitespace, returning Error::Config before any network call is made.
Client Options
&str
The URL of your FissionPlane control plane. Reads from the
FISSIONPLANE_API_URL environment variable when not called.&str
Your API key. Reads from the
FISSIONPLANE_API_KEY environment variable when not called. Takes precedence over access_token().&str
An OIDC bearer token. Used when
api_key() is not set.Duration
default:"DEFAULT_REQUEST_TIMEOUT"
Bounds one HTTP attempt on either plane, including reading the response body, and also bounds a WebSocket handshake. Pass
Duration::ZERO to disable timeouts entirely.usize
default:"DEFAULT_MAX_RETRIES"
Number of additional attempts after a first failure, spaced by exponential backoff with full jitter. Pass
0 to disable retries. The SDK only retries safe operations or writes with an idempotency key.&str
Replaces the default
User-Agent: fissionplane-rust/<version> header on all requests to both the control plane and the sandbox data plane.Create a Sandbox and Run a Command
Sandbox creation returns after a node acknowledges the sandbox. UseCommands::run() when you need the command’s full output after it finishes.
Commands::run() waits for the process to exit and returns its exit code, standard output, standard error, and an optional truncation flag. Use Commands::list_processes() to list supervised processes, and Commands::kill(pid, Some(Signal::Term)) to signal one.
Background Processes and PTY
When you need to follow output in real time or keep stdin open, start a background process withcommands.start(). Pass a PtySize to allocate a pseudo-terminal.
attachment implements StreamExt, so you can use .next().await in a loop or combine it with other stream combinators. Break out at any time to stop consuming events.
Filesystem Operations
Access filesystem operations throughsandbox.files()?. The handle provides:
list()— read directory entries below a pathstat()— read metadata for a single pathmake_dir()— create a directory (and parents)write()/upload()— upload bytes to a pathread()/download()— download bytes from a pathmove_path()— move or rename a pathremove()— remove a file or directorywatch()— open a recursive WebSocket watch for filesystem change events
Sandbox Lifecycle
A sandbox moves through four visible states:Running, Paused, Terminated, and Failed.
pause() snapshots the sandbox and releases the underlying node capacity. resume() restores the snapshot on a node and gives the sandbox a new epoch.
Capability tokens are scoped to a single sandbox epoch. After
resume(), the SDK automatically replaces the token on the handle. Handles returned by Sandboxes::get() or Sandboxes::list() carry no token — call Sandbox::mint_token() before creating a Commands or Files handle from them. When the data plane rejects an expired token, the SDK mints a replacement through the control plane and replays the call once. A WebSocket handshake the agent rejects reconnects the same way. The replacement preserves the port scope of the token it replaces, so a refresh never widens an attenuated token.Sandboxes::create() so that retries return the same sandbox instead of creating a duplicate.
Port Exposure
Every sandbox port is private by default, accessible only with a capability token. Make a port public only when anonymous access is required.unexpose() removes the exposure record and returns the port to private access.
Build and Use a Template
Template builds run asynchronously on your FissionPlane installation. Start a build, wait for it to finish, then reference the template by alias when creating sandboxes.TemplateBuildHandle::logs(offset). Pass next_offset from each response into the next call to avoid re-reading lines. Use Templates::get_build(build_id) to reconnect to a build started in a previous process.
List Sandboxes
Read a single page of sandboxes filtered by state, metadata, or limit:Sandboxes::stream() to walk every page automatically. The SDK fetches the next page only when the current one is exhausted.
? inside the loop surfaces it. Use Sandboxes::list_all() when you want the entire collection in memory at once.
Error Handling
Every SDK operation returnsfissionplane::Error. Match on its variants to handle specific cases:
Error distinguishes transport failures, API errors with structured fields, missing capability tokens, failed template builds, wait timeouts, and invalid configuration.
Tracing
The SDK emitstracing events at the DEBUG level when it replays a request, re-mints a capability token, or fetches a page of sandboxes. Install any tracing subscriber to see them — without one they cost nothing at runtime. Credentials and capability tokens never appear in events or in a Debug rendering of ClientOptions.
The
fissionplane crate is version 0.0.1. The public API is unstable and may change without notice until the project publishes a stable release.