<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog</id>
    <title>atmos Blog</title>
    <updated>2026-07-13T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog"/>
    <subtitle>atmos Blog</subtitle>
    <icon>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/img/atmos-logo.png</icon>
    <entry>
        <title type="html"><![CDATA[oci:// Sources Now Work with JIT Auto-Provisioning]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/oci-source-jit-provisioning</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/oci-source-jit-provisioning"/>
        <updated>2026-07-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A component with an oci true failed the moment you ran any Terraform operation against it. JIT auto-provisioning (the before.terraform.init hook) failed with go-getter's download not supported for scheme 'oci', even though atmos vendor pull handled the exact same source fine. Registries distributing modules in OpenTofu's native OCI module-package format couldn't be pulled by either path at all.]]></summary>
        <content type="html"><![CDATA[<p>A component with an <code>oci://</code> source and <code>provision.workdir.enabled: true</code> failed the moment you ran any Terraform operation against it. JIT auto-provisioning (the <code>before.terraform.init</code> hook) failed with go-getter's <code>download not supported for scheme 'oci'</code>, even though <code>atmos vendor pull</code> handled the exact same source fine. Registries distributing modules in OpenTofu's native OCI module-package format couldn't be pulled by either path at all.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-problem">The Problem<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/oci-source-jit-provisioning#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<ul>
<li class="">JIT auto-provisioning and <code>atmos vendor pull</code> had two separate, non-overlapping implementations of "download a source." Only the vendor-pull one understood <code>oci://</code>.</li>
<li class="">Registries publishing modules via OpenTofu's native "install modules from OCI registries" format ship their content as a ZIP-archive layer, not the tar+gzip layer Atmos expected. Pulling one failed with <code>archive/tar: invalid tar header</code> regardless of which path you used.</li>
<li class="">OCI pulls also had no timeout, so a slow or unresponsive registry could hang a command indefinitely.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-fix">The Fix<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/oci-source-jit-provisioning#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<ul>
<li class="">The OCI-fetch implementation moved into a shared <code>pkg/oci</code> package so both <code>atmos vendor pull</code> and JIT auto-provisioning use the same implementation instead of two divergent ones.</li>
<li class="">The puller now recognizes ZIP-layer OCI artifacts (OpenTofu's module-package format) in addition to Atmos's own tar+gzip format, with the same directory-traversal and decompression-size guards either way.</li>
<li class="">OCI pulls are now bounded by a 10-minute timeout, matching the existing go-getter download path.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="how-to-use-it">How to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/oci-source-jit-provisioning#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">terraform</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">my-component</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">source</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">uri</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"oci://ghcr.io/my-org/my-module:v1.2.0"</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">provision</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">workdir</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">          </span><span class="token key atrule">enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span></span><br></div></code></pre></div></div>
<p>Running <code>atmos terraform plan my-component -s &lt;stack&gt;</code> now auto-provisions the source before running, the same way it already does for git and HTTP sources.</p>
<p>Authentication works the same way it already does for <code>atmos vendor pull</code>: your existing registry credentials are picked up automatically, with an anonymous fallback if none are configured.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/oci-source-jit-provisioning#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>See the <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/stacks/components/provision/workdir">Workdir Provisioning</a> docs for the full <code>provision.workdir</code> reference, or open an issue if you hit an OCI registry format that still doesn't extract cleanly.</p>]]></content>
        <author>
            <name>Zack A</name>
            <uri>https://github.com/zack-is-cool</uri>
        </author>
        <category label="Feature" term="Feature"/>
        <category label="Bug Fix" term="Bug Fix"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Bulk `terraform init --all` and `--affected`]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-init-bulk-execution</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-init-bulk-execution"/>
        <updated>2026-07-13T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Bulk commands like terraform apply, plan, and destroy could already run across every component in dependency order with --all, but init couldn't — reinitializing a whole stack meant scripting a loop over components yourself, or falling back to one-at-a-time runs.]]></summary>
        <content type="html"><![CDATA[<p>Bulk commands like <code>terraform apply</code>, <code>plan</code>, and <code>destroy</code> could already run across every component in dependency order with <code>--all</code>, but <code>init</code> couldn't — reinitializing a whole stack meant scripting a loop over components yourself, or falling back to one-at-a-time runs.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-problem">The Problem<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-init-bulk-execution#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<ul>
<li class="">Bulk execution flags <code>--all</code> and <code>--affected</code> landed on <code>apply</code>/<code>plan</code>/<code>destroy</code> when Terraform bulk execution moved onto the scheduler-backed dependency graph, but <code>init</code> was left out.</li>
<li class="">Reinitializing every component after a provider upgrade, or bootstrapping a new environment, meant looping <code>atmos terraform init &lt;component&gt; -s &lt;stack&gt;</code> by hand.</li>
<li class="">The scheduler also capped concurrency to <code>1</code> for any subcommand it didn't explicitly recognize, so there was no way to route around it either.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-fix">The Fix<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-init-bulk-execution#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<ul>
<li class=""><code>terraform init</code> now accepts <code>--all</code>, <code>--affected</code>, <code>--max-concurrency</code>, <code>--failure-mode</code>, and <code>--log-order</code>, matching <code>destroy</code>.</li>
<li class="">Init keeps the natural forward dependency order — prerequisites before dependents — unlike <code>destroy</code>, which reverses the graph.</li>
<li class="">Concurrent bulk init automatically disables the shared provider plugin cache for worker subprocesses, since sharing it isn't safe across concurrent <code>terraform init</code> runs.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="how-to-use-it">How to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-init-bulk-execution#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Initialize every Terraform component, in dependency order</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform init </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--all</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> prod</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Initialize only the affected components</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform init </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--affected</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Run independent components concurrently</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform init </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--all</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> prod --max-concurrency </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Keep going past a failed component instead of stopping</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform init </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--all</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> prod --failure-mode keep-going</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-init-bulk-execution#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Have a bulk-execution flag you'd like to see on another command? Open an issue or join the discussion on <a href="https://github.com/cloudposse/atmos" target="_blank" rel="noopener noreferrer" class="">GitHub</a>.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Feature" term="Feature"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Archive Step Type: Pack Zip/Tar Archives Without Shelling Out]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/archive-step-type</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/archive-step-type"/>
        <updated>2026-07-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Packaging a directory into a deployable archive — most commonly zipping a Lambda]]></summary>
        <content type="html"><![CDATA[<p>Packaging a directory into a deployable archive — most commonly zipping a Lambda
function's source into <code>handler.zip</code> before <code>terraform plan</code>/<code>apply</code> — has always
meant reaching for a shell-based hook that wraps the <code>zip</code>/<code>tar</code> binary. That works
until you actually depend on it: the flags aren't even the same between BSD <code>tar</code>
(macOS) and GNU <code>tar</code> (most Linux CI images), errors surface as opaque shell exit
codes instead of anything typed, and — the part that's easy to miss — the archive you
get back isn't reproducible. Build the exact same source twice and you get two
different files. A new <code>archive</code> step type fixes all three: implemented on the Go
standard library only, it behaves identically everywhere Atmos runs, validates its
config before touching the filesystem, and can now produce byte-identical output for
identical input.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-problem">The Problem<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/archive-step-type#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>This surfaced while migrating a Terragrunt Lambda example (Lambda + DynamoDB + IAM
role) to Atmos. The source unit used a <code>before_hook "package"</code> wrapping
<code>scripts/package.sh</code>, which itself wrapped the <code>zip</code> binary, before every
<code>plan</code>/<code>apply</code>/<code>destroy</code>. Translating that directly meant an equivalent shell-based
hook:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">hooks</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">package</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> command</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> bash</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">args</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(173, 219, 103)">"-c"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"cd src &amp;&amp; zip -r ../handler.zip . -x '*.test.js'"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">before.terraform.plan</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> before.terraform.apply</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> before.terraform.destroy</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span></span><br></div></code></pre></div></div>
<p>Three problems with this, once you look past "it worked when I tested it":</p>
<ul>
<li class=""><strong>The invocation isn't even portable between macOS and Linux</strong>, let alone Windows.
<code>zip -x</code> and <code>tar --exclude</code> take different glob syntax; BSD <code>tar</code> (what macOS
ships) and GNU <code>tar</code> (most Linux CI images) disagree on flags like <code>--exclude</code> vs.
<code>-X excludefile</code>. Two engineers on the same team can get different results running
the "same" hook.</li>
<li class=""><strong>Failures are opaque.</strong> A typo in a glob, a missing source directory — all of it
surfaces as a shell exit code with no structure Atmos can validate ahead of time.</li>
<li class=""><strong>The output isn't reproducible.</strong> Zip and tar both bake in each file's real
modification time and permission bits. A fresh <code>git clone</code> sets every file's mtime
to checkout time, and umask varies across machines and CI images — so identical
source content produces a <em>different archive</em> on every rebuild. This is the same
failure mode Terraform's own <code>archive_file</code> provider has been
<a href="https://github.com/hashicorp/terraform-provider-archive/issues/34" target="_blank" rel="noopener noreferrer" class="">reported for</a>
over the years: two runs, same input, different checksum. Anything downstream that
keys off the archive's hash — Lambda only redeploying when the zip's checksum
changes, a build cache, a provenance check — sees a "change" that isn't one.</li>
</ul>
<p>A <code>data "archive_file"</code> Terraform data source was tried first for the packaging step
itself. It works fine when a config references the data source's own output attribute
directly (<code>output_path</code>, <code>output_base64sha256</code>) — Terraform's graph orders that
correctly. It broke here because the migrated module computed the zip path
independently in a <code>locals</code> block, mirroring the original Terragrunt script's own
variable, instead of referencing the data source's attribute — so there was no
dependency edge forcing <code>archive_file</code> to run first. That's not a one-off: it's a
<a href="https://github.com/hashicorp/terraform/issues/30042" target="_blank" rel="noopener noreferrer" class="">documented class of bug</a>,
closed once the reporter switched to referencing the output attribute directly — the
same fix this migration's module hadn't made. A <code>before.terraform.*</code> hook sidesteps
the whole class of problem
structurally — it runs and completes before Terraform's graph is even evaluated, so
there's no reference to get wrong.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-fix">The Fix<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/archive-step-type#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>The new <code>archive</code> step type packages a directory or file into a <code>zip</code>, <code>tar</code>, or
<code>tgz</code> archive using only Go's standard library — <code>archive/zip</code>, <code>archive/tar</code>,
<code>compress/gzip</code>. No shelling out, so the same config produces the same archive
structure everywhere Atmos runs:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> package</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> archive</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">source</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> src/</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">destination</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> handler.zip</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">exclude</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"**/*.test.js"</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"**/node_modules/**"</span></span><br></div></code></pre></div></div>
<p>It has no dedicated hook kind — like every step type added since
<a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/hooks-step-types"><code>kind: step</code></a> shipped, it reaches hooks through the same
bridge, so it works as a lifecycle hook with zero extra plumbing:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">hooks</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">package</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> step</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> archive</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">before.terraform.plan</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> before.terraform.apply</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> before.terraform.destroy</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">with</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">source</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> src/</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">destination</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> handler.zip</span></span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="how-to-use-it">How to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/archive-step-type#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<ul>
<li class=""><code>source</code> / <code>destination</code> — required. What to archive, and where to write it.</li>
<li class=""><code>format</code> — <code>zip</code>, <code>tar</code>, <code>tgz</code>, <code>tar.bz2</code>, or <code>tar.xz</code>. Inferred from
<code>destination</code>'s extension when omitted (writing <code>tar.bz2</code>/<code>tar.xz</code> isn't
implemented yet — see below).</li>
<li class=""><code>subpath</code> — nests <code>source</code>'s content under a path inside the archive, e.g.
<code>subpath: opt/nodejs</code> for a Lambda Layer.</li>
<li class=""><code>include</code> / <code>exclude</code> — glob filters, evaluated exclude-then-include.</li>
<li class=""><code>action</code> — <code>replace</code> (default) always rebuilds the archive fresh from <code>source</code>.
<code>update</code> adds/refreshes entries in an existing archive without touching the rest —
supported for <code>zip</code> and uncompressed <code>tar</code> only, since <code>tgz</code>/<code>tar.bz2</code>/<code>tar.xz</code>
compress the whole stream as one unit and can't be edited surgically. Selecting
<code>update</code> on one of those formats fails with a clear error instead of silently
falling back to a full rebuild.</li>
</ul>
<p><code>create</code> and <code>extract</code> are reserved in the schema for a future release, so it won't
need a breaking change to add them later.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="reproducible-output">Reproducible Output<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/archive-step-type#reproducible-output" class="hash-link" aria-label="Direct link to Reproducible Output" title="Direct link to Reproducible Output" translate="no">​</a></h2>
<p>A native step type fixes the shelling-out problems, but not the reproducibility one
by itself — by default, entries still carry the source files' real mtime and
permission bits (same as omitting the field, or setting it to <code>filesystem</code>
explicitly). Set <code>mtime: epoch</code> or <code>mtime: git</code> to fix that too:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> package</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> archive</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">source</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> src/</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">destination</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> handler.zip</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">mtime</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> epoch</span></span><br></div></code></pre></div></div>
<p><code>mtime</code> names the mechanism, not an outcome: it's the modification-time metadata
stamped into each <em>archive entry</em> — not the source files on disk, and not the
archive file's own OS-level mtime.</p>
<ul>
<li class=""><code>filesystem</code> — the default. Every entry carries the source file's real mtime and
permission bits.</li>
<li class=""><code>epoch</code> — every entry gets the same timestamp: the most recent Git commit that
touched anything under <code>source</code>. One timestamp, whole archive. Named after the
<a href="https://reproducible-builds.org/docs/source-date-epoch/" target="_blank" rel="noopener noreferrer" class=""><code>SOURCE_DATE_EPOCH</code></a>
reproducible-builds convention, which this mirrors conceptually — one shared
reference timestamp for the whole build — even though the value here comes from
Git history rather than an environment variable.</li>
<li class=""><code>git</code> — each entry gets its own timestamp, from its most recent commit. Files
with no Git history (build output, <code>node_modules/</code>) fall back to the same value
<code>epoch</code> would use.</li>
</ul>
<p><code>epoch</code> and <code>git</code> both also normalize permission bits (<code>0644</code>, or <code>0755</code> if the
source is executable), since inconsistent umask-derived permissions produce different
archive bytes just as reliably as inconsistent timestamps do. Timestamps come from
Git commit history via <code>go-git</code> — no shelling out to <code>git log</code>, and no dependency on
<code>SOURCE_DATE_EPOCH</code> being threaded through every tool in the chain. Outside a Git
repository, both modes fall back to a fixed reference date rather than failing the
step. It's opt-in: existing workflows that don't set <code>mtime</code> see no change in
behavior.</p>
<p><strong><code>action: replace</code> + <code>mtime</code> is idempotent — <code>action: update</code> is not.</strong> With
<code>replace</code>, the same <code>source</code> produces the same bytes on every rerun, because
<code>replace</code> always rebuilds from scratch. <code>update</code> doesn't get that guarantee even with
<code>mtime</code> set: its existing entries keep whatever mtime/mode a prior write already gave
them, and only the entries a given <code>update</code> call adds or refreshes get normalized —
so the final bytes depend on the archive's history, not just <code>source</code>'s current
content. If you need the idempotent guarantee, use <code>replace</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/archive-step-type#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>See the <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/workflows/steps/type/archive">archive step reference</a> for the full field
list, and the <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/stacks/hooks#kind-step-run-a-step-type">hooks reference</a> for using it
as a lifecycle hook. Questions or ideas? Join us in the
<a href="https://cloudposse.com/slack" target="_blank" rel="noopener noreferrer" class="">Cloud Posse community Slack</a>.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Feature" term="Feature"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Fixing Gatekeeper SIGKILLs on Downloaded Toolchain Verifiers]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/macos-toolchain-verifier-trust</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/macos-toolchain-verifier-trust"/>
        <updated>2026-07-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[On macOS, Atmos would sometimes install a verifier CLI (like cosign, used to check signatures on]]></summary>
        <content type="html"><![CDATA[<p>On macOS, Atmos would sometimes install a verifier CLI (like <code>cosign</code>, used to check signatures on
downloaded toolchain binaries) through <code>verifier_install: auto</code>, checksum-verify it successfully — and
then have the OS kill it the instant Atmos tried to run it. Gatekeeper and AMFI re-validate a downloaded
binary's code-signing trust on every execution, not just the first Finder launch, so a checksum match
alone wasn't enough to let a freshly downloaded, ad-hoc-signed release asset actually run.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-fix">The Fix<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/macos-toolchain-verifier-trust#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>After Atmos installs and checksum-verifies a verifier binary, it now strips the macOS quarantine
extended attributes (<code>com.apple.quarantine</code>, <code>com.apple.provenance</code>) and ad-hoc re-signs the binary —
the same trick Homebrew uses for downloaded formula binaries. This only ever runs on binaries Atmos
itself just downloaded into its own bootstrap path; a verifier already found on <code>PATH</code> is user-managed
and already OS-trusted, so it's left untouched. On Linux and Windows, this is a no-op — only macOS
re-validates trust on every exec.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="how-to-use-it">How to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/macos-toolchain-verifier-trust#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<p>This is on by default (<code>verifier_trust: auto</code>) — most users won't need to touch it. To opt out entirely:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">toolchain</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">verification</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">verifier_trust</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> disabled</span></span><br></div></code></pre></div></div>
<p>See the <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/toolchain/verification">toolchain verification docs</a> for the full settings
reference.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/macos-toolchain-verifier-trust#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Questions or feedback? Open an issue on <a href="https://github.com/cloudposse/atmos" target="_blank" rel="noopener noreferrer" class="">GitHub</a> or join the
conversation in our community Slack.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Bug Fix" term="Bug Fix"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Manage MCP Servers Without Hand-Editing YAML]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-server-management-commands</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-server-management-commands"/>
        <updated>2026-07-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Getting Atmos connected to an MCP server, or letting your AI assistant call Atmos's own tools, used to]]></summary>
        <content type="html"><![CDATA[<p>Getting Atmos connected to an MCP server, or letting your AI assistant call Atmos's own tools, used to
mean opening <code>atmos.yaml</code> and hand-writing a <code>mcp.servers</code> entry — then, separately, remembering which
<code>atmos mcp</code> command actually pushes it into Claude Code, Cursor, or VS Code. If all you wanted was
"let my AI assistant use Atmos," there was no single command that got you there.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-fix">The Fix<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-server-management-commands#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p><code>atmos mcp add</code> and <code>atmos mcp remove</code> manage <code>mcp.servers</code> in <code>atmos.yaml</code> directly — no YAML editing
required. Two built-in presets skip the boilerplate entirely: <code>self</code> wires up Atmos's own MCP server, and
<code>atmos-pro</code> wires up the Atmos Pro MCP server. Run <code>atmos mcp add</code> with no arguments at all and it defaults
to <code>atmos mcp add self</code>, so the entire "let my AI assistant use Atmos" flow is one command.</p>
<p>On the other side, <code>atmos mcp uninstall</code> is the mirror image of the existing <code>atmos mcp install</code> — it
removes servers from an AI client's config without touching <code>atmos.yaml</code>. <code>add</code>/<code>remove</code> manage the
declarative source of truth; <code>install</code>/<code>uninstall</code> push and pull it to your client. They compose, but
never step on each other.</p>
<p><code>atmos mcp list</code> and <code>atmos mcp status</code> also now mention these commands directly instead of just saying
"no servers configured," and nudge you to run <code>atmos mcp add atmos-pro</code> if Atmos Pro is already configured
but its MCP server hasn't been added yet.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="how-to-use-it">How to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-server-management-commands#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-bash codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Let your AI assistant use Atmos's own tools -- writes mcp.servers.atmos,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># prompts to enable mcp.enabled if it's off, and installs into detected clients.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos mcp </span><span class="token function" style="color:rgb(130, 170, 255)">add</span><span class="token plain"> self </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--install</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Add the Atmos Pro MCP server.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos mcp </span><span class="token function" style="color:rgb(130, 170, 255)">add</span><span class="token plain"> atmos-pro</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Add an external server -- name and transport are inferred.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos mcp </span><span class="token function" style="color:rgb(130, 170, 255)">add</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"uvx awslabs.aws-documentation-mcp-server@latest"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos mcp </span><span class="token function" style="color:rgb(130, 170, 255)">add</span><span class="token plain"> https://mcp.example.com/mcp </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--header</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"Authorization: Bearer </span><span class="token string variable" style="color:rgb(214, 222, 235)">${TOKEN}</span><span class="token string" style="color:rgb(173, 219, 103)">"</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Remove a server, and uninstall it from wherever it was pushed.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos mcp remove aws-docs</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos mcp uninstall aws-docs</span><br></div></code></pre></div></div>
<p>See the <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/mcp">MCP documentation</a> for the full command reference and built-in preset details.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-server-management-commands#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Questions or feedback? Open an issue on <a href="https://github.com/cloudposse/atmos" target="_blank" rel="noopener noreferrer" class="">GitHub</a> or join the
conversation in our community Slack.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Feature" term="Feature"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[MCP Servers No Longer Need a Second Flag to Do Anything]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-tools-always-available</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-tools-always-available"/>
        <updated>2026-07-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[You set mcp.enabled `failed to initialize AI components:]]></summary>
        <content type="html"><![CDATA[<p>You set <code>mcp.enabled: true</code>, ran <code>atmos mcp start</code>, and got: <code>failed to initialize AI components: tools are disabled</code>. MCP was on. Why did anything else need to be "enabled" for a command whose
entire job is exposing tools?</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-problem">The Problem<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-tools-always-available#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p><code>ai.tools.enabled</code> was designed for <code>atmos ai chat</code>/<code>ask</code>/<code>exec</code> — Atmos's own assistant deciding
whether it's allowed to call tools during a conversation. <code>atmos mcp start</code> reused that same flag
as a hard gate, even though the MCP server has nothing to do with Atmos's own chat loop: its only
job is exposing Atmos tools to <em>external</em> clients like Claude Desktop or Cursor. <code>mcp.enabled: true</code>
was already the explicit, purpose-built opt-in for that — requiring a second, differently-named
flag on top of it just to get a non-empty server was pure friction, not safety.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-fix">The Fix<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-tools-always-available#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p><code>atmos mcp start</code> no longer checks <code>ai.tools.enabled</code> at all. Once <code>mcp.enabled: true</code>, tools
register unconditionally — <code>ai.tools.enabled</code> now only governs <code>atmos ai chat</code>/<code>ask</code>/<code>exec</code>'s own
tool-use loop, which is what it was always meant for.</p>
<p>While in there, we also renamed three related settings for consistency. They're already nested
under <code>tools:</code>, so the <code>_tools</code> suffix was redundant:</p>
<table><thead><tr><th>Old</th><th>New</th></tr></thead><tbody><tr><td><code>tools.allowed_tools</code></td><td><code>tools.allowed</code></td></tr><tr><td><code>tools.restricted_tools</code></td><td><code>tools.restricted</code></td></tr><tr><td><code>tools.blocked_tools</code></td><td><code>tools.blocked</code></td></tr></tbody></table>
<p><code>tools.allowed</code> also picked up a second job. Previously it only skipped the confirmation prompt —
every tool was still registered and callable, just some needed a "yes" first. Now, when non-empty,
it also controls which tools <em>exist</em> at all: unlisted tools aren't registered, aren't visible in
<code>tools/list</code>, and aren't offered to the AI. An empty or unset list still means "everything is
registered, subject to normal confirmation rules" — unchanged.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="how-to-use-it">How to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-tools-always-available#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<div><div class="file"><div class="file-header"><div class="file-title"><svg stroke="currentColor" fill="currentColor" stroke-width="0" role="img" viewBox="0 0 24 24" class="file-type-icon file-type-icon--yaml" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="m0 .97 4.111 6.453v4.09h2.638v-4.09L11.053.969H8.214L5.58 5.125 2.965.969Zm12.093.024-4.47 10.544h2.114l.97-2.345h4.775l.804 2.345h2.26L14.255.994Zm1.133 2.225 1.463 3.87h-3.096zm3.06 9.475v10.29H24v-2.199h-5.454v-8.091zm-12.175.002v10.335h2.217v-7.129l2.32 4.792h1.746l2.4-4.96v7.295h2.127V12.696h-2.904L9.44 17.37l-2.455-4.674Z"></path></svg><span>atmos.yaml</span></div></div><div class="viewport"><div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">mcp</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain" style="display:inline-block"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain"></span><span class="token key atrule">ai</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">tools</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Optional -- omit entirely for a fully-populated MCP server.</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># When set, ONLY these are registered, and they skip confirmation:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">allowed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> atmos_describe_*</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> atmos_list_*</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">blocked</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> execute_bash_command</span></span><br></div></code></pre></div></div></div></div></div>
<div class="language-bash codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-bash codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos mcp start</span><br></div></code></pre></div></div>
<p>No <code>ai.tools.enabled</code> required.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="breaking-change">Breaking Change<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/mcp-tools-always-available#breaking-change" class="hash-link" aria-label="Direct link to Breaking Change" title="Direct link to Breaking Change" translate="no">​</a></h2>
<p><code>tools.allowed_tools</code>, <code>tools.restricted_tools</code>, and <code>tools.blocked_tools</code> are no longer read —
there's no fallback or deprecation warning, just the new names. If your <code>atmos.yaml</code> sets any of
these under <code>ai.tools</code>, rename them before upgrading. If you were relying on <code>allowed_tools</code> to
skip confirmation for a subset of tools <em>while still allowing everything else to run with a
prompt</em>, note the semantics changed: an unlisted tool is no longer registered at all. Move it to
an empty <code>allowed</code> (or drop the list) and lean on <code>restricted</code>/<code>blocked</code> instead.</p>
<p>See <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/ai/tools">AI Tools Configuration</a> for the full reference.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Enhancement" term="Enhancement"/>
        <category label="Breaking Change" term="Breaking Change"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Tags and Labels: a First-Class Way to Categorize and Select Anything in Atmos]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/tags-and-labels</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/tags-and-labels"/>
        <updated>2026-07-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Your stack hierarchy picks one way to organize your infrastructure — org, account, region, component type — and it can only pick one. vpc in stacks/orgs/acme/prod/network.yaml tells you where it lives in that tree; it doesn't tell you it's tier-1, or that platform owns it, or that it's in scope for SOX. Those characteristics don't belong to one branch of the tree — they apply across many stacks and many components at once, and a single component is usually several of them simultaneously. Your AWS accounts and auth identities have the same problem: prod-admin doesn't tell you it's the production one, or the elevated one, until you already know that.]]></summary>
        <content type="html"><![CDATA[<p>Your stack hierarchy picks one way to organize your infrastructure — org, account, region, component type — and it can only pick one. <code>vpc</code> in <code>stacks/orgs/acme/prod/network.yaml</code> tells you where it lives in that tree; it doesn't tell you it's tier-1, or that platform owns it, or that it's in scope for SOX. Those characteristics don't belong to one branch of the tree — they apply across many stacks and many components at once, and a single component is usually several of them simultaneously. Your AWS accounts and auth identities have the same problem: <code>prod-admin</code> doesn't tell you it's the production one, or the elevated one, until you already know that.</p>
<p>Tags and labels give components that organizational context directly — components get both; auth identities and providers get tags — so you can select and act on infrastructure by what it is instead of by where you filed it.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-problem">The Problem<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/tags-and-labels#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>A hierarchy can only organize infrastructure one way, but you need to operate on it along lines that hierarchy doesn't capture:</p>
<ul>
<li class=""><strong>A component's path describes its place in the tree, not what it is.</strong> It tells you the org, account, and region; it says nothing about tier, ownership, or compliance scope — and those apply across stacks and component types, not within one branch.</li>
<li class=""><strong>That context ended up living outside the system instead of on the resource.</strong> A <code>--query</code> expression like <code>.settings.tier == "network"</code> encoded "tier-1" for one command; a hand-maintained <code>--components</code> list encoded it for another. Neither traveled with the component, and both went stale the moment something changed.</li>
<li class=""><strong>The same gap showed up wherever Atmos manages many things.</strong> Components across every type (Terraform, Kubernetes, Helm, containers), plus auth identities and providers, all needed a way to carry their own organizational context instead of relying on someone remembering it.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-fix">The Fix<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/tags-and-labels#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>Atmos now carries that organizational context as metadata, in two shapes:</p>
<ul>
<li class=""><strong>Tags</strong> — a simple list of words, for basic categorical membership. Filtering matches <em>any</em> of the given tags.</li>
<li class=""><strong>Labels</strong> — a set of key-value pairs, for richer metadata. Filtering requires <em>all</em> of the given key=value pairs, the same semantics as a Kubernetes label selector.</li>
</ul>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockTitle_JJ7b">stacks/orgs/acme/prod/network.yaml</div><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">terraform</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">vpc</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">tags</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">production</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> networking</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> tier</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">labels</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">          </span><span class="token key atrule">cost-center</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> platform</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">          </span><span class="token key atrule">compliance</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> sox</span></span><br></div></code></pre></div></div>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockTitle_JJ7b">atmos.yaml</div><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">auth</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">providers</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">sso-prod</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> aws/iam</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">identity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">center</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">start_url</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> https</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">//my</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">org.awsapps.com/start</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">tags</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">production</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> aws</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> sso</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain" style="display:inline-block"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">identities</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">prod-admin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">kind</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> aws/permission</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">set</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">via</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">provider</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> sso</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">prod</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">principal</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> AdministratorAccess</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">account</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> production</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">tags</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">admin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> production</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> elevated</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">access</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span></span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="how-to-use-it">How to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/tags-and-labels#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<p><strong>Listing and filtering components:</strong></p>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos list components </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--tags</span><span class="token plain"> production,tier-1</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos list components </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--labels</span><span class="token plain"> cost-center</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">platform,compliance</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">sox</span><br></div></code></pre></div></div>
<p><strong>Bulk operations</strong> — <code>--tags</code>/<code>--labels</code> compose with <code>--all</code>/<code>--affected</code> everywhere Atmos already supports bulk selection, across every component type:</p>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform apply </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--affected</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--tags</span><span class="token plain"> production</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos kubernetes apply </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--all</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--labels</span><span class="token plain"> cost-center</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">platform</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos helm apply </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--affected</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--tags</span><span class="token plain"> production</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos container up </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--all</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--tags</span><span class="token plain"> production</span><br></div></code></pre></div></div>
<p>Because this lives in the shared component registry (<code>pkg/component</code>), any component type — built-in or custom — that adopts the standard bulk-execution pattern gets <code>--tags</code>/<code>--labels</code> filtering automatically, with no per-type code.</p>
<p><strong>The same filtering works for auth</strong>, since providers and identities are tagged the same way:</p>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos auth list </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--tags</span><span class="token plain"> production</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos auth login </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--tags</span><span class="token plain"> admin,production   </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># auto-selects if exactly one match, else prompts</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos auth </span><span class="token builtin class-name" style="color:rgb(255, 203, 139)">logout</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--tags</span><span class="token plain"> production        </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># logs out every matching provider</span><br></div></code></pre></div></div>
<p><strong>Bridging into your modules</strong> — four new YAML functions read a component's own <code>metadata.tags</code>/<code>metadata.labels</code> without the usual <code>!template</code>/<code>toJson</code> boilerplate: <code>!tags</code> and <code>!labels</code> return the values directly, and <code>!labels.keys</code>/<code>!labels.values</code> return just the label map's keys or values. The most common use is feeding <code>metadata.labels</code> into the <code>var.tags</code> a <code>terraform-null-label</code>-style module expects (Terraform and AWS call a map "tags"; Atmos calls it a "label" — same data, different name):</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockTitle_JJ7b">stacks/orgs/acme/prod/network.yaml</div><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">components</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">terraform</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">vpc</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">metadata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">labels</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">          </span><span class="token key atrule">Namespace</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> eg</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">          </span><span class="token key atrule">Environment</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> prod</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">vars</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">tags</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token tag" style="color:rgb(127, 219, 202)">!labels</span><span class="token plain">   </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># var.tags (map) &lt;- metadata.labels</span></span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/tags-and-labels#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Tags and labels are supported today on components across Terraform, Kubernetes, Helm, and container components; auth identities and providers support tags. Auto-discovering tags/labels from cloud provider metadata (for example, mapping AWS SSO PermissionSet tags into Atmos labels automatically) is a natural next step — if that's something you need, open an issue and let us know your use case.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Feature" term="Feature"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[See what changed before you update a vendored component]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/vendor-diff-and-update</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/vendor-diff-and-update"/>
        <updated>2026-07-09T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Bumping a vendored component to a newer version has always meant guessing. atmos vendor pull]]></summary>
        <content type="html"><![CDATA[<p>Bumping a vendored component to a newer version has always meant guessing. <code>atmos vendor pull</code>
fetches whatever version is pinned — it doesn't tell you a newer one exists, and it definitely
doesn't show you what changed. Finding out meant a manual <code>git clone</code>, a <code>git diff</code> between two
tags, and then hand-editing the <code>version</code> field in <code>vendor.yaml</code> without breaking a comment or a
YAML anchor.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-problem">The Problem<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/vendor-diff-and-update#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Every vendored component in <code>vendor.yaml</code> pins a version, but nothing checked whether a newer one
was available or what it would change. Bumping a version meant three separate manual steps: check
upstream tags yourself, clone the repo somewhere to diff two versions, then edit the <code>version</code>
field by hand — risking a stripped comment or a mangled anchor, since most YAML tools rewrite the
whole file to make one change.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-fix">The Fix<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/vendor-diff-and-update#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>Two new commands close that loop, both built on Atmos's format-preserving <code>pkg/yaml</code> engine (the
same one behind <code>atmos config|stack|vendor get|set|delete</code>):</p>
<ul>
<li class=""><strong><code>atmos vendor update</code></strong> checks every Git-backed source in <code>vendor.yaml</code> for a newer version —
honoring each source's <code>constraints</code> (semver range, excluded versions, <code>no_prereleases</code>) — and
writes the new <code>version</code> in place, preserving comments, anchors, and <code>{{.Version}}</code> templates.
<code>--check</code> previews updates without writing anything; <code>--pull</code> runs <code>atmos vendor pull</code>
immediately after.</li>
<li class=""><strong><code>atmos vendor diff</code></strong> shows the Git diff between two versions (tags, branches, or commits) of a
component, with no local checkout — it clones to a temp directory and cleans up after itself.</li>
</ul>
<p>Both commands also work for components vendored purely through a per-component <code>component.yaml</code>
instead of a repo-level <code>vendor.yaml</code>, falling back to it the same way <code>atmos vendor pull</code> already
does (<code>vendor.yaml</code> wins if it declares the component). A repo with no <code>vendor.yaml</code> at all gets
this for free; <code>--component-manifests</code> runs the same sweep alongside an existing <code>vendor.yaml</code> for
repos that mix both styles, and <code>component.yaml</code> sources can declare their own <code>constraints</code>,
matching <code>vendor.yaml</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="how-to-use-it">How to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/vendor-diff-and-update#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Dry run: show what would update, without touching any files.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos vendor update </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--check</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Update one component, or everything tagged 'networking'.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos vendor update </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--component</span><span class="token plain"> vpc</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos vendor update </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--tags</span><span class="token plain"> networking</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Update and immediately pull the new versions.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos vendor update </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--pull</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Diff the current pinned version against the latest tag.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos vendor </span><span class="token function" style="color:rgb(130, 170, 255)">diff</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--component</span><span class="token plain"> vpc</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Diff two specific versions, restricted to one file.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos vendor </span><span class="token function" style="color:rgb(130, 170, 255)">diff</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-c</span><span class="token plain"> vpc </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--from</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1.0</span><span class="token plain">.0 </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--to</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">2.0</span><span class="token plain">.0 --diff-file variables.tf</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># Works with component.yaml-only vendoring too — no vendor.yaml required.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos vendor update </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--component</span><span class="token plain"> vpc </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--check</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos vendor </span><span class="token function" style="color:rgb(130, 170, 255)">diff</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--component</span><span class="token plain"> vpc </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--type</span><span class="token plain"> helmfile</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="also-fixed-vendorbase_path-and---chdir">Also Fixed: <code>vendor.base_path</code> and <code>--chdir</code><a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/vendor-diff-and-update#also-fixed-vendorbase_path-and---chdir" class="hash-link" aria-label="Direct link to also-fixed-vendorbase_path-and---chdir" title="Direct link to also-fixed-vendorbase_path-and---chdir" translate="no">​</a></h2>
<p><code>atmos --chdir=&lt;dir&gt; vendor update --check</code> (and <code>diff</code>/<code>get</code>/<code>set</code>) failed with "No vendor.yaml
found in the current directory" whenever <code>&lt;dir&gt;</code>'s <code>atmos.yaml</code> configured <code>vendor.base_path</code> to
anything other than a literal <code>./vendor.yaml</code> — common in <code>infra-live</code>-style repos. Vendor-wide
discovery only checked the process's working directory and ignored <code>atmos.yaml</code> entirely. All four
commands now resolve <code>vendor.base_path</code> (and <code>ATMOS_VENDOR_BASE_PATH</code>) the same way <code>atmos vendor pull</code> already does.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/vendor-diff-and-update#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>See the <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/vendor/vendor-diff"><code>vendor diff</code></a> and
<a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/vendor/vendor-update"><code>vendor update</code></a> docs for the full flag reference, or open an
issue if you hit a vendoring setup this doesn't cover yet.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Feature" term="Feature"/>
        <category label="DX" term="DX"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Interactive Workflow & Command Steps Now Run in CI]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/interactive-steps-ci-defaults</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/interactive-steps-ci-defaults"/>
        <updated>2026-07-08T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[You built a slick interactive workflow — choose an account, input a release tag, then deploy. It is perfect on your laptop. Then CI runs it and everything stops with interactive terminal required for step. The prompts that make the workflow friendly locally are exactly what make it unrunnable in a pipeline, so you end up maintaining a second, prompt-free copy just for CI.]]></summary>
        <content type="html"><![CDATA[<p>You built a slick interactive workflow — <code>choose</code> an account, <code>input</code> a release tag, then deploy. It is perfect on your laptop. Then CI runs it and everything stops with <code>interactive terminal required for step</code>. The prompts that make the workflow friendly locally are exactly what make it unrunnable in a pipeline, so you end up maintaining a second, prompt-free copy just for CI.</p>
<p>Interactive steps now fall back to their <code>default</code> value when there is no TTY, so the <em>same</em> workflow runs unattended in CI — no duplicate variant required.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-problem">The Problem<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/interactive-steps-ci-defaults#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Interactive step types (<code>choose</code>, <code>input</code>, <code>confirm</code>, <code>filter</code>, <code>file</code>, <code>write</code>) need a terminal to prompt you. In CI there is no TTY, so every one of them failed hard with <code>interactive terminal required for step</code>. The usual workaround was to fork your automation: an interactive version for humans and a flag-driven version for pipelines.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-fix">The Fix<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/interactive-steps-ci-defaults#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>When an interactive step has a <code>default</code> and there is no TTY, Atmos now uses that default instead of erroring. With a TTY it still prompts (using the default as the pre-selected value). Without a default, the existing error stands — so you never silently deploy an unintended value.</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">workflows</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">build-manifests</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> account</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> choose</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">prompt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"Account"</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">options</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">dev</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> prod</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token tag" style="color:rgb(127, 219, 202)">!env</span><span class="token plain"> STACK_ACCOUNT dev</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> tag</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> input</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">prompt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"Release tag"</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">default</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token tag" style="color:rgb(127, 219, 202)">!env</span><span class="token plain"> RELEASE_TAG latest</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> shell</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> atmos kube build "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> .steps.account.value </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">/tao" </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">tag "</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> .steps.tag.value </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain">"</span></span><br></div></code></pre></div></div>
<p>Locally, this prompts. In CI, it reads <code>STACK_ACCOUNT</code> / <code>RELEASE_TAG</code> (falling back to <code>dev</code> / <code>latest</code>), then runs the shell step with the captured values.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="dynamic-defaults-from-the-environment">Dynamic Defaults from the Environment<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/interactive-steps-ci-defaults#dynamic-defaults-from-the-environment" class="hash-link" aria-label="Direct link to Dynamic Defaults from the Environment" title="Direct link to Dynamic Defaults from the Environment" translate="no">​</a></h2>
<p>Defaults can come from the environment with the <code>!env</code> function (<code>!env VAR fallback</code>) in a workflow step's <code>default</code>, <code>prompt</code>, <code>options</code>, and <code>placeholder</code>. <code>!exec</code> is supported too. Custom commands defined in <code>atmos.yaml</code> already resolved <code>!env</code>; workflows now do as well.</p>
<p>Consuming those captured values in later <code>shell</code>/<code>atmos</code> steps (<code>{{ .steps.&lt;name&gt;.value }}</code>) works thanks to a companion fix that brought workflow command templating to parity with custom command steps.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="how-to-use-it">How to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/interactive-steps-ci-defaults#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<ul>
<li class="">Give each interactive step a <code>default</code> so it can run unattended.</li>
<li class="">Use <code>!env VAR fallback</code> to pull that default from the environment in CI.</li>
<li class="">Leave <code>default</code> off when a human must choose — the step still errors in CI, by design.</li>
</ul>
<p>The behavior is automatic based on TTY detection; there is no new flag to set. It applies to both workflows and custom commands, which share the same step engine.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/interactive-steps-ci-defaults#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Try converting one of your prompt-driven workflows to run in CI by adding <code>default</code> values, and let us know how it goes in <a href="https://github.com/cloudposse/atmos/discussions" target="_blank" rel="noopener noreferrer" class="">GitHub Discussions</a>.</p>]]></content>
        <author>
            <name>Brian Ojeda</name>
            <uri>https://github.com/sgtoj</uri>
        </author>
        <category label="Feature" term="Feature"/>
        <category label="DX" term="DX"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Record and Render Terminal Sessions with Atmos Cast]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/cast-record-render</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/cast-record-render"/>
        <updated>2026-07-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Atmos can now record terminal sessions as asciicast files and render them into]]></summary>
        <content type="html"><![CDATA[<p>Atmos can now record terminal sessions as asciicast files and render them into
shareable formats for documentation, demos, and CI artifacts.</p>
<div class="language-bash codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-bash codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos cast render demo.cast </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--output</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">demo.gif</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos cast render demo.cast </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--output</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">demo.html</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos cast render demo.cast </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--output</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">demo.out </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--format</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">html</span><br></div></code></pre></div></div>
<p>The <code>render</code> command turns a recording into a rendered artifact — here it's converted straight to a GIF:</p>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos cast render</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<p>Replaying a recording in the terminal with <code>play</code> reproduces it exactly as it was captured:</p>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos cast play</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<p>And any command can capture its own session as it runs with <code>--cast</code>, no separate recording step required:</p>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">record a cast with --cast</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="what-changed">What Changed<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/cast-record-render#what-changed" class="hash-link" aria-label="Direct link to What Changed" title="Direct link to What Changed" translate="no">​</a></h2>
<p>The <code>atmos cast</code> command now has a render interface built around <code>--output</code> and
<code>--format</code>. Atmos infers the format from common output extensions such as
<code>.gif</code>, <code>.mp4</code>, <code>.html</code>, <code>.ascii</code>, <code>.png</code>, <code>.jpg</code>, and <code>.jpeg</code>, while
<code>--format</code> handles custom output filenames.</p>
<p>The same recording and rendering engine is also available to workflow and custom
command steps. That means a runbook can capture the exact terminal session it
executes, then turn the recording into an artifact without a separate wrapper
script.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="workflow-friendly-captures">Workflow-Friendly Captures<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/cast-record-render#workflow-friendly-captures" class="hash-link" aria-label="Direct link to Workflow-Friendly Captures" title="Direct link to Workflow-Friendly Captures" translate="no">​</a></h2>
<p>Cast support is designed for repeatable automation:</p>
<ul>
<li class="">Terminal output is recorded through the shared Atmos execution paths.</li>
<li class="">Final terminal state can be rendered as static text, HTML, or images.</li>
<li class="">Animated outputs are available for demos and walkthroughs.</li>
<li class="">Render options are explicit, so CI and local commands use the same interface.</li>
</ul>
<p>This is useful when a workflow needs to publish a proof-of-run artifact, attach a
terminal demo to documentation, or keep a reproducible recording of an
interactive command.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="why-it-matters">Why It Matters<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/cast-record-render#why-it-matters" class="hash-link" aria-label="Direct link to Why It Matters" title="Direct link to Why It Matters" translate="no">​</a></h2>
<p>Teams often rely on external tools and custom shell scripts to capture terminal
demos. Bringing cast recording and rendering into Atmos makes those captures part
of the same command and workflow system that runs the work.</p>
<p>The result is easier to automate, easier to review, and easier to reproduce.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Feature" term="Feature"/>
        <category label="DX" term="DX"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Topic-Specific CLI Help]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/topic-specific-cli-help</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/topic-specific-cli-help"/>
        <updated>2026-07-06T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Atmos help showed too much at once. A simple command like atmos terraform plan --help explained the command, its examples, its own flags, compatibility flags, and every inherited global flag, which made the options you actually needed harder to find.]]></summary>
        <content type="html"><![CDATA[<p>Atmos help showed too much at once. A simple command like <code>atmos terraform plan --help</code> explained the command, its examples, its own flags, compatibility flags, and every inherited global flag, which made the options you actually needed harder to find.</p>
<p>Topic-specific help fixes that by making default help focused, while keeping usage examples, command flags, and the full reference one flag away.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="what-changed">What Changed<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/topic-specific-cli-help#what-changed" class="hash-link" aria-label="Direct link to What Changed" title="Direct link to What Changed" translate="no">​</a></h2>
<p>Default <code>--help</code> now shows the command description, usage, examples, subcommands, and flags for that command. Atmos no longer dumps every inherited global flag by default, so command-specific options stay visible.</p>
<p>When you need a narrower or broader view, use a help topic:</p>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform plan </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--help</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">usage</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform plan </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--help</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">flags</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform plan </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--help</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">all</span><br></div></code></pre></div></div>
<p><code>--help=usage</code> shows just usage and examples. <code>--help=flags</code> shows command-specific flags, plus compatibility flags when Atmos forwards options to a native tool. <code>--help=all</code> restores the full reference view, including global flags.</p>
<p>Every default help page includes a short reminder:</p>
<div class="language-text codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-text codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">Use --help=usage for examples or --help=all for all flags and full help.</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="why-it-matters">Why It Matters<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/topic-specific-cli-help#why-it-matters" class="hash-link" aria-label="Direct link to Why It Matters" title="Direct link to Why It Matters" translate="no">​</a></h2>
<ul>
<li class=""><strong>Less noise by default.</strong> Atmos still exposes global flags, but they no longer bury the flags that actually change the command you are reading about.</li>
<li class=""><strong>Examples are one command away.</strong> Atmos already maintains usage snippets in markdown help files, and those snippets now have their own focused view.</li>
<li class=""><strong>Full reference stays available.</strong> <code>--help=all</code> keeps the exhaustive output available for scripting, documentation, and deep inspection.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="try-it">Try It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/topic-specific-cli-help#try-it" class="hash-link" aria-label="Direct link to Try It" title="Direct link to Try It" translate="no">​</a></h2>
<p>Compare the focused and full views:</p>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform plan </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--help</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform plan </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--help</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">all</span><br></div></code></pre></div></div>
<p>Use <code>--help=usage</code> when you only need examples, and <code>--help=flags</code> when you are checking command-specific options.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Enhancement" term="Enhancement"/>
        <category label="DX" term="DX"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[One Catalog for Every Version Pin: the Atmos Version Tracker]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-version-tracker</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-version-tracker"/>
        <updated>2026-07-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Your infrastructure's versions live everywhere except one place. actions/checkout@v4 in a dozen workflow files, TOFU_VERSION=1.9.0 in a Dockerfile, nginx a catalog in atmos.yaml, a deterministic lock file, policy-driven updates, and file managers that rewrite your workflows, Dockerfiles, and rendered files from the lock.]]></summary>
        <content type="html"><![CDATA[<p>Your infrastructure's versions live everywhere except one place. <code>actions/checkout@v4</code> in a dozen workflow files, <code>TOFU_VERSION=1.9.0</code> in a Dockerfile, <code>nginx:1.27</code> in a stack, <code>kubectl</code> wherever your bootstrap script says. When a version needs to move, you grep and hope. When it shouldn't move, nothing enforces that either — and every unpinned mutable tag is a supply-chain incident waiting for its moment. The Atmos Version Tracker gives all of those versions a single source of truth: a catalog in <code>atmos.yaml</code>, a deterministic lock file, policy-driven updates, and file managers that rewrite your workflows, Dockerfiles, and rendered files from the lock.</p>
<p>Here's the same idea applied to vendored component versions:</p>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos component version vendoring</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<p><a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/examples/demo-component-versions">View the full example</a></p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-problem">The Problem<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-version-tracker#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Version pins are configuration, but nobody manages them like configuration:</p>
<ul>
<li class=""><strong>No source of truth.</strong> The same tool version is repeated across workflow YAML, Dockerfiles, stack manifests, and CI scripts. Environments drift silently because there is nothing to drift <em>from</em>.</li>
<li class=""><strong>Bolt-on updaters don't understand your stacks.</strong> Renovate and Dependabot see files, not Atmos configuration. They can't resolve a version into a stack, don't know your tracks or environments, and produce PR noise you tune with regex managers instead of policy.</li>
<li class=""><strong>Mutable tags are a supply-chain risk.</strong> <code>actions/checkout@v4</code> and <code>nginx:latest</code> can change underneath you. Pinning to SHAs by hand is the fix everyone agrees on and nobody keeps up with.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-fix">The Fix<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-version-tracker#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>The Atmos Version Tracker makes external versions first-class Atmos configuration. You declare a catalog under <code>version:</code> in <code>atmos.yaml</code>; Atmos owns resolution, locking, policy, and file rewriting:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockTitle_JJ7b">atmos.yaml</div><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">version</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">track</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> prod</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain" style="display:inline-block"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">dependencies</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">checkout</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">ecosystem</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> github</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">actions</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">package</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> actions/checkout</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">desired</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> v6</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">update</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">pin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> sha        </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># lock and render the immutable commit SHA</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain" style="display:inline-block"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">opentofu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">ecosystem</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> toolchain</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">package</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> opentofu</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">desired</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"~1.10"</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain" style="display:inline-block"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">nginx</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">ecosystem</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> oci</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">package</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> library/nginx</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">desired</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"1.29.0"</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain" style="display:inline-block"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">tracks</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">prod</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">dependencies</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">nginx</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">          </span><span class="token key atrule">desired</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"1.29.1"</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain" style="display:inline-block"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">files</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">manager</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> github</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">actions</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">paths</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">.github/workflows/</span><span class="token important">*.yaml</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">manager</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> marker</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">paths</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">Dockerfile</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">manager</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> template</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token key atrule">paths</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(173, 219, 103)">"**/*.tmpl"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span></span><br></div></code></pre></div></div>
<p>Resolved versions land in a committed <code>versions.lock.yaml</code>, so local runs and CI are deterministic. Updates are policy-driven — strategy caps (<code>major</code>/<code>minor</code>/<code>patch</code>), cooldown windows (<code>14d</code>, <code>2w</code>), include/exclude rules, and prerelease policy — and every version held back by policy is reported with the reason instead of silently skipped:</p>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos version track update</span><br></div></code></pre></div></div>
<p>In an interactive terminal this renders as a styled table. Use <code>--format=csv</code> or
<code>--format=tsv</code> for delimited output; piped table output remains a table:</p>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">Track,Name,From,To,Updated,Reason</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">prod,checkout,v6.1.0,v6.2.0,true,</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">prod,nginx,1.29.0,,false,</span><span class="token string" style="color:rgb(173, 219, 103)">"1.30.0 released 3d ago; cooldown 14d has not elapsed"</span><br></div></code></pre></div></div>
<p>File managers then rewrite your actual project files from the lock. Pinned entries get the immutable SHA with the human-readable version as a trailing comment — the same round-trip convention Renovate and Dependabot use:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockTitle_JJ7b">.github/workflows/ci.yaml</div><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> actions/checkout@8edcb1bdb4e267140fa742c62e395cd74f332709 </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># v6.1.0</span><br></div></code></pre></div></div>
<p>Any text file with comments can carry a managed version via a marker annotation:</p>
<div class="language-dockerfile codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockTitle_JJ7b">Dockerfile</div><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># atmos:version opentofu</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain"></span><span class="token instruction keyword" style="color:rgb(127, 219, 202)">ENV</span><span class="token instruction"> TOFU_VERSION=1.10.6</span></span><br></div></code></pre></div></div>
<p>And comment-hostile formats (like JSON) render from <code>*.tmpl</code> templates with the <code>.version</code> context. In stacks, <code>!version name</code> and <code>{{ .version.name }}</code> resolve from the lock, so versions stop being copy-pasted into stack manifests at all.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="how-to-use-it">How to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-version-tracker#how-to-use-it" class="hash-link" aria-label="Direct link to How to Use It" title="Direct link to How to Use It" translate="no">​</a></h2>
<p>Add an entry (the ecosystem is inferred from the package), lock, and apply:</p>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos version track </span><span class="token function" style="color:rgb(130, 170, 255)">add</span><span class="token plain"> checkout </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--package</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">actions/checkout </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--pin</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">sha</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos version track lock      </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># resolve desired versions into versions.lock.yaml</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos version track apply     </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># rewrite managed files from the lock</span><br></div></code></pre></div></div>
<p>Then gate CI on the whole thing staying honest:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockTitle_JJ7b">.github/workflows/version-check.yaml</div><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">uses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> actions/checkout@v6</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> atmos version track apply </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">check   </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># fail if any managed file is stale</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">run</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> atmos version track verify          </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># lock fresh AND files current</span></span><br></div></code></pre></div></div>
<p><code>atmos version track status</code> shows where you stand at any time — including <code>newer-available (blocked)</code> when a newer version exists upstream but your cooldown or strategy is deliberately holding it back. That's a passing state, not a failure: the locked version is exactly what your policy wants deployed.</p>
<p>See the <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/version/track"><code>atmos version track</code> command reference</a> and <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/version/managed-versions">Managed Versions configuration</a> for the full surface, or try the runnable <a href="https://github.com/cloudposse/atmos/tree/main/examples/version-tracker" target="_blank" rel="noopener noreferrer" class=""><code>examples/version-tracker</code></a> example.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-version-tracker#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>If you've been stitching together Renovate configs to approximate this, we'd love to hear which datasources and ecosystems you need next. Open a discussion or issue in the <a href="https://github.com/cloudposse/atmos" target="_blank" rel="noopener noreferrer" class="">Atmos repo</a>, or join us in the <a href="https://cloudposse.com/slack" target="_blank" rel="noopener noreferrer" class="">Cloud Posse Slack</a>.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Feature" term="Feature"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Unsupported YAML Function Validation]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/unsupported-yaml-function-validation</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/unsupported-yaml-function-validation"/>
        <updated>2026-07-04T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Atmos now detects unsupported and misspelled YAML function tags before configuration]]></summary>
        <content type="html"><![CDATA[<p>Atmos now detects unsupported and misspelled YAML function tags before configuration
processing continues. Invalid tags return a clear error with the supported Atmos YAML
functions, so typos fail fast instead of being silently treated as ordinary YAML.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="what-changed">What Changed<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/unsupported-yaml-function-validation#what-changed" class="hash-link" aria-label="Direct link to What Changed" title="Direct link to What Changed" translate="no">​</a></h2>
<p>Atmos validates explicit custom YAML tags during <code>atmos.yaml</code> and stack manifest
processing. If a tag is not one of the supported Atmos YAML functions, Atmos returns an
unsupported tag error that includes the valid options.</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">vars</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">home</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token tag" style="color:rgb(127, 219, 202)">!envv</span><span class="token plain"> HOME</span></span><br></div></code></pre></div></div>
<p>Instead of quietly accepting the misspelled <code>!envv</code> tag, Atmos reports that the tag is
unsupported and points users toward valid functions like <code>!env</code>, <code>!exec</code>, <code>!include</code>, and
the other supported YAML tags.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="exact-matching">Exact Matching<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/unsupported-yaml-function-validation#exact-matching" class="hash-link" aria-label="Direct link to Exact Matching" title="Direct link to Exact Matching" translate="no">​</a></h2>
<p>Validation uses exact tag matching. A misspelled function such as <code>!envv</code> no longer
matches the supported <code>!env</code> prefix, which prevents typos from slipping through parser
or resolver paths that previously checked only the beginning of a tag.</p>
<p>Standard YAML tags such as <code>!!str</code> continue to work normally.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="why-it-matters">Why It Matters<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/unsupported-yaml-function-validation#why-it-matters" class="hash-link" aria-label="Direct link to Why It Matters" title="Direct link to Why It Matters" translate="no">​</a></h2>
<p>YAML functions are often used for dynamic values: environment variables, Terraform
outputs, secrets, Git metadata, and included files. A misspelled tag can otherwise hide
until much later in a deployment workflow, where the failure is harder to connect to the
original configuration.</p>
<p>Failing at parse or processing time makes the error immediate and actionable.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-started">Get Started<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/unsupported-yaml-function-validation#get-started" class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started" translate="no">​</a></h2>
<p>No configuration is required. Use the documented <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml">Atmos YAML functions</a>
as usual, and Atmos will report unsupported tags when it finds them.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Feature" term="Feature"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Atmos Now Builds Atmos]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-builds-atmos</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-builds-atmos"/>
        <updated>2026-07-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Atmos now builds itself through a first-class Atmos command:]]></summary>
        <content type="html"><![CDATA[<p>Atmos now builds itself through a first-class Atmos command:</p>
<div class="language-bash codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-bash codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos build </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--target</span><span class="token plain"> linux</span><br></div></code></pre></div></div>
<p>We replaced the old Make-based build and CI entrypoints with Atmos custom commands to improve the developer experience and dogfood our own workflow engine. Build and test workflows now expose the flags developers actually care about, such as the target platform, while Atmos owns the shell details, cross-compilation wiring, output paths, and CI glue behind the command.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="what-changed">What Changed<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-builds-atmos#what-changed" class="hash-link" aria-label="Direct link to What Changed" title="Direct link to What Changed" translate="no">​</a></h2>
<p>The repository's development commands now live in <code>.atmos.d/</code> command groups instead of Make targets. The root <code>atmos.yaml</code> stays focused on project configuration, while the command surface is split by concern:</p>
<ul>
<li class=""><code>atmos build ...</code> for dependencies, binaries, versions, and docs generation.</li>
<li class=""><code>atmos test</code> plus mode flags for short, acceptance, coverage, and race-test workflows.</li>
<li class=""><code>atmos lint ...</code> for changed-file linting, custom lintroller rules, go.mod checks, and link checks.</li>
<li class=""><code>atmos check ...</code>, <code>atmos format ...</code>, and <code>atmos cache ...</code> for repository maintenance workflows.</li>
<li class=""><code>atmos screengrabs ...</code> for website screengrab generation.</li>
</ul>
<p>Makefiles remain only as migration guards. If someone runs an old target, the Makefile exits and points them to the Atmos command that replaced it.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="a-cleaner-command-surface">A Cleaner Command Surface<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-builds-atmos#a-cleaner-command-surface" class="hash-link" aria-label="Direct link to A Cleaner Command Surface" title="Direct link to A Cleaner Command Surface" translate="no">​</a></h2>
<p>The result is intentionally plain. The repository now has command groups that read like the workflows contributors actually run:</p>
<div class="language-bash codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-bash codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos build deps</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos build </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--target</span><span class="token plain"> linux</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos </span><span class="token builtin class-name" style="color:rgb(255, 203, 139)">test</span><span class="token plain"> acceptance </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--cover</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos lint </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--changed</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos screengrabs all</span><br></div></code></pre></div></div>
<p>This keeps the developer contract narrow. The command can grow flags like <code>--target</code> without forcing every contributor or CI job to understand the lower-level build minutia. Atmos handles the parsing, defaults, and orchestration once, and every caller gets the same behavior.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="why-it-matters">Why It Matters<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-builds-atmos#why-it-matters" class="hash-link" aria-label="Direct link to Why It Matters" title="Direct link to Why It Matters" translate="no">​</a></h2>
<p>This is dogfooding in the useful sense: Atmos exercises its own custom command engine for the daily loops that maintain Atmos. That gives contributors one command vocabulary locally and in CI, and it gives us immediate feedback when custom commands need to become better.</p>
<p>It also removes a layer. CI now calls grouped Atmos commands such as <code>atmos build deps</code>, <code>atmos build --target linux</code>, and <code>atmos test acceptance --cover</code>. The screengrab workflow calls <code>atmos screengrabs all</code>. The install script has its own Linux, macOS, and Windows smoke test, so the installer path gets exercised directly too.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="try-the-pattern">Try the Pattern<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-builds-atmos#try-the-pattern" class="hash-link" aria-label="Direct link to Try the Pattern" title="Direct link to Try the Pattern" translate="no">​</a></h2>
<p>If you are maintaining a repo with an aging Makefile, <code>.atmos.d/</code> is a good place to split the command surface by concern. Keep project configuration in <code>atmos.yaml</code>; keep operational commands in grouped files such as <code>.atmos.d/build.yaml</code>, <code>.atmos.d/test.yaml</code>, and <code>.atmos.d/lint.yaml</code>.</p>
<p>For the general command schema, see the <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/commands">custom commands documentation</a>. For a smaller standalone example, browse the <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/examples/custom-commands">custom commands example</a>.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="DX" term="DX"/>
        <category label="Core" term="Core"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Clearer Help Sections and Error Explanations]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/help-command-groups-error-formatting</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/help-command-groups-error-formatting"/>
        <updated>2026-07-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Atmos help output now separates built-in commands from custom commands, and error output now makes explanations easier to scan without adding extra headings.]]></summary>
        <content type="html"><![CDATA[<p>Atmos help output now separates built-in commands from custom commands, and error output now makes explanations easier to scan without adding extra headings.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="what-changed">What Changed<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/help-command-groups-error-formatting#what-changed" class="hash-link" aria-label="Direct link to What Changed" title="Direct link to What Changed" translate="no">​</a></h2>
<p>Command help now groups native Atmos commands under <strong>BUILT-IN COMMANDS</strong> and commands defined in <code>atmos.yaml</code> under <strong>CUSTOM COMMANDS</strong>. Teams with project-specific runbooks can now see what Atmos provides out of the box and what their repository adds locally.</p>
<p>Error formatting also got cleaner. Explanations render as a styled callout when color is enabled, while hints stay as direct, actionable lines. The formatter reserves room for callout padding before wrapping text, so long explanations stay aligned instead of reflowing inside the box.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="why-it-matters">Why It Matters<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/help-command-groups-error-formatting#why-it-matters" class="hash-link" aria-label="Direct link to Why It Matters" title="Direct link to Why It Matters" translate="no">​</a></h2>
<ul>
<li class=""><strong>Faster command discovery.</strong> Built-in commands and custom shortcuts no longer compete in one flat list.</li>
<li class=""><strong>Cleaner troubleshooting.</strong> Error explanations are visually distinct from hints without adding extra section headers.</li>
<li class=""><strong>More consistent output.</strong> Snapshot comparisons and stderr formatting now preserve intentional whitespace unless a test opts into trailing-whitespace tolerance.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/help-command-groups-error-formatting#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Run <code>atmos --help</code> or any command-specific <code>--help</code> page in a repository with custom commands to see the new grouping.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Enhancement" term="Enhancement"/>
        <category label="DX" term="DX"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Native Container Image Summaries in CI]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-container-image-ci-summaries</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-container-image-ci-summaries"/>
        <updated>2026-07-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Atmos container builds and pushes now write rich image summaries directly to the CI job summary when]]></summary>
        <content type="html"><![CDATA[<p>Atmos container builds and pushes now write rich image summaries directly to the CI job summary when
native CI is enabled. Use <code>type: container</code> workflow steps or <code>atmos container build/push</code> component
commands and GitHub Actions gets a readable image report without adding a separate Docker summary
action.</p>
<p>The summary includes the image reference, digest, image ID, OCI metadata, runtime configuration,
environment variables, labels, layer digests, and the formatted raw inspect JSON. Push summaries use
the pushed digest when the registry returns one, so reviewers can see the canonical artifact that was
published.</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">ci</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">summary</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span></span><br></div></code></pre></div></div>
<p>Summaries are best-effort. A successful build or push is not failed just because image inspection or
job-summary writing is unavailable. When <code>ci.summary.enabled: false</code> is set, Atmos skips the image
summary entirely.</p>
<p>This keeps native Atmos container pipelines self-contained: build, push, and review the image metadata
from the same workflow or component command you already run locally.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Feature" term="Feature"/>
        <category label="ci" term="ci"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Path-Based Custom Commands]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/path-based-custom-commands</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/path-based-custom-commands"/>
        <updated>2026-07-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Atmos custom commands now support path-based names. Instead of writing a deeply nested command tree just to describe a command path, you can put the full command path in name.]]></summary>
        <content type="html"><![CDATA[<p>Atmos custom commands now support path-based names. Instead of writing a deeply nested command tree just to describe a command path, you can put the full command path in <code>name</code>.</p>
<p>The result is easier to read, easier to review, and keeps the same recursive merge behavior that existing custom commands rely on.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="what-changed">What Changed<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/path-based-custom-commands#what-changed" class="hash-link" aria-label="Direct link to What Changed" title="Direct link to What Changed" translate="no">​</a></h2>
<p>Before, command hierarchies had to be expressed as nested <code>commands</code> arrays:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> casts</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> generate</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> examples</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">            </span><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> custom</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">commands</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">                </span><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">                  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> hello</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">greet</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">                    </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Regenerate the Custom Commands example cast</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">                    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">                      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> shell</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">                        </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> atmos casts setup</span></span><br></div></code></pre></div></div>
<p>That shape is programmatically consistent, but it is not very friendly when the nesting only exists to spell out the command path.</p>
<p>Now you can write the same command as:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> casts generate examples custom</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">commands hello</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">greet</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Regenerate the Custom Commands example cast</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">steps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">type</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> shell</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">command</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> atmos casts setup</span></span><br></div></code></pre></div></div>
<p>Atmos expands the path-based name into the normal recursive command tree before merging configuration.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="merge-behavior-is-preserved">Merge Behavior Is Preserved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/path-based-custom-commands#merge-behavior-is-preserved" class="hash-link" aria-label="Direct link to Merge Behavior Is Preserved" title="Direct link to Merge Behavior Is Preserved" translate="no">​</a></h2>
<p>This is syntax sugar, not a new command model. A command named <code>casts generate demo</code> is normalized to the same internal structure as:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> casts</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> generate</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">        </span><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> demo</span></span><br></div></code></pre></div></div>
<p>Because normalization happens before config merge and unmarshal, later configs and imports still override matching command fields by segment name. Nested <code>commands</code> arrays still merge recursively, and sibling commands that share a prefix still collapse into one command tree.</p>
<p>That means you can define a shared branch in one config:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> casts generate</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Generate casts</span></span><br></div></code></pre></div></div>
<p>And add leaves elsewhere:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">commands</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> casts generate examples sops</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">secrets secret</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">lifecycle</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Regenerate the SOPS secrets example cast</span></span><br></div></code></pre></div></div>
<p>Atmos treats both definitions as part of the same <code>casts -&gt; generate</code> command branch.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="when-to-use-it">When to Use It<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/path-based-custom-commands#when-to-use-it" class="hash-link" aria-label="Direct link to When to Use It" title="Direct link to When to Use It" translate="no">​</a></h2>
<p>Use path-based names when the intermediate command levels do not carry their own behavior. This is ideal for demo generation, validation commands, and operational command groups where the path is the structure.</p>
<p>Keep the nested form when an intermediate command needs its own description, flags, environment, steps, or child-specific organization that is clearer when written explicitly.</p>
<p>Both forms can coexist. The important rule is simple: spaces in <code>commands[].name</code> are treated as command path separators, so literal spaces inside one command segment are not supported.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Enhancement" term="Enhancement"/>
        <category label="DX" term="DX"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[See Atmos in Action]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-demo-workflows</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-demo-workflows"/>
        <updated>2026-06-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Start with the recording.]]></summary>
        <content type="html"><![CDATA[<p>Start with the recording.</p>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos terraform plan</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<p>That is the point of this update: the docs now have short terminal casts for the parts of Atmos that are easier to understand by watching them run.</p>
<p>No big setup. No long pitch before the useful part. Open a page, press play, and see what happens.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="new-recordings">New Recordings<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-demo-workflows#new-recordings" class="hash-link" aria-label="Direct link to New Recordings" title="Direct link to New Recordings" translate="no">​</a></h2>
<p>The first set covers the runs people usually want to inspect first:</p>
<ul>
<li class="">plan</li>
<li class="">deploy</li>
<li class="">output</li>
<li class="">source pull</li>
<li class="">stack list</li>
<li class="">component details</li>
<li class="">stack details</li>
<li class="">local AWS demo</li>
</ul>
<p>Each cast is meant to answer the same question: what will I see when I run this?</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="plan-deploy-output">Plan, Deploy, Output<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-demo-workflows#plan-deploy-output" class="hash-link" aria-label="Direct link to Plan, Deploy, Output" title="Direct link to Plan, Deploy, Output" translate="no">​</a></h2>
<p>The plan cast starts the set. The next two show the follow-up runs:</p>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos terraform deploy</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos terraform output</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<p>Together, they show the basic path from preview to apply to result.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="source-pull">Source Pull<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-demo-workflows#source-pull" class="hash-link" aria-label="Direct link to Source Pull" title="Direct link to Source Pull" translate="no">​</a></h2>
<p>This cast shows the source pull by itself:</p>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos vendor pull</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<p>It is intentionally plain. You can see what is fetched and what the terminal prints when it finishes.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="look-around-first">Look Around First<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-demo-workflows#look-around-first" class="hash-link" aria-label="Direct link to Look Around First" title="Direct link to Look Around First" translate="no">​</a></h2>
<p>Sometimes the next step is to inspect the project before changing anything.</p>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos list stacks</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos describe component</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos describe stacks</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<p>These casts show what Atmos sees before you ask it to do anything else.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="local-aws-demo">Local AWS Demo<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-demo-workflows#local-aws-demo" class="hash-link" aria-label="Direct link to Local AWS Demo" title="Direct link to Local AWS Demo" translate="no">​</a></h2>
<p>The longest cast shows a full local AWS run:</p>
<div class="window_X9dN"><div class="titlebar_DN7h"><span class="dots_R2sg" aria-hidden="true"><i></i><i></i><i></i></span><span class="title_Dael">atmos emulator aws lifecycle</span></div><pre class="screen__b5c noPreWrap_ImkX screenLoading_abuO"><span> </span></pre><div class="controls_eyLV"><button type="button" class="playButton_kD9r" aria-label="Pause cast"><svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M6 5H8V19H6V5ZM16 5H18V19H16V5Z"></path></svg></button><input aria-label="Cast position" type="range" min="0" max="0" step="0.01" value="0"><span>00:00.0<!-- --> / <!-- -->00:00.0</span></div></div>
<p>It brings the local service up, waits for it, runs against it, prints the result, and shuts it down.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="kept-current">Kept Current<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-demo-workflows#kept-current" class="hash-link" aria-label="Direct link to Kept Current" title="Direct link to Kept Current" translate="no">​</a></h2>
<p>The recordings are made by Atmos:</p>
<p><a href="https://github.com/cloudposse/atmos/blob/main/demo/casts/atmos.yaml" target="_blank" rel="noopener noreferrer" class="">github.com/cloudposse/atmos/blob/main/demo/casts/atmos.yaml</a></p>
<p>That file builds the binary, prepares the demo files, records the casts, copies them into the website, and checks the result.</p>
<p>The docs get a visible example. The repo gets a repeatable way to refresh it.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Feature" term="Feature"/>
        <category label="DX" term="DX"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Structured Diagnostics for Agentic Troubleshooting]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/diagnostics-jsonl</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/diagnostics-jsonl"/>
        <updated>2026-06-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Human logs are useful while you are watching a command run, but they are not enough when you need to diagnose subprocess execution, CI failures, or agent runs after the fact.]]></summary>
        <content type="html"><![CDATA[<p>Human logs are useful while you are watching a command run, but they are not enough when you need to diagnose subprocess execution, CI failures, or agent runs after the fact.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-problem">The Problem<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/diagnostics-jsonl#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>When a run fails, the important question is usually not "what did the terminal print?" It is "what command ran, with which arguments, from which directory, for how long, and how did it exit?"</p>
<p>Humans can sometimes reconstruct that from logs. Agents and support tooling should not have to scrape terminal prose to find the root cause.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-change">The Change<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/diagnostics-jsonl#the-change" class="hash-link" aria-label="Direct link to The Change" title="Direct link to The Change" translate="no">​</a></h2>
<p>Atmos now supports an opt-in diagnostics stream: machine-readable JSONL events written to a file.</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">diagnostics</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">enabled</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">file</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> .atmos/diagnostics.jsonl</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">include_output</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">false</span></span><br></div></code></pre></div></div>
<p>The same settings can be controlled with environment variables:</p>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token assign-left variable" style="color:rgb(214, 222, 235)">ATMOS_DIAGNOSTICS_ENABLED</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">true </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(214, 222, 235)">ATMOS_DIAGNOSTICS_FILE</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">.atmos/diagnostics.jsonl </span><span class="token punctuation" style="color:rgb(199, 146, 234)">\</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform plan vpc </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> plat-ue2-dev</span><br></div></code></pre></div></div>
<p>Because the output is JSONL, it is easy to inspect with tools like <code>jq</code>:</p>
<div class="language-shell codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-shell codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A"><div class="token-line" style="color:#d6deeb"><span class="token plain">jq </span><span class="token string" style="color:rgb(173, 219, 103)">'select(.type == "process.exit")'</span><span class="token plain"> .atmos/diagnostics.jsonl</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="diagnostics-vs-logging">Diagnostics vs. Logging<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/diagnostics-jsonl#diagnostics-vs-logging" class="hash-link" aria-label="Direct link to Diagnostics vs. Logging" title="Direct link to Diagnostics vs. Logging" translate="no">​</a></h2>
<p>Logs are human-readable status and narrative output. They explain what Atmos is doing for someone watching the run.</p>
<p>Diagnostics are machine-readable event records for tooling, agents, and post-run inspection. They are designed to accelerate root-cause analysis by giving agents structured facts about subprocesses, exits, durations, cancellation, and failures without requiring them to parse terminal output.</p>
<p><code>diagnostics.include_output</code> can include masked subprocess stdout and stderr chunks, but it is disabled by default. Diagnostic output is masked before it is written.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="why-it-matters">Why It Matters<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/diagnostics-jsonl#why-it-matters" class="hash-link" aria-label="Direct link to Why It Matters" title="Direct link to Why It Matters" translate="no">​</a></h2>
<ul>
<li class=""><strong>Agentic troubleshooting gets faster.</strong> Agents can reason from structured events, identify the failing step, and move from diagnosis to remediation.</li>
<li class=""><strong>CI artifacts become more useful.</strong> Save the JSONL file with a failed job and inspect it after the terminal session is gone.</li>
<li class=""><strong>Logs stay for people.</strong> Diagnostics add a tooling-oriented layer without replacing human-readable logs.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/diagnostics-jsonl#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Enable diagnostics when you need a structured troubleshooting artifact, especially for CI and agent-driven workflows.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Enhancement" term="Enhancement"/>
        <category label="DX" term="DX"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Profiles Can Now Import Shared Configuration]]></title>
        <id>https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/profile-imports</id>
        <link href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/profile-imports"/>
        <updated>2026-06-30T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Auth profiles and team defaults are often managed centrally, but workload or app repositories still need to use them. Until now, that usually meant copying profile YAML into each repository and keeping those copies in sync by hand.]]></summary>
        <content type="html"><![CDATA[<p>Auth profiles and team defaults are often managed centrally, but workload or app repositories still need to use them. Until now, that usually meant copying profile YAML into each repository and keeping those copies in sync by hand.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-problem">The Problem<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/profile-imports#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Many teams keep authentication, identity, terminal, and CI defaults in a central infrastructure repository. That works well for governance, but it creates friction for workload or app repositories: every repo needs the same profile definitions, and every update has to be copied everywhere.</p>
<p>That duplication is especially painful for auth profiles. The central platform team owns the provider and identity shape, while each app repository only wants to consume the right profile and add a small local override.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="the-change">The Change<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/profile-imports#the-change" class="hash-link" aria-label="Direct link to The Change" title="Direct link to The Change" translate="no">​</a></h2>
<p>Profile config files can now use <code>import:</code>, including remote imports. That means a profile in a workload or app repository can pull shared configuration from a central repository and then override only the local pieces it owns.</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockTitle_JJ7b">profiles/developer/atmos.yaml</div><div class="codeBlockContent_gU9i"><pre tabindex="0" class="prism-code language-yaml codeBlock_dlrW thin-scrollbar" style="color:#d6deeb;background-color:#011627"><code class="codeBlockLines_YA7A codeBlockLinesWithNumbering_UQ30" style="counter-reset:line-count 0"><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token key atrule">import</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"github.com/my-org/platform-atmos//profiles/shared-auth.yaml?ref=v1.4.0"</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain" style="display:inline-block"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain"></span><span class="token key atrule">logs</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">level</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Debug</span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain" style="display:inline-block"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain"></span><span class="token key atrule">settings</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">  </span><span class="token key atrule">terminal</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"></span></span><br></div><div class="token-line codeLine_MYOh" style="color:#d6deeb"><span class="codeLineNumber_C7H_"></span><span class="codeLineContent_hnsy"><span class="token plain">    </span><span class="token key atrule">max_width</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">140</span></span><br></div></code></pre></div></div>
<p>The imported file provides the baseline. Values in the local profile are merged over it, so the workload repository can keep its local preferences without forking the shared auth profile.</p>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="why-it-matters">Why It Matters<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/profile-imports#why-it-matters" class="hash-link" aria-label="Direct link to Why It Matters" title="Direct link to Why It Matters" translate="no">​</a></h2>
<ul>
<li class=""><strong>Centralize auth profiles.</strong> Platform teams can publish shared provider and identity configuration once.</li>
<li class=""><strong>Keep app repos small.</strong> Workload or app repositories can consume the shared profile instead of duplicating it.</li>
<li class=""><strong>Override locally when needed.</strong> Imported profile configuration is still just layered Atmos configuration, so local profile values win.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_K69Q" id="get-involved">Get Involved<a href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/profile-imports#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>See the <a class="" href="https://pr-2720.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/profiles">profiles documentation</a> for profile discovery, activation, and merge behavior.</p>]]></content>
        <author>
            <name>Erik Osterman</name>
            <uri>https://github.com/osterman</uri>
        </author>
        <category label="Enhancement" term="Enhancement"/>
        <category label="DX" term="DX"/>
    </entry>
</feed>