# atmos stack create

Create a new stack using the existing scaffold catalog and generation engine.
Preview the rendered files and generation hooks before writing. Existing files are never overwritten.

## Usage

```shell
atmos stack create --file=stacks/deploy/dev.yaml --name=dev
atmos stack create --file=stacks/deploy/dev.yaml \
  --import=catalog/defaults \
  --component=terraform:network \
  --component=helmfile:services \
  --dry-run
```

Choose either `--file` for a manifest or `--target` for a directory layout. These flags
are mutually exclusive. A `--file` must end in `.yaml` or `.yml` and match the project's
stack discovery paths. A relative `--file` resolves from the project base path, not the
current directory, and output files are rooted there too. Relative `source` paths in
`scaffold.templates` resolve from the configuration file that declares the source.
Named templates honor `--config`, configuration imports, and active profiles.
`--name` explicitly sets the stack name in the built-in scaffold. When omitted,
the generated manifest leaves naming to the project's conventions; provide the
variables required by your `stacks.name_template`, directly or through imports.

Repeat `--import` to add imports and `--component=kind:name` to add component
stubs. These stubs have `metadata.enabled: false` and empty `vars`. Configure them
and enable them when ready. The command does not generate component sources unless
your selected scaffold includes them. Component order does not imply dependencies.

If a write fails or creation is canceled, Atmos rolls back files created by that
attempt so you can correct the cause and retry. It preserves preexisting files,
hook-created files, and generated files changed after creation. If cleanup cannot
finish, the error lists the remaining paths for manual recovery. A replaced stale
generation record is restored when possible. Hook side effects are not rolled back.
If generation succeeds but an after hook fails, the generated files and record remain.

## Flags

- **`--file`**
  Path of the new stack manifest. Mutually exclusive with 
  `--target`
  . Must end in 
  `.yaml`
   or 
  `.yml`
   and fall under the project's stack discovery paths. Existing files are never overwritten.
- **`--target`**
  Directory for generated stack files. Mutually exclusive with 
  `--file`
  . Relative paths resolve from the project base path. The directory must be under 
  `stacks.base_path`
  ; template outputs are relative to it. Existing directories are allowed, but existing files are never overwritten.
- **`--template`**
  Scaffold name or source: a name from 
  `scaffold.templates`
  , an embedded catalog template, or a direct local or remote source. Default: 
  `stack`
  .
- **`--name`**
  Explicit stack name. When omitted, the generated manifest follows the project's naming convention. Default: Empty.
- **`--import`**
  Stack import to add. Repeatable. Each occurrence is one value, so commas and braces such as 
  `catalog/{a,b}`
   are kept as written. Default: None.
- **`--component`**
  Disabled component stub to add, in the form 
  `kind:name`
  . Repeatable. The kind must be a supported component kind, including custom kinds declared by custom commands, and the name cannot contain whitespace. Duplicates are rejected. Default: None.
- **`--set`**
  Scaffold answer in the form 
  `key=value`
  . Repeatable. An entry without 
  `=`
   is an error. The reserved inputs 
  `stack_file`
  , 
  `stack_name`
  , 
  `stack_imports`
  , and 
  `stack_components`
   cannot be set. Default: None.
- **`--ref`**
  Git revision to use for a scaffold fetched from a Git source. Using it with an embedded or local scaffold is an error. Default: The source's default revision.
- **`--interactive`, `-i`**
  Prompt for the destination and scaffold answers when connected to a terminal, including during 
  `--dry-run`
  . Without a terminal, Atmos uses defaults and errors on missing required inputs. Default: 
  `true`
  .
- **`--defaults`**
  Use scaffold defaults and 
  `--set`
   values without prompting. 
  `--interactive=false`
   has the same effect. Default: 
  `false`
  .
- **`--skip-hooks[=names]`**
  Skip all scaffold hooks, or the comma-separated hook names. Environment variable: 
  `ATMOS_SKIP_HOOKS`
  . Default: No hooks skipped.
- **`--dry-run`**
  Print the files and scaffold hooks without writing or running anything. Environment variable: 
  `ATMOS_DRY_RUN`
  . Default: 
  `false`
  .

