Skip to content

Coming from GitHub Actions, GitLab CI or Buildkite

You want to run tests on a push and see whether they passed. That path is short, and nothing on it involves the canvas. This page maps the words you already have onto the ones used here, then shows the thing you can’t do in a CI system: a pipeline that keeps running after the deploy.

A pipeline is YAML in your repo, at any path you like. .cryo/ci.yaml:

if: 'event.ref == "refs/heads/main"'
jobs:
test:
steps:
- name: install
run: npm ci
- name: test
run: npm test

Run it against a ref without waiting for a push:

Terminal window
cryo submit --repo-path .cryo/ci.yaml --repo me/app --repo-credential gh-read --ref main

Run it on your own machine, against your working tree, with no server at all:

Terminal window
cryo dev # in another terminal
cryo run .cryo/ci.yaml

To fire it on every push, register a webhook and route its deliveries to the pipeline. That part is a small graph, and CI from a repo walks through it.

The top-level if: is evaluated server-side when the delivery lands, before any run exists, so a filtered push costs nothing. It is one CEL expression over the event, covering branch filters and path filters together:

if: 'event.ref == "refs/heads/main" && event.paths.exists(p, p.startsWith("api/"))'
Your word Here Worth knowing
workflow file pipeline YAML in your repo, fetched at the commit that triggered it
job job one entry under jobs:
step step entries under steps:; the whole job runs as one activity on one agent
needs: depends_on: same shape
runner agent you run them; each advertises capabilities
runner label requires: a job claims only agents carrying those capabilities
runs-on: ${{ matrix.os }} requires: ["${{ matrix.target.cap }}"] one job across platforms; the capability is read per combination
on: push top-level if: one expression, evaluated before a run is created
paths: / paths-ignore: paths: / paths_ignore: same names; they fail open when the forge reports no file list
concurrency group concurrency: group plus queue, cancel-running, cancel-queued or skip
artifact upload cryo artifact put same verb stores a build cache with --key
artifact download cryo artifact get exits 1 on a miss, so a cache lookup is plain shell
secret credential resolved to auth headers at dispatch, never stored in the definition
environment approval approval: job pauses at any point in the graph, not only before a deploy
reusable workflow workflow: job runs another pipeline as a durable child
job output outputs: cryo output set key=value from a step
matrix matrix: one job per combination, read as ${{ matrix.<name> }}

Jobs can wait. An approval: job parks on a signal and holds no agent while it does, so a pipeline can stop for a person and pick up hours later with its state intact:

promote:
depends_on: [deploy-staging]
approval:
prompt: "Promote to production?"
fields:
- { name: env, type: select, options: [staging, production] }

A wait: job does the same for a timer or a named signal. There is no cap on how long either parks; a run waiting a month occupies a database row.

The agents are yours. An agent claims work matching its capabilities, so build hardware, GPU boxes and network-restricted machines share one queue inside your infrastructure. Nothing is metered per minute.

One history. Runs, schedules, bus events and child runs are the same product with one timeline, so the thing that happens after the deploy doesn’t move to a different tool with its own logs.

The reason to move a pipeline here is usually the deploy that watches itself. One run builds the commit, ships it to staging, sleeps through a soak subscribed to alert events, waits for a human, promotes, and reports on how the release landed a week later. It is one script and one run:

Terminal window
cryo step build -- make release
cryo step deploy-staging -- ./deploy.sh staging
cryo sleep 2w
verdict="$(cryo wait-signal ship)"
cryo step deploy-prod -- ./deploy.sh production

Kill the agent, restart the server, come back in a fortnight: the run resumes from its last checkpoint. See the authoring model for the rules that make that work, and examples/release-watch for the whole thing including the report at the end.

  • A status badge endpoint.
  • A marketplace. Steps are shell commands and scripts in your language; there is no third-party action to pin to a SHA.