Migrating to Atmos
Overview
This skill is a decision guide. Use it to migrate an existing Terraform repository to Atmos.
Atmos can adopt an existing repository without a reorganization. The components/terraform/
layout is a recommendation. It is not a requirement. Start with the smallest change that gives
value. Add more only when the user has a real need for it.
This skill also covers migrating CLI tool-version management from mise or Aqua CLI to the Atmos
toolchain -- see from-mise.md and
from-aqua.md in the routing table below.
For full tutorials for end users, see:
Terraform or OpenTofu
This skill applies the same way to Terraform and to OpenTofu. Atmos runs the binary set in
components.terraform.command in atmos.yaml. The default binary is terraform. The migration
steps, file layouts, and the remote-state bridge do not change based on the binary. Use the same
word the user uses. If the user says "OpenTofu," write "OpenTofu" in your response.
Core Principles
These principles come before your normal instincts. Read them before you propose a change to the
user's repository.
- Migration is opt-in, not all-or-nothing. Atmos does not require a filesystem
reorganization. Point
base_path at the user's existing layout (e.g., base_path: "terraform"
or base_path: ".") when preserving layout lowers adoption risk. The components/terraform/
convention is still the best-practice layout for new or fully migrated repos because Atmos
supports multiple toolchains (Terraform, Helmfile, Packer, Ansible); it is not a prerequisite
for adopting Atmos in Terraform-only repos.
- Existing
.tfvars files may be kept during migration. Use !include to pull them into
stacks when the user wants minimal disruption. Converting values into native stack YAML remains
the best-practice end state when the user wants deep-merge inheritance and richer stack
composition, but it can happen progressively.
- No Terraform code changes are required. Don't rewrite providers, backends, or modules
during migration. Atmos generates
backend.tf.json and *.auto.tfvars.json at runtime.
- Workspaces are not the enemy. If the user has
terraform.workspace-driven environments,
Atmos can map onto their existing state via metadata.terraform_workspace and
workspace_key_prefix. They do not have to abandon their workspace state to adopt Atmos.
- Prefer YAML functions over Gomplate datasources. When both can express the same thing
(
!include vs gomplate.datasources for files, !exec vs templated shell, !env vs
gomplate getenv, !store vs custom datasource URLs), reach for the YAML function first.
YAML functions are type-safe, can't break YAML parsing, produce clear errors, and don't
require enabling Gomplate. See the atmos-yaml-functions
and atmos-templates skills for the boundary.
- Crawl → walk → run. Get the user to a working
atmos terraform plan in 20 minutes; defer
inheritance, catalogs, and multi-account hierarchies until they have a concrete need.
- Task runners are not a blocker. Atmos custom commands and workflows can replace the
targets, recipes, and tasks that Make, Just, and Task provide. This doesn't have to happen all
at once — a Makefile, Justfile, or Taskfile can stay as a thin wrapper around
atmos commands
during migration, the same incremental approach described in Principle 6. The end state turns
each leaf target into a custom command; a target chain usually stays a custom command too,
using dependencies.commands/dependencies.workflows for its prerequisites. Reserve
workflows for fixed, multi-step orchestration across more than one component — not every
dependency chain needs one.
Decide the Migration Shape First
Find the user's source pattern before you propose any change. Each pattern points to a different
reference file:
| User has... |
Use reference |
One TF root module, env config via .tfvars or env vars |
from-native-terraform.md |
| Multiple TF root modules in scattered dirs |
from-native-terraform.md |
terraform.workspace-driven environments with shared state backend |
from-terraform-workspaces.md |
.tm.hcl files, stack.tm.hcl, generate_hcl blocks (Terramate project) |
from-terramate.md |
| Need to read outputs from un-migrated TF (legacy or another repo) |
remote-state-bridge.md |
| User has a Makefile driving builds/tests/deploys |
from-makefile.md |
User has a Justfile (just command runner) |
from-justfile.md |
| User has a Taskfile.yml (go-task) |
from-taskfile.md |
cloudposse/github-action-atmos-component-updater |
from-component-updater.md |
Terragrunt (terragrunt.hcl or terragrunt.stack.hcl) |
from-terragrunt.md |
mise config (mise.toml, .mise.toml, .mise/config.toml, .tool-versions) for tool versions |
from-mise.md |
aqua.yaml (Aqua CLI) for tool versions |
from-aqua.md |
The remote-state-bridge pattern makes progressive migration possible. It lets a team migrate one
component at a time. Without it, the team must migrate everything at once. Use this pattern when
the user has existing Terraform state that a new Atmos component must read.
Common Problems in Task-Runner Migration
These behaviors apply to every task runner. Check them before you open a reference file:
- The default order can change, and it differs by source tool. Task runs
deps: at the same
time by default, so command-level dependencies.commands/dependencies.workflows -- also
concurrent by default -- is its direct match. Make and Just run dependencies one after another
by default; make -j is required for concurrency. Do not describe dependencies.commands as
matching Make's/Just's default -- it changes the order, and can introduce a race between
prerequisites that were only ever sequential by accident, not by a declared dependency. For an
ordinary Make/Just chain, ordered steps preserve the default; reach for dependencies.commands
there only when the source used -j, the prerequisites are genuinely independent, or a
prerequisite is shared by more than one caller (it dedups a shared dependency to a single run
regardless of concurrency -- true for every one of these tools). Check the source tool's real
default before you move it.
- Freshness checks map to
inputs/artifacts, not to plain steps -- and the scope is per
step. Task's sources:/generates: fields and non-.PHONY Make targets both skip the
entire recipe/task when a file has not changed. Atmos's step-level inputs.sources/
artifacts.paths fields are the direct match: with no explicit when:, declaring them
implicitly means when: checksum.changed, and that one step is skipped when nothing has
changed since its last successful run -- later steps in the same command still run regardless.
If the source recipe/task runs more than one command and the freshness decision must gate all
of them together, combine them into a single shell/script step rather than spreading
inputs/artifacts across several steps. This does not carry over on its own -- add
inputs/artifacts to the migrated step yourself. The require/assert step type does not
replace this. It only checks that a file exists, not whether it is fresh.
workflows.base_path needs to be set explicitly once the user has their own atmos.yaml.
Only fixed, multi-step orchestration across more than one component becomes an Atmos workflow
(Principle 7) -- most target chains stay a custom command with dependencies.commands instead.
atmos workflow <name> fails with
'workflows.base_path' must be configured in 'atmos.yaml' until you add it (for example,
workflows.base_path: "stacks/workflows"). None of this skill's atmos.yaml snippets show it
by default -- add it the moment the user's migration reaches its first workflow.
Each reference file has its own "Common Problems" section with the exact field names and steps
for that tool. This section is only a short summary.
The Minimum-Viable Migration
Use this checklist when the user wants to try Atmos on an existing repository. Do not change the
order unless the user's setup requires it.
- Install Atmos. See
atmos.tools/install.
- Create
atmos.yaml at the repo root, pointing base_path and components.terraform.base_path
at the user's existing layout. Do not ask them to move files.
- Create one stack file for one environment. Use
!include of an existing .tfvars file so
nothing has to be rewritten:# stacks/dev.yaml
import:
- _defaults
components:
terraform:
vpc:
vars: !include ../path/to/existing/dev.tfvars
- Run
atmos terraform plan vpc -s dev and confirm output matches what terraform plan -var-file=dev.tfvars produced before.
A working example of this shape is at examples/native-terraform/ in the Atmos repository.
File-Layout Options
Pick the layout that matches the user's goals. Atmos recommends the components/terraform/
layout, especially for a new repository or a multi-tool project. You can keep an existing layout
when the user wants less disruption.
base_path |
Use when |
base_path: "." |
TF root modules live at the repo root; user wants zero file moves |
base_path: "terraform" |
TF-only repo with code already in terraform/; preserve dir name |
base_path: "." + components.terraform.base_path: "components/terraform" |
Multi-toolchain or new repo; canonical Atmos layout |
For more organization patterns, such as multi-region, multi-account, and organization
hierarchies, see the skill atmos-design-patterns.
YAML Functions vs Gomplate Datasources
This is a common mistake: an agent chooses a Gomplate datasource when a YAML function is safer
and clearer. Use the option in the right column:
| Goal |
Reach for (NOT this) |
Use instead |
| Include a file's contents |
gomplate.datasources with file URL |
!include path/to/file |
| Read an environment variable |
gomplate getenv "FOO" |
!env FOO |
| Run a shell command |
Template + gomplate exec |
!exec "command" |
| Read a store value |
Custom datasource URL |
!store store_name component stack key |
| Read Terraform output |
Templated remote-state datasource |
!terraform.state component output |
| Get current AWS account ID |
gomplate.datasources AWS plugin |
!aws.account_id |
A YAML function checks its own types. It gives a clear error message. It works without Gomplate
turned on. It does not require the template text to stay valid YAML. Use a Go template only for
control flow, such as a conditional, a loop, or a dynamic key, that a YAML function cannot
express. See atmos-templates for when to use a Go template.
What Does NOT Need to Change
Tell the user this list first, if they are afraid of a large rewrite. None of these items must
change to adopt Atmos:
- Terraform code. Providers, resources, data sources, and modules stay the same.
- Module sources. A local path, such as
source = "../../modules/foo", or a registry
source, keeps working.
- Backend code. You can delete the
backend "s3" {} block from the .tf files, because
Atmos creates backend.tf.json. Or you can keep the block and turn off backend generation in
atmos.yaml. Both methods work.
.tfvars files. Atmos reads them through !include. Convert them to YAML later, only if
the user wants deep-merge inheritance.
- Custom provider configuration. Providers stay in the
.tf files. Pass environment
variables through stack env:. Pass Terraform variables through stack vars:.
When to Escalate to Other Skills
After the minimum migration works, the user will often ask what to do next. Send each question
to the correct skill:
- Organize many stacks, such as by organization, tenant, account, or region. Use
atmos-design-patterns.
- Build abstract components, inheritance, or catalog patterns. Use
atmos-components.
- Use deep merging, imports, or overrides. Use atmos-stacks.
- Vendor third-party components. Use atmos-vendoring.
- Set up authentication or provider credentials. Use atmos-auth.
- Add validation policies, such as OPA or JSON Schema. Use
atmos-validation.
- Set up CI/CD with affected-component detection. Use atmos-ci.
- Share data between components through a store. Use
atmos-stores.
Anti-Patterns
Push back if a user or another agent proposes one of these methods during migration:
- "You must move all Terraform into
components/terraform/ before you use Atmos." This is
false. That layout is a recommendation, not a requirement. Let the user pick: adopt the
recommended layout now, or point base_path at the current layout and reorganize later.
- "You must rewrite all
.tfvars files as YAML before you run Atmos." This is false. Native
stack YAML is the best final format for inheritance and composition. But !include lets the
user keep existing .tfvars files during a step-by-step migration.
- "Delete your workspace state and start over." This is false. Connect the existing state
with
metadata.terraform_workspace and the remote-state-bridge pattern.
- "Add a Gomplate datasource for everything." This is false. Use a YAML function first.
- "Adopt the full multi-account organization hierarchy on day one." This is false. Start
with one stack file.
- "Wrap atmos commands in a Makefile, Justfile, or Taskfile forever." This is false. A
wrapper is a good bridge while the user builds trust in Atmos. But it is not the final state.
Change each leaf target to a custom command. An ordinary Make or Just dependency chain (for
example,
deploy: build test) stays a custom command with ordered steps or
dependencies.commands -- it does not need a workflow. A Taskfile's deps: is different: Task
runs deps: concurrently by default, so it maps directly onto dependencies.commands (also
concurrent by default) on the custom command -- reach for ordered steps instead only when the
user's dependency chain actually requires serial execution. Reserve workflows for fixed,
multi-step orchestration across more than one component, not for an ordinary target chain.
Additional Resources
- References/from-native-terraform.md: steps for a plain
Terraform migration, matched to each shape.
- References/from-terraform-workspaces.md: how to map
workspaces to stacks without losing state.
- References/remote-state-bridge.md: the dummy-component and
abstract-component patterns. Use them to read state from Terraform that is not yet migrated, or
from an external repository.
- References/from-terramate.md: construct-by-construct mapping
from Terramate (
stack.tm.hcl, globals, generate_hcl, script{}, tags/labels) to Atmos,
including the one remaining known gap (.tmtriggers).
- references/from-terragrunt.md -- concept mapping and migration
workflow for classic Terragrunt and Terragrunt Stacks.
- References/from-makefile.md: steps for a Makefile, matched to
each shape.
- References/from-justfile.md: steps for a Justfile, matched to
each shape.
- References/from-taskfile.md: steps for a Taskfile.yml (go-task)
file, matched to each shape.
- References/from-mise.md -- migrating tool versions, tasks, and env
vars from mise to the Atmos toolchain.
- References/from-aqua.md -- migrating tool versions from Aqua CLI's
aqua.yaml to the Atmos toolchain.
1---2name: atmos-migration3description: This skill helps you migrate a repository to Atmos. It covers native Terraform, Terraform Workspaces, Terramate, Terragrunt, Makefiles, Justfiles, and Taskfiles. It gives minimum-disruption paths, file-layout options, workspace mapping, task-to-command mapping, generate_hcl/script decomposition, and the remote-state bridge for a step-by-step migration; also covers migrating CLI tool-version management from mise or Aqua CLI to the Atmos toolchain.4---56# Migrating to Atmos78## Overview910This skill is a decision guide. Use it to migrate an existing Terraform repository to Atmos.11Atmos can adopt an existing repository without a reorganization. The `components/terraform/`12layout is a recommendation. It is not a requirement. Start with the smallest change that gives13value. Add more only when the user has a real need for it.1415This skill also covers migrating CLI tool-version management from mise or Aqua CLI to the Atmos16toolchain -- see [from-mise.md](references/from-mise.md) and17[from-aqua.md](references/from-aqua.md) in the routing table below.1819For full tutorials for end users, see:2021- [Migrating from Native Terraform](https://atmos.tools/migration/native-terraform)22- [Migrating from Terraform Workspaces](https://atmos.tools/migration/terraform-workspaces)23- [Migrating from Terragrunt](https://atmos.tools/migration/terragrunt) -- see24 [from-terragrunt.md](references/from-terragrunt.md) for the agent-actionable recipes25- Migrating from Terramate -- covered by this skill via26 [references/from-terramate.md](references/from-terramate.md) (no atmos.tools tutorial yet)27- [Migrating from Makefiles](https://atmos.tools/migration/makefile)28- [Migrating from Justfiles](https://atmos.tools/migration/justfile)29- [Migrating from Taskfile.yml](https://atmos.tools/migration/taskfile)3031## Terraform or OpenTofu3233This skill applies the same way to Terraform and to OpenTofu. Atmos runs the binary set in34`components.terraform.command` in `atmos.yaml`. The default binary is `terraform`. The migration35steps, file layouts, and the remote-state bridge do not change based on the binary. Use the same36word the user uses. If the user says "OpenTofu," write "OpenTofu" in your response.3738## Core Principles3940These principles come before your normal instincts. Read them before you propose a change to the41user's repository.42431. **Migration is opt-in, not all-or-nothing.** Atmos does not require a filesystem44 reorganization. Point `base_path` at the user's existing layout (e.g., `base_path: "terraform"`45 or `base_path: "."`) when preserving layout lowers adoption risk. The `components/terraform/`46 convention is still the best-practice layout for new or fully migrated repos because Atmos47 supports multiple toolchains (Terraform, Helmfile, Packer, Ansible); it is not a prerequisite48 for adopting Atmos in Terraform-only repos.492. **Existing `.tfvars` files may be kept during migration.** Use `!include` to pull them into50 stacks when the user wants minimal disruption. Converting values into native stack YAML remains51 the best-practice end state when the user wants deep-merge inheritance and richer stack52 composition, but it can happen progressively.533. **No Terraform code changes are required.** Don't rewrite providers, backends, or modules54 during migration. Atmos generates `backend.tf.json` and `*.auto.tfvars.json` at runtime.554. **Workspaces are not the enemy.** If the user has `terraform.workspace`-driven environments,56 Atmos can map onto their existing state via `metadata.terraform_workspace` and57 `workspace_key_prefix`. They do not have to abandon their workspace state to adopt Atmos.585. **Prefer YAML functions over Gomplate datasources.** When both can express the same thing59 (`!include` vs `gomplate.datasources` for files, `!exec` vs templated shell, `!env` vs60 `gomplate getenv`, `!store` vs custom datasource URLs), reach for the YAML function first.61 YAML functions are type-safe, can't break YAML parsing, produce clear errors, and don't62 require enabling Gomplate. See the [atmos-yaml-functions](../atmos-yaml-functions/SKILL.md)63 and [atmos-templates](../atmos-templates/SKILL.md) skills for the boundary.646. **Crawl → walk → run.** Get the user to a working `atmos terraform plan` in 20 minutes; defer65 inheritance, catalogs, and multi-account hierarchies until they have a concrete need.667. **Task runners are not a blocker.** Atmos custom commands and workflows can replace the67 targets, recipes, and tasks that Make, Just, and Task provide. This doesn't have to happen all68 at once — a Makefile, Justfile, or Taskfile can stay as a thin wrapper around `atmos` commands69 during migration, the same incremental approach described in Principle 6. The end state turns70 each leaf target into a custom command; a target chain usually stays a custom command too,71 using `dependencies.commands`/`dependencies.workflows` for its prerequisites. Reserve72 workflows for fixed, multi-step orchestration across more than one component — not every73 dependency chain needs one.7475## Decide the Migration Shape First7677Find the user's source pattern before you propose any change. Each pattern points to a different78reference file:7980| User has... | Use reference |81|----------------------------------------------------------------------|--------------------------------------------------|82| One TF root module, env config via `.tfvars` or env vars | [from-native-terraform.md](references/from-native-terraform.md) |83| Multiple TF root modules in scattered dirs | [from-native-terraform.md](references/from-native-terraform.md) |84| `terraform.workspace`-driven environments with shared state backend | [from-terraform-workspaces.md](references/from-terraform-workspaces.md) |85| `.tm.hcl` files, `stack.tm.hcl`, `generate_hcl` blocks (Terramate project) | [from-terramate.md](references/from-terramate.md) |86| Need to read outputs from un-migrated TF (legacy or another repo) | [remote-state-bridge.md](references/remote-state-bridge.md) |87| User has a Makefile driving builds/tests/deploys | [from-makefile.md](references/from-makefile.md) |88| User has a Justfile (`just` command runner) | [from-justfile.md](references/from-justfile.md) |89| User has a Taskfile.yml (go-task) | [from-taskfile.md](references/from-taskfile.md) |90| `cloudposse/github-action-atmos-component-updater` | [from-component-updater.md](references/from-component-updater.md) |91| Terragrunt (`terragrunt.hcl` or `terragrunt.stack.hcl`) | [from-terragrunt.md](references/from-terragrunt.md) |92| mise config (`mise.toml`, `.mise.toml`, `.mise/config.toml`, `.tool-versions`) for tool versions | [from-mise.md](references/from-mise.md) |93| `aqua.yaml` (Aqua CLI) for tool versions | [from-aqua.md](references/from-aqua.md) |9495The remote-state-bridge pattern makes progressive migration possible. It lets a team migrate one96component at a time. Without it, the team must migrate everything at once. Use this pattern when97the user has existing Terraform state that a new Atmos component must read.9899### Common Problems in Task-Runner Migration100101These behaviors apply to every task runner. Check them before you open a reference file:102103- **The default order can change, and it differs by source tool.** Task runs `deps:` at the same104 time by default, so command-level `dependencies.commands`/`dependencies.workflows` -- also105 concurrent by default -- is its direct match. Make and Just run dependencies one after another106 by default; `make -j` is required for concurrency. Do not describe `dependencies.commands` as107 matching Make's/Just's *default* -- it changes the order, and can introduce a race between108 prerequisites that were only ever sequential by accident, not by a declared dependency. For an109 ordinary Make/Just chain, ordered steps preserve the default; reach for `dependencies.commands`110 there only when the source used `-j`, the prerequisites are genuinely independent, or a111 prerequisite is shared by more than one caller (it dedups a shared dependency to a single run112 regardless of concurrency -- true for every one of these tools). Check the source tool's real113 default before you move it.114- **Freshness checks map to `inputs`/`artifacts`, not to plain steps -- and the scope is per115 step.** Task's `sources:`/`generates:` fields and non-`.PHONY` Make targets both skip the116 *entire* recipe/task when a file has not changed. Atmos's step-level `inputs.sources`/117 `artifacts.paths` fields are the direct match: with no explicit `when:`, declaring them118 implicitly means `when: checksum.changed`, and *that one step* is skipped when nothing has119 changed since its last successful run -- later steps in the same command still run regardless.120 If the source recipe/task runs more than one command and the freshness decision must gate all121 of them together, combine them into a single `shell`/`script` step rather than spreading122 `inputs`/`artifacts` across several steps. This does not carry over on its own -- add123 `inputs`/`artifacts` to the migrated step yourself. The `require`/`assert` step type does not124 replace this. It only checks that a file exists, not whether it is fresh.125- **`workflows.base_path` needs to be set explicitly once the user has their own `atmos.yaml`.**126 Only fixed, multi-step orchestration across more than one component becomes an Atmos workflow127 (Principle 7) -- most target chains stay a custom command with `dependencies.commands` instead.128 `atmos workflow <name>` fails with129 `'workflows.base_path' must be configured in 'atmos.yaml'` until you add it (for example,130 `workflows.base_path: "stacks/workflows"`). None of this skill's `atmos.yaml` snippets show it131 by default -- add it the moment the user's migration reaches its first workflow.132133Each reference file has its own "Common Problems" section with the exact field names and steps134for that tool. This section is only a short summary.135136## The Minimum-Viable Migration137138Use this checklist when the user wants to try Atmos on an existing repository. Do not change the139order unless the user's setup requires it.1401411. **Install Atmos.** See `atmos.tools/install`.1422. **Create `atmos.yaml`** at the repo root, pointing `base_path` and `components.terraform.base_path`143 at the user's existing layout. Do not ask them to move files.1443. **Create one stack file** for one environment. Use `!include` of an existing `.tfvars` file so145 nothing has to be rewritten:146 ```yaml147 # stacks/dev.yaml148 import:149 - _defaults150 components:151 terraform:152 vpc:153 vars: !include ../path/to/existing/dev.tfvars154 ```1554. **Run `atmos terraform plan vpc -s dev`** and confirm output matches what `terraform plan156 -var-file=dev.tfvars` produced before.157158A working example of this shape is at `examples/native-terraform/` in the Atmos repository.159160## File-Layout Options161162Pick the layout that matches the user's goals. Atmos recommends the `components/terraform/`163layout, especially for a new repository or a multi-tool project. You can keep an existing layout164when the user wants less disruption.165166| `base_path` | Use when |167|------------------------------------------|-------------------------------------------------------------------------|168| `base_path: "."` | TF root modules live at the repo root; user wants zero file moves |169| `base_path: "terraform"` | TF-only repo with code already in `terraform/`; preserve dir name |170| `base_path: "."` + `components.terraform.base_path: "components/terraform"` | Multi-toolchain or new repo; canonical Atmos layout |171172For more organization patterns, such as multi-region, multi-account, and organization173hierarchies, see the skill [atmos-design-patterns](../atmos-design-patterns/SKILL.md).174175## YAML Functions vs Gomplate Datasources176177This is a common mistake: an agent chooses a Gomplate datasource when a YAML function is safer178and clearer. Use the option in the right column:179180| Goal | Reach for (NOT this) | Use instead |181|-------------------------------|---------------------------------------------------|------------------------------------------|182| Include a file's contents | `gomplate.datasources` with file URL | `!include path/to/file` |183| Read an environment variable | `gomplate getenv "FOO"` | `!env FOO` |184| Run a shell command | Template + `gomplate exec` | `!exec "command"` |185| Read a store value | Custom datasource URL | `!store store_name component stack key` |186| Read Terraform output | Templated remote-state datasource | `!terraform.state component output` |187| Get current AWS account ID | `gomplate.datasources` AWS plugin | `!aws.account_id` |188189A YAML function checks its own types. It gives a clear error message. It works without Gomplate190turned on. It does not require the template text to stay valid YAML. Use a Go template only for191control flow, such as a conditional, a loop, or a dynamic key, that a YAML function cannot192express. See [atmos-templates](../atmos-templates/SKILL.md) for when to use a Go template.193194## What Does NOT Need to Change195196Tell the user this list first, if they are afraid of a large rewrite. None of these items must197change to adopt Atmos:198199- **Terraform code.** Providers, resources, data sources, and modules stay the same.200- **Module sources.** A local path, such as `source = "../../modules/foo"`, or a registry201 source, keeps working.202- **Backend code.** You can delete the `backend "s3" {}` block from the `.tf` files, because203 Atmos creates `backend.tf.json`. Or you can keep the block and turn off backend generation in204 `atmos.yaml`. Both methods work.205- **`.tfvars` files.** Atmos reads them through `!include`. Convert them to YAML later, only if206 the user wants deep-merge inheritance.207- **Custom provider configuration.** Providers stay in the `.tf` files. Pass environment208 variables through stack `env:`. Pass Terraform variables through stack `vars:`.209210## When to Escalate to Other Skills211212After the minimum migration works, the user will often ask what to do next. Send each question213to the correct skill:214215- **Organize many stacks**, such as by organization, tenant, account, or region. Use216 [atmos-design-patterns](../atmos-design-patterns/SKILL.md).217- **Build abstract components, inheritance, or catalog patterns.** Use218 [atmos-components](../atmos-components/SKILL.md).219- **Use deep merging, imports, or overrides.** Use [atmos-stacks](../atmos-stacks/SKILL.md).220- **Vendor third-party components.** Use [atmos-vendoring](../atmos-vendoring/SKILL.md).221- **Set up authentication or provider credentials.** Use [atmos-auth](../atmos-auth/SKILL.md).222- **Add validation policies, such as OPA or JSON Schema.** Use223 [atmos-validation](../atmos-validation/SKILL.md).224- **Set up CI/CD with affected-component detection.** Use [atmos-ci](../atmos-ci/SKILL.md).225- **Share data between components through a store.** Use226 [atmos-stores](../atmos-stores/SKILL.md).227228## Anti-Patterns229230Push back if a user or another agent proposes one of these methods during migration:231232- **"You must move all Terraform into `components/terraform/` before you use Atmos."** This is233 false. That layout is a recommendation, not a requirement. Let the user pick: adopt the234 recommended layout now, or point `base_path` at the current layout and reorganize later.235- **"You must rewrite all `.tfvars` files as YAML before you run Atmos."** This is false. Native236 stack YAML is the best final format for inheritance and composition. But `!include` lets the237 user keep existing `.tfvars` files during a step-by-step migration.238- **"Delete your workspace state and start over."** This is false. Connect the existing state239 with `metadata.terraform_workspace` and the remote-state-bridge pattern.240- **"Add a Gomplate datasource for everything."** This is false. Use a YAML function first.241- **"Adopt the full multi-account organization hierarchy on day one."** This is false. Start242 with one stack file.243- **"Wrap atmos commands in a Makefile, Justfile, or Taskfile forever."** This is false. A244 wrapper is a good bridge while the user builds trust in Atmos. But it is not the final state.245 Change each leaf target to a custom command. An ordinary Make or Just dependency chain (for246 example, `deploy: build test`) stays a custom command with ordered steps or247 `dependencies.commands` -- it does not need a workflow. A Taskfile's `deps:` is different: Task248 runs `deps:` concurrently by default, so it maps directly onto `dependencies.commands` (also249 concurrent by default) on the custom command -- reach for ordered steps instead only when the250 user's dependency chain actually requires serial execution. Reserve workflows for fixed,251 multi-step orchestration across more than one component, not for an ordinary target chain.252253## Additional Resources254255- [References/from-native-terraform.md](references/from-native-terraform.md): steps for a plain256 Terraform migration, matched to each shape.257- [References/from-terraform-workspaces.md](references/from-terraform-workspaces.md): how to map258 workspaces to stacks without losing state.259- [References/remote-state-bridge.md](references/remote-state-bridge.md): the dummy-component and260 abstract-component patterns. Use them to read state from Terraform that is not yet migrated, or261 from an external repository.262- [References/from-terramate.md](references/from-terramate.md): construct-by-construct mapping263 from Terramate (`stack.tm.hcl`, globals, `generate_hcl`, `script{}`, tags/labels) to Atmos,264 including the one remaining known gap (`.tmtriggers`).265- [references/from-terragrunt.md](references/from-terragrunt.md) -- concept mapping and migration266 workflow for classic Terragrunt and Terragrunt Stacks.267- [References/from-makefile.md](references/from-makefile.md): steps for a Makefile, matched to268 each shape.269- [References/from-justfile.md](references/from-justfile.md): steps for a Justfile, matched to270 each shape.271- [References/from-taskfile.md](references/from-taskfile.md): steps for a Taskfile.yml (go-task)272 file, matched to each shape.273- [References/from-mise.md](references/from-mise.md) -- migrating tool versions, tasks, and env274 vars from mise to the Atmos toolchain.275- [References/from-aqua.md](references/from-aqua.md) -- migrating tool versions from Aqua CLI's276 `aqua.yaml` to the Atmos toolchain.