Workflows
The pipeline a run follows: phases, gates, defaults, and the board automation that starts them.
A workflow says what happens, in what order, and where a person looks at it. It is stored with your project as plain YAML and edited in a visual editor — in the extension, the dashboard, the Mac app, or a phone — so the whole team shares one definition and every run is reproducible.
What one looks like
version: 1
id: feature # stable identity — renaming never breaks a reference
name: Feature pipeline
phases:
- id: spec
title: Spec
gate: true # stop for review after the spec
steps:
- type: prompt
prompt: Write a short spec for the task. List the files you expect to touch.
- id: coding
title: Coding
gate: true
steps:
- { type: command, name: install, run: pnpm install }
- { type: prompt, prompt: Implement the approved spec. }
- { type: check, name: lint, run: pnpm lint }
- { type: check, name: test, run: pnpm test }
- id: merge
title: Merge
terminal: true
steps:
- { type: git, action: merge, method: squash }
- { type: notify, to: [slack], message: Merged and shipped. }
A project keeps as many workflows as it likes, and each run picks one. With none defined at all, a built-in spec → coding → merge pipeline applies, so a fresh project runs out of the box — and the marketplace has ready-made ones to install.
Every run also carries whatever skills and MCP servers its project has picked, without a workflow having to say so.
Phases
| Field | What it does |
|---|---|
gate: true | When the phase's steps finish, the run stops and waits for a person. See Gates & reviews. |
terminal: true | Marks the closing phase. The editor keeps exactly the last phase terminal, and a terminal phase cannot gate. |
approvers, self | Who may approve this phase, and whether the author may approve their own work. |
runner | Where the phase executes — see Run on your own machine. |
when | Run this phase only when a condition holds. See below. |
onStatus,
setStatus | Board automation. See below. |
Steps run in order within a phase. Nine types cover the pipeline — see the step reference.
Skipping a phase
A phase can say when it applies:
- id: notify-release
title: Announce
when: branch == "release/*" && !trigger
steps: […]
The expression reads the run's own facts at the moment the phase would
start: source (manual, trigger, api…), branch,
repo, trigger, and task (whether a
backlog task is behind the run).
The grammar fits in a sentence: clauses joined by &&
or by || — one or the other, never mixed — where a clause is
a bare field (task), a negated one (!trigger),
or a comparison against a quoted string. Comparisons match with the same
wildcards trigger filters use. A phase whose condition is false settles
as skipped and the run carries on.
Identity, order, and the default
A workflow's identity is its id, which never changes.
Renaming changes only the display name; every task and routing rule keeps
pointing at the same workflow.
There is no magic filename either. The project's default workflow is simply the first one in order, which is what an unpinned task or a routing rule's fallback resolves to.
Defaults
defaults:
agent: { provider: claude, model: opus-5, effort: high }
systemPrompt: Never touch files under legal/.
basePrompt: Keep diffs small; follow the repo architecture docs.
cacheWorkspace: true
ownsStatus: true
runner: { labels: [linux] }
secrets: [NPM_TOKEN, SENTRY_AUTH_TOKEN]
| Field | What it does |
|---|---|
agent | The provider, model, and reasoning effort every prompt-driven step inherits. Any step can override it. See Agents & models. |
systemPrompt | Standing instructions for every agent in the run. When set, it replaces the project's system prompt for these runs. |
basePrompt | Additive conventions layered on top rather than replacing anything. |
cacheWorkspace | Reuse one workspace across the run's phases, for install-heavy repositories. See Runners & isolation. |
ownsStatus | Whether a run of this workflow moves the task's board status. Defaults to true; set it false on a component workflow meant to be used as a lane. |
runner | The default machine selector for every phase. |
secrets | At the top level, beside
phases. Names of organization secrets to put in the run's
environment — only what is listed resolves, and values never appear in
the file. |
Status automation: the board drives execution
Phases can bind to board statuses, and the binding works both ways:
phases:
- id: spec
title: Spec
gate: true
onStatus: in-spec # dragging a task here starts the workflow at this phase
setStatus: in-spec-review # when the phase finishes, the task moves here
steps: […]
- onStatus — a task dragged into that status starts this workflow at this phase. Starting mid-pipeline is fine. While the phase runs, the task shows that status, so the board always mirrors what is happening.
- setStatus — where the task lands when the phase's work completes.
Statuses are qualified by where they come from. A bare name like
in-spec means your own board; a tracker's real status is
written as <connector>:<Status>. A list holds
one per tracker, so a single workflow can drive tasks from several
origins, each in its own vocabulary:
onStatus:
- peractor:queued
- "linear-a1b2c3:Todo"
setStatus:
- peractor:building
- "linear-a1b2c3:In Progress"
With those two fields, dragging a card is what starts, advances, and files work.
Next: the step reference · Gates & reviews