atmos init
Initialize a project from a proven Atmos starting point. atmos init selects a project template,
collects its validated answers, generates the project, and records the source needed for later
updates.
Usage
atmos init [template] [target] [flags]
# Choose a template and target interactively.
atmos init
# Initialize a minimal cloud-agnostic project.
atmos init basic ./my-project
# Initialize an AWS application or landing-zone foundation.
atmos init aws/app ./my-app
atmos init aws/landing-zone ./my-platform
# Provide values for automated project creation.
atmos init basic ./my-project --set project_name=my-project --interactive=false
Templates
The built-in catalog includes basic, simple, atmos, aws/app,
aws/landing-zone, gcp/landing-zone, and azure/landing-zone. Run
atmos scaffold list to see the complete catalog, including
configured and remote sources available to the current project.
basic is a small cloud-agnostic project with a real local greeting component. aws/app starts
an application SDLC layout with development, staging, and production stacks. The landing-zone
templates establish cloud-specific platform foundations.
[template] also accepts a direct source instead of a catalog name — a local path, git, HTTPS,
S3, or an OCI registry reference:
atmos init oci://ghcr.io/example/templates:v1.0.0 ./my-project
An OCI source is pulled the same way atmos vendor pull fetches OCI-hosted components; see
Vendor URL Syntax for authentication details.
Shared Scaffold Contract
Project templates use the same AtmosScaffoldConfig manifest and generation engine as
atmos scaffold generate. A template can define validated
spec.fields, conditional spec.files, and step-backed spec.hooks:
apiVersion: atmos/v1
kind: AtmosScaffoldConfig
metadata:
name: application-project
spec:
fields:
- name: environments
type: multiselect
options: [dev, staging, prod]
default: [dev]
- name: enable_monitoring
type: confirm
default: false
files:
- path: monitoring.tf
when: "answers.enable_monitoring == true"
hooks:
format:
events: [after.scaffold.generate]
kind: step
type: shell
with:
command: terraform fmt -recursive
Conditions use when: predicates or CEL over earlier answers. Generation hooks can use only
kind: step and ordered kind: steps; see scaffold templates for the
complete authoring model, including --skip-hooks and answer templating.
An unset (or bare-relative) working_directory: on a hook step defaults to the generated
project's target directory, so terraform fmt -recursive above runs against the generated files
even when the target differs from the directory atmos was launched from. Set
working_directory: "." to opt back into running the hook in the original working directory. 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.
Updating an Initialized Project
init records the selected source, base revision, and answers in .atmos/scaffold.yaml. Re-run
with --update to bring an existing project forward using an optimistic three-way merge:
cd my-project
atmos init --update
atmos init --update --merge-strategy=theirs
atmos init --update --update-strategy=rendered
manual is the default merge strategy and surfaces conflicts. ours preserves local changes;
theirs applies the template side of a conflict. atmos init creates Git history by default; pass
--no-git when that is not wanted.
--update-strategy controls where the merge's base comes from — an independent choice from
--merge-strategy. tracked (the default) reads it from the project's own Git history at
--base-ref. rendered instead re-renders the template at the ref that produced what's currently
on disk, using that generation's recorded answers, without requiring the target project's Git history. 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 project 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).
Flags and Automation
--set key=value(repeatable)- Provide a template answer; repeat for multiple fields.
--interactive=false- Run without form prompts when values and defaults satisfy active fields.
--force- Permit writes into an existing target.
--update- Merge a generated project with its template's newer revision.
--base-refOverride the recorded merge base. Only applies to
--update-strategy=tracked—rendered's base comes from the project's own recorded.atmos/scaffold.yaml, not--base-ref. Combining--base-refwith--update-strategy=renderedis rejected; drop--base-refwhen usingrendered.--update-strategy(defaulttracked)Choose where
--update's three-way merge base comes from.trackedreads it from the project's own Git history at--base-ref.renderedinstead re-renders the template at the ref that produced what's currently on disk, using that generation's recorded answers, with no dependency on Git history at all. This needs the template itself to define ascaffold.yamlmanifest (so the old ref's fields can be resolved) and the project to already carry a prior generation's.atmos/scaffold.yamlrecord (so the original answers are recoverable) — two separate files, not one. Underrendered,--updatealso deletes a file the template stopped generating between refs, unless you've edited it locally — in that case the update fails with an unresolved conflict instead of silently deleting or keeping it.trackeddoesn't support this: there's no safe way to know which files a historical commit actually belonged to the template.--merge-driver(defaultauto)Choose
auto(YAML-aware for.yaml/.yml, text otherwise) ortextto force every file through the line-oriented text merge driver, preserving formatting (e.g. blank lines) that a YAML-aware re-encode would otherwise collapse.--merge-strategy- Select
manual,ours, ortheirs. --max-changes(default50)Maximum percentage of changed lines allowed in a
--updatethree-way merge before it fails instead of applying.0disables this check entirely — the merge is never rejected for having too many changes (conflicts still write markers for--merge-strategy=manualto resolve). Any other value is compared against a computed change percentage that has no upper bound, so no positive value is a guaranteed bypass the way0is — raising it only makes a hard failure less likely, not impossible. Configurable viaATMOS_INIT_MAX_CHANGES.--recreate-deleted(defaultfalse)By default,
--updateleaves in place a file you deleted that the template still generates, instead of silently recreating it. Pass--recreate-deletedto always recreate it with the template's current content. This is independent of--force/--merge-strategy:--forcealready means "on conflict, the template's version wins," so tying recreation to it would make manual conflict resolution and recreating a deleted file mutually exclusive.--skip-hooks- Skip all hooks or named generation hooks.
--no-git- Do not initialize or commit Git history.