Manage Lifecycle Events with Hooks
Atmos hooks run automated actions at specific points in a component's
lifecycle — before/after terraform plan, apply, deploy, or init.
Built-in kinds cover the common cases (cost analysis, security scanning,
storing outputs) and the generic command kind plugs in any binary you
need. Tools auto-install through the Atmos toolchain and their output
renders identically in your terminal and on Atmos Pro.
Hooks Schema
Each hook has a kind that selects an engine and a set of defaults. The
generic command kind runs any binary; named kinds like infracost and
trivy ship sane defaults so you don't need to write any wiring.
components:
terraform:
vpc:
hooks:
# Cost diff after every plan — zero config.
cost:
events: [after.terraform.plan]
kind: infracost
# Security scan after every plan.
security:
events: [after.terraform.plan]
kind: trivy
# Store outputs after apply (the original hook use case).
outputs:
events: [after.terraform.apply]
kind: store
name: prod/ssm
outputs:
vpc_id: .id
Hooks can be declared at the global level, the terraform section, an
individual component, or in the overrides section. Partial config at
each level merges into the final result so you can keep configuration
DRY.
Supported Lifecycle Events
| Event | When it fires |
|---|---|
before.terraform.init | Before atmos terraform init runs |
after.terraform.init | After atmos terraform init finishes |
before.terraform.plan | Before atmos terraform plan runs (after init has completed) |
after.terraform.plan | After atmos terraform plan finishes |
before.terraform.apply | Before atmos terraform apply runs |
after.terraform.apply | After atmos terraform apply finishes |
before.terraform.deploy | Alias of before.terraform.apply (deploy is apply with -auto-approve) |
after.terraform.deploy | Alias of after.terraform.apply |
Hooks with no events list fire on every supported event for backward
compatibility with configs written before event filtering existed. You
should use the dotted form (after.terraform.plan) in new configs. The
legacy hyphenated form (after-terraform-plan) is still accepted and
equivalent for backward compatibility.
The before.terraform.init and after.terraform.init events fire around the
explicit atmos terraform init command. They do not fire for the implicit
init that plan, apply, and deploy run automatically — use
before.terraform.plan / before.terraform.apply for those.
Built-in Kinds
Each named kind below ships defaults for command, args, env, and
on_failure so the minimal config (just events and kind) does the
right thing. Every default is overridable — set the field on your hook
and your value wins. See Overriding Kind Defaults
for the override rules (notably: args and env are full replacement,
not merge).
kind: infracost
Runs Infracost to compute monthly cloud cost estimates from your Terraform plan. Renders a cost diff card with the top resources by monthly cost.
hooks:
cost:
events: [after.terraform.plan]
kind: infracost
Requires INFRACOST_API_KEY to be set in the shell or on the hook
(free at infracost.io).
kind: trivy
Trivy is an open-source security and misconfiguration
scanner from Aqua Security. The trivy kind
runs Trivy in config mode against the component's Terraform sources and
feeds the SARIF output through Atmos's shared scanner result handler.
hooks:
security:
events: [after.terraform.plan]
kind: trivy
command(default)trivy.args(default)config --format sarif --output $ATMOS_OUTPUT_FILE --quiet $ATMOS_COMPONENT_PATH.- Output
- Single SARIF file written directly to
$ATMOS_OUTPUT_FILE. on_failure(default)warn— a scanner finding does not block your plan unless you override this.- Runtime requirements
- The
trivybinary on PATH. Declare it independencies.toolsto have Atmos auto-install through the toolchain. - Authentication
- None required for
configscans.
kind: checkov
Checkov is an open-source policy-as-code scanner
maintained by Bridgecrew / Prisma Cloud
(Palo Alto Networks). The checkov kind runs Checkov over the component's
Terraform sources and feeds the SARIF output through Atmos's shared scanner
result handler.
hooks:
policy:
events: [after.terraform.plan]
kind: checkov
command(default)checkov.args(default)-d $ATMOS_COMPONENT_PATH -o sarif --output-file-path $ATMOS_OUTPUT_DIR --quiet --soft-fail. Note: Checkov's--output-file-pathtakes a directory and writesresults_sarif.sarifinside it.- Output
- SARIF file written to
$ATMOS_OUTPUT_DIR/results_sarif.sarif; the kind's result handler reads from that nested path. on_failure(default)warn.- Runtime requirements
- The
checkovbinary on PATH. Declare it independencies.toolsto have Atmos auto-install through the toolchain. - Default env additions
- Atmos sets
SSL_CERT_FILEfrom the host CA bundle when one is detected. The PyInstaller-packaged Checkov release ships a frozencertifibundle that often cannot validate the TLS chain servingapi0.prismacloud.io(the API Checkov hits at startup to fetch guideline mappings); pointingSSL_CERT_FILEat the host bundle is the official PyInstaller workaround. On hosts where Atmos cannot detect a CA bundle, the kind makes no env change and Checkov falls back to its bundledcertifi.
kind: kics
KICS (Keeping Infrastructure as Code Secure) is an
open-source IaC scanner from Checkmarx. The
kics kind runs KICS over the component's Terraform sources and feeds
the SARIF output through Atmos's shared scanner result handler.
hooks:
iac-scan:
events: [after.terraform.plan]
kind: kics
command(default)kics.args(default)scan -p $ATMOS_COMPONENT_PATH -o $ATMOS_OUTPUT_DIR --report-formats sarif --no-progress.- Output
- SARIF file written to
$ATMOS_OUTPUT_DIR/results.sarif. on_failure(default)warn.- Runtime requirements
- The
kicsbinary on PATH. Declare it independencies.toolsto have Atmos auto-install through the toolchain — Atmos ships a curated registry override sokics: "<version>"resolves correctly even though the upstream Aqua entry uses an unsupportedgo_buildtype. KICS_QUERIES_PATH- Required at runtime. The KICS release tarball does not include the query library. Homebrew install:
export KICS_QUERIES_PATH=$(brew --prefix kics)/share/kics/assets/queries. For toolchain installs, point at the unpackedassets/queriesdirectory shipped alongside the release archive.
All three scanner kinds emit SARIF and share a result handler that renders
findings as a compact markdown table — severity, rule ID (linked to the
upstream remediation guide when available), short description, and
file:line location. The same markdown body flows to your terminal, the
Atmos Pro run page, and PR comments.
kind: store
Reads Terraform outputs and writes them to an external store such as
kind: aws/ssm, kind: aws/asm, Azure Key Vault, or Google Secret Manager.
Use this to share state between components without backend wiring — paired with
the !store function for reading.
hooks:
outputs:
events: [after.terraform.apply]
kind: store
name: prod/ssm
outputs:
vpc_id: .id
private_subnet_ids: .private_subnet_ids
See Store function reference below for configuration details.
kind: git
Publishes component artifacts to a Git repository on lifecycle events — commit (and optionally push) generated files through the shared Atmos Git service, with its safety rules (no force push, path-scoped commits, bounded push retry) and authentication built in.
By default the hook targets the current repository — the repo the
component already lives in — matching the common case of committing
generated files back to the working repo after terraform apply:
components:
terraform:
app:
hooks:
publish-artifacts:
events:
- after.terraform.apply
kind: git
# repository omitted -> the current repository
commit:
message: "Update generated artifacts for {{ .component }} in {{ .stack }}"
paths:
- generated/{{ .stack }}/{{ .component }}
push: true
Setting repository: <name> targets a managed repository configured
under the top-level git.repositories section
instead — Atmos clones/reconciles its workdir, commits, and pushes with
the repository's configured identity, signing, and retry settings:
components:
terraform:
app:
hooks:
publish-artifacts:
events:
- after.terraform.apply
kind: git
repository: generated-terraform
commit:
message: "Update generated artifacts for {{ .component }} in {{ .stack }}"
push: true
Behavior notes:
- Clean no-op: when there are no changes to commit, the hook succeeds without creating a commit — no empty commits.
- Push only on commit:
push: truepushes only when a commit was actually created. - Provenance trailers: published commits carry
Atmos-Stack,Atmos-Component, andAtmos-Source-SHAtrailers, making deployment-repo commits traceable back to exactly what produced them. - Failure mode: unlike the advisory tool kinds,
kind: gitdefaults toon_failure: fail— a silently dropped commit or push loses artifacts. Override withon_failure: warnorignoreif publishing is best-effort. - Templating:
commit.messageandcommit.pathssupport the standard hook template context ({{ .component }},{{ .stack }},{{ .vars.* }}).
kind: git hooks are separate from local Git hooks (pre-commit,
commit-msg, ...) — those are configured under git.hooks and managed
by atmos git hooks.
kind: command (generic engine)
The escape hatch — runs any toolchain-resolved binary with Atmos's
standard ATMOS_* env-var contract. Use when no built-in kind fits
your tool.
hooks:
custom-scan:
events: [after.terraform.plan]
kind: command
command: my-internal-scanner
args:
- "--component"
- "{{ .atmos_component }}"
- "--source"
- "$ATMOS_COMPONENT_PATH"
- "--out"
- "$ATMOS_OUTPUT_FILE"
format: markdown # optional; tells Atmos to render the output file as markdown
on_failure: warn # warn | fail | ignore
The subprocess receives these environment variables:
ATMOS_COMPONENT_PATH- On-disk path to the component's Terraform module (honors workdir resolution).
ATMOS_PLANFILE- Planfile path on after-plan events (when threaded — currently a stub).
ATMOS_OUTPUT_DIR- A fresh temp directory created by Atmos before the subprocess starts (via
os.MkdirTemp("", "atmos-hook-*")). Unique per hook invocation — two hooks firing on the same event get separate directories and do not share state through these env vars. The directory and everything inside it is deleted automatically when the hook returns. Use this for tools that write to a directory rather than a single file (e.g., KICS, Checkov). ATMOS_OUTPUT_FILE$ATMOS_OUTPUT_DIR/output. Write structured output here for the kind's result handler to read. Same lifetime asATMOS_OUTPUT_DIR.ATMOS_STACK- The stack name.
ATMOS_COMPONENT- The component name.
Atmos creates a fresh temp directory per hook invocation, points
ATMOS_OUTPUT_DIR and ATMOS_OUTPUT_FILE at it, and deletes the entire
directory after the hook returns. Custom commands can write any
additional files they need into $ATMOS_OUTPUT_DIR — sibling hooks won't
collide, and cleanup is automatic.
Tool stdout/stderr stream through Atmos's I/O layer so you see them in real time — same UX as Terraform plan output.
kind: step (run a step type)
Runs any registered workflow / custom-command step type
— container, toast, log, markdown, http, and the rest — on a
lifecycle event. Instead of growing the hook-kind list one tool at a
time, kind: step makes the whole step library available as hooks, so a
step you already use in a workflow runs identically as a hook.
hooks:
notify-slack:
kind: step
type: http # any registered step type
events: [after.terraform.apply]
on_failure: warn # envelope policy: warn | fail | ignore
retry: # envelope policy: same schema as a workflow step's retry
max_attempts: 3
with: # the step's own parameters
url: https://hooks.slack.com/services/XXX
method: POST
body: '{"text": "Deployed {{ .atmos_component }} to {{ .stack }}"}'
http step ships separatelyThe Slack example above needs the http step type. If your Atmos build
doesn't have it yet, use a step type that is registered (e.g. container,
toast, log, markdown) — the bridge itself works with every
registered step type.
The split between the envelope and with: is deliberate:
- The envelope (
kind,type,events,on_failure,retry,env) is what the hook runner interprets. with:is what the step interprets — it is the step's own parameter block, exactly as you'd write it in a workflow.
on_failure and retry sit at the envelope because Atmos applies them
around the step (retry the whole step, then decide warn/fail/ignore) —
the step never sees them.
# Build and push an image after apply, retried, non-blocking.
hooks:
publish-image:
kind: step
type: container
events: [after.terraform.apply]
on_failure: warn
with:
action: build
image: example:latest
build:
context: .
tags: [example:latest]
type- The step type to run — any registered workflow/custom-command step type. A typo fails the preflight check before Terraform runs.
with- The step's parameters. These are rendered with the standard hook template context and YAML functions (so
{{ .atmos_component }}and!store ...work insidewith:), then handed to the step. The step's own validation is the gate — the schema keepswith:open. when(defaultsuccess)- Declarative condition controlling whether this hook runs. See Reacting to success or failure.
retry- Optional. Wraps the step execution in Atmos's retry policy — same schema as a workflow step's
retry. Applied by the hook runner, not the step. env- Extra environment variables layered on top of the standard
ATMOS_*variables (ATMOS_STACK,ATMOS_COMPONENT,ATMOS_COMPONENT_PATH, …) the step receives. on_failure(defaultwarn)warn|fail|ignore, applied to the step's own outcome (not the terraform operation's). Usewhen:to react to the operation outcome.
All step types are available, including interactive ones — Atmos does not restrict them. Whether an interactive step makes sense on a (usually headless / CI) lifecycle event is the step's responsibility, not the hook's.
Reacting to success or failure
By default an after-* hook runs only when the operation succeeds — a
store hook must not write outputs after a failed apply. Set when: to change
that. Hooks support the same declarative predicates as workflow and custom
command steps, plus the hook-specific lifecycle status predicates:
when: success(default)- Run only when the operation succeeded.
when: failure- Run only when the operation failed.
when: always- Run on both outcomes.
when: ci- Run in CI after a successful operation. Hooks apply
successimplicitly when the condition does not mentionsuccess,failure, oralways. when: [ci, always]- Run in CI after both successful and failed operations.
Built-in predicates are ci, local, always, never, success, and
failure. Compose them with list shorthand, all, any, and not:
hooks:
ci-summary:
kind: command
events: [after.terraform.plan]
command: ./scripts/write-ci-summary.sh
when: [ci, always]
local-cleanup:
kind: command
events: [after.terraform.apply]
command: ./scripts/cleanup.sh
when:
all:
- local
- failure
skip-in-ci:
kind: command
events: [after.terraform.plan]
command: ./scripts/local-report.sh
when:
not: ci
Condition filtering also applies during hook preflight. For example,
when: ci hooks are skipped outside CI before Atmos validates or installs the
hook's tools.
The outcome is available to the step both as template context and as environment variables, alongside the component and stack — so a hook can announce exactly what happened:
hooks:
announce:
kind: step
type: say
events: [after.terraform.apply]
when: always
with:
print: always
content: >-
The {{ .atmos_component }} component in the {{ .stack }} stack
{{ if eq .status "failure" }}was not successful{{ else }}was successful{{ end }}
{{ .status }}successorfailure. AlsoATMOS_HOOK_STATUS.{{ .exit_code }}- The operation's exit code (
0on success). AlsoATMOS_HOOK_EXIT_CODE. {{ .error }}- The error message on failure, empty on success. Also
ATMOS_HOOK_ERROR. {{ .atmos_component }}/{{ .stack }}- The component and stack (already part of the hook template context). Also
ATMOS_COMPONENT/ATMOS_STACK.
Steps that read the environment instead of templates (e.g. a shell or say
step) get the same values via ATMOS_HOOK_STATUS, ATMOS_HOOK_EXIT_CODE,
ATMOS_HOOK_ERROR, ATMOS_COMPONENT, and ATMOS_STACK.
when: and the ATMOS_HOOK_* variables apply to every hook kind, not just
kind: step — e.g. a kind: command cleanup hook with when: failure. The
outcome is only meaningful on after-* events; before-* events always run as
success.
Overriding Kind Defaults
Every named kind (infracost, trivy, checkov, kics, store)
ships defaults for command, args, env, and on_failure. Any
field you set on the hook overrides the kind's default for that field.
args and env are full replacement — if you set args on the
hook, the kind's default arg list is discarded entirely (you must
restate every arg you want). Same for env. If you only need to tweak
one flag, use kind: command directly and pass the full command line.
A common case is bumping a scanner's severity threshold or adding a config file. Because override replaces the entire arg list, copy the default args from the kind's reference section above and add your overrides:
hooks:
security:
events: [after.terraform.plan]
kind: trivy
args:
- config
- --format
- sarif
- --output
- $ATMOS_OUTPUT_FILE
- --severity
- HIGH,CRITICAL # added
- --quiet
- $ATMOS_COMPONENT_PATH
You can also override just on_failure (independent of args/env) to
make a scanner finding block the run:
hooks:
security:
events: [after.terraform.plan]
kind: trivy
on_failure: fail # default is warn
Or override env to inject a tool-specific config path:
hooks:
policy:
events: [after.terraform.plan]
kind: checkov
env:
CHECKOV_CONFIG_FILE: $ATMOS_COMPONENT_PATH/.checkov.yaml
Setting env on the hook replaces the kind's DefaultEnv map
entirely. For kind: checkov specifically, that means losing the
default SSL_CERT_FILE workaround (see kind: checkov)
— restate it if you still need it.
Tool Auto-Install via dependencies.tools
Declare which tools a hook needs and Atmos installs them automatically through the toolchain before the hook fires. Same syntax used by component dependencies:
components:
terraform:
vpc:
dependencies:
tools:
infracost: "0.10.44"
checkov: "3.2.529"
hooks:
cost: { events: [after.terraform.plan], kind: infracost }
security: { events: [after.terraform.plan], kind: checkov }
A pre-flight check runs once per command invocation:
- Resolve every tool the component declares.
- Install any that aren't already present.
- Build a PATH augmentation that points at the installed pinned versions.
- Verify each hook's binary is resolvable.
If any binary is missing, the run aborts before Terraform with a
clear error including a hint to declare it in dependencies.tools. You
won't lose a 90-second plan to find out a hook is misconfigured.
Pin a concrete version ("3.2.529") or use a SemVer constraint
("~> 3.2"). "latest" is accepted but the resulting PATH may not match
what the toolchain installed — pin a version for reliable behavior.
Curated Atmos Registry
Atmos ships a small curated registry baked into the binary that
overrides upstream Aqua registry entries for tools that don't model
cleanly with Aqua's defaults. Today this covers KICS (the upstream
entry uses type: go_build which the Atmos installer doesn't support
yet). The override is invisible to users — you just write kics: "2.1.20" in dependencies.tools and it works.
You can override even the built-in overrides with your own registry entry at higher priority — see Toolchain Configuration for the registry syntax.
Skipping Hooks at Runtime
Set --skip-hooks (or the ATMOS_SKIP_HOOKS environment variable) to
bypass hooks for a single invocation without editing stack config.
Useful for emergency operations, local iteration, or when a scanner is
producing noisy false positives you want to ignore for one run.
atmos terraform plan vpc -s prod --skip-hooks # skip all
atmos terraform plan vpc -s prod --skip-hooks=cost,security # skip specific hooks by name
ATMOS_SKIP_HOOKS=true atmos terraform apply vpc -s prod # via env var
Skipped hooks are logged at INFO level so it stays visible in CI
output. The flag is per-invocation only — it doesn't propagate to
nested commands or workflows. Because hooks only run on terraform
operations, --skip-hooks is a flag of the
atmos terraform command and all its
subcommands (plan, apply, deploy, …).
Hooks with --all
atmos terraform plan --all / atmos terraform apply --all walks every
terraform component in the selected stack(s) in dependency order and runs
the command for each. Hooks fire just like a single-component invocation,
with these specifics:
- Hooks fire per component, in dependency order.
destroy --allreverses the order so dependents tear down before their dependencies. - Tool auto-install runs per component. Each component's
dependencies.toolsis resolved on its own, so different components in the same--allrun can pin different versions of the same tool — the toolchain PATH is rebuilt per component. --skip-hookspropagates across the whole run. The flag is set on the shared invocation state and applies uniformly to every component--allvisits.on_failure: failaborts the remaining traversal. A failing hook on component K stops--allbefore it visits any downstream node. Components already processed stay processed — there is no rollback.
Failure Modes
Every hook can declare an on_failure mode:
warn(default)- Log a warning if the hook fails, continue. Built-in scanner kinds default to
warnso a security or cost issue doesn't block your plan unless you explicitly want it to. fail- Propagate the subprocess error — the terraform command aborts. Use when a hook finding should block the operation (e.g., critical security violations).
ignore- Silently swallow failures. Useful for opportunistic notifications you don't want to ever break a run.
on_failure vs whenThese answer different questions. on_failure controls what happens when the
hook itself fails. when (success | failure | always) controls whether
the hook runs based on the terraform operation's outcome — see
Reacting to success or failure.
Format Symmetry
When a hook's kind produces a markdown summary (every built-in kind does), Atmos renders the same bytes in:
- Your terminal (via
ui.MarkdownMessage) - The GitHub Actions job step summary
- The Atmos Pro run page (when Pro is connected)
No separate "terminal-friendly" vs "Pro-friendly" variants — write markdown once, get it everywhere.
CI Reporting
When running in CI (GitHub Actions), Atmos can surface scanner-hook findings
in the pipeline itself instead of leaving them buried in the terraform plan
log. Three independent outputs are available, all under ci: and all gated by
the ci.enabled master switch:
ci:
enabled: true # required for any CI reporting to fire
summary: true # markdown report in the job step summary (default: on)
annotations: true # inline ::error/::warning on the PR diff (default: on)
results: true # upload SARIF to GitHub Code Scanning (default: off)
ci.summary- Appends each hook's markdown summary to the GitHub Actions job step summary. Default on.
ci.annotations- Renders each finding as an inline GitHub annotation (
::error/::warning) anchored at its file and line on the pull request diff. This is the non-Code-Scanning path — it needs no GitHub Advanced Security. Default on. ci.results- Uploads the raw SARIF to GitHub Code Scanning (the Security tab) as tracked alerts. Code Scanning is free on public repositories; on private/internal repositories it requires GitHub Advanced Security — a paid add-on that GitHub licenses per active committer. Default off (opt-in). The analysis category is derived automatically from the scan target (
atmos/<component>for shared component source,atmos/<stack>/<component>for a per-stack workdir) so per-component uploads don't overwrite each other.
All three are best-effort: a reporting failure logs at debug and never fails
the hook or the terraform command. Outside CI they no-op. Findings derive from the
tool's SARIF, so the three built-in SARIF scanners — checkov, trivy, kics —
all participate; infracost (cost, not findings) does not.
ci.annotations and ci.results can both place line-level feedback on a pull
request. Enable both when you intentionally want the lightweight Actions
annotation and the tracked Code Scanning alert; otherwise enable only one of
them to avoid duplicate comments on the same lines.
Required GitHub Actions permissions
permissions:
contents: read
security-events: write # ONLY required for ci.results (SARIF upload)
ci.summary and ci.annotations need no special permissions and no paid
add-on — the step summary is a file write and annotations are log output, so
they work on any repository. ci.results uploads to Code Scanning, which
requires the security-events: write permission and — on private/internal
repositories — GitHub Advanced Security, which GitHub licenses as a paid
add-on per active committer (Code Scanning is free on public repositories).
Note: pull requests from forks do not receive
security-events: write on the default token, so ci.results is skipped there.
Custom hooks
A custom kind: command hook gets the same reporting as the built-in scanners by
declaring format: sarif — any SARIF-emitting tool (tfsec, semgrep, gitleaks,
snyk, …) then flows to the summary, annotations, and Code Scanning with no extra
code:
hooks:
tfsec:
events: [after.terraform.plan]
kind: command
command: tfsec
args: ["--format", "sarif", "--out", "$ATMOS_OUTPUT_FILE", "$ATMOS_COMPONENT_PATH"]
format: sarif # parse output as SARIF
# results: results.sarif # optional: read SARIF from this file in $ATMOS_OUTPUT_DIR
The report is labeled by the SARIF's own tool name (e.g. "tfsec").
Backwards Compatibility
The pre-rename command: YAML key is still accepted as an alias for
kind:. Existing stack manifests like:
hooks:
vpc-id:
events: [after.terraform.apply]
command: store # legacy form — still works
name: vpc/id
outputs:
id: .vpc_id
…parse identically post-upgrade. No migration required.
Hyphenated lifecycle events such as after-terraform-apply are also still
accepted. New documentation and examples use the canonical dotted form
(after.terraform.apply).
Store Function Reference
For complete details on the store kind (configuring stores, supported
backends, output mapping, etc.), see Sharing State with
Stores.
hooks.<name>- Map key is the hook's name (unique per component).
hooks.<name>.events- List of lifecycle events that trigger this hook.
hooks.<name>.kind- Which engine runs the hook. One of
store,command,git,step,infracost,checkov,trivy,kics. Aliased from legacycommand:field. hooks.<name>.type- For
kind: step: the step type to run (e.g.container,http,toast,log). hooks.<name>.with- For
kind: step: the step's own parameters. Rendered with the hook template context and YAML functions, then validated by the step at run time. hooks.<name>.retry- For
kind: step: retry policy wrapping the step execution. Same schema as a workflow step'sretry. hooks.<name>.command- For
kind: command: the binary to execute (resolved via the toolchain or PATH). Named kinds default this. hooks.<name>.args- For
kind: command: arguments passed to the binary. Supports Go template syntax ({{ .atmos_component }}) for stack metadata and$ATMOS_*env-var substitution at exec time. hooks.<name>.env- Additional env vars exported to the subprocess. Supports the same templating as
args. hooks.<name>.format- Optional rendering hint. v1 supports
markdown— tells Atmos to render the tool's output file as markdown in the terminal. hooks.<name>.on_failurewarn(default),fail, orignore. Applies to the hook's own outcome, not the terraform operation's.hooks.<name>.when- Declarative condition controlling whether the hook runs. Omitted means
success; if the condition does not mentionsuccess,failure, oralways, Atmos appliessuccessimplicitly. See Reacting to success or failure. hooks.<name>.name/hooks.<name>.outputs- Store-kind specific. See store function reference.
hooks.<name>.repository- For
kind: git: the name of a managed repository under the top-levelgit.repositoriesconfig. Omit to target the current repository. hooks.<name>.commit.message- For
kind: git: the commit message. Supports the standard hook template context. Empty selects the engine default (Update artifacts for <component> in <stack>). hooks.<name>.commit.paths- For
kind: git: repo-relative paths staged for the commit. Paths must resolve inside the repository worktree. hooks.<name>.push- For
kind: git: push the created commit to the remote whentrue(only when a commit was actually created).
Examples
Five working examples live in the Examples gallery:
hooks-infracost— cost analysis withkind: infracosthooks-trivy— security scanning withkind: trivyhooks-checkov— policy scanning withkind: checkovhooks-kics— IaC scanning withkind: kicshooks-custom-command— custom Python script viakind: command
Each uses dummy AWS provider config so tofu plan succeeds offline.
Related
atmos terraform—--skip-hooksand other terraform flags- Global Flags — flags available on every command
- Component Dependencies —
dependencies.toolssyntax used for auto-install - Toolchain Configuration — registry overrides
- External Stores — reading data written by
kind: store - Git Configuration — managed repositories used by
kind: git atmos git— imperative Git operations on the same shared service- Terraform State — alternative state-sharing pattern via
!terraform.state