atmos stack destroy
Destroy selected components that remain defined in the current stack configuration. Consumers run before their prerequisites, using each component type's registered destroy handler.
Usage
atmos stack destroy --stack=dev [--component=app,api]
atmos stack destroy --component=app --component=api --stack=dev --dry-run
atmos stack destroy --all --stack=dev --dry-run
atmos stack destroy --affected --base=origin/main --stack=dev
atmos stack destroy --all --stack=dev --max-concurrency=2 --auto-approve
atmos stack destroy --tags=ephemeral --stack=dev --dry-run
With --stack=dev and no component filter, Atmos selects the whole stack.
Use --component=app to select an exact name, --component=app,api to select
several names, or repeat the flag: --component=app --component=api. Repeated and
comma-separated values can be combined; duplicate names are selected once.
Positional component arguments are not accepted. Unknown component or stack names
are errors.
Names match across component kinds. For example, if dev defines a Terraform
component named app and prod defines a Helm component named app, then
atmos stack destroy --all --component=app selects both.
Adding --stack=prod selects only the Helm component. If several kinds in the
same stack define app, each matching kind participates.
Use bare --component to open a multiselect picker. Explicit names supplied
alongside the bare flag start selected; otherwise nothing is preselected.
An empty selection or cancellation stops before any operations start.
The picker lists available names in the selected stack, or across stacks with
--all or --affected. Affected, tag, and label filters then narrow the selection.
--all and --affected are mutually exclusive.
When --stack, --all, and --affected are all omitted, Atmos first prompts for
a stack. If component names were supplied, the picker only lists stacks containing
all those names with handlers for the operation. The component picker appears
only when explicitly requested with bare --component. Both prompts work during
--dry-run. In CI, without an interactive terminal, or with --interactive=false,
a missing stack or bare --component produces an error explaining which values
to supply.
atmos stack destroy --stack=prod --dry-run
atmos stack destroy --stack=prod --component --dry-run
atmos stack destroy --component=app,api --component=worker --stack=prod --dry-run
A --stack value narrows the initial selection. To select across stacks, pass
--all or --affected; tag/label filters alone still need a supplied or prompted
stack. Dependency expansion is explicit and can cross stack boundaries and select
components with other names. Unselected prerequisites are not executed unless
included by expansion. Ordering is preserved through unchanged intermediates.
Execution reverses dependency order: consumers are destroyed before their prerequisites. Expansion flags retain their normal graph meaning.
Supported component kinds
- Terraform runs
atmos terraform destroy. - Helmfile runs
atmos helmfile destroy. - Helm runs
atmos helm destroy, an alias ofatmos helm delete. - Kubernetes runs
atmos kubernetes destroy, an alias ofatmos kubernetes delete. - AWS CloudFormation runs
atmos aws cloudformation destroy, an alias ofatmos aws cloudformation delete. - Custom component kinds are supported when a custom command named
destroydeclarescomponent.type. Whole-stack selection,--component,--all, and dependency expansion select these components;--affecteddoes not select custom kinds yet.
Packer and other kinds without a destroy handler are excluded with a notice.
Checks before execution
Atmos builds the full plan before it starts any component:
- Components with
metadata.lockedare excluded with a notice. - The command fails when a component outside the selection still requires a
component that would be destroyed. The error lists each
consumer -> targetpair. Add--include-dependentsto destroy the consumers first, or widen--stackto cover them. Optional dependencies do not block a destroy, and neither do consumers of kinds without adestroyoperation, such as Packer. Those are reported in a notice that names the component they still require. - Dependency cycles are reported as readable paths, such as
terraform/dev/a -> terraform/dev/b -> terraform/dev/a.
Approval
Each component command owns its approval behavior. One worker preserves stdin and
live output for interactive prompts. The --auto-approve flag appends the approval
arguments that each handler registers:
- Terraform destroy and CloudFormation destroy prompt for confirmation, so
--auto-approvepasses-auto-approveand--auto-approveto them respectively. - Helm, Kubernetes, and Helmfile deletes do not prompt, so
--auto-approveadds nothing for them. - Custom commands receive no approval arguments.
Concurrent workers have no stdin. With --max-concurrency above 1, a plan that
contains a component that would prompt is rejected before anything runs, unless
--auto-approve is set or the command is a --dry-run.
Output
Each excluded component produces a notice with its kind, stack, component, and the reason. During execution, every component reports a success, failure, or skipped line. The command finishes with a tally:
3 succeeded, 0 failed, 0 skipped, 1 excluded
With fail-fast, components still pending after a failure are skipped. With
keep-going, only the components that wait on the failed one are skipped.
CI
In CI mode, each component command runs with ATMOS_CI=true. Children inherit the rest
of the environment, so provider variables such as GITHUB_ACTIONS pass through. The
--ci flag sets ATMOS_CI for the children without forwarding the flag itself, because
not every component command accepts it. Job summaries and outputs also require
ci.enabled: true in atmos.yaml. Explicit --ci=false disables CI reporting
and grouping in child Atmos commands even when the environment identifies a CI provider.
A valid selection matching no components publishes a successful result with zero
execution counts, success=true, results=[], and a job summary. Dry runs do not
publish execution results.
Concurrent components would otherwise append to the same job summary and overwrite the same output keys. Atmos gives each component private summary and output files and, when the run finishes, writes:
- One job summary: a table of component, kind, stack, and result with the tally, followed by each component's own summary in a collapsible block, so per-component detail is preserved.
- One set of outputs, listed below.
components_total- Number of components in the plan, excluding the ones reported as excluded.
components_succeeded- Number of components that succeeded.
components_failed- Number of components that failed.
components_skipped- Number of components skipped because of an earlier failure.
components_excluded- Number of components excluded from the plan with a notice, excluding deleted definitions.
components_deleted- Number of selected definitions removed from configuration and awaiting teardown. These are reported separately from excluded components and are not executed.
successtruewhen no component failed.results- Compact JSON array with one entry per component:
kind,stack,component,status, andoutputs, the key-value outputs that component's command produced. The per-componentsummaryoutput is omitted because the job summary already shows it.
atmos stack destroy --all --stack=dev --ci --max-concurrency=2 --auto-approve
Workflow commands such as ::add-mask::, ::group::, ::error::, ::warning::, and
::notice:: stay intact with --max-concurrency greater than 1. Atmos writes these
lines without the component prefix, because CI providers only recognize them at the
start of a line.
Each component command groups its own output, and with ci.groups.mode: invocation
each component gets exactly one group. The stack destroy command itself opens no
group, because providers do not nest groups.
Hooks
Helm, Kubernetes, and CloudFormation expose destroy aliases for their existing
delete operations. The preview shows the actual hook events those commands fire;
for these aliases, hook events retain the delete name. Helmfile destroy fires
before.helmfile.destroy and after.helmfile.destroy. Single-component Terraform
destroy currently does not fire user lifecycle hooks, so none are promised in its
preview.
Before execution, Atmos checks named identities and component authentication defaults
across the selected components. An undefined identity stops the operation before any
component starts and includes matching profile suggestions when available. This check
does not log in; credential acquisition remains with each component command. Dry runs
and --identity=false bypass this authentication check.
Skipped status lines include the reason, such as fail-fast after terraform/dev/vpc failed,
dependency terraform/dev/vpc failed, or context canceled.
Flags
--component[=names]- Filter by exact component names across kinds. Repeat the flag or comma-separate names; matching any supplied name is sufficient. With no value, open a multiselect picker. Supplied names start selected when combined with a bare flag. Empty names and empty picker selections are errors. Omit the flag to select every eligible component in the chosen scope. Dependency expansion can add other names.
--all- Select every component that defines a
destroyoperation. May be narrowed by component names, stack, tags, or labels. Cannot combine--alland--affected. Default:false. --affected- Select components affected by the Git comparison. May be narrowed by component names, stack, tags, or labels. Cannot combine
--alland--affected. Default:false. --tags- Select components whose
metadata.tagsinclude any of the given tags (comma-separated). Selects matching components in a supplied or prompted stack. With component names,--all, or--affected, it narrows that selection. Dependency expansion still follows declared dependencies regardless of tags. Environment variable:ATMOS_TAGS. Default: No tag filter. --labels- Select components whose
metadata.labelscontain every givenkey=value(orkey:value) pair. Repeat the flag or separate pairs with commas. Used alone or combined like--tags; when both are given, a component must match both. Environment variable:ATMOS_LABELS. Default: No label filter. --stack,-s- Intersect the initial selection with a canonical stack name. A name that matches no stack is an error. Environment variable:
ATMOS_STACK. Without--allor--affected, a missing stack is prompted interactively or reported as an error. With either bulk flag, omitting this selects across stacks. --base- Base Git ref or SHA for the comparison. Atmos detects it automatically in supported CI environments. Requires
--affected. Default: Existing affected baseline rules. --ref- Git reference to compare against. Requires
--affected. --sha- Git SHA to compare against. Requires
--affected. --repo-path- Existing repository to use as the comparison baseline. Requires
--affected; cannot be combined with--base,--ref,--sha,--ssh-key,--ssh-key-password, or--clone-target-ref. --ssh-key- SSH key for cloning the comparison baseline. Requires
--affected. --ssh-key-password- Password for the SSH key. Requires
--affected. --clone-target-ref- Clone the comparison baseline. Requires
--affected. Default:false. --include-dependencies[=N]- Include prerequisites of the selected components. The bare flag expands without a depth limit; use the
=Nform, such as--include-dependencies=2, to limit the depth. Default: Disabled. --include-dependents[=N]- Include consumers of the selected components. The bare flag expands without a depth limit; use the
=Nform to limit the depth. Default: Disabled. --max-concurrency- Maximum number of active component operations. One worker permits interactive prompts. Default:
1. --failure-modefail-faststops at the first failure.keep-goingfinishes independent branches while prerequisites of failed components are skipped, leaving them in place because they wait for their consumers in destroy order. Default:fail-fast.--log-orderstreamprints component output as it arrives.groupedemits complete component logs in stable dependency order and applies when--max-concurrencyis greater than1. Grouped mode shows live start and completion messages on stderr while buffering child logs. It sends each component's stdout to stdout and its headers and stderr to stderr. Default:stream.--dry-run- Preview selection, commands, relationships, and lifecycle hooks without destroying anything. Environment variable:
ATMOS_DRY_RUN. Default:false. --identity,-i- Forward the identity to each child. Use
--identitywithout a value to select interactively, which requires--max-concurrency=1. Environment variable:ATMOS_IDENTITY. Default: Component command behavior. --auto-approve- Append each handler's registered approval arguments. Terraform destroy and CloudFormation destroy prompt without it; Helm, Kubernetes, and Helmfile deletes do not prompt. Default:
false. --ci- Run in CI mode. Every child component command runs with
ATMOS_CI=true, and Atmos publishes one combined job summary and one set of outputs for the whole run. Without the flag, CI mode turns on whenATMOS_CIorCIis truthy or a CI provider is detected; an explicit--ci=falseturns it off. Environment variables:ATMOS_CI,CI. Default:false. --skip-hooks[=names]- Skip all hooks, or the comma-separated hook names; previews identify skipped hooks. Environment variable:
ATMOS_SKIP_HOOKS.
Comparison flags (--base, --ref, --sha, --repo-path, --ssh-key,
--ssh-key-password, and --clone-target-ref) require --affected and are rejected
otherwise. Only the environment variables listed above apply to this command. Variables
that other commands bind to similar settings, such as ATMOS_TERRAFORM_DESTROY_ALL, do
not change the selection.
Scope
This command does not recover removed definitions. Deleted affected components are
reported and omitted. It does not remove stack manifests; use stack config delete
for configuration values. Manifest deletion under stack delete is reserved for a
future breaking release.