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.
Run tests on push
Section titled “Run tests on push”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 testRun it against a ref without waiting for a push:
cryo submit --repo-path .cryo/ci.yaml --repo me/app --repo-credential gh-read --ref mainRun it on your own machine, against your working tree, with no server at all:
cryo dev # in another terminalcryo run .cryo/ci.yamlTo 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/"))'Vocabulary
Section titled “Vocabulary”| 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> }} |
What is different
Section titled “What is different”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 part that isn’t CI
Section titled “The part that isn’t CI”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:
cryo step build -- make releasecryo step deploy-staging -- ./deploy.sh stagingcryo sleep 2wverdict="$(cryo wait-signal ship)"cryo step deploy-prod -- ./deploy.sh productionKill 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.
What we don’t have yet
Section titled “What we don’t have yet”- 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.