steps
The steps field is the work a custom command performs. Custom commands run steps through the same engine as workflows and support the same step types — from plain shell and Atmos commands to interactive prompts, spinners, tables, and container operations.
Simple and structured steps
In its simplest form, steps is a list of shell command strings:
commands:
- name: hello
description: Say hello
steps:
- "echo Hello world!"
- "echo Goodbye!"
For anything beyond a plain shell command, use the structured form — an object per step with a
type and the fields for that type. The two forms can be mixed in the same list:
commands:
- name: deploy
description: Deploy with a confirmation prompt
steps:
- type: confirm
name: proceed
prompt: "Deploy to production?"
default: false
- "echo Deploying..."
- type: atmos
command: terraform apply vpc -s plat-ue2-prod
A structured step is the same object documented for workflows. See the
step reference for the common step fields (name, type, command,
output, and more).
Conditional steps
Structured custom command steps support the same when condition syntax as
workflow steps. Omitted when means the step runs while the command status is
still success. After a step fails, Atmos keeps evaluating later structured
steps so when: failure and when: always steps can run. A false condition
skips the step without failing the command. Atmos evaluates built-in predicate
keywords first; any other scalar string is evaluated as a CEL expression. Use
!cel when you want to make that explicit.
commands:
- name: release
description: Run release checks
steps:
- type: shell
command: ./scripts/ci-release-checks.sh
when: ci
- type: shell
command: ./scripts/local-summary.sh
when:
not: ci
- type: shell
command: ./scripts/prod-only.sh
when: !cel 'stack == "prod" && ci'
String shorthand steps remain plain shell commands and always run. Use the structured form when a custom command step needs a condition.
Use when: always for cleanup that must run even when an earlier step fails:
commands:
- name: preview
description: Start a local service, run a preview, then tear it down
steps:
- type: shell
name: start-emulator
command: atmos emulator up aws -s dev --ephemeral
- type: shell
name: run-preview
command: atmos terraform apply demo -s dev -auto-approve
- type: shell
name: stop-emulator
when: always
command: atmos emulator down aws -s dev
- type: shell
name: validate
command: atmos terraform output demo -s dev
If run-preview fails, stop-emulator still runs and validate is skipped
because its omitted when is equivalent to success-only. The command still
returns the original preview failure; cleanup does not hide it.
Step predicates are:
ci- Run only when Atmos detects CI using its standard CI detection.
local- Run only outside CI.
always- Run after success or failure. Use this for teardown and cleanup steps.
never- Never run.
success- Run when the step condition is evaluated with success status.
failure- Run only after an earlier step has failed.
CEL expressions can read ci, status, stack, component, workflow,
step, env, flags, and arguments. For workflow and custom command steps,
status is the current command status: success before any step fails and
failure after an earlier step failed. flags and arguments mirror the
command's own declared --flag/positional values — the same data available to
steps as {{ .Flags.name }}/{{ .Arguments.name }} in templates — so a step
can gate on how the command was invoked:
commands:
- name: deploy
flags:
- name: dry-run
type: bool
steps:
- type: shell
command: terraform apply
when: !cel '!flags["dry-run"]'
Also available: os/arch/platform (for example when: "os == 'darwin'")
and the freshness facts checksum, timestamp, preconditions, sources,
artifacts — see inputs,
artifacts, and
preconditions.
Continue on error
Set continue: always on a step to forgive its own failure — later steps still
run and the command's overall exit status is unaffected, the same semantics as
GitHub Actions' continue-on-error. See continue
for the full field reference.
commands:
- name: release
description: Run release checks
steps:
- type: shell
command: golangci-lint run ./...
continue: always
- type: atmos
command: terraform apply vpc -auto-approve
Freshness inputs
Set inputs.sources/artifacts.paths on a step to skip it when nothing has
changed since it last ran successfully — without an explicit when, declaring
inputs/artifacts implicitly means when: checksum.changed. See
inputs and artifacts
for the full field reference.
commands:
- name: build
description: Compile the deployable artifact
steps:
- type: shell
command: go build -o bin/handler ./cmd/handler
inputs:
sources: ["cmd/**/*.go", "go.sum"]
artifacts:
paths: ["bin/handler"]
Declare preconditions.tools instead when a step's freshness only depends on
whether a tool is already on PATH — without an explicit when, declaring
preconditions alone implicitly means when: "!preconditions.success" (run only
when the tool is not already there). See
preconditions for the full field reference.
commands:
- name: install-stringer
description: Install stringer if it isn't already on PATH
steps:
- type: shell
command: go install golang.org/x/tools/cmd/stringer@latest
preconditions:
tools: ["stringer"]
Step types
Custom commands and workflows share one step-type registry, so every step type works the same in both. The full reference lives with the workflow docs — see the step type reference for each type's fields, examples, and behavior.
Atmos supports 25+ step types for workflows and custom command steps. Step type values live in the type field on a step object; type-specific fields stay on that same step object.
Step Types Overview
| Category | Step Types | Description |
|---|---|---|
| Command | atmos, shell, exec, container, emulator, http, archive | Run Atmos, shell, process-replacement, container, or emulator-lifecycle operations, call an HTTP endpoint, or pack/update a zip/tar/tgz archive |
| Orchestration | parallel, matrix, wait, wait-all, cancel | Run child steps concurrently, expand across a matrix, or wait for and tear down background container services |
| Interactive | input, confirm, choose, filter, file, write | Collect user input in a TTY |
| UI | toast, markdown, alert, say, title, clear, linebreak, stage, sleep, env, exit | Display status, control terminal output, or influence workflow control flow |
| Output | spin, table, pager, format, join, style, log | Format, render, log, or capture output |
Status Messages
Use type: toast for themed status messages. success, info, warn, and error are level values, not step types:
steps:
- name: done
type: toast
level: success
content: Deployment complete.