Skip to content

Getting started

Install the spool CLI, run a workflow, then watch one survive a crash. Everything here runs on your own machine - no server to stand up, no account to create.

Terminal window
curl -fsSL https://hyperspool.com/install.sh | sh

That drops a single static spool binary on your PATH. Check it:

Terminal window
spool --version

A workflow can be a plain script. Write one and run it:

Terminal window
echo 'echo "hello from Hyperspool"' > hello.sh
spool run ./hello.sh

spool run spins up a throwaway in-memory instance, executes the file, streams its output, and exits with the run’s status. Nothing persists: when the command returns, the instance and its history are gone. It’s the fastest way to try something out.

YAML pipelines run the same way:

Terminal window
spool run ./pipeline.yaml

Against a persistent instance, spool submit --follow does the same and opens the run’s live view - each step checked off as it lands:

Submitting a two-step pipeline and following it: the TUI shows the run reach completed, with build and test each ticked off and their output beneath.

The reason to reach for Hyperspool is that a run outlives the process executing it: kill the engine mid-run and the run picks up from its last checkpoint. spool run is in-memory, so it can’t show that. A persistent instance can.

spool init writes a few starter workflows into the current directory:

Terminal window
spool init

One of them, durable.sh, is a checkpointed bash workflow. It draws a random number, sleeps, and then does arithmetic on the number it drew:

#!/usr/bin/env bash
set -e
# Drawn once, ever. From here on the number lives in the run's log.
n="$(spool step "pick" -- bash -c 'echo $(( RANDOM % 100 ))')"
echo "picked $n"
# The script exits here. When the timer fires the run is dispatched
# again, to whichever agent is free - which need not be this one - and
# the script starts over from the top.
spool sleep 5s
# `pick` does not draw a new number on that second pass. It replays the
# recorded one, so $n is what it was before the sleep: new process, new
# machine, five seconds or thirty days later, same value.
m="$(spool step "add" -- expr "$n" + 1)"
echo "$n + 1 = $m"

Run it as-is first, before any crash test:

Terminal window
spool run ./durable.sh
run: dev:default:run-2qyEKiaS7pTtkkZi
picked 74
spool: script suspended for 5000ms; agent re-dispatch on wakeup
- replaying from checkpoint (completed steps are cached, not re-run)
picked 74
74 + 1 = 75
dev:default:run-2qyEKiaS7pTtkkZi completed

The text above is the whole of it, but the timing is the part that reads better moving — the pause is the process being gone:

Running durable.sh: it prints a random number, suspends for the timer, then replays from the checkpoint and prints the same number again before doing arithmetic on it.

Two things to read off that. picked 74 appears twice because the whole script really did run twice - spool sleep ends the process rather than pausing inside it, and the wake-up starts the script again from the first line. And it says 74 both times, because pick was recorded on the first pass and replayed on the second.

A random number is the easiest thing to catch lying. Had the second pass re-run pick you would be looking at a different number, and $n would be useless to everything after the sleep. It doesn’t, so $n is ordinary state that survives an arbitrary gap, and the arithmetic on the far side is arithmetic on the number you actually drew.

None of that depends on staying put. agent re-dispatch on wakeup is the run being handed back out for anyone to claim, and the claim can go to a different agent on a different machine: the workflow log carries the recorded value, so any agent that picks the run up can serve it. Make the sleep 30d and the run is rows in a database for a month; whoever resumes it in September gets 74.

(The generated file sleeps for 5s. Widen it to 60s for the crash test below, so you have room to interrupt it.)

Start a persistent instance, pointed at a database file you name:

Terminal window
spool dev --db ./cryo-demo.db

This one process is the server, an agent, and the web UI at http://localhost:18753. Leave it running. In a second terminal, submit the script - other spool commands find the running instance on their own, no flags needed:

Terminal window
spool submit ./durable.sh --follow

pick runs and prints its number, then the run parks on spool sleep. Note the number down. While it’s parked, kill the instance - hard, so there’s no doubt it’s a real crash:

Terminal window
kill -9 "$(pgrep -f 'spool dev')"

(That targets the spool dev you just started. If you happen to be running more than one instance, kill the specific process id instead.)

The run’s state lives in ./cryo-demo.db, not in the process you just killed. Start the instance again against the same file:

Terminal window
spool dev --db ./cryo-demo.db

On startup it says resumed 1 in-flight run(s) from storage and the run finishes. spool logs <run-id> shows the completed pass:

picked 74
74 + 1 = 75

The same number you noted down before the kill. pick was not re-run

  • its checkpoint came out of ./cryo-demo.db, which is the one thing the kill -9 couldn’t touch. Open http://localhost:18753 to see the timeline.

(The log holds the last pass, so picked 74 appears once here. Live, as in the spool run transcript above, you watch both passes stream by.)

The whole test, recorded — start, submit, park, kill, restart, and the run finishing on the number it drew before the process died:

That crash test is the durable model in one move: kill the engine mid-run, restart it, and the run resumes with its recorded values intact. It behaves the same whether the interruption is a kill -9, a deploy, a reboot, or a thirty-day sleep that outlives the machine entirely.

Durability needs a database. Without one, a run lives only as long as its process.

  • spool run <file> is in-memory by default - nothing survives the command. spool run --db <path> <file> persists to a sqlite file, so the same crash test works for a one-shot run.
  • spool dev keeps state in sqlite and survives restarts. With no --db it uses a default file under your state directory; --db <path> names the file; --db :memory: makes it ephemeral.

Everything above runs on your own machine and needs no account. If you have been invited to a Hyperspool org, the same workflows run there, with one difference to state plainly: jobs execute on machines you provide. With no agent running, a submitted run waits for a machine that never arrives.

1. Point the CLI at the server. Sign in at hyperspool.dev/workflows, mint a personal access token under Settings -> Tokens, then:

Terminal window
spool login https://api.hyperspool.dev

It verifies the token, resolves your org and project, and writes ~/.config/spool/config.toml.

2. Start an agent. Mint a token for it, then install it on a machine that should run your jobs:

Terminal window
spool agents issue my-runner --project acme/web --cap shell --cap polyglot
curl -fsSL https://hyperspool.com/install.sh | sh -s -- \
--service --server https://api.hyperspool.dev \
--id my-runner --token csat_... --caps shell,polyglot

The token prints once. An agent claims only jobs whose requires: its capabilities cover. spool agents ls lists it as soon as the token is minted, with last=never until the process connects, which is how to tell a token nothing ever used from an agent that is running.

See Deploying agents for systemd, macOS, containers and self-update.

3. Submit.

Terminal window
spool submit pipeline.yaml --follow

A run that stops with nothing to say is usually the missing agent: the CLI reports what it is waiting for, and spool agents ls shows what the fleet advertises.

  • Tour - thirty minutes through steps, timers, approvals, signals, events, and child workflows, all locally.
  • Concepts - the vocabulary in nine terms.
  • The authoring model - the checkpoint/replay rules; read once before writing a real workflow.
  • Workflows in your language - the same primitives in Python, TypeScript, Go, and Rust.
  • Deploying agents - run agents where your work needs to happen.
  • Local and the server - how far spool dev takes you, and what the server adds when the work outgrows one machine.