Ephemeral compute for AWS.
Instances terminate themselves via TTL, idle detection, or completion signal — no forgotten bills.
Requires AWS credentials.
macOS / Linux (Homebrew)
brew install spore-host/tap/spawnWindows (Scoop)
scoop bucket add spore-host https://github.com/spore-host/scoop-bucket
scoop install spawnDebian / Ubuntu
# GoReleaser puts the version in the asset name, so there is no version-less
# "latest/download" URL to fetch — resolve the tag first.
VER=$(curl -fsSL https://api.github.com/repos/spore-host/spawn/releases/latest \
| sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
curl -LO "https://github.com/spore-host/spawn/releases/download/v${VER}/spawn_${VER}_linux_amd64.deb"
sudo dpkg -i "spawn_${VER}_linux_amd64.deb"RHEL / Fedora
VER=$(curl -fsSL https://api.github.com/repos/spore-host/spawn/releases/latest \
| sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
sudo rpm -i "https://github.com/spore-host/spawn/releases/download/v${VER}/spawn_${VER}_linux_amd64.rpm"Direct download — pre-built binaries for Linux, macOS, and Windows (amd64/arm64) on the releases page.
Build from source
git clone https://github.com/spore-host/spawn
cd spawn && make build && sudo make install# Launch with auto-terminate on completion
spawn launch my-job --instance-type c6a.xlarge --ttl 4h --on-complete terminate
# Connect by name (auto-starts if stopped)
spawn connect my-job
# Run a one-shot command
spawn connect my-job -- 'nohup bash /tmp/run.sh > /tmp/run.log 2>&1 &'
# Check status
spawn status my-job
# Extend TTL without reconnecting
spawn extend my-job 2h
# List all instances
spawn list| Command | Description |
|---|---|
launch |
Launch an EC2 instance (Linux or Windows) |
connect |
Connect to an instance by name (auto-starts if stopped): SSH on Linux; RDP, PowerShell-over-SSM, or --ssh on Windows |
app |
Launch a streamed GUI app, a bare Linux desktop, or a self-serving web app (see below) |
list |
List all managed instances |
status |
Instance status, TTL, cost |
extend |
Extend TTL on a running instance |
stop / start |
Stop or start an instance |
hibernate |
Hibernate (saves RAM to disk) |
terminate |
Terminate an instance (permanent — destroys the instance) |
image |
Build a custom AMI from a Windows ISO (EC2 Image Builder; auto-warms for fast boot) |
ami |
List / delete spawn-managed AMIs |
snapshot |
Build an EBS data snapshot from a directory, tarball, or raw image (for launch --attach-volume) |
queue |
Batch job queue management |
schedule |
Scheduled execution |
sweep |
Parameter sweeps |
sweep cancel |
Cancel a running parameter sweep |
slurm |
Convert Slurm sbatch scripts |
resources |
List all AWS resources spawn has created (tagged spawn:managed) |
orphans |
Report spawn-managed resources that look abandoned (billable leaks) |
cleanup |
Remove orphaned spawn-managed resources |
task |
Inspect and diagnose individual tasks (instances) |
pool |
Pooled execution: fungible workers drain a shared task queue (#70) |
array |
Manage job arrays (status, collect, cancel) |
pipeline |
Manage multi-stage pipelines |
service |
Run a long-lived HTTP service on an instance and tunnel to it |
results |
Inspect task results in S3 |
logs |
Show a spore's command or spored log, including after it has terminated |
cost |
Show cost breakdown for a sweep or a single instance |
availability |
Display availability statistics for instance types across regions |
capacity-block |
Purchase and manage EC2 Capacity Blocks for ML |
fsx |
FSx filesystem management commands |
dns |
Manage DNS records for spawn instances |
plugin |
Manage plugins on spore instances |
team |
Manage team-based resource sharing |
burst |
Launch cloud instances to join local job array |
instance-config |
Read or write runtime config on a running instance via SSH |
defaults |
Manage default launch settings (~/.spawn/config.yaml) |
upgrade-spored |
Upgrade the spored agent on a running instance in place |
reaper |
Manage the out-of-band TTL reaper in your own AWS account |
doctor |
Check that your environment is ready to launch a spore instance |
footprint |
Report everything spawn has created in this account, including the control plane |
onboard |
Bring this AWS account onto the spore.host portal (BYOA) |
validate |
Validate compliance and infrastructure configuration |
- Structured output: use the root
-o/--outputflag (-o json) on any command. Per-command--jsonflags are deprecated aliases and will be removed; prefer-o json. - Destructive commands (
cancel,terminate,delete,remove) prompt for confirmation and accept-y/--yesto skip it (required for non-interactive use). A piped/non-interactive run without--yesaborts rather than acting.
See docs/flag-conventions.md for the full convention reference (shared across spawn, truffle, lagotto, and spored).
TTL always terminates — it fully bounds cost. But the default idle action
(and --on-complete stop) only stops the instance, and a stopped instance
keeps billing for its EBS volumes and any attached Elastic IP, indefinitely.
For batch/headless workloads — especially in accounts without a hosted reaper —
prefer --on-complete terminate so completion fully releases the spend.
To find money quietly leaking:
spawn orphans # billable leaks: detached volumes, stopped-instance EIPs, …
spawn cleanup # remove them (never touches running instances)spawn status <instance> also reports any Elastic IP attached to an instance —
informational while running, a billing warning while stopped. Note: spawn never
allocates an Elastic IP, so it never releases one; any EIP shown is a static
address you allocated, and it's yours to release with aws ec2 release-address.
spawn app launches a research application in the cloud and opens it in your
browser — no VNC/RDP client, no AMI to build. It streams a GUI app over an
Amazon DCV virtual session, or reverse-proxies
a web app straight to a https:// URL. Instances self-terminate on idle/TTL just
like spawn launch.
# See what you can launch (public apps + anything your account can pull)
spawn app list
# 1. A single GUI app streamed to a browser tab (the default kind). ParaView,
# ChimeraX and the other GUI apps are "recipe available": build the image
# from the recipe, then launch it (on a GPU instance)
spawn app launch paraview --image 123456789012.dkr.ecr.us-east-1.amazonaws.com/paraview:5.13.2
# 2. A bare Linux desktop over DCV — "open a terminal and run anything"
spawn app launch desktop
# 3. A web app that serves its own UI on a port — no DCV. jupyter, code-server
# and openrefine are in the catalog; any other image needs only a port and
# an instance type
spawn app launch jupyter
spawn app launch my-notebook --image 123456789012.dkr.ecr.us-east-1.amazonaws.com/jupyter --web-port 8888 --instance-type m7i.largeThree launch kinds (set by the catalog entry's kind, or inferred):
application(default; also whatdcv: truemeans) — one Linux GUI app streamed over a DCV virtual session to a browser tab.desktop— a bare Linux desktop (GNOME) over DCV, no specific app;spawn app launch desktop.web— an app that serves its own web UI on a port (Jupyter, code-server, OpenRefine). No DCV:sporedfronts it with a built-in TLS reverse proxy on:443. Launch awebcatalog entry, or bring your own image ad hoc with--image <ref> --web-port <n>(add--health-pathif readiness isn't at/).
Prerequisites
- AWS credentials — sign in with
aws login(spore.host uses the AWS CLI'slogincommand). No creds →spawn app listshows only the public apps. - For GPU apps (most streamed GUI apps), a GPU-instance quota in the target region. The base image is the AWS GPU Deep Learning AMI, resolved via SSM at launch, with Amazon DCV installed at boot — there is no AMI to pre-build.
What you get — for a GUI app or desktop, spawn writes a session file under
~/.spawn/sessions/ and opens it in your browser (the DCV client connects once
the session is ready); for a web app it prints and opens the https://<host>/
URL. Reconnect later with spawn connect <instance>. Useful flags:
--instance-type, --region, --spot, --ttl 4h, --idle-timeout 20m,
--app-version <tag>, and --no-open (write the session file / print the URL but
don't open a browser). The instance stops on idle and terminates at its TTL, so a
forgotten session doesn't keep billing.
To author or override catalog entries (your own images, an in-house app, or a pinned AMI), see docs/catalog-schema.md and the example overlay at docs/catalog-overlay.example.yaml.
Slack, Teams and Discord notifications (spawn notify, spawn launch --slack-workspace / --notify-platform, and the slack-workspace default) are
experimental and not supported in this release. They are hidden from
--help and refuse to run unless you opt in with SPAWN_EXPERIMENTAL_CHAT=1
(or experimental: {chat: true} in ~/.spawn/config.yaml). spore.host no
longer hosts a bot, so even opted in they need your own self-hosted spore-bot
(SPORE_NOTIFY_URL, SPORE_BOT_LAMBDA_ROLE_ARN). For lifecycle notices, use
--completion-webhook-url and --spot-webhook-url, which POST straight to
your own endpoint and are unaffected.
spored is the lifecycle daemon that runs inside each instance as a systemd service. It handles TTL enforcement, idle detection, completion signals, and DNS registration. It is built and distributed alongside spawn. As an on-instance CLI it follows the same flag conventions (subcommands status, config get/set/list, reload, complete, version).
pkg/launcher is the recommended entry point — it provisions a fully-functional
spore (auto-detects the AMI, sets up the spored IAM role, installs the spored
bootstrap so the instance honors TTL / idle / on-complete), the same way the CLI
does. SDK consumers like lagotto use it.
import (
"github.com/spore-host/spawn/pkg/aws"
"github.com/spore-host/spawn/pkg/launcher"
)
client, _ := aws.NewClient(ctx)
result, _ := launcher.Provision(ctx, client, aws.LaunchConfig{
InstanceType: "c6a.xlarge",
Region: "us-east-1",
TTL: "4h",
OnComplete: "terminate",
}, launcher.Options{})For lower-level control, client.Launch(ctx, config) launches an instance
without the bootstrap — but then the spore won't self-manage; prefer Provision.
Full reference at docs.spore.host/tools/spawn.
- Windows beta guide — end-to-end: Windows 11 ISO → custom (auto-warmed) AMI → launch → connect via RDP, PowerShell-over-SSM, or SSH.
- Reference data volumes — get large
reference data (Kraken2 DB, BLAST index, model weights) onto spores without
baking it into an AMI:
snapshot createfrom a dir/tarball/raw image →launch --attach-volume. - Service readiness contract — the one
JSON line a long-lived HTTP service prints so
spawn serviceknows which port to forward to. Read this to make a binary spawnable.
Apache 2.0 — Copyright 2025-2026 Scott Friedman.