The template must consume the flags you pass. If `--name`, `--import`, or `--component`
is given and the rendered manifest does not contain the value (or no generated stack
document contains it in directory mode), creation fails and
names the flag, so no input is dropped silently. A custom template reads these flags
through `stack_name`, `stack_imports`, and `stack_components`.

## Checks before writing

Before any hook runs or any file is written, Atmos processes the existing stack
manifests together with every generated stack file, using the same pipeline as
`atmos describe stacks`. Creation fails, and nothing is written, when the result has:

- A stack name that cannot be resolved. Pass `--name`, or set the variables that
  `stacks.name_template` uses.
- A missing import. Import paths are relative to `stacks.base_path`; create the
  imported manifest or correct the `--import` value.
- A component defined in more than one top-level manifest resolving to the same stack.
  Disjoint component definitions may share a stack name. Choose distinct component
  definitions or stack names, or edit the existing stack with
  [`atmos stack config set`](/cli/commands/stack/config/set).
- An invalid generated stack file.

If the project's existing stacks already fail to process, the error says so and points
to `atmos validate stacks`, rather than blaming the new files.

Existing files are never overwritten. When the manifest exists, edit it with
`atmos stack config set` or delete it first and run the command again.

## Use an existing scaffold

`--template` selects a name from the existing `scaffold.templates` configuration,
an embedded/catalog template, or a direct local or remote source. Without it,
creation uses the built-in `stack` scaffold.

```yaml title="atmos.yaml"
scaffold:
  templates:
    application-stack:
      description: Application stack with network and services
      source: ./scaffolds/application-stack
```

```shell
atmos stack create --template application-stack \
  --file stacks/deploy/dev.yaml --set environment=dev --dry-run
```

For `--file`, a stack-compatible scaffold declares its manifest output using `spec.stack.manifest`:

```yaml title="scaffolds/application-stack/scaffold.yaml"
apiVersion: atmos/v1
kind: AtmosScaffoldConfig
metadata:
  name: application-stack
spec:
  stack:
    manifest: '{{ .Config.stack_file }}'
  fields:
    - name: environment
      type: input
      required: true
  files:
    - path: stack.yaml
      target: '{{ .Config.stack_file }}'
```

```yaml title="scaffolds/application-stack/stack.yaml"
# atmos:template
vars:
  stage: {{ .Config.environment | quote }}
components:
  terraform:
    network:
      vars: {}
```

The generated manifest must match `--file`. Other outputs are relative to the project
base path; a scaffold can conditionally create component sources or documentation.
Custom templates decide how to use these reserved inputs:

- **`stack_file`**
  Project-relative manifest path from 
  `--file`
  . In directory mode, defaults to 
  `stack.yaml`
  , relative to 
  `--target`
  ; templates do not have to use it.
- **`stack_name`**
  Explicit 
  `--name`
  , or an empty string.
- **`stack_imports`**
  List of requested imports.
- **`stack_components`**
  Component map containing disabled stubs, grouped by kind.

These inputs cannot be supplied through `--set` or declared as questionnaire fields.
Existing template defaults, questions, conditions, matrices, and per-file delimiters
work through the same engine as [`scaffold generate`](/cli/commands/scaffold/generate).
Use `--set key=value` for answers, `--defaults` or `--interactive=false` for automation,
and `--ref` to select a Git source revision. Required answers are validated before writing.

## Create a directory layout

Use `--target` when the recipe produces several stack files. It supports both one
logical stack split across files and several distinct stacks:

```shell
atmos stack create --template application-stack \
  --target stacks/deploy/dev \
  --set environment=dev --set name=dev \
  --component terraform:network --component helmfile:services \
  --import catalog/defaults --dry-run
```

The template chooses which files receive the requested imports and component stubs.
Each supplied value must appear in a generated stack document. The `--set name=dev`
answer belongs to the template; `--name dev` supplies the reserved `stack_name` input.

Directory templates do not need `spec.stack.manifest`. If they declare it, its path
is relative to the target and must identify a generated, discoverable stack manifest.
The built-in `stack` template creates `stack.yaml` inside the target directory.

For example, a recipe can generate this layout:

```text
stacks/deploy/dev/
├── _defaults.yaml
├── network.yaml
└── services.yaml
```

Configure discovery to include `deploy/**/*` and exclude `**/_*`. The excluded
`_defaults.yaml` is an import fragment, while the other two files are entrypoints:

