Overview
Drive sandboxes on a shard server from code. Both SDKs are named useshards, have the same methods and talk to shard serve on your server.
npm install useshardsThe package needs Node 20.3 or later. It is an ES module, so load it with import, and it ships its own type definitions.
pip install useshardsThe package needs Python 3.11 or later and ships with type hints. Shard is for blocking code and AsyncShard is for asyncio. The examples in this reference use Shard, and Asyncio covers the differences.
Get started
export SHARD_REMOTE=https://shard.example.comexport SHARD_API_KEY='your-api-key'import { Shard } from "useshards";
const shard = new Shard();try { // Create a sandbox. const sandbox = await shard.create({ image: "alpine:3.20", name: "demo", memoryMiB: 512 }); try { // Run a command in it. Prints 0 hello. const result = await sandbox.exec(["echo", "hello"]); console.log(result.exitCode, result.stdout.trim()); } finally { // Remove the sandbox. await sandbox.remove({ force: true }); }} finally { shard.close();}Run it with node demo.mjs.
from useshards import Shard
with Shard() as shard: # Create a sandbox. sandbox = shard.create("alpine:3.20", name="demo", memory_mib=512) try: # Run a command in it. Prints 0 hello. result = sandbox.exec(["echo", "hello"]) print(result.exit_code, result.stdout.strip()) finally: # Remove the sandbox. sandbox.remove(force=True)Run it with python demo.py.
Replace https://shard.example.com with your server URL and your-api-key with your API key. The script prints 0 hello. Its finally removes the sandbox even when a command fails, because a sandbox outlives the script that made it.
Methods
Section titled “Methods”Client
| Method | Description |
|---|---|
Shard |
connect to shard serve on a server |
shard.close |
release the pooled connections, so the process can exit |
shard.version |
return the versions of the daemon and its API |
shard.capabilities |
report which lifecycle verbs the server’s provider supports |
Sandboxes
| Method | Description |
|---|---|
shard.create |
create a sandbox and wait until it is running |
shard.get |
find a sandbox by ID, ID prefix or name |
shard.list |
list active sandboxes |
sandbox.inspect |
read the sandbox’s record again |
sandbox.stop |
stop the sandbox and preserve its files |
sandbox.start |
start a stopped sandbox with its saved files |
sandbox.pause |
suspend the sandbox and save its state |
sandbox.resume |
resume a paused sandbox from its saved state |
sandbox.fork |
create a sandbox from a running sandbox’s memory and files |
sandbox.remove |
remove the sandbox and its files |
Commands
| Method | Description |
|---|---|
sandbox.exec |
execute a command in a running sandbox and return how it ended |
command.wait |
wait for a background command to end and return how it ended |
command.kill |
send a signal to a background command |
command.writeStdin / write_stdin |
send input to a background command |
command.closeStdin / close_stdin |
end the command’s input |
command.resize |
change the terminal size of a command that runs on a terminal |
command.inspect |
read the command’s record from the daemon |
command.disconnect |
close the command’s stream and leave the command running |
command.reconnect |
attach to the command again |
sandbox.commands.list |
list the commands of a sandbox, running or ended |
sandbox.commands.get |
find a command by ID and return a handle to it |
Processes
| Method | Description |
|---|---|
sandbox.run |
start a supervised process in a running sandbox |
process.wait |
wait until the process ends and will not restart |
process.kill |
stop the process and cancel its restarts |
process.logs |
return the output of every run of the process |
process.followLogs / follow_logs |
stream the log from its start, then new output as it arrives |
process.inspect |
read the process’s record from the daemon |
sandbox.processes.list |
list the processes of a sandbox, in the order they were first run |
sandbox.processes.get |
find a process by name and return a handle to it |
Files
| Method | Description |
|---|---|
sandbox.files.write |
write text or bytes to a file in a running sandbox |
sandbox.files.read |
read a file in a running sandbox |
sandbox.files.stat |
return the type, size, mode, owner and modification time of a path |
sandbox.files.list |
list the entries of a directory in a running sandbox |
sandbox.files.mkdir |
make a directory in a running sandbox |
sandbox.files.remove |
delete a path in a running sandbox |
sandbox.files.upload |
copy a local file into a running sandbox |
sandbox.files.download |
copy a file out of a running sandbox into a local file |
sandbox.files.uploadDir / upload_dir |
copy a local directory into a running sandbox, as a tar archive |
sandbox.files.downloadDir / download_dir |
copy a directory out of a running sandbox into a local directory |
Ports
| Method | Description |
|---|---|
sandbox.ports.add |
forward a host port to a port on the sandbox’s 127.0.0.1, or change the forward it has |
sandbox.ports.list |
list the forwards of a sandbox, in host port order |
sandbox.ports.remove |
end a forward and the connections it carries |
shard.ports |
list the forwards of every sandbox, in host port order |
Snapshots
| Method | Description |
|---|---|
shard.snapshots.create |
save a stopped sandbox’s files as a snapshot |
shard.snapshots.list |
list snapshots |
shard.snapshots.inspect |
return one snapshot |
shard.snapshots.remove |
delete a snapshot and its files |
Secrets
| Method | Description |
|---|---|
shard.secrets.set |
store a secret, or replace its value |
shard.secrets.list |
list secrets without their values |
shard.secrets.remove |
delete a stored secret |
shard.secrets.grant |
let a sandbox use a stored secret |
shard.secrets.ungrant |
remove a sandbox’s access to a secret |
Network policies
| Method | Description |
|---|---|
shard.policies.set |
store a network policy, or replace all of its rules |
shard.policies.get |
return a policy and the sandboxes that use it |
shard.policies.list |
list network policies |
shard.policies.remove |
delete an unused network policy |
shard.policies.attach |
assign a network policy to a sandbox |
shard.policies.detach |
remove a sandbox’s network policy |
sandbox.egressLog / egress_log |
return the network decisions the daemon holds for a sandbox, oldest first |
sandbox.followEgressLog / follow_egress_log |
stream network decisions as they happen |
For the errors each method raises, the client timeouts and when to retry, see Errors and timeouts.
Environment variables
Section titled “Environment variables”| Variable | Description |
|---|---|
SHARD_REMOTE |
URL of shard serve, read when the client gets no remote |
SHARD_API_KEY |
API key, read when the client gets no API key |
SHARD_CA_FILE |
PEM file of the CA that signed the server’s certificate, read when the client gets no CA file |
The SDKs never read the connection that shard setup saves. See Shard for the precedence rules.
Asyncio
Section titled “Asyncio”AsyncShard takes the same arguments as Shard, and with none it reads the same environment variables. Await its request methods:
import asyncio
from useshards import AsyncShard
async def main() -> None: async with AsyncShard() as shard: # Create a sandbox. sandbox = await shard.create("alpine:3.20", memory_mib=512) try: # Run three commands at once. Prints their outputs in order, 0 to 2. results = await asyncio.gather(*(sandbox.exec(f"echo {n}") for n in range(3))) print([r.stdout for r in results]) finally: # Remove the sandbox. await sandbox.remove(force=True)
asyncio.run(main())Use async with, or call await shard.aclose() when you are done. Iterate follow_logs() and follow_egress_log() with async for. Cancelling the task ends the wait but not the command.