inputs
The step-level inputs field declares the files that determine a step's freshness, so Atmos can skip the step when nothing has changed since it last ran successfully. Pair it with artifacts (the step's outputs) — the two are separate, sibling fields.
steps:
- name: compile
type: shell
command: go build -o bin/handler ./cmd/handler
inputs:
sources: ["cmd/**/*.go", "go.sum"]
artifacts:
paths: ["bin/handler"]
With no explicit when, declaring inputs/artifacts is enough — the step implicitly means when: checksum.changed and runs only when the hash of the matched source files differs from the hash recorded after the last successful run. Run the same workflow twice in a row and the second run skips compile entirely; edit a matched source file and the next run executes it again.
inputs stays a general-purpose container — today it only holds sources, but it isn't narrowed to mean "source file globs" specifically, since other kinds of input signal may be added here later.
Fields
sources- List of glob patterns (relative to the step's working directory) for files whose content determines freshness. Supports
**for recursive matching and brace expansion ({a,b}).
Facts exposed to when
inputs doesn't introduce a second skip mechanism — it feeds facts into the same when/CEL engine every other step condition already uses, computed lazily: Atmos only does the work (hashing file content, statting mtimes) for the specific fact your when expression actually references.
checksum.changedtruewhen the content hash of the resolvedsourcesfiles differs from the hash recorded after the last successful run of this step. The default and recommended fact — content hashing survives a freshgit clone/actions/checkout, which resets every file's mtime and makestimestamp.changedunreliable right after a checkout.timestamp.changedtruewhen the newestsourcesfile is newer than the oldestartifactsfile. Stateless — no persisted record, cheaper than hashing, but unreliable immediately after a fresh checkout since CI resets every file's mtime to checkout time.sources- The resolved list of files matched by
inputs.sources, as structured records (path,mtime,checksum) rather than bare strings — see Advanced: structured records below.
Power users can reference these facts directly instead of relying on the implicit default, combining them with anything else when already supports:
steps:
- name: conditional-rebuild
type: shell
command: go build -o bin/handler ./cmd/handler
inputs:
sources: ["cmd/**/*.go"]
artifacts:
paths: ["bin/handler"]
when: timestamp.changed
Advanced: structured records
sources (and artifacts) resolve to lists of structured records — path, mtime (Unix seconds, content-modification time — not ctime/atime, which don't reflect content changes and aren't portable across platforms), and checksum — rather than bare path strings. This lets when express custom staleness logic directly using CEL's built-in exists/all macros, for cases the checksum.changed/timestamp.changed convenience facts don't cover:
when: "sources.exists(s, artifacts.all(a, s.mtime > a.mtime))"
This is the same comparison timestamp.changed already makes ("rebuild if any source is newer than the oldest artifact") — spelled out explicitly for when you need to combine it with other conditions or compare a subset of files.
Storage
The recorded checksum for checksum.changed persists under {base_path}/.atmos/cache/freshness/ — a project-relative directory, not a user-home cache — specifically so it composes with CI cache: add .atmos/cache/freshness to your ci.cache.paths and freshness state survives across CI runs the same way a .terraform/ directory would.
timestamp.changed is stateless and never touches this directory. A step's recorded checksum is only updated after the step's own execution succeeds — a failed step never falsely marks itself up to date.
The same inputs field works identically on custom command steps.