```yaml title="scaffold.yaml"
apiVersion: atmos/v1
kind: AtmosScaffoldConfig
metadata:
  name: application-stack
spec:
  fields:
    - name: environment
      type: input
      required: true
    - name: name
      type: input
      required: true
  files:
    - path: _defaults.yaml
    - path: network.yaml
    - path: services.yaml
```

```yaml title="_defaults.yaml"
# atmos:template
name: {{ .Config.name | quote }}
vars:
  environment: {{ .Config.environment | quote }}
```

```yaml title="network.yaml"
# atmos:template
import:
  - ./_defaults
{{ range .Config.stack_imports }}  - {{ . | quote }}
{{ end }}components:
  terraform:
{{ range $name, $_ := .Config.stack_components.terraform }}    {{ $name | quote }}:
      metadata:
        enabled: false
      vars: {}
{{ end }}
```

The `services.yaml` template follows the same pattern using the `helmfile` group
from `stack_components`. Both entrypoints import the shared name and variables;
their distinct components participate in one logical stack. To create separate
stacks, give their entrypoints distinct names or naming variables. Existing scaffold
matrices can repeat an entrypoint for several environments or regions.

Files do not merge merely because they share a directory. Atmos uses its existing
imports, discovery, and stack naming rules. At least one generated stack file must
match discovery; excluded fragments can be imported by entrypoints. All generated
stack YAML is validated before hooks or writes. Output paths cannot escape the target.

## Interactive inputs

When no destination is supplied in an interactive terminal, Atmos asks for a single
file or directory layout, then its destination. The single-file option is selected
initially. The scaffold questionnaire follows, with defaults and `--set` answers
prefilled for review. Required fields, conditions, and dynamic choices behave like
`scaffold generate`.

Interactive dry runs collect answers and then preview the files. Pass `--defaults`
or `--interactive=false` to suppress prompts. Without a terminal, provide a destination
and any required answers that have no defaults. Canceling a prompt writes nothing
and runs no hooks.

## Preview, hooks, and generation records

A dry run prints a stream of file previews: a `# <path>` comment followed by each
file's content, with `---` between files. The stream goes to stdout so it can be
piped, but it is not guaranteed to be valid YAML: files can contain Terraform
sources, documentation, or other content. It creates no output files or directories
and runs no hooks. Resolving a remote template can still download it.

The preview also lists each scaffold hook in the order it would run, with `before`
hooks ahead of `after` hooks, including its actions and conditions. A hook whose events
are not scaffold events is listed as ignored, along with the events it declares, and
a hook skipped by `--skip-hooks` is identified as skipped.

Scaffold hooks run around file creation using the normal `before.scaffold.generate`
and `after.scaffold.generate` events. Use `--skip-hooks` to skip all, or
`--skip-hooks=name1,name2` for specific hooks. These are separate from component
hooks that run during deployment. Step-backed scaffold hooks receive the outcome of the
creation as `ATMOS_HOOK_STATUS` (`success` or `failure`), `ATMOS_HOOK_EXIT_CODE`, and
`ATMOS_HOOK_ERROR`. Hooks on `before` events always run with a `success` status.

Every destination is checked before hooks or writes. Files are created exclusively,
so existing stack manifests, component sources, and project files are never overwritten.
Creation writes the same rendered content shown in the preview. Filesystem or hook
failures are reported; external hook effects are not rolled back automatically.

Each creation has an independent generation record under `.atmos/stack-generations/`.
File-mode records are keyed by the project-relative manifest path. Directory-mode
records use a separate key for the target directory and list its generated manifests.
Each record stores the template, answers, source revision when available, and generated
file hashes. Directory hooks use the target directory as their default working directory.
Creating another stack
does not replace project-level init/scaffold records. If you delete a created manifest
and run `stack create` for the same path again, the new run replaces that manifest's
generation record. A directory record can be replaced only after all outputs recorded
by the previous generation have been removed. Updating an existing stack from this record is not yet supported
by `stack create`.

[`init`](/cli/commands/init) bootstraps a project; `scaffold generate` runs general
recipes; `stack create` requires and validates a stack output. Creation changes
configuration only. Use [`stack config`](/cli/commands/stack/config) to edit values
and [`stack deploy`](/cli/commands/stack/stack-deploy) to deploy components.
