cruise
A CLI tool that orchestrates coding agent workflows defined in a YAML config file.
Cruise wraps CLI coding agents such as claude -p and drives them through a declarative workflow: plan → approve → write tests → implement → test → review → open PR. It handles variable passing between steps, conditional branching, and loop control.
Installation
cargo install
Homebrew
Usage
# Run the default cruise.yaml workflow
# Use a custom config file
# Resume from a specific step
# Preview the flow without executing
CLI Reference
cruise [OPTIONS] [INPUT]
Arguments:
[INPUT] Initial input passed to the workflow (reads from stdin if omitted and stdin is piped)
Options:
-c, --config <PATH> Path to the workflow config file [default: cruise.yaml]
--from <STEP> Step name to start from (resume mid-workflow)
--max-retries <N> Maximum times a loop edge may be traversed [default: 10]
--rate-limit-retries <N> Maximum rate-limit retries per step [default: 5]
--dry-run Print the workflow flow without executing
Config File Reference
Basic Structure
command:
- claude
- --model
- "{model}"
- -p
model: sonnet # default model for all prompt steps (optional)
plan: plan.md # optional: file path bound to the {plan} variable
steps:
step_name:
# step configuration
Dynamic Model Selection
When the command array contains a {model} placeholder, cruise resolves it at runtime based on the effective model for each step:
- Model specified (via top-level
modelor step-levelmodel): replaces{model}with the model name. - No model specified: removes the
{model}argument and its immediately-preceding--modelflag automatically.
A step-level model field overrides the top-level model default for that step only.
command:
- claude
- --model
- "{model}" # replaced at runtime, or --model/{model} pair is stripped if no model
- -p
model: sonnet # default; steps without model: use this
steps:
planning:
model: opus # overrides the default for this step only
prompt: "Create a plan for: {input}"
Step Types
Prompt Step (LLM call)
steps:
planning:
model: claude-opus-4-5 # model to use (optional; overrides top-level model)
instruction: | # system prompt (optional)
You are a senior engineer.
prompt: | # prompt body (required)
Create an implementation plan for:
{input}
output: plan # variable to store the output in (optional)
# if output matches the top-level plan field name,
# the result is also written to that file automatically
Command Step (shell execution)
steps:
run_tests:
command: cargo test # single command (required)
description: Running tests # display label (optional)
lint_and_test:
command: # list of commands: run sequentially, stop on first failure
- cargo fmt --all
- cargo clippy -D warnings
- cargo test
Option Step (interactive selection)
Each item in option is either a selector (menu choice) or a text-input (free-text prompt):
steps:
review_plan:
description: Review the plan
option:
- selector: Approve and continue # shown in selection menu
next: implement
- selector: Revise the plan
next: planning
- text-input: Other (free text) # shows a text prompt when selected;
next: planning # entered text is available as {prev.input}
- selector: Cancel
next: ~ # null next = end of workflow
Flow Control
Explicit next step
steps:
step_a:
command: echo "hello"
next: step_c # jump over step_b
step_b:
command: echo "skipped"
step_c:
command: echo "world"
Skipping a step
steps:
optional_step:
command: cargo fmt
skip: true # always skip
fix_errors:
command: cargo fix
skip: prev.success # skip if the variable "prev.success" resolves to "true"
The skip field accepts a static boolean (true/false) or a variable reference string. When a variable reference is given, the step is skipped if that variable's current value is "true".
Conditional execution (file-changed detection)
steps:
implement:
command: claude -p "implement: "
run_tests:
command: cargo test
commit:
command: git commit -am "feat: "
if:
file-changed: implement # only run if files changed since `implement`
Note: Snapshots for
file-changedchecks are taken only after command steps. Prompt and option steps do not create snapshots. If the referenced step has never run (no snapshot exists), the condition evaluates tofalseand the step is skipped.
Variable Reference
| Variable | Description |
|---|---|
{input} |
Initial input from CLI argument or stdin |
{prev.output} |
LLM output from the previous step |
{prev.input} |
User text input from the previous option step |
{prev.stderr} |
Stderr captured from the previous command step |
{prev.success} |
Exit status of the previous command step (true/false) |
{plan} |
Contents of the file specified by the top-level plan field; also written automatically when a prompt step uses output: plan |
{name} |
Named variable defined via the output field |
Note:
{model}is not a template variable — it is a special placeholder resolved only within the top-levelcommandarray. It is not available insideprompt,instruction, orcommandstep fields.
Example Config
Full Development Flow
command:
- claude
- --model
- "{model}"
- -p
model: sonnet
plan: .cruise/plan.md
steps:
plan:
model: opus
instruction: "What will you do?"
prompt: |
I am trying to implement the following features. Create an implementation plan.
---
{input}
output: plan
approve-plan:
description: "{prev.output}"
option:
- selector: Approve
next: write-tests
- text-input: Fix
next: fix-plan
- text-input: Ask
next: ask-plan
fix-plan:
model: opus
prompt: |
The user has requested the following changes to the {plan} implementation plan. Make the modifications:
{prev.input}
next: approve-plan
ask-plan:
prompt: |
The user has the following questions about the implementation plan for {plan}. Provide answers:
{prev.input}
next: approve-plan
write-tests:
prompt: |
Based on the {plan} implementation schedule, please first create the test code,
then update the {plan} if necessary.
implement:
prompt: |
Tests have been created according to {plan}. Please implement them to pass.
If necessary, update {plan}.
test:
command:
- cargo fmt --all
- cargo clippy --fix --allow-dirty -D warnings
- cargo test
fix-test-error:
skip: prev.success # skip if tests passed
prompt: |
The following error occurred. Please correct it:
---
{prev.stderr}
next: test
pr:
prompt: create a PR
if:
file-changed: test # only if files changed since `test` step
Simple Auto-Commit Flow
command:
- claude
- -p
steps:
implement:
prompt: "{input}"
commit:
command: git add -A && git commit -m "feat: "
if:
file-changed: implement
Rate Limit Retry
When a rate-limit error (HTTP 429) is detected in a prompt or command step, cruise retries with exponential backoff:
- Initial delay: 2 seconds
- Maximum delay: 60 seconds
- Default retry count: 5 (override with
--rate-limit-retries)
License
MIT