Skip to content

Getting started

Install the cryo 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://cryosleep.io/install.sh | sh

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

Terminal window
cryo --version

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

Terminal window
echo 'echo "hello from cryosleep"' > hello.sh
cryo run ./hello.sh

cryo 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
cryo run ./pipeline.yaml

Against a persistent instance, cryo 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 cryosleep is that a run outlives the process executing it: kill the engine mid-run and the run picks up from its last checkpoint. cryo run is in-memory, so it can’t show that. A persistent instance can.

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

Terminal window
cryo 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="$(cryo 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.
cryo 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="$(cryo step "add" -- expr "$n" + 1)"
echo "$n + 1 = $m"

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

Terminal window
cryo run ./durable.sh
run: dev:default:run-2qyEKiaS7pTtkkZi
picked 74
cryo: 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 - cryo 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
cryo 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 cryo commands find the running instance on their own, no flags needed:

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

pick runs and prints its number, then the run parks on cryo 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 'cryo dev')"

(That targets the cryo 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
cryo dev --db ./cryo-demo.db

On startup it says resumed 1 in-flight run(s) from storage and the run finishes. cryo 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 cryo 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.

  • cryo run <file> is in-memory by default - nothing survives the command. cryo run --db <path> <file> persists to a sqlite file, so the same crash test works for a one-shot run.
  • cryo 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.
  • 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 hosted - how far cryo dev takes you, and what a hosted org adds when the work outgrows one machine.