Skip to main content

atmos scaffold

Give your team reusable templates for components, configuration, and projects. Scaffolds generate consistent files from validated answers and can merge later template improvements into previously generated output.

Commands​

CommandPurpose
atmos scaffold listList embedded, configured, and catalog templates.
atmos scaffold generateGenerate or update output from a template.
atmos scaffold validateValidate a template's scaffold.yaml manifest.

Template Contract​

Each template directory contains a versioned scaffold.yaml plus files to generate. Files are discovered automatically; use spec.files only to conditionally gate discovered files.

scaffold.yaml
apiVersion: atmos/v1
kind: AtmosScaffoldConfig
metadata:
name: terraform-component
description: Standard Terraform component
spec:
fields:
- name: component_name
label: Component name
type: input
required: true
validation:
pattern: "^[a-z0-9-]+$"
message: Use lowercase letters, digits, and hyphens.
- name: environments
label: Environments
type: multiselect
options: [dev, staging, prod]
default: [dev]

spec.fields replaces the retired prompts: shape. Fields are available to rendered files as {{ .Config.component_name }}. Atmos validates declared fields after it merges interactive input, defaults, persisted spec.values, and repeated --set key=value flags, so automation follows the same rules as an interactive run.

Supported field types are input, text, string, select, multiselect, confirm, bool, boolean, and computed. Required fields reject missing or blank text and empty multiselect values; false is a valid boolean answer. Select values must come from options, and text fields can use validation.pattern with an optional validation.message. A computed field is never prompted for — see Computed Fields in the generate reference.

Conditions and Files​

Use when: to make one template adapt to its answers. A condition can be always, never, ci, or local; a CEL expression; or a list treated as an implicit logical all. A field can only read answers from fields declared before it.

scaffold.yaml
spec:
fields:
- name: enable_monitoring
type: confirm
default: false
- name: alert_email
type: input
when: "answers.enable_monitoring == true"
files:
- path: monitoring/alerts.tf
when: "answers.enable_monitoring == true"
- path: stacks/staging.yaml
when: "'staging' in answers.environments"

Use CEL operators such as &&, ||, and ! for compound conditions. The map form {all: ...}, {any: ...}, or {not: ...} is not accepted in scaffold manifests.

Generation Hooks​

Scaffold hooks run around generation at before.scaffold.generate and after.scaffold.generate. They use the shared hook envelope but intentionally support only kind: step and kind: steps because generation has no stack/component context.

scaffold.yaml
spec:
hooks:
format:
events: [after.scaffold.generate]
kind: step
type: shell
with:
command: terraform fmt -recursive
verify:
events: [after.scaffold.generate]
kind: steps
when: "answers.enable_monitoring == true"
with:
- type: require
tools: [terraform]
- type: shell
command: terraform validate

For kind: step, type: selects one registered step type and with: is its configuration. For kind: steps, with: is an ordered step list. The envelope owns events, when, env, retry, and on_failure; answer values are available in conditions as answers and in step templates as {{ .Answers.<field> }}. Hooks run in stable name order.

A step's working_directory: defaults to (or, if bare-relative, resolves under) the scaffold's target directory, also exposed as {{ .TargetPath }}, so the format/verify hooks above run against the generated project. Set working_directory: "." to run a step in the directory atmos was launched from instead. A type: atmos step is exempt from this default -- it keeps running in the directory atmos was launched from when working_directory: is unset, since the nested atmos invocation must resolve its own config there, but an explicit working_directory: on that step is still honored.

Use --skip-hooks or --skip-hooks=name1,name2 when inspecting an untrusted template or diagnosing generation. See lifecycle hooks for the broader stack-hook kinds and the shared step bridge.

Update Existing Output​

atmos scaffold generate terraform-component ./components/terraform/vpc
atmos scaffold generate terraform-component ./components/terraform/vpc --update
atmos scaffold generate terraform-component ./components/terraform/vpc --update --merge-strategy=theirs
atmos scaffold generate terraform-component ./components/terraform/vpc --update --update-strategy=rendered

--update uses the recorded base revision to perform an optimistic three-way merge. The default manual strategy surfaces real conflicts; ours keeps local changes and theirs applies the template side of a conflict.

--update-strategy controls where the merge's base comes from, independently of --merge-strategy. tracked (the default) reads it from the target's own Git history. rendered instead re-renders the template at the ref that produced what's currently on disk, using that generation's recorded answers, with no Git history dependency at all. This needs two separate things, not one: the template itself must define a scaffold.yaml manifest (so the old ref's fields can be resolved when re-rendering), and the target must already carry a prior generation's .atmos/scaffold.yaml record (a different file, at a different path — it stores that generation's recorded answers, not the template's field definitions).

--max-changes (default 50) caps the percentage of changed lines a three-way merge is allowed to touch before --update fails outright instead of applying it. 0 disables this check entirely (guaranteed to never fail); any other value is compared against a computed percentage with no upper bound, so raising it only makes a hard failure less likely, never impossible.

Project Initialization​

atmos init consumes the same manifest and generation engine for complete project templates. Use init to select a built-in or catalog project starting point; use scaffold generate to distribute an organization-specific component, configuration, or other golden path.

atmos scaffold generate
 
00:00.0 / 00:00.0

Example: Scaffold Templates

Scaffold templates for generating new Atmos projects and components.

Learn more in the Scaffold Command Documentation.

What You'll See

  • Scaffold template configuration with scaffold.yaml
  • Interactive prompts for customizing generated projects
  • Template files with Go templating support
  • Conditional prompts — vendor_version is only asked when: enable_vendoring was answered true
  • Conditional file generation — vendor.yaml is only generated when: enable_vendoring is true, and is skipped entirely otherwise

Try It

# List available scaffold templates
atmos scaffold list

# Generate a new project from a template
atmos scaffold generate example ./my-project

# Generate with a pinned component version
atmos scaffold generate example ./my-project --set project_name=my-app --set enable_vendoring=true --set vendor_version=1.536.0

# Skip vendoring entirely — vendor_version is never asked and vendor.yaml is never generated
atmos scaffold generate example ./my-project --set enable_vendoring=false

Key Files

FilePurpose
scaffold.yamlTemplate configuration with prompts, conditional when: rules, and metadata
atmos.yamlTemplate for generated Atmos configuration
vendor.yamlConditionally-generated vendor manifest (only when enable_vendoring: true)

Learn More: Generation Hooks

Templates can also declare hooks that run automatically before or after generation — for example, formatting generated files or running a linter. Hooks reuse the same when: condition engine as Atmos workflows and CI hooks, and support --skip-hooks to opt out per invocation. This example doesn't wire one up, but the syntax looks like:

hooks:
format:
events:
- after.scaffold.generate
kind: step
type: shell
with:
command: "terraform fmt"

Creating Custom Templates

Scaffold templates use Go templates with access to:

  • .Config - Values from prompts and --vars flags
  • Sprig functions for string manipulation
  • Gomplate functions for advanced templating

See the Scaffold Templates Guide for more details.

Learn More​