diff --git a/agent-skills/skills/atmos-migration/SKILL.md b/agent-skills/skills/atmos-migration/SKILL.md index 89bf8dbd8d..e2a7515055 100644 --- a/agent-skills/skills/atmos-migration/SKILL.md +++ b/agent-skills/skills/atmos-migration/SKILL.md @@ -1,6 +1,6 @@ --- name: atmos-migration -description: "Migrating to Atmos from existing IaC: techniques, tactics, and design patterns for native Terraform and Terraform Workspaces — minimum-disruption paths, file-layout options, workspace mapping, and the remote-state bridge for progressive migration" +description: "Migrating to Atmos from existing IaC: techniques, tactics, and design patterns for native Terraform and Terraform Workspaces — minimum-disruption paths, file-layout options, workspace mapping, and the remote-state bridge for progressive migration. This skill also explains how to move from asdf, aqua, tfenv, tofuenv, tenv, or a Homebrew Brewfile to the Atmos toolchain." metadata: copyright: Copyright Cloud Posse, LLC 2026 version: "1.0.0" @@ -9,6 +9,12 @@ references: - references/from-terraform-workspaces.md - references/remote-state-bridge.md - references/from-component-updater.md + - references/from-asdf.md + - references/from-aqua.md + - references/from-tfenv.md + - references/from-tofuenv.md + - references/from-tenv.md + - references/from-homebrew-brewfile.md --- # Migrating to Atmos @@ -80,6 +86,44 @@ The remote-state-bridge pattern is what makes **progressive, component-by-compon possible. Without it, a team is forced into a big-bang cutover. Cover it any time the user has existing Terraform state they need to read from new Atmos components. +## Replace a Tool-Version Manager + +This section covers a topic separate from the IaC-layout question above. A user can migrate the +Terraform or OpenTofu layout, the tool-version manager, or both. Each choice is independent. + +If the user currently pins CLI tool versions with asdf, aqua, tfenv, tofuenv, tenv, or a Homebrew +Brewfile, use the matching reference below. Do not write a new config translation by hand. + +| Current tool | Reference | +|-----------------------------|---------------------------------------------------------------------| +| asdf | [from-asdf.md](references/from-asdf.md) | +| aqua CLI (`aqua.yaml`) | [from-aqua.md](references/from-aqua.md) | +| tfenv | [from-tfenv.md](references/from-tfenv.md) | +| tofuenv | [from-tofuenv.md](references/from-tofuenv.md) | +| tenv | [from-tenv.md](references/from-tenv.md) | +| Homebrew Brewfile | [from-homebrew-brewfile.md](references/from-homebrew-brewfile.md) | + +Each reference includes a command-mapping table. This table shows the old tool's commands next to +the equivalent Atmos toolchain command. Use it to translate familiar commands directly. + +Each reference also includes a Shell Integration section. Most tools that a user migrates from add +themselves to every shell automatically. asdf, aqua, tfenv, tofuenv, and tenv do this through a +shim or proxy on `PATH`. The shim or proxy re-resolves the nearest per-directory config file on +every invocation. Homebrew works a different way. `brew shellenv` puts one global `bin` directory +on `PATH`. It has no per-directory resolution. Either way, the Atmos toolchain does not add itself +to `PATH` by default. The Atmos toolchain resolves tools only while an `atmos ` runs. + +A user can still get the old shell experience back, where a plain `terraform` command works in any +shell. This is a supported feature, not a missing feature. To enable it, add a wrapped form of +`atmos toolchain env` or `atmos toolchain path` to `~/.bashrc`, `~/.zshrc`, the fish config, or the +PowerShell profile. A bare `atmos toolchain env` or `atmos toolchain path` line does nothing on its +own. It must be wrapped in `eval` or `export`, for example `eval "$(atmos toolchain env +--format=bash)"` in Bash or Zsh, or `export PATH="$(atmos toolchain path):$PATH"` in any POSIX +shell. See each reference's Shell Integration section for the exact form for every shell. + +Always tell the user about this option when they are used to a tool that adds itself to `PATH` +automatically. + ## The Minimum-Viable Migration When a user says "I want to try Atmos on my existing repo," this is the checklist. Do not deviate @@ -164,6 +208,7 @@ those questions to the right skill: - **Validation policies (OPA, JSON Schema)** → [atmos-validation](../atmos-validation/SKILL.md) - **CI/CD with affected-detection** → [atmos-ci](../atmos-ci/SKILL.md) - **Cross-component data sharing via stores** → [atmos-stores](../atmos-stores/SKILL.md) +- **Toolchain configuration (`dependencies.tools`, registries, verification)** → [atmos-toolchain](../atmos-toolchain/SKILL.md) ## Anti-Patterns @@ -179,6 +224,11 @@ Things to push back on if a user (or another agent) proposes them during migrati `metadata.terraform_workspace` and the remote-state-bridge pattern. - **"Add Gomplate datasources for everything."** No -- reach for YAML functions first. - **"Adopt the full multi-account org hierarchy on day one."** No -- start with one stack file. +- **"Copy `aqua.yaml` packages into Atmos verbatim."** Do not do this. Atmos supports only part + of the Aqua registry schema. Check the Functional Gaps table in + [from-aqua.md](references/from-aqua.md) first. +- **"Replace the whole Brewfile with Atmos toolchain."** Do not do this. Casks, `mas` entries, and + source-built formulae are out of scope. See [from-homebrew-brewfile.md](references/from-homebrew-brewfile.md). ## Additional Resources @@ -188,3 +238,18 @@ Things to push back on if a user (or another agent) proposes them during migrati workspaces to stacks without losing state - [References/remote-state-bridge.md](references/remote-state-bridge.md) -- the dummy-component and abstract-component patterns for reading state from un-migrated or external Terraform +- [References/from-asdf.md](references/from-asdf.md): steps to move `.tool-versions` and asdf + plugins to the Atmos toolchain. Includes a command mapping and shell integration steps. +- [References/from-aqua.md](references/from-aqua.md): steps to move `aqua.yaml` packages to the + Atmos toolchain. Includes the schema-gap table, a command mapping, and shell integration steps. +- [References/from-tfenv.md](references/from-tfenv.md): steps to move `.terraform-version` and + `tfenv use` pins to the Atmos toolchain. Includes a command mapping and shell integration steps. +- [References/from-tofuenv.md](references/from-tofuenv.md): steps to move `.opentofu-version` and + `tofuenv use` pins to the Atmos toolchain. Includes a command mapping and shell integration + steps. +- [References/from-tenv.md](references/from-tenv.md): steps to move tenv's version files for + Terraform, OpenTofu, Terragrunt, and TFLint to the Atmos toolchain. Includes a command mapping + and shell integration steps. +- [References/from-homebrew-brewfile.md](references/from-homebrew-brewfile.md): steps to move the + CLI-tool part of a Brewfile to the Atmos toolchain. Includes the partial-scope rules, a command + mapping, and shell integration steps. diff --git a/agent-skills/skills/atmos-migration/references/from-aqua.md b/agent-skills/skills/atmos-migration/references/from-aqua.md new file mode 100644 index 0000000000..561a633e0f --- /dev/null +++ b/agent-skills/skills/atmos-migration/references/from-aqua.md @@ -0,0 +1,212 @@ +# Replace Aqua with the Atmos Toolchain + +This reference explains how to replace the [Aqua](https://aquaproj.github.io/) CLI with the Atmos +toolchain. For the skill's decision guide, see [../SKILL.md](../SKILL.md). For the full toolchain +feature reference, see [atmos-toolchain](../../atmos-toolchain/SKILL.md). + +## Overview + +The Atmos toolchain reimplements the Aqua registry YAML schema with its own parser. It does not +use the Aqua Go SDK. The toolchain understands the same `pkgs/` registry format as Aqua. However, +the toolchain supports only a **subset** of the schema. It is **not** a full reimplementation. + +Migration is mechanical for plain GitHub-release packages. Migration is not purely mechanical for +packages that use the schema features listed in Functional Gaps below. Check each package against +that table before you assume a 1:1 port. + +## Before / After + +**Before** (`aqua.yaml`): +```yaml +registries: + - type: standard + ref: v4.245.0 # renovate: depName=aquaproj/aqua-registry + +packages: + - name: hashicorp/terraform + version: v1.9.8 + - name: kubernetes/kubectl + version: v1.28.0 + - name: jqlang/jq + version: v1.7.1 +``` +Aqua also generates `aqua-checksums.json`. This file records checksums for supply-chain +verification. + +**After** (`atmos.yaml` + `.tool-versions`): +```yaml +# atmos.yaml +toolchain: + use_lock_file: true + registries: + - name: aqua + type: aqua + source: https://github.com/aquaproj/aqua-registry/pkgs + ref: v4.245.0 + priority: 10 + verification: + checksums: when_available + signatures: when_available +``` +```text +# .tool-versions +hashicorp/terraform 1.9.8 +kubernetes/kubectl 1.28.0 +jqlang/jq 1.7.1 +``` +```bash +atmos toolchain install +``` +Atmos also generates a lock file when you set `use_lock_file: true`. By default, Atmos writes it +as `toolchain.lock.yaml` under the toolchain install path. Set `toolchain.lock_file` to choose a +different path, for example a repo-relative path you can commit. This file records the resolved +version and checksum for each tool. It serves the same purpose as `aqua-checksums.json`. + +## Steps + +1. **Mirror the registry.** Map Aqua's `type: standard` registry with a `ref:` pin to a + `toolchain.registries` entry of `type: aqua`. Set `source` to + `https://github.com/aquaproj/aqua-registry/pkgs`. Set `ref` to the same tag Aqua pinned. Atmos + resolves the pin through the separate `ref` field, not through the URL path. If `aqua.yaml` used + a private or custom registry, add it as a second `type: aqua` registry entry. Use a `file://` or + GitHub `source` for this entry. Set its `priority` higher than the public registry. +2. **Convert each plain package.** For a `packages:` entry with no unusual fields, run + `atmos toolchain add owner/repo@version`. You can also hand-write the `.tool-versions` line. + Both methods produce the same result. +3. **Flag nonstandard packages.** For any entry that uses a field or package type from the + Functional Gaps table below, do not assume it ports automatically. Follow that row's + workaround. Or leave the tool on Aqua temporarily until the team decides how to handle it. +4. **Replace `aqua-checksums.json` with `toolchain.verification` and `use_lock_file`.** Atmos + verifies packages against checksum and signature metadata published by the registry itself. + Set `checksums` and `signatures` to `when_available`, `required`, or `disabled`. Set + `use_lock_file: true` to also record resolved versions and checksums in `toolchain.lock.yaml`, + for the same reproducibility `aqua-checksums.json` provides. +5. **Verify the migration.** Run `atmos toolchain install`, then run `atmos toolchain list`. + Confirm the resolved versions match what `aqua list` reported before. + +## Command Mapping + +| aqua command | Atmos toolchain equivalent | +|---|---| +| `aqua install` | `atmos toolchain install` | +| `aqua install github.com/hashicorp/terraform@v1.9.8` (ad hoc) | `atmos toolchain install hashicorp/terraform@1.9.8` | +| `aqua g -i` (generate + insert into `aqua.yaml`) | `atmos toolchain add owner/repo@version` (writes to `.tool-versions`) | +| `aqua list` | `atmos toolchain list` | +| `aqua which terraform` | `atmos toolchain which terraform` | +| `aqua exec -- terraform plan` | `atmos toolchain exec terraform@ -- plan` (direct third-party use only). `atmos terraform plan` already resolves the toolchain automatically. Do not wrap it in `atmos toolchain exec`. | +| `aqua update-checksum` | No separate command. `toolchain.verification` handles this automatically at install time. | + +## Shell Integration + +Aqua uses the same shim-based method as asdf. Add `export PATH="$(aqua root-dir)/bin:$PATH"` to +`~/.bashrc` or `~/.zshrc`. This puts Aqua's proxy directory on `PATH`. `aqua-proxy` resolves the +nearest `aqua.yaml` again on every invocation. As a result, plain `terraform` always resolves +correctly in any shell. This method needs no per-project setup. + +**The Atmos toolchain does not do this by default.** Atmos resolves tools declared in +`.tool-versions` (the project-wide default) or `dependencies.tools` (a scoped override) and injects +them into `PATH` only for the duration of one `atmos ` invocation. If you run plain +`terraform` in your shell, it will not use the Atmos-managed version unless you opt in to shell +integration. This is a **supported mode**, not a limitation. Use `atmos toolchain env` to export the +resolved `PATH` into your interactive shell: + +**Bash** (add to `~/.bashrc`): +```bash +eval "$(atmos toolchain env --format=bash)" +``` + +**Zsh** (add to `~/.zshrc`): +```zsh +eval "$(atmos toolchain env --format=bash)" +``` +Atmos has no separate `--format=zsh` option. The `bash` format emits plain POSIX +`export PATH=...`. Zsh evaluates this output the same way. + +**Fish** (add to `~/.config/fish/config.fish`): +```fish +atmos toolchain env --format=fish | source +``` + +**PowerShell** (add to `$PROFILE`): +```powershell +Invoke-Expression (atmos toolchain env --format powershell | Out-String) +``` + +Verify with `which terraform` (use `Get-Command terraform` on PowerShell). It must resolve under +the Atmos toolchain install directory, not Aqua's proxy directory. + +**Important: this method takes a static snapshot, not Aqua's dynamic per-directory resolution.** +`aqua-proxy` resolves the nearest `aqua.yaml` again on every command. As a result, when you `cd` +into a different project, Aqua automatically switches versions. `atmos toolchain env` bakes the +resolved paths of the current directory into `PATH` one time, at eval time. It does not update +automatically when you `cd`. Re-run the `eval` line after you switch projects. Or use +`atmos terraform ...` instead of bare `terraform` when you work across multiple projects. +`atmos terraform ...` always resolves per invocation, regardless of shell state. + +**Atmos also has a direct equivalent to `aqua-proxy`: `toolchain.proxies`.** Configure a proxy to +expose a toolchain tool under a command name that differs from the tool's own binary name. Atmos +creates a link in `${toolchain.install_path}/bin/proxy`. That link re-invokes Atmos under the +configured command name. Atmos then resolves the tool, installs it if needed, and forwards the +arguments. `atmos toolchain env` puts this proxy directory on `PATH` when you configure at least +one proxy. Use this when a package name differs from the command name, for example a multicall +binary such as `coreutils` that must run under the name `ls`. You do not need a proxy for the +common case, where the tool's binary already has the name you want to type. In that case, the +direct `PATH` export above already provides it. The +[atmos-toolchain](../../atmos-toolchain/SKILL.md) skill does not yet cover `toolchain.proxies` in +depth; see [Toolchain Proxies](https://atmos.tools/cli/configuration/toolchain/proxies) for the +full reference. + +## Functional Gaps + +### Planned + +| Aqua package type | Status | Workaround until it lands | +|---|---|---| +| `github_archive` | In progress. [PR #2416](https://github.com/cloudposse/atmos/pull/2416) adds this feature. It resolves to `https://github.com/{owner}/{repo}/archive/refs/tags/{version}.tar.gz`, matching upstream Aqua semantics. | Hand-port to a `type: atmos` inline registry entry (`http` type pointed at the archive URL). Or leave the tool on Aqua until the PR merges. | +| `github_content` | In progress. [PR #2416](https://github.com/cloudposse/atmos/pull/2416) also adds this feature. | Hand-port to a `type: atmos` inline registry entry (`http` type pointed at the raw file URL). Or leave the tool on Aqua until the PR merges. | + +Check whether PR #2416 has merged before you tell a user these types are unsupported. If it has +merged, treat both types as supported and remove this section. The Not Supported table below +still applies. + +### Not Supported + +Atmos intentionally does not support the following Aqua schema features. These come from the +"Unsupported Aqua Features" list in [atmos-toolchain](../../atmos-toolchain/SKILL.md). + +| Aqua feature | Why it does not port directly | Workaround | +|---|---|---| +| `go_build` package type | Not implemented. Atmos does not build tools from source. | Use a pre-built release if the project publishes one. Add it via a `type: atmos` inline registry. | +| `cargo` package type | Not implemented. Atmos has no Cargo or crates.io installer. | No direct equivalent exists. Source the binary another way. | +| `version_filter` / `version_prefix` | Atmos does not support version-string manipulation. | Pin an exact version. Or normalize the version with `toolchain.aliases`. | +| `version_expr` / `version_expr_prefix` | Same as above. | Same as above. | +| `go_version_file` | Atmos does not support reading a version from a Go source file. | Pin the version explicitly in `.tool-versions`. | +| `import` | Atmos does not support Aqua's registry-composition mechanism. | Add multiple `toolchain.registries` entries instead of one registry that imports others. | +| `command_aliases` | Atmos does not support this Aqua field. | Use `toolchain.proxies` in `atmos.yaml` instead. `toolchain.proxies` creates a command-name link, the same role `command_aliases` plays in Aqua. Do not use `toolchain.aliases` for this. `toolchain.aliases` only maps a short tool name to an `owner/repo` registry entry for lookup. It does not change the command name a tool runs under. See the Shell Integration section above. | +| `tags` | Not supported. | No equivalent exists. Atmos does not filter installs by tag. | +| `vars` | Atmos does not support Aqua's per-package template variables. | Hard-code the value into the `url` template of a `type: atmos` inline registry entry. | + +## Worked Example + +This mixed `aqua.yaml` file shows both cases: +```yaml +packages: + - name: hashicorp/terraform # plain GitHub release -- migrates cleanly + version: v1.9.8 + - name: some-org/custom-tool # uses go_build -- needs manual porting + version: v2.1.0 +``` + +`hashicorp/terraform` becomes `atmos toolchain add hashicorp/terraform@1.9.8`. For +`some-org/custom-tool`, add a `type: atmos` inline registry entry that points at a pre-built +release asset, if one exists. Otherwise, leave it out of scope for this migration pass. + +## Cross-Links + +- [atmos-toolchain SKILL.md](../../atmos-toolchain/SKILL.md): the Registries section and the + "Unsupported Aqua Features" list. The Not Supported table above comes from this list. +- [PR #2416](https://github.com/cloudposse/atmos/pull/2416): adds `github_archive` and + `github_content` package-type support. Check its merge status before you cite the Planned table + above as still accurate. +- [atmos-toolchain commands-reference.md](../../atmos-toolchain/references/commands-reference.md): + covers `atmos toolchain add`, `registry list`, `registry search`. diff --git a/agent-skills/skills/atmos-migration/references/from-asdf.md b/agent-skills/skills/atmos-migration/references/from-asdf.md new file mode 100644 index 0000000000..5bc754cfae --- /dev/null +++ b/agent-skills/skills/atmos-migration/references/from-asdf.md @@ -0,0 +1,161 @@ +# Replace asdf with the Atmos Toolchain + +This reference describes how to replace [asdf](https://asdf-vm.com/) with the Atmos toolchain. For +the skill's decision guide, see [../SKILL.md](../SKILL.md). For the full toolchain feature +reference, see [atmos-toolchain](../../atmos-toolchain/SKILL.md). + +## Overview + +asdf and the Atmos toolchain read the same file format. Both use `.tool-versions`, with one +` ` pair per line. + +When you migrate from asdf, you do not need to rewrite this file. The existing `.tool-versions` +file usually needs no changes. + +Two things change: the tool download source and the install method. Atmos downloads tools from an +Atmos or Aqua registry. asdf downloads tools from an asdf plugin. asdf installs tools with the +`asdf install` command. Atmos installs tools automatically when you run an `atmos` command. + +## Before / After + +**Before** (asdf-managed): +```text +# .tool-versions +terraform 1.9.8 +kubectl 1.28.0 +helm 3.13.0 +``` +```bash +asdf plugin add terraform +asdf plugin add kubectl +asdf plugin add helm +asdf install +``` + +**After** (Atmos-managed, same `.tool-versions` file, unchanged): +```yaml +# atmos.yaml +toolchain: + aliases: + terraform: hashicorp/terraform + kubectl: kubernetes/kubectl + helm: helm/helm + registries: + - name: aqua + type: aqua + source: https://github.com/aquaproj/aqua-registry/tree/main/pkgs + priority: 10 +``` +```bash +atmos toolchain install +``` + +## Steps + +1. **Leave `.tool-versions` in its current location.** If the file is not at the repo root, set + `toolchain.versions_file` (or `ATMOS_TOOL_VERSIONS`) to its path. Do not move the file. +2. **Add a minimal `toolchain:` block to `atmos.yaml`.** Add an `aliases:` entry for each tool + whose asdf plugin name does not match an `owner/repo` value in the public Aqua registry. Also + add the public Aqua registry itself as a fallback. See Before/After above for an example. +3. **Verify tool resolution.** Run `atmos toolchain install` to install every tool declared in + `.tool-versions`. Then run `atmos toolchain list`. Run `atmos toolchain which terraform` to + confirm the resolved binary path. +4. **Move frequently used tools to `dependencies.tools`.** `.tool-versions` is a good default for + the whole repository's developer shell. But if a specific component, workflow, or custom + command needs a pinned version as part of its contract, declare the tool there instead. See the + "Default Rule" and "Where to Declare a Tool" table in + [atmos-toolchain](../../atmos-toolchain/SKILL.md). This step is optional. It is not required + for the migration to work. +5. **Remove the asdf shims last.** First confirm that `atmos ` resolves tools correctly + without the shims on `PATH`. Uninstall asdf plugins (`asdf plugin remove `) or asdf + itself only after the whole team has switched to the Atmos toolchain. + +## Command Mapping + +| asdf command | Atmos toolchain equivalent | +|---|---| +| `asdf plugin add terraform` | No plugin step needed. Add the tool to `toolchain.aliases`/`registries` only if the public Aqua registry does not already resolve it. | +| `asdf install` | `atmos toolchain install` | +| `asdf install terraform 1.9.8` | `atmos toolchain install terraform@1.9.8` | +| `asdf global terraform 1.9.8` | `atmos toolchain set terraform 1.9.8` (writes the default version to `.tool-versions`) | +| `asdf local terraform 1.9.8` | `atmos toolchain add terraform@1.9.8` (adds/updates the `.tool-versions` entry) | +| `asdf current` | `atmos toolchain list` | +| `asdf current terraform` | `atmos toolchain get terraform` | +| `asdf which terraform` | `atmos toolchain which terraform` | +| `asdf uninstall terraform 1.9.8` | `atmos toolchain uninstall terraform@1.9.8` | +| `asdf plugin list all` | `atmos toolchain registry search ` | +| `asdf shell terraform 1.9.8` (session-only override) | `atmos toolchain exec terraform@1.9.8 -- ` (one-off pinned run of the raw binary) | +| `. ~/.asdf/asdf.sh` in shell rc (shim-based, automatic) | `eval "$(atmos toolchain env --format=bash)"` in shell rc | + +Note: `atmos terraform`, `atmos helmfile`, and other Atmos commands do not need any of these +steps. These commands resolve and inject declared tool versions automatically. The table above +maps commands for direct, asdf-style interactive use: installing, listing, pinning, and running a +raw third-party binary. + +## Shell Integration + +asdf uses shims to work. The line `. "$HOME/.asdf/asdf.sh"` in `~/.bashrc` or `~/.zshrc` adds +`~/.asdf/shims` to `PATH`. Each shim reads the nearest `.tool-versions` file again each time it +runs. As a result, plain `terraform` always resolves correctly in any shell, IDE terminal, or +script. This works with no per-project setup. + +**The Atmos toolchain does not do this by default.** Atmos resolves and injects tools declared in +`.tool-versions` (the project-wide default) or `dependencies.tools` (a scoped override) into `PATH` +only for the duration of an `atmos ` invocation. If you run plain `terraform` in your +shell, it will not use the Atmos-managed version. To use the Atmos-managed version in your shell, +you must opt in to shell integration. This is a supported mode, not a limitation. Use +`atmos toolchain env` to export the resolved `PATH` into your interactive shell: + +**Bash** (add to `~/.bashrc`): +```bash +eval "$(atmos toolchain env --format=bash)" +``` + +**Zsh** (add to `~/.zshrc`): +```zsh +eval "$(atmos toolchain env --format=bash)" +``` +Atmos has no separate `--format=zsh` option. The `bash` format emits plain POSIX +`export PATH=...` syntax. Zsh evaluates this syntax identically to bash. + +**Fish** (add to `~/.config/fish/config.fish`): +```fish +atmos toolchain env --format=fish | source +``` + +**PowerShell** (add to `$PROFILE`): +```powershell +Invoke-Expression (atmos toolchain env --format powershell | Out-String) +``` + +Verify the result with `which terraform` (`Get-Command terraform` on PowerShell). The command must +resolve to the Atmos toolchain install directory, not the system `terraform` or an asdf shim. + +**Important: `atmos toolchain env` creates a static snapshot. It does not match asdf's dynamic +per-directory resolution.** asdf shims read `.tool-versions` again on every command. So when you +change directory (`cd`) into a different project, asdf automatically switches versions. `atmos +toolchain env` sets the resolved paths for the current directory into `PATH` one time, at eval +time. It does not update automatically when you change directory. Run the `eval` line again after +you switch projects. Alternatively, use `atmos terraform ...` instead of bare `terraform` when you +work across multiple projects. `atmos terraform ...` always resolves tools per invocation, +regardless of shell state. + +## Functional Gaps + +- **Atmos has no equivalent for plugin-specific behavior.** asdf plugins can run arbitrary shell + commands during install. These commands can include custom build steps, post-install hooks, and + non-standard download URLs. An Atmos tool is either an Aqua registry entry (GitHub-release or + HTTP download) or a `type: atmos` inline registry entry. Atmos has no hook mechanism. Most + common CLI tools work through the public Aqua registry without changes. A tool that depends on a + custom asdf plugin script can need a custom `type: atmos` registry entry. Some such tools cannot + migrate to Atmos at all. +- **The Atmos toolchain has no equivalent to asdf's `.tool-versions` `system` sentinel.** The + `system` sentinel tells asdf to use the tool already on `PATH`. Atmos resolves and installs + every declared tool instead. + +## Cross-Links + +- [atmos-toolchain SKILL.md](../../atmos-toolchain/SKILL.md): full `toolchain:` config reference, + `dependencies.tools`, registries, aliases. +- [atmos-toolchain commands-reference.md](../../atmos-toolchain/references/commands-reference.md): + full CLI command reference. diff --git a/agent-skills/skills/atmos-migration/references/from-homebrew-brewfile.md b/agent-skills/skills/atmos-migration/references/from-homebrew-brewfile.md new file mode 100644 index 0000000000..5fed2576f6 --- /dev/null +++ b/agent-skills/skills/atmos-migration/references/from-homebrew-brewfile.md @@ -0,0 +1,158 @@ +# Replace a Homebrew Brewfile with the Atmos Toolchain + +This reference explains how to replace the CLI-tool part of a [Homebrew Brewfile](https://github.com/Homebrew/homebrew-bundle) +(`brew bundle`) with the Atmos toolchain. For the skill decision guide, see +[../SKILL.md](../SKILL.md). For the full toolchain feature reference, see +[atmos-toolchain](../../atmos-toolchain/SKILL.md). + +## Scope + +This migration covers only part of the Brewfile. The Atmos toolchain manages only CLI binaries. +Atmos toolchain fetches these binaries from a GitHub release or a plain HTTP download. This is +the same model Aqua uses. + +The Atmos toolchain does **not** replace these items: + +- `cask` entries (GUI apps) +- `mas` entries (Mac App Store apps) +- Homebrew formulae that require a build from source or a complex dependency graph + +Keep these items in the Brewfile. Continue to install them with `brew bundle`. Only plain +`brew ""` lines that map to a standalone, prebuilt CLI binary are migration candidates. + +## Before / After + +**Before** (`Brewfile`): +```ruby +tap "hashicorp/tap" + +brew "hashicorp/tap/terraform" +brew "kubernetes-cli" +brew "jq" +cask "docker" +mas "Xcode", id: 497799835 +``` + +**After** (`atmos.yaml` and `.tool-versions`, with the Brewfile reduced to items that stay out of +scope): +```yaml +# atmos.yaml +toolchain: + aliases: + terraform: hashicorp/terraform + kubectl: kubernetes/kubectl + registries: + - name: aqua + type: aqua + source: https://github.com/aquaproj/aqua-registry/tree/main/pkgs + priority: 10 +``` +```text +# .tool-versions +terraform 1.9.8 +kubectl 1.28.0 +jq 1.7.1 +``` +```bash +atmos toolchain install +``` +```ruby +# Brewfile (slimmed -- only what Atmos toolchain doesn't cover) +cask "docker" +mas "Xcode", id: 497799835 +``` + +## Steps + +1. **Classify each Brewfile line.** A plain `brew ""` entry for a standalone CLI tool is + a candidate. `cask` entries, `mas` entries, and formulae that pull in a heavy dependency tree + or require a source build stay out of scope. Leave these entries in the Brewfile. +2. **Resolve each candidate's GitHub `owner/repo`.** Homebrew formula names often differ from the + upstream GitHub repository name. This differs from asdf or aqua. For example, `kubernetes-cli` + maps to `kubernetes/kubectl`, and `hashicorp/tap/terraform` maps to `hashicorp/terraform`. + You must do this step manually. If the mapping is not obvious, check the formula's `homepage` or + `url` field with `brew info `. +3. **Pick a version to pin.** A Brewfile has no native per-project version pinning. `brew bundle` + always installs the current version in the tap. Ask the user which version to pin. Or use the + currently installed version as a starting point: run `brew list --versions `. +4. **Add each tool.** Run `atmos toolchain add owner/repo@version` for each resolved candidate. +5. **Add the `toolchain:` block to `atmos.yaml`** if the repository does not already have one. + See the Before/After section above. +6. **Verify the result.** Run `atmos toolchain install`, then run `atmos toolchain list`. +7. **Reduce the Brewfile to the out-of-scope entries only**: casks, `mas` entries, and + source-built formulae. Continue to run `brew bundle` for these entries. Do not delete the + Brewfile unless every line in it was a migration candidate. + +## Command Mapping + +| Homebrew command | Atmos toolchain equivalent | +|---|---| +| `brew bundle` (installs everything in the Brewfile) | `atmos toolchain install` (installs everything in `.tool-versions`). This covers only the CLI-tool subset, not casks or `mas` entries. | +| `brew install terraform` | `atmos toolchain add hashicorp/terraform@`, then `atmos toolchain install`. Or run `atmos toolchain install hashicorp/terraform@` for a one-time install. | +| `brew list --versions terraform` | `atmos toolchain list` | +| `brew bundle dump` (generates a Brewfile from the installed state) | No direct equivalent. Build `.tool-versions` by running `atmos toolchain add` for each tool, or write the file by hand. | +| `brew uninstall terraform` | `atmos toolchain uninstall hashicorp/terraform@` | +| `brew upgrade terraform` | `atmos toolchain add hashicorp/terraform@`, then `atmos toolchain install`. Atmos pins exact versions. It does not track "latest" implicitly. | + +## Shell Integration + +Homebrew already uses this same pattern. Add `eval "$(/opt/homebrew/bin/brew shellenv)"` to +`~/.bashrc` or `~/.zshrc` (use `/usr/local/bin/brew shellenv` on Intel Macs). This command puts +Homebrew's `bin` directory on `PATH` once, permanently. Every formula's binary lives in that +directory. Homebrew installs are global, not per-project, so each binary is the same version in +every shell and every directory. + +The Atmos toolchain uses the same eval-into-rc-file pattern. But the tools it resolves are +**project-scoped**, not global. The nearest `.tool-versions` file or `dependencies.tools` section +drives the resolution: + +**Bash** (add to `~/.bashrc`): +```bash +eval "$(atmos toolchain env --format=bash)" +``` + +**Zsh** (add to `~/.zshrc`): +```zsh +eval "$(atmos toolchain env --format=bash)" +``` +Atmos has no separate `--format=zsh` option. The `bash` format emits plain POSIX +`export PATH=...` syntax. Zsh evaluates this syntax the same way. + +**Fish** (add to `~/.config/fish/config.fish`): +```fish +atmos toolchain env --format=fish | source +``` + +**PowerShell** (add to `$PROFILE`): +```powershell +Invoke-Expression (atmos toolchain env --format powershell | Out-String) +``` + +Verify the result with `which terraform` (use `Get-Command terraform` on PowerShell). The command +must resolve to the Atmos toolchain install directory, not Homebrew's `bin` directory. + +**Important: this is a real behavior change from Homebrew's global installs, not only a syntax +change.** With Homebrew, `terraform` was the same version in every shell and every directory. +`atmos toolchain env` sets `PATH` from the current directory's resolved paths at eval time. If you +switch to a project with a different pinned version, you must re-run the `eval` line. Or use +`atmos terraform ...` instead of bare `terraform`. The `atmos terraform ...` command always +resolves the version per invocation, regardless of shell state. Tell the user about this +tradeoff. It is the cost of the per-project reproducibility that the Brewfile never provided. + +## Functional Gaps + +- **The Brewfile has no native versioning. This is a behavior change, not a bug.** When you move + these tools under the Atmos toolchain, the team gets reproducible, pinned versions for the + first time. Flag this as an improvement. But confirm the user wants pinning, not + always-latest, before you migrate. +- **The formula-to-repository name mapping is manual.** No registry maps Homebrew formula names + to GitHub repositories automatically. Each candidate needs a one-time lookup. +- **The Atmos toolchain does not support casks, `mas` entries, or source-built formulae.** Do not + propose replacement of the whole Brewfile. Only the plain CLI-binary subset is in scope. + +## Cross-Links + +- [atmos-toolchain SKILL.md](../../atmos-toolchain/SKILL.md): `.tool-versions`, + `dependencies.tools`, registries, aliases. +- [atmos-toolchain commands-reference.md](../../atmos-toolchain/references/commands-reference.md): + full CLI command reference. diff --git a/agent-skills/skills/atmos-migration/references/from-tenv.md b/agent-skills/skills/atmos-migration/references/from-tenv.md new file mode 100644 index 0000000000..a41f19954b --- /dev/null +++ b/agent-skills/skills/atmos-migration/references/from-tenv.md @@ -0,0 +1,173 @@ +# Replace tenv with the Atmos Toolchain + +This reference explains how to replace [tenv](https://github.com/tofuutils/tenv) with the Atmos +toolchain. For the skill's decision guide, see [../SKILL.md](../SKILL.md). For the full toolchain +feature reference, see [atmos-toolchain](../../atmos-toolchain/SKILL.md). + +If the user manages only 1 tool, see [from-tfenv.md](from-tfenv.md) or +[from-tofuenv.md](from-tofuenv.md) instead. The steps are the same. This file covers tenv's +multi-tool scope only. + +## Overview + +tenv replaces tfenv and tofuenv. It is one binary that manages version pinning for Terraform, +OpenTofu, Terragrunt, and TFLint. Each tool uses its own version file, or a `tenv use` +command. + +The Atmos toolchain treats each tool as an independent tool declaration. To migrate, apply the +same one-line-per-tool process to each tool that tenv currently manages. + +## Version Files and Tool Names + +| tenv-managed file | Tool | `.tool-versions` line | +|-------------------------|--------------|----------------------------| +| `.terraform-version` | Terraform | `terraform ` | +| `.opentofu-version` | OpenTofu | `opentofu ` | +| `.terragrunt-version` | Terragrunt | `terragrunt ` | +| `.tflint-version` | TFLint | `tflint ` | + +Convert only the files that exist in the repo. Most projects use 1 or 2 of these files. Few +projects use all 4. + +## Before / After + +**Before:** +```text +# .terraform-version +1.9.8 +# .tflint-version +0.54.0 +``` +You can also set versions with commands: `tenv terraform use 1.9.8` or `tenv tflint use 0.54.0`. + +**After:** +```text +# .tool-versions +terraform 1.9.8 +tflint 0.54.0 +``` +```yaml +# atmos.yaml +toolchain: + aliases: + terraform: hashicorp/terraform + tflint: terraform-linters/tflint + registries: + - name: aqua + type: aqua + source: https://github.com/aquaproj/aqua-registry/tree/main/pkgs + priority: 10 +``` +```bash +atmos toolchain install +``` + +## Steps + +1. **Identify which version files exist** in the repo. See the mapping table above. If a file is + missing but a version is pinned another way, run `tenv detect` to find the current + resolved version. +2. **Add one `.tool-versions` line for each tool.** Use the mapping table. +3. **Add the `toolchain:` block** to `atmos.yaml` if the repo does not already have one. See + Before/After above. If OpenTofu is the primary binary for `atmos terraform` commands, add + `components.terraform.command: tofu` too. +4. **Verify the setup.** Run `atmos toolchain install`, then run `atmos toolchain list`. Confirm + each tool resolves to the expected version. +5. **Promote versions to `dependencies.tools`** on the specific component or workflow when a + version is part of that unit's contract. Use this instead of a repo-wide default. See the + "Default Rule" in [atmos-toolchain](../../atmos-toolchain/SKILL.md). +6. **Remove the version files and uninstall tenv last.** Do this only after the team verifies + that `atmos` commands resolve every tool correctly without tenv. + +## Command Mapping + +| tenv command | Atmos toolchain equivalent | +|---|---| +| `tenv terraform install 1.9.8` | `atmos toolchain install terraform@1.9.8` | +| `tenv terraform use 1.9.8` | `atmos toolchain set terraform 1.9.8` | +| `tenv tofu install 1.10.3` | `atmos toolchain install opentofu@1.10.3` | +| `tenv tofu use 1.10.3` | `atmos toolchain set opentofu 1.10.3` | +| `tenv terragrunt install 0.67.0` | `atmos toolchain install terragrunt@0.67.0` | +| `tenv tflint install 0.54.0` | `atmos toolchain install tflint@0.54.0` | +| `tenv terraform list` (installed) | `atmos toolchain list` | +| `tenv terraform list --remote` (available) | `atmos toolchain search terraform` | +| `tenv terraform detect` | `atmos toolchain get terraform` | +| `tenv terraform uninstall 1.9.8` | `atmos toolchain uninstall terraform@1.9.8` | + +For the last 4 rows, replace `terraform` with `tofu`, `terragrunt`, or `tflint` as needed. + +## Shell Integration + +tenv works through shims. Its installer adds `~/.tenv/bin` to `PATH`, typically with +`export PATH="$HOME/.tenv/bin:$PATH"` in `~/.bashrc` or `~/.zshrc`. + +Each shim (`terraform`, `tofu`, `terragrunt`, `tflint`) reads its matching version file again on +every invocation. Plain commands such as `terraform` or `tofu` always resolve correctly in any +shell. This setup needs no per-project configuration. + +**The Atmos toolchain does not do this by default.** Atmos resolves tools declared in +`.tool-versions` (the project-wide default) or `dependencies.tools` (a scoped override) and injects +them into `PATH` only for the duration of an `atmos ` invocation. If you run one of +these tools plain in your shell, it will not use the Atmos-managed version. To use the +Atmos-managed version in your shell, opt in to shell integration. + +Shell integration is a **supported mode**. It is not a limitation. Use `atmos toolchain env` to +export the resolved `PATH` into your interactive shell: + +**Bash** (add to `~/.bashrc`): +```bash +eval "$(atmos toolchain env --format=bash)" +``` + +**Zsh** (add to `~/.zshrc`): +```zsh +eval "$(atmos toolchain env --format=bash)" +``` +Atmos has no separate `--format=zsh` option. The `bash` format emits plain POSIX +`export PATH=...` output. Zsh evaluates this output the same way. + +**Fish** (add to `~/.config/fish/config.fish`): +```fish +atmos toolchain env --format=fish | source +``` + +**PowerShell** (add to `$PROFILE`): +```powershell +Invoke-Expression (atmos toolchain env --format powershell | Out-String) +``` + +Verify the setup with `which terraform` (use `Get-Command terraform` on PowerShell). The command +must resolve under the Atmos toolchain install directory, not a tenv shim. Repeat this check for +`tofu`, `terragrunt`, and `tflint` as needed. + +**Important: `atmos toolchain env` creates a static snapshot. It does not repeat tenv's +per-directory resolution.** tenv's shims read their version files again on every command. Because +of this, changing directories (`cd`) into a different project automatically switches versions for +every tool tenv manages. + +`atmos toolchain env` writes the current directory's resolved paths into `PATH` one time, at eval +time. It does not update automatically when you change directories. Re-run the `eval` line after +you switch projects. Alternatively, when you work across multiple projects, use +`atmos terraform ...` instead of bare tool commands. `atmos terraform ...` always resolves the +version for each invocation, regardless of shell state. + +## Functional Gaps + +- **Atmos toolchain has no equivalent for partial or range-based version selectors yet.** Like + tfenv and tofuenv, tenv supports these selectors (for example, `latest:^1.9`, `latest-stable`) + for `tenv install`. Atmos toolchain version specs support exact versions, `latest`, + `pr:`, `sha:`, and `ref:`. SemVer range constraints are documented as + **planned, not yet implemented**. Pin exact versions for now. +- **Atmos does not natively orchestrate Terragrunt** the way it orchestrates Terraform and + OpenTofu. Atmos toolchain can still install and pin the `terragrunt` binary through + `.tool-versions` or `dependencies.tools`. Running Terragrunt is the user's own workflow or + custom command. It is not a built-in Atmos component type. + +## Cross-Links + +- [atmos-toolchain SKILL.md](../../atmos-toolchain/SKILL.md): `.tool-versions`, + `dependencies.tools`, version spec syntax. +- [atmos-toolchain commands-reference.md](../../atmos-toolchain/references/commands-reference.md): + full CLI command reference. +- [from-tfenv.md](from-tfenv.md) / [from-tofuenv.md](from-tofuenv.md): single-tool version of + these same steps. diff --git a/agent-skills/skills/atmos-migration/references/from-tfenv.md b/agent-skills/skills/atmos-migration/references/from-tfenv.md new file mode 100644 index 0000000000..0df8f2eacb --- /dev/null +++ b/agent-skills/skills/atmos-migration/references/from-tfenv.md @@ -0,0 +1,139 @@ +# Replace tfenv with the Atmos Toolchain + +This reference explains how to replace [tfenv](https://github.com/tfutils/tfenv) with the Atmos +toolchain. For the skill's decision guide, see [../SKILL.md](../SKILL.md). For the full toolchain +feature reference, see [atmos-toolchain](../../atmos-toolchain/SKILL.md). Some users also manage +OpenTofu versions with tofuenv, or Terragrunt and TFLint versions with tenv. For these tools, see +[from-tofuenv.md](from-tofuenv.md) and [from-tenv.md](from-tenv.md). The steps are the same. Only +the tool changes. + +## Overview + +tfenv has one purpose. It pins a Terraform version. It uses a `.terraform-version` file, which +holds a single version string. It also uses the `tfenv use X.Y.Z` command. The Atmos equivalent is +one line in `.tool-versions`. For most cases, this migration is mechanical. One gap remains: +tfenv's partial or range-based version selectors. See Functional Gaps. + +## Before / After + +**Before:** +```text +# .terraform-version +1.9.8 +``` +You can also set the version with the `tfenv use 1.9.8` command. This command records the version +in `~/.tfenv/version` as the global default. Or it records the version in `.terraform-version` for +a per-project pin. + +**After:** +```text +# .tool-versions +terraform 1.9.8 +``` +```yaml +# atmos.yaml +toolchain: + aliases: + terraform: hashicorp/terraform + registries: + - name: aqua + type: aqua + source: https://github.com/aquaproj/aqua-registry/tree/main/pkgs + priority: 10 +``` +```bash +atmos toolchain install +``` + +## Steps + +1. **Read the current pin.** Run `cat .terraform-version` if the file exists. Otherwise, run + `tfenv version-name` for the current active version. +2. **Add it to `.tool-versions`.** Append `terraform `. Create the file if it does not + exist. +3. **Add the `toolchain:` block** to `atmos.yaml` if the repository does not already have one. See + Before/After above. +4. **Verify** the setup. Run `atmos toolchain install`. Then run `atmos toolchain which terraform`. + Confirm that `atmos terraform plan -s ` uses the expected version. +5. **Promote to `dependencies.tools`** on the specific component. Do this if the version must apply + only to that component, not to the whole repository. See the "Default Rule" in + [atmos-toolchain](../../atmos-toolchain/SKILL.md). +6. **Remove `.terraform-version` and uninstall tfenv last.** Do this only after the team verifies + that `atmos terraform` commands resolve the correct version without it. + +## Command Mapping + +| tfenv command | Atmos toolchain equivalent | +|---|---| +| `tfenv install 1.9.8` | `atmos toolchain install terraform@1.9.8` | +| `tfenv use 1.9.8` | `atmos toolchain set terraform 1.9.8` | +| `tfenv version-name` | `atmos toolchain get terraform` | +| `tfenv list` (installed versions) | `atmos toolchain list` | +| `tfenv list-remote` (available versions) | `atmos toolchain search terraform` | +| `tfenv uninstall 1.9.8` | `atmos toolchain uninstall terraform@1.9.8` | + +## Shell Integration + +tfenv works through shimming. Its installer adds `~/.tfenv/bin` to `PATH`. It typically does this +with `export PATH="$HOME/.tfenv/bin:$PATH"` in `~/.bashrc` or `~/.zshrc`. The `terraform` shim +re-reads the nearest `.terraform-version` file on every command. As a result, plain `terraform` +always resolves to the correct version in any shell. This setup needs no per-project configuration. + +**The Atmos toolchain does not do this by default.** Atmos resolves tools declared in +`.tool-versions` (the project-wide default) or `dependencies.tools` (a scoped override) and injects +them into `PATH`. It does this only for the duration of one `atmos ` command. If you +run plain `terraform` in your shell, it will not use the Atmos-managed version. To use it, you must +opt in to shell integration. This is a **supported mode**, not a limitation. Use +`atmos toolchain env` to export the resolved `PATH` into your interactive shell: + +**Bash** (add to `~/.bashrc`): +```bash +eval "$(atmos toolchain env --format=bash)" +``` + +**Zsh** (add to `~/.zshrc`): +```zsh +eval "$(atmos toolchain env --format=bash)" +``` +Atmos has no separate `--format=zsh` option. The `bash` format emits plain POSIX +`export PATH=...` syntax. Zsh evaluates this syntax the same way. + +**Fish** (add to `~/.config/fish/config.fish`): +```fish +atmos toolchain env --format=fish | source +``` + +**PowerShell** (add to `$PROFILE`): +```powershell +Invoke-Expression (atmos toolchain env --format powershell | Out-String) +``` + +Verify the result with `which terraform`. On PowerShell, use `Get-Command terraform`. The command +must resolve to the Atmos toolchain install directory, not the tfenv shim. + +**Important: this is a static snapshot, not tfenv's dynamic per-directory resolution.** tfenv's +shim re-reads `.terraform-version` on every command. So when you `cd` into a different project, +tfenv switches versions automatically. `atmos toolchain env` sets `PATH` once, at eval time, using +the resolved paths of the *current* directory. It does not update automatically when you `cd`. +Re-run the `eval` line after you switch projects. Or use `atmos terraform ...` instead of bare +`terraform` when you work across multiple projects. The `atmos terraform ...` command always +resolves the version per invocation, regardless of shell state. + +## Functional Gaps + +- **The Atmos toolchain has no equivalent for partial or range-based version selectors yet.** + tfenv supports selectors like `latest:^1.5` or `latest:1.9.*` through `tfenv install` arguments. + These selectors use a partial constraint and select the latest matching release. Atmos toolchain + version specs support exact versions, `latest`, `pr:`, `sha:`, and `ref:`. + SemVer range constraints, such as `~> 1.9.0` or `>= 1.8.0, < 2.0.0`, are documented as + **planned, not yet implemented**. If the user relies on a floating constraint, pin an exact + version for now. Note that range support is coming. + +## Cross-Links + +- [atmos-toolchain SKILL.md](../../atmos-toolchain/SKILL.md): covers `.tool-versions`, + `dependencies.tools`, and version spec syntax. +- [atmos-toolchain commands-reference.md](../../atmos-toolchain/references/commands-reference.md): + full CLI command reference. +- [from-tofuenv.md](from-tofuenv.md): same steps, for OpenTofu. +- [from-tenv.md](from-tenv.md): same steps, for tenv's multi-tool version files. diff --git a/agent-skills/skills/atmos-migration/references/from-tofuenv.md b/agent-skills/skills/atmos-migration/references/from-tofuenv.md new file mode 100644 index 0000000000..a3c2e894f1 --- /dev/null +++ b/agent-skills/skills/atmos-migration/references/from-tofuenv.md @@ -0,0 +1,145 @@ +# Replace tofuenv with the Atmos Toolchain + +This reference describes how to replace [tofuenv](https://github.com/tofuutils/tofuenv) with the +Atmos toolchain. For the decision guide, see [../SKILL.md](../SKILL.md). For the full toolchain +feature reference, see [atmos-toolchain](../../atmos-toolchain/SKILL.md). + +The user can also manage Terraform versions with tfenv, or Terragrunt and TFLint versions with +tenv. In that case, see [from-tfenv.md](from-tfenv.md) and [from-tenv.md](from-tenv.md). The steps +are the same. Only the tool differs. + +## Overview + +tofuenv has one purpose. It pins an OpenTofu version. Use an `.opentofu-version` file (a single +bare version string), or use the `tofuenv use X.Y.Z` command. + +The Atmos equivalent is one line in `.tool-versions`. For the common case, this migration is +mechanical. The one gap is tofuenv's partial or range-based version selectors. See Functional Gaps. + +## Before / After + +**Before:** +```text +# .opentofu-version +1.10.3 +``` +You can also set the version with the `tofuenv use 1.10.3` command. tofuenv records this version +in `~/.tofuenv/version` as the global default. Or tofuenv records the version in +`.opentofu-version` as a per-project pin. + +**After:** +```text +# .tool-versions +opentofu 1.10.3 +``` +```yaml +# atmos.yaml +toolchain: + aliases: + opentofu: opentofu/opentofu + registries: + - name: aqua + type: aqua + source: https://github.com/aquaproj/aqua-registry/tree/main/pkgs + priority: 10 +components: + terraform: + command: tofu # tell Atmos to invoke the OpenTofu binary +``` +```bash +atmos toolchain install +``` + +## Steps + +1. **Read the current pin.** Run `cat .opentofu-version` if the file exists. Otherwise, run + `tofuenv version-name` to find the active version. +2. **Add the version to `.tool-versions`.** Append `opentofu `. Create the file if it + does not exist. +3. **Add the `toolchain:` block to `atmos.yaml`** if the repository does not already have one. + Set `components.terraform.command: tofu`. This makes `atmos terraform` invoke OpenTofu instead + of Terraform (see Before/After above). +4. **Verify the setup.** Run `atmos toolchain install`, then run `atmos toolchain which opentofu`. + Confirm that `atmos terraform plan -s ` uses the expected version. +5. **Promote the version to `dependencies.tools`** on the specific component. Do this if the + version must apply only to that component's execution context, not to the whole repository as + a default. See the "Default Rule" in [atmos-toolchain](../../atmos-toolchain/SKILL.md). +6. **Remove `.opentofu-version` and uninstall tofuenv last.** Do this only after the team + verifies that `atmos terraform` commands resolve the correct version without it. + +## Command Mapping + +| tofuenv command | Atmos toolchain equivalent | +|---|---| +| `tofuenv install 1.10.3` | `atmos toolchain install opentofu@1.10.3` | +| `tofuenv use 1.10.3` | `atmos toolchain set opentofu 1.10.3` | +| `tofuenv version-name` | `atmos toolchain get opentofu` | +| `tofuenv list` (installed versions) | `atmos toolchain list` | +| `tofuenv list-remote` (available versions) | `atmos toolchain search opentofu` | +| `tofuenv uninstall 1.10.3` | `atmos toolchain uninstall opentofu@1.10.3` | + +## Shell Integration + +tofuenv works through shimming. Its installer adds `~/.tofuenv/bin` to `PATH`. It typically does +this with `export PATH="$HOME/.tofuenv/bin:$PATH"` in `~/.bashrc` or `~/.zshrc`. The `tofu` shim +reads the nearest `.opentofu-version` file on every invocation. Plain `tofu` always resolves to +the correct version in any shell. This needs no per-project setup. + +**The Atmos toolchain does not do this by default.** Atmos resolves tools declared in +`.tool-versions` (the project-wide default) or `dependencies.tools` (a scoped override) and injects +them into `PATH` only for the duration of one `atmos ` invocation. Plain `tofu` in your +shell does not pick up the Atmos-managed version unless you opt in to shell integration. This is a +**supported mode**, not a limitation. Use `atmos toolchain env` to export the resolved `PATH` into +your interactive shell: + +**Bash** (add to `~/.bashrc`): +```bash +eval "$(atmos toolchain env --format=bash)" +``` + +**Zsh** (add to `~/.zshrc`): +```zsh +eval "$(atmos toolchain env --format=bash)" +``` +Atmos has no separate `--format=zsh` option. The `bash` format emits plain POSIX +`export PATH=...` syntax. Zsh evaluates this syntax the same way. + +**Fish** (add to `~/.config/fish/config.fish`): +```fish +atmos toolchain env --format=fish | source +``` + +**PowerShell** (add to `$PROFILE`): +```powershell +Invoke-Expression (atmos toolchain env --format powershell | Out-String) +``` + +Verify with `which tofu` (`Get-Command tofu` on PowerShell). The result must point to the Atmos +toolchain install directory, not the tofuenv shim. + +**Important: this is a static snapshot, not tofuenv's dynamic per-directory resolution.** +tofuenv's shim re-reads `.opentofu-version` on every command. Changing directory into a different +project automatically switches versions. `atmos toolchain env` sets the resolved paths for the +*current* directory into `PATH` one time, at eval time. It does not update automatically when you +change directory. Re-run the `eval` line after you switch projects. Or, when you work across +multiple projects, use `atmos terraform ...` instead of bare `tofu`. `atmos terraform ...` always +resolves the version per invocation, regardless of shell state. + +## Functional Gaps + +- **Partial or range-based version selectors have no equivalent today.** tofuenv supports + selectors similar to tfenv's selectors (`latest:^1.9`, `latest:1.10.*`) through + `tofuenv install` arguments. Atmos toolchain version specs support exact versions, `latest`, + `pr:`, `sha:`, and `ref:`. SemVer range constraints (`~> 1.9.0`, + `>= 1.8.0, < 2.0.0`) are documented as **planned, not yet implemented**. If the user relies on + a floating constraint, pin an exact version for now. Tell the user that range support is + planned. + +## Cross-Links + +- [atmos-toolchain SKILL.md](../../atmos-toolchain/SKILL.md): covers `.tool-versions`, + `dependencies.tools`, and version spec syntax. +- [atmos-toolchain commands-reference.md](../../atmos-toolchain/references/commands-reference.md): + full CLI command reference. +- [from-tfenv.md](from-tfenv.md): the same steps, for Terraform. +- [from-tenv.md](from-tenv.md): the same steps, for tenv's multi-tool version files.