CLI

atlantide init                                # scaffold a project
atlantide plan    infra.py                    # preview changes
atlantide apply   infra.py                    # reconcile (parallel)
atlantide refresh                             # detect drift vs live state
atlantide graph   infra.py --format mermaid   # dependency graph
atlantide destroy                             # tear down

Starting a project

atlantide init [DIRECTORY] writes atlantide.toml, a starter config and a .gitignore, then compiles the config before reporting success. --template takes minimal (the default, local provider, no credentials) or aws, and --state local|s3|postgres writes the matching [state] table. See Installation for the full flag set.

Adopting existing resources

atlantide import records a resource that already exists, so the next plan reports it unchanged instead of proposing to build a second copy. It creates, updates and deletes nothing.

atlantide import                                  # list what is importable, and how
atlantide import aws.S3Bucket:assets              # located by name
atlantide import aws.Vpc:main vpc-0abc123         # located by a provider id
atlantide import aws.Vpc:main vpc-0abc123 --dry-run

Declare the resource in config first, then name its node here. Some types are found by name alone; others need an id AWS assigned — a VPC's vpc_id, a certificate's arn — which config cannot know. Running import with no arguments lists which is which.

A resource whose live values differ from config is not imported. A successful import that quietly means "your next apply will change your infrastructure" is not a success. Reconcile the config, or pass --allow-drift to adopt it anyway and let the next plan show the update. -v names the fields the provider's read did not cover.

The undo is atlantide state rm <node>, which forgets the row and leaves the resource alone.

Detecting drift

atlantide refresh reads live provider state and reports how it differs from what state records. It is read-only unless given --write, which syncs drifted outputs back.

A resource the provider cannot find is reported but kept, unless --prune is also given: one failed read is not enough evidence to discard the only record that a resource exists, and discarding it means the next apply builds a second one.

Drift is only visible in fields a provider's read reports. The report says how many of each resource's inputs that covered, and -v names the rest.

Common options

State defaults to atlantide.db. Override it with --state.

The mutating commands — apply, deploy, destroy and refresh — accept --confirm/-y, --region and --parallelism/-p. Those that write state also accept --on-failure, which takes rollback or halt. The default is rollback: when a run fails, the nodes it already completed are undone.

Narrowing a run

--target/-t accepts a full node id, a short form, or a glob:

atlantide apply   -t aws.S3Bucket:assets        # and its dependencies
atlantide destroy -t aws.Vpc:main               # and its dependents
atlantide apply   --replace aws.LambdaFunction:worker

Targeting closes over the graph in the direction that matters for the command: apply includes the target's dependencies, destroy includes its dependents.

A pattern that matches nothing is an error rather than an empty run — a run narrowed to nothing otherwise looks exactly like a run with nothing to do. --replace still honours prevent_destroy.

Interrupting a run

Ctrl-C cancels the run and follows the same path as a failure. Under the default --on-failure rollback, resources already created are undone before the process exits with code 130.

A second Ctrl-C abandons that cleanup. State may then no longer describe what exists, so run atlantide refresh before applying again.

The run's lock is deliberately not released on the second press. An abandoned run may still have provider calls in flight, so the lease is left to lapse — or to be cleared explicitly with atlantide state unlock — rather than handed to a second writer.

Output and diagnostics

--log-level debug|info traces a run to stderr; add --log-format json for a machine-readable stream. --audit-log FILE appends every run's events to a JSONL file.

Every command that touches state prints which state it is using before doing anything:

state: s3://acme-atlantide-state/prod/atlantide.json

With a shared backend, "no changes" and "wrong target" are otherwise indistinguishable. Under --json the same value appears as a state field on the payload.

Exit codes

Code Meaning
0 Success. With --detailed-exitcode: nothing to do — no pending changes, no drift.
1 An error, or a mandatory policy denied the plan, or (providers) a plugin failed to load.
2 Only with --detailed-exitcode: plan has changes pending, or refresh found drift.
130 The run was interrupted (Ctrl-C).

--detailed-exitcode is what makes plan usable as a CI gate — without it a plan with pending changes and a plan with none both exit 0:

atlantide plan --detailed-exitcode || case $? in
  2) echo "changes pending" ;;
  *) exit 1 ;;
esac

A denied plan exits 1 whether or not --detailed-exitcode is given, so a policy failure is never mistaken for "there is work to do".

Other commands

build / verify / deploy — produce, check and apply portable .atlas artifacts. An artifact is content-hashed with provider versions pinned, so a config can be compiled once and the identical bytes promoted between environments.

validate — check that a config compiles: that it stays within the Atlas-lang subset and that its graph is acyclic. It touches no state and calls no provider, so it needs no credentials. This is the check to run in a pre-commit hook or on a pull request, where plan would require a state backend it should not be given.

output — print what a previous apply exported. It reads state and nothing else, so it still works while the config is mid-edit:

vpc=$(atlantide output vpc_id)

Sensitive values require --reveal.

state — inspect and administer the state store. See Remote state.

secret — manage the local AES-GCM encrypted name-to-value store:

atlantide secret set app/signing-key       # value prompted (hidden) if omitted
atlantide secret get app/signing-key -r    # print plaintext (--reveal required)
atlantide secret list                      # names only, no values
atlantide secret rm  app/signing-key

componentadd, lock, vendor and verify for published components.

providers — list the provider plugins this installation can see, including any that failed to load. A plugin that fails to load is otherwise invisible: config simply cannot find its types, which presents as a typo.

resources / schema — discover the available resource types, and inspect one type's fields and their mutability.