<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>atmos Blog</title>
        <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog</link>
        <description>atmos Blog</description>
        <lastBuildDate>Sun, 04 Oct 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[See why a Helm release failed, right in the Atmos error]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-crashloop-diagnostics</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-crashloop-diagnostics</guid>
            <pubDate>Sun, 04 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A controller rollout times out. The deploy fails with "release did not become ready within 5m0s" and nothing else. So you switch to the cluster, run kubectl get pods, then describe, then logs on whichever pod looks wrong - and in CI you often can't do any of that. Worse, if the release is set to roll back on failure, the rollback has already deleted the crashing pods by the time you look, taking the evidence with it.]]></description>
            <content:encoded><![CDATA[<p>A controller rollout times out. The deploy fails with "release did not become ready within 5m0s" and nothing else. So you switch to the cluster, run <code>kubectl get pods</code>, then <code>describe</code>, then <code>logs</code> on whichever pod looks wrong - and in CI you often can't do any of that. Worse, if the release is set to roll back on failure, the rollback has already deleted the crashing pods by the time you look, taking the evidence with it.</p>
<p>Native Helm releases in Atmos now capture that evidence at the moment of failure and fold it straight into the error: which pod is failing, what the container is reporting, and - at debug level - the crash log and recent events.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-crashloop-diagnostics#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>A failed readiness wait tells you <em>that</em> a release did not come up, but not <em>why</em>. The error names the release and namespace, yet the actual cause - a <code>CrashLoopBackOff</code>, an <code>ImagePullBackOff</code> from a bad registry mirror, a container exiting non-zero on a bad config value - lives on the pods, not in the release record.</p>
<p>So the cause is one <code>kubectl</code> session away. Except:</p>
<ul>
<li class="">In CI there is usually no interactive cluster access, so the run just fails with a timeout and no cause.</li>
<li class="">When a release is configured to roll back or uninstall on failure, that recovery deletes the failing pods first. By the time anyone looks, the pod - and its logs - are gone.</li>
</ul>
<p>The result is a dependency-ordered rollout that stops at a release nobody can diagnose from the output alone.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-crashloop-diagnostics#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>On a release failure, and <strong>before</strong> any rollback or uninstall runs, Atmos now enumerates the release's pods, finds the not-ready containers, and appends their diagnostics to the same error:</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 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 plain">Error: failed to perform helm release operation</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">  workload diagnostics:</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">    pod keda-operator-7d9f  keda-operator CrashLoopBackOff (exit 1, 5 restarts)</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">      last log (keda-operator):</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">        panic: failed to load config: invalid duration "5x"</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">      events:</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">        BackOff  Back-off restarting failed container</span></span><br></div></code></pre></div></div>
<p>The container-status summary (reason, exit code, restart count) is always included on failure. The log tail and the pod's recent events are added when you run at debug or trace level, so normal output stays concise.</p>
<p>To guarantee the evidence survives, Atmos now performs the configured <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/stacks/components/helm#release-lifecycle"><code>on_failure</code> rollback or uninstall</a> itself, after collecting the diagnostics rather than before - the rollback and history-retention behavior you configure is unchanged, it just no longer races the diagnostics.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-crashloop-diagnostics#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>There is nothing to enable. Any native Helm <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/helm/apply"><code>apply</code></a> or <code>deploy</code> that fails readiness surfaces the diagnostics automatically. To include the log tail and events, raise the log level:</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 helm apply keda </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> plat-ue2-prod --logs-level</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">Debug</span><br></div></code></pre></div></div>
<p>Diagnostics are best-effort: if the cluster cannot be reached, Atmos reports the original failure unchanged rather than masking it.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-crashloop-diagnostics#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>This pairs with the native Helm <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/stacks/components/helm#release-lifecycle">release lifecycle</a> controls. If there is a failure signal you want surfaced that Atmos does not yet capture, open an issue or discussion on <a href="https://github.com/cloudposse/atmos" target="_blank" rel="noopener noreferrer" class="">GitHub</a>.</p>]]></content:encoded>
            <category>Feature</category>
            <category>Experimental</category>
        </item>
        <item>
            <title><![CDATA[Clear server-side apply conflicts without leaving the deploy path]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-force-conflicts</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-force-conflicts</guid>
            <pubDate>Fri, 02 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Kubernetes server-side apply tracks who owns every field of a managed object. When two actors write the same field - a controller that reconciles an object a release also sets, or an object whose ownership ledger was lost - the next apply fails with a field-ownership conflict. The standard escape is a one-off kubectl apply --server-side --force-conflicts or hand-editing managedFields, then re-running your deploy. That is fine on a laptop and impossible in CI, and a conflicted release blocks every dependent waiting on it.]]></description>
            <content:encoded><![CDATA[<p>Kubernetes server-side apply tracks who owns every field of a managed object. When two actors write the same field - a controller that reconciles an object a release also sets, or an object whose ownership ledger was lost - the next apply fails with a field-ownership conflict. The standard escape is a one-off <code>kubectl apply --server-side --force-conflicts</code> or hand-editing <code>managedFields</code>, then re-running your deploy. That is fine on a laptop and impossible in CI, and a conflicted release blocks every dependent waiting on it.</p>
<p>Native Helm components now expose the two Helm 4 controls that resolve this - <code>server_side_apply</code> and <code>force_conflicts</code> - as release-policy settings and command-line flags, so a conflict clears in the normal <code>atmos helm apply</code> path.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-force-conflicts#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Helm 4 applies release manifests with server-side apply by default, so field ownership is shared with any other actor that writes the same fields. Two situations routinely put another manager on a field a release also declares:</p>
<ul>
<li class="">A controller continuously reconciles an object it also received from a release, and takes ownership of fields the release sets.</li>
<li class="">An object's <code>managedFields</code> ledger is orphaned - for example, a custom resource whose CRD hosts a conversion webhook loses its ledger when a conversion fails during a controller disruption. The next apply synthesizes a stand-in manager that owns the pre-existing fields, and a later release apply that changes those fields conflicts with it.</li>
</ul>
<p>In both cases the apply reports a conflict and the install or upgrade aborts. Because Atmos set no conflict-resolution option, there was no way to clear it through the deploy path: you had to repair the object out of band and re-run. That breaks dependency-ordered rollouts, cannot be remediated in CI, and hid a control Helm 4 already implements.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-force-conflicts#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>Two keys are added to the native Helm <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/stacks/components/helm#release-lifecycle"><code>release</code> policy</a>, alongside the existing wait, timeout, history, install, and upgrade controls:</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">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">helm</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">release</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"># Apply method. Omit to use the Helm default.</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">server_side_apply</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 comment" style="color:rgb(99, 119, 119);font-style:italic"># Resolve field-ownership conflicts by overwriting the contested</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"># fields and becoming their sole manager. Opt-in; default false.</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">force_conflicts</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>With <code>force_conflicts</code> enabled, a release apply that meets a field owned by another manager overwrites the contested fields and becomes their sole owner, so the release reaches a successful completion state and its dependents proceed. It is opt-in by design: forcing overrides other managers, so a controller that legitimately co-owns a field loses it on the next apply. That trade-off is yours to make per component, which is why the default leaves conflicts fatal and visible.</p>
<p><code>server_side_apply</code> accepts <code>auto</code>, <code>true</code>, or <code>false</code>. Omitting it preserves the Helm default - server-side apply on install, and the prior release's method on upgrade - so a release that sets neither key behaves exactly as before.</p>
<p>Both settings resolve through the same path as the rest of the release lifecycle: stack type defaults, base-component inheritance, concrete component configuration, and command-line override. A release-wide value is the common case, and the per-phase <code>install</code> and <code>upgrade</code> blocks can override it when first install and later upgrades need different behavior. The configured values are validated before any chart download or cluster mutation.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-force-conflicts#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>Set the policy in a stack for steady-state behavior, or force a single recovery apply from the command line without editing configuration:</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 comment" style="color:rgb(99, 119, 119);font-style:italic"># One-off recovery: take ownership of the contested fields and continue.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos helm apply my-component </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> plat-ue2-prod --force-conflicts</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"># Override the apply method for this run (a bare flag selects true).</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos helm apply my-component </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> plat-ue2-prod --server-side-apply</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">false</span><br></div></code></pre></div></div>
<p>The <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/helm/apply#flags"><code>--force-conflicts</code> and <code>--server-side-apply</code></a> flags are available on <code>apply</code> and <code>deploy</code>, and take precedence over stack <code>release</code> configuration.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-force-conflicts#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-3263.atmos-docs.ue2.dev.plat.cloudposse.org/stacks/components/helm#release-lifecycle">native Helm release lifecycle</a> documentation for the full policy reference. If you hit a server-side apply scenario this does not cover, open an issue or discussion on <a href="https://github.com/cloudposse/atmos" target="_blank" rel="noopener noreferrer" class="">GitHub</a> - we would like to hear about it.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[File deletion handling for scaffold/init --update]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-file-deletion</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-file-deletion</guid>
            <pubDate>Thu, 01 Oct 2026 12:00:00 GMT</pubDate>
            <description><![CDATA[Templates change over time: a file that made sense when you first generated your project gets]]></description>
            <content:encoded><![CDATA[<p>Templates change over time: a file that made sense when you first generated your project gets
renamed, split up, or just stops being relevant. Most codegen tools treat that evolution as
something only a brand-new scaffold run can fix — your existing project just keeps carrying the
leftover file forever. And if you'd deleted that file yourself to clean up, the next update used
to bring it right back, overwriting the choice you'd already made.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-file-deletion#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p><a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate"><code>atmos scaffold generate --update</code></a> and
<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/init"><code>atmos init --update</code></a> compute a three-way merge for every file the template
still generates: what changed upstream, layered onto what you've customized locally. But that
merge only ever ran for files that exist on both sides. Two real gaps followed from that:</p>
<ul>
<li class="">When the template stopped generating a file, <code>--update</code> never noticed. The stale file just sat
there, untouched, on every future update, forever.</li>
<li class="">When you deleted a file yourself — because you didn't need it, or you'd replaced it with
something else — the next <code>--update</code> silently wrote it straight back, as if your deletion had
never happened.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-file-deletion#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p><code>--update-strategy=rendered</code> now detects a file the template stopped generating and removes it,
but only when your copy still matches exactly what the template last produced. If you'd edited
that file since, <code>--update</code> doesn't guess: it surfaces an unresolved conflict instead, the same
way a genuine merge conflict does, so you decide whether to keep it or let it go.
<code>--update-strategy=tracked</code> can't offer this part safely — there's no reliable way to know which
files in your project's own git history actually belonged to the template versus anything else
that happened to live there.</p>
<p>Independently of strategy, <code>--update</code> also stops silently overwriting a deletion you made
yourself. Both <code>tracked</code> and <code>rendered</code> now check whether a file was previously generated before
recreating it, and leave your deletion in place if so. Pass <code>--recreate-deleted</code> to opt back into
the old always-recreate behavior — it's deliberately its own flag rather than folded into
<code>--force</code>, since <code>--force</code> already means "the template's version wins" for merge conflicts, and
tying file recreation to it would make "resolve conflicts manually" and "recreate what I deleted"
mutually exclusive. <code>--force</code> does, however, now resolve a deletion conflict the same way it
resolves any other: if the template removed a file you'd since edited, <code>--force</code> deletes it anyway
instead of leaving you stuck with a conflict only manual cleanup could clear.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-file-deletion#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"># A file the template no longer generates is removed automatically on --update,</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"># as long as you haven't edited it -- otherwise you'll get a conflict to resolve.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos scaffold generate my-template ./my-project </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</span><span class="token plain"> --update-strategy</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">rendered</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"># Recreate a file you deleted instead of leaving the deletion in place.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos scaffold generate my-template ./my-project </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</span><span class="token plain"> --recreate-deleted</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"># Force past a deletion conflict -- the template's choice (delete it) wins.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos scaffold generate my-template ./my-project </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</span><span class="token plain"> --update-strategy</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">rendered </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--force</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-file-deletion#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-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate"><code>atmos scaffold generate</code></a> and
<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/init"><code>atmos init</code></a> docs for the full flag reference. Have feedback on this
feature? <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">Open an issue</a> or join the conversation in
the <a href="https://cloudposse.com/slack" target="_blank" rel="noopener noreferrer" class="">Cloud Posse community Slack</a>.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[Use !include and other YAML functions in scaffold templates]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-include</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-include</guid>
            <pubDate>Thu, 01 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Two fields in the same scaffold template often need the exact same list of choices — a license]]></description>
            <content:encoded><![CDATA[<p>Two fields in the same scaffold template often need the exact same list of choices — a license
picker and a region list are both really just "options sourced from some small reference table."
Until now, that table had nowhere to live but inside <code>scaffold.yaml</code> itself, copied into every
field that needed it. And a value as simple as the current git branch, an environment variable, or
a random suffix had no path into a template at all, short of prompting the user for it by hand.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-include#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Small pieces of reference data — license choices, region codes, a naming convention lookup — show
up constantly in real scaffold templates, and they rarely stay confined to one field. A <code>select</code>
field needs them as <code>{label, value}</code> options; a file elsewhere in the same template needs the raw
table to look values up by key. Duplicating that table by hand, once per field that needs it, means
every future edit has to find and update every copy — and a missed one quietly drifts out of sync
with the rest. Beyond reference data, templates also commonly need small dynamic values — the
user's git branch or commit SHA, an environment variable, a random suffix for a resource name —
with no way to derive any of them automatically.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-include#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p><code>scaffold.yaml</code> now resolves a set of <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml">Atmos YAML functions</a> — the same
explicit-tag mechanism stack manifests already use — anywhere it currently accepts a literal
value: <code>options:</code>, a <code>type: computed</code> field's <code>value:</code>, or a <code>matrix:</code> axis.</p>
<ul>
<li class=""><a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml/include"><code>!include</code></a>/<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml/include.raw"><code>!include.raw</code></a> pulls in a
local or remote file, optionally reshaped with a YQ filter.</li>
<li class=""><a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml/env"><code>!env</code></a> reads an environment variable, <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml/random"><code>!random</code></a>
generates a random number, and <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml/cwd"><code>!cwd</code></a> reads the current working directory.</li>
<li class="">The <code>!git.*</code>/<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml/repo-root"><code>!repo-root</code></a> family exposes the current git branch,
commit SHA, repository name, and more.</li>
<li class=""><a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml/literal"><code>!literal</code></a> preserves a value exactly as written, bypassing scaffold's
own template evaluation — useful when a value legitimately contains <code>{{ }}</code> and shouldn't be
treated as a template expression.</li>
</ul>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockTitle_JJ7b">scaffold.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">spec</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">fields</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"> license</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"> select</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 tag" style="color:rgb(127, 219, 202)">!include</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"./lib/licenses.yaml '. | to_entries | map({\"label\": .value.full_name, \"value\": .key})'"</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 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"> license_lookup</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"> computed</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">value</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)">!include</span><span class="token plain"> ./lib/licenses.yaml</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 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"> branch</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"> computed</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">value</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)">!git.branch</span></span><br></div></code></pre></div></div>
<p>A locally-included file that exists solely to be included is automatically excluded from generated
output, the same way <code>scaffold.yaml</code> itself is. <code>atmos scaffold validate</code> resolves everything too,
not just <code>generate</code>, so a missing file, a bad filter, or a malformed value is caught up front.</p>
<p>Not every YAML function is available here: anything that needs real stack, component, or backend
context (<code>!terraform.state</code>, <code>!store</code>, <code>!secret</code>, and similar) is rejected with a clear error
instead. A template's <code>scaffold.yaml</code> is often resolved just to show its name and description in
<code>atmos scaffold list</code> or the interactive picker — before a user has chosen or generated anything —
so only functions that are safe to run in that situation are supported.</p>
<p>The <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml/exec"><code>!exec</code></a> function is excluded for a different reason: it needs no stack
context at all, but <code>scaffold.yaml</code> is resolved for every template configured in <code>atmos.yaml</code> just
to populate the list and picker, not only the one a user actually generates — so allowing shell
execution there would let any configured template, including a shared or vendored one, run
arbitrary code merely by being listed.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-include#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 any of the functions above anywhere <code>options:</code>, a computed field's
<code>value:</code> (see <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate#computed-fields">Computed Fields</a>), or a matrix axis
currently accepts a literal value. See the full
<a href="https://github.com/cloudposse/atmos/tree/main/examples/scaffolding-yaml-functions" target="_blank" rel="noopener noreferrer" class=""><code>examples/scaffolding-yaml-functions</code></a>
example, or the
<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate#loading-external-data-with-include-and-other-yaml-functions">Loading External Data with <code>!include</code> and Other YAML Functions</a>
section of the <code>atmos scaffold generate</code> docs.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-include#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-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate#loading-external-data-with-include-and-other-yaml-functions"><code>atmos scaffold generate</code></a>
docs for the full reference, or <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">open an issue</a> with
feedback.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[Component Mocks Now Fill Gaps Instead of Replacing Real State]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-component-mocks-fallback</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-component-mocks-fallback</guid>
            <pubDate>Thu, 01 Oct 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A local plan rarely depends on infrastructure that is entirely missing or entirely deployed. For example, the VPC exists, the database has not been created yet, and the cluster is somewhere in between. Until now, component mocks forced an all-or-nothing choice: with --use-mocks, every Terraform lookup returned its mock, even for components whose real state was sitting in the backend.]]></description>
            <content:encoded><![CDATA[<p>A local plan rarely depends on infrastructure that is entirely missing or entirely deployed. For example, the VPC exists, the database has not been created yet, and the cluster is somewhere in between. Until now, <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/stacks/components/mocks">component mocks</a> forced an all-or-nothing choice: with <code>--use-mocks</code>, every Terraform lookup returned its mock, even for components whose real state was sitting in the backend.</p>
<p>By default, <code>--use-mocks</code> now treats mocks as fallbacks. Real state wins whenever it exists, and a mock fills in only for a component that has not been provisioned or an output that is missing.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-component-mocks-fallback#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Mocks were designed to let a plan or <code>describe component</code> run before its dependencies exist. In practice, a stack is usually partly deployed. Turning mocks on replaced every <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml/terraform.state"><code>!terraform.state</code></a> and <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/functions/yaml/terraform.output"><code>!terraform.output</code></a> lookup with literal values, so a plan against a half-built environment showed fake IDs for resources that already had real ones. The only alternative was to turn mocks off and fail on the components that were not there yet.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-component-mocks-fallback#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>The behavior is configurable. In the new default <code>fallback</code> mode, each lookup resolves in this order:</p>
<ol>
<li class="">The real value, when the referenced component's state exists and declares the output.</li>
<li class="">The component's mock, when the state is not provisioned or the output is missing.</li>
<li class="">A YQ <code>//</code> default in the expression, if one is present.</li>
<li class="">The same result as without mocks: the not-provisioned error for a component that was never applied, or <code>null</code> for an output missing from applied state.</li>
</ol>
<p>Mocks never hide real problems. Credential, network, and backend failures still fail the command instead of quietly returning a mock value. As before, only <code>atmos terraform plan</code> and <code>atmos describe component</code> accept <code>--use-mocks</code>; every other Terraform subcommand, such as apply, deploy, and destroy, rejects it. Map outputs are merged: a mock fills keys that are missing from a real map output, while every value present in real state wins.</p>
<p>The other mode, <code>always</code>, keeps the previous behavior for lookups that must not depend on what is deployed, such as describing a component on a machine without cloud credentials. In <code>always</code> mode, <code>!terraform.state</code> and <code>!terraform.output</code> lookups resolve from mocks only and never initialize Terraform, authenticate, or read a backend for the components they reference. A plan still runs Terraform against the component being planned, with that component's own backend and provider credentials. Choose the mode per run with the flag, or set a project default with <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/components/terraform"><code>mocks.mode</code></a>, as shown below.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-component-mocks-fallback#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>Declare mocks on the producer component as before:</p>
<div class="language-yaml codeBlockContainer_W6UR theme-code-block" style="--prism-color:#d6deeb;--prism-background-color:#011627"><div class="codeBlockTitle_JJ7b">stacks/dev.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">mocks</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_id</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> vpc</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">local</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">private_subnet_ids</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">subnet</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> subnet</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">b</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">app</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">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">vpc_id</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)">!terraform.state</span><span class="token plain"> vpc vpc_id</span></span><br></div></code></pre></div></div>
<p>Then pick the mode per run, or set a project default:</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 comment" style="color:rgb(99, 119, 119);font-style:italic"># Real state where it exists, mocks for the gaps.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform plan app </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> dev --use-mocks</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"># Lookups use mocks only, with no backend reads or credentials for them.</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"># The plan itself still uses app's own backend and provider credentials.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform plan app </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> dev --use-mocks</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">always</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">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">mocks</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">mode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> always   </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># fallback (default) | always</span></span><br></div></code></pre></div></div>
<p>The <code>mocks.mode</code> setting can also be set with <code>ATMOS_COMPONENTS_TERRAFORM_MOCKS_MODE</code>. Attach a mode to the flag with <code>=</code>, because <code>--use-mocks always</code> does not select one. An explicit mode passed with the flag, such as <code>--use-mocks=fallback</code> or <code>--use-mocks=always</code>, wins over the environment variable, which wins over <code>atmos.yaml</code>. A bare <code>--use-mocks</code> turns mocks on and keeps the configured mode.</p>
<h3 class="anchor anchorTargetStickyNavbar_cA1_" id="upgrading">Upgrading<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-component-mocks-fallback#upgrading" class="hash-link" aria-label="Direct link to Upgrading" title="Direct link to Upgrading" translate="no">​</a></h3>
<p>This changes what a bare <code>--use-mocks</code> does, so the new default is tied to <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/edition">config editions</a>. Projects pinned to an edition before <code>2026-10-01</code> keep the previous mocks-only behavior with no changes. Unpinned projects, and projects that move their edition forward, get the fallback behavior. To keep mocks-only regardless of edition, set <code>mocks.mode: always</code> or pass <code>--use-mocks=always</code>.</p>
<p>See <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/stacks/components/mocks#resolution-modes">resolution modes</a> for the full details.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-component-mocks-fallback#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Try the provider-free <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/examples/terraform-component-mocks">component mocks example</a>, which walks through both the fallback and <code>always</code> flows. Questions and feedback are welcome in <a href="https://github.com/cloudposse/atmos/discussions" target="_blank" rel="noopener noreferrer" class="">GitHub Discussions</a> or the <a href="https://cloudposse.com/slack" target="_blank" rel="noopener noreferrer" class="">SweetOps Slack</a>.</p>]]></content:encoded>
            <category>Enhancement</category>
            <category>DX</category>
        </item>
        <item>
            <title><![CDATA[Activate a PIM-eligible Azure role as part of your identity chain]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/azure-pim-role-activation</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/azure-pim-role-activation</guid>
            <pubDate>Wed, 30 Sep 2026 12:00:00 GMT</pubDate>
            <description><![CDATA[More and more Azure resource roles are handed out as PIM-eligible rather than standing: you hold]]></description>
            <content:encoded><![CDATA[<p>More and more Azure resource roles are handed out as PIM-eligible rather than standing: you hold
the role only after you activate it, for a time-boxed window, with a justification. That activation
is a multi-step REST dance against Azure Resource Manager - enumerate what you are eligible for,
file a self-activation request, then poll until it provisions - and there is no native <code>az</code> command
for activating an eligible Azure <em>resource</em> role. So every working session starts with hand-rolled
<code>az rest</code> calls or a third-party script before you can actually run anything.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/azure-pim-role-activation#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Just-in-time access is the right default for privileged roles, but the activation step lands on the
operator every single session, outside the tool they actually came to use. You want to run a plan
against production; first you have to remember the role definition id, the scope, a justification,
and the sequence of REST calls to turn your eligibility into an active assignment - and redo it
when the window expires. Worse, nothing downstream benefits from a single place that performs the
elevation: the credential your tooling consumes is the same either way, so there is no natural seam
to hang "activate my role, then run" on. Atmos already modeled the two things this needs - becoming
something more privileged through <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/auth/identities#identity-chaining">identity chaining</a>,
and credential time-boxing - but Azure only had the <code>azure/subscription</code> identity. There was no way to
express the elevation at all.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/azure-pim-role-activation#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>A new <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/auth/identities#pim-role-activation"><code>azure/pim-role</code></a> identity chains from an existing
Azure identity and, on authentication, runs the Azure Resource Manager PIM self-activation for a
role you are eligible for - scoped and time-boxed by config. Because the elevation lives in the
identity chain, every consumer inherits it with no extra wiring: <code>atmos terraform</code>, <code>atmos auth exec</code>, the AKS kubeconfig exec plugin, and MCP servers all just see the role active.</p>
<p>Unlike assuming a role, <code>azure/pim-role</code> mints no new credentials. Azure RBAC evaluates roles by
object id at request time, not as token claims, so the activation elevates the principal you already
authenticated as - server-side - and the identity hands back the parent credentials unchanged, now
carrying the active role. That is what lets it sit transparently anywhere in a chain.</p>
<p>It is also careful about not being noisy:</p>
<ul>
<li class=""><strong>It does not re-request on every command.</strong> If an active assignment already covers the scope, it
returns immediately instead of filing another request and tripping PIM throttling.</li>
<li class=""><strong>It resumes instead of duplicating.</strong> If a request for the same role and scope is already waiting
on an approver, a later run attaches to that pending request rather than starting a new one.</li>
<li class=""><strong>It refuses clearly when it cannot proceed.</strong> A missing eligibility is reported as "not eligible"
(this activates an eligibility, it does not grant one), distinct from an activation that failed.
In a non-interactive context with no justification, it fails fast and tells you how to supply one.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/azure-pim-role-activation#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 a <code>azure/pim-role</code> identity that elevates from an identity you already have:</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">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">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">azure-dev</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"> azure/subscription</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"> azure</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">interactive</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">subscription_id</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)">"00000000-0000-0000-0000-000000000000"</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">prod-contributor</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"> azure/pim</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">role</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">identity</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">dev          </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># elevate from who I already am</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">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">role_definition_id</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)">"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"</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">scope</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)">"/subscriptions/00000000-0000-0000-0000-000000000000"</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">duration</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)">"8h"</span><span class="token plain">               </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># converted to ISO-8601; Azure enforces the role's policy maximum</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">justification</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)">"planned change window"</span></span><br></div></code></pre></div></div>
<p>Then authenticate or run as usual - the role activates as part of the chain:</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 login </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--identity</span><span class="token plain"> prod-contributor</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)">exec</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--identity</span><span class="token plain"> prod-contributor -- terraform plan</span><br></div></code></pre></div></div>
<p>Need a different reason for a specific run? Pass the <code>--justification</code> global flag (or set the
<code>ATMOS_AUTH_JUSTIFICATION</code> environment variable) - it overrides the configured default:</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 </span><span class="token builtin class-name" style="color:rgb(255, 203, 139)">exec</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--identity</span><span class="token plain"> prod-contributor </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--justification</span><span class="token plain"> </span><span class="token string" style="color:rgb(173, 219, 103)">"incident INC-123"</span><span class="token plain"> -- terraform apply</span><br></div></code></pre></div></div>
<p>In a non-interactive context (CI, a running MCP server) with no justification available at all, the
login fails fast and tells you to pass <code>--justification</code> or set <code>ATMOS_AUTH_JUSTIFICATION</code>. If a role
requires approval, the login bounds its wait and shows progress; a later invocation picks up the
pending request instead of starting over.</p>
<p>This covers Azure <em>resource</em> roles. Entra directory roles and PIM for Groups activate through
different APIs and will be separate identity kinds.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/azure-pim-role-activation#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>The <code>azure/pim-role</code> identity is part of the broader <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/auth">Atmos Auth</a> effort to
make least-privilege, just-in-time access something you configure once and forget. If you run PIM in
Azure, try it against an eligible role and let us know how it fits your workflow in
<a href="https://github.com/cloudposse/atmos/discussions" target="_blank" rel="noopener noreferrer" class="">GitHub Discussions</a>.</p>]]></content:encoded>
            <category>Feature</category>
            <category>Security</category>
        </item>
        <item>
            <title><![CDATA[Configurable merge-conflict threshold for --update]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-max-changes-flag</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-max-changes-flag</guid>
            <pubDate>Wed, 30 Sep 2026 12:00:00 GMT</pubDate>
            <description><![CDATA[Running --update against a generated project is supposed to save you from re-doing your own]]></description>
            <content:encoded><![CDATA[<p>Running <code>--update</code> against a generated project is supposed to save you from re-doing your own
customizations by hand. But once your local changes and the template's own changes overlap enough
— more than half of a file's lines, by the merge's own accounting — the merge doesn't hand you
conflict markers to work through. It refuses outright, with no way to say "I understand, show me
the conflict anyway."</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-max-changes-flag#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p><a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate"><code>atmos scaffold generate --update</code></a> and
<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/init"><code>atmos init --update</code></a> compute a three-way merge for every existing file: what
changed in the template, layered onto what you've customized locally. If that merge would touch
more than 50% of a file's lines, it bails out entirely — no conflict markers, no partial result,
just a hard failure and the file left untouched. That 50% ceiling was hardcoded, with no flag to
raise it, even though a large conflict is often exactly the kind of thing a person wants surfaced
for manual review rather than blocked outright.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-max-changes-flag#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p><code>--max-changes</code> on both commands controls that same conflict-percentage threshold. The default
stays <code>50</code> — no behavior change if you don't pass it. <code>0</code> disables the check entirely: the merge
always proceeds and writes conflict markers for you to resolve, instead of refusing the update.</p>
<p>One nuance worth understanding before you reach for a specific number: the change percentage this
is compared against isn't itself capped at 100. When your local edits and the template's changes
both diverge significantly from the common base, the computed percentage can climb well past
100% (200%+ in some cases). That means only <code>--max-changes=0</code> is a guaranteed "never fail on this"
setting — raising it to 100, 200, or higher only makes a hard failure progressively less likely,
it doesn't rule one out. If what you actually want is "always give me conflict markers, never a
hard failure," reach for <code>0</code>, not a large number.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-max-changes-flag#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"># Default behavior is unchanged: fails if a merge would touch more than 50% of a file.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos scaffold generate my-template ./my-project </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</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"># Always get conflict markers instead of a hard failure.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos scaffold generate my-template ./my-project </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</span><span class="token plain"> --max-changes</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos init </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</span><span class="token plain"> --max-changes</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0</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"># Or configure it once via environment variable.</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_SCAFFOLD_MAX_CHANGES</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain"> atmos scaffold generate my-template ./my-project </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</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_INIT_MAX_CHANGES</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain"> atmos init </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-max-changes-flag#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-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate"><code>atmos scaffold generate</code></a> and
<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/init"><code>atmos init</code></a> docs for the full flag reference. Have feedback on this
feature? <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">Open an issue</a> or join the conversation in
the <a href="https://cloudposse.com/slack" target="_blank" rel="noopener noreferrer" class="">Cloud Posse community Slack</a>.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[Automatic CLI Exception Reporting to Atmos Pro]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-pro-exception-reporting</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-pro-exception-reporting</guid>
            <pubDate>Fri, 25 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Finding the stack, component, and team behind a failed infrastructure command can]]></description>
            <content:encoded><![CDATA[<p>Finding the stack, component, and team behind a failed infrastructure command can
require piecing together several CI logs. Atmos can now report CLI failures to
Atmos Pro with execution context and your existing metadata tags and labels.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-pro-exception-reporting#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Exception capture previously depended on configuring a separate Sentry destination.
Enabling Atmos Pro for a stack did not automatically send CLI exceptions to Pro,
leaving failures disconnected from the execution records already uploaded there.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-pro-exception-reporting#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>The <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/settings/pro#automatic-exception-reporting">automatic Pro exception reporter</a>
sends failures from GitHub Actions when the effective <code>settings.pro.enabled</code> is
<code>true</code>, using fresh GitHub OIDC credentials and the configured Pro base URL.
Separately configured Sentry destinations continue to receive events with the same
IDs and fingerprints.</p>
<p>Resolved <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/stacks/components/component-metadata">component metadata</a>, including
inherited stack defaults, becomes unprefixed Sentry tags. A <code>production</code> presence
tag becomes <code>production: "true"</code>; a <code>team: platform</code> label becomes
<code>team: "platform"</code>. Events also include stack/component identity and the execution
ID used by Pro uploads, with Atmos's existing masking applied.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-pro-exception-reporting#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>Enable Pro in <code>atmos.yaml</code> for invocation-wide reporting, or use the existing
stack/component Pro setting:</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">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">pro</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>Grant the GitHub Actions workflow <code>id-token: write</code> permission:</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">permissions</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">contents</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> read</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">id-token</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> write</span></span><br></div></code></pre></div></div>
<p><strong>Upgrade behavior:</strong> existing stacks with <code>settings.pro.enabled: true</code> now send
CLI exceptions automatically in eligible GitHub Actions runs. To retain the
previous behavior while keeping other Pro features, explicitly opt out:</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">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">pro</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">errors</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)">false</span></span><br></div></code></pre></div></div>
<p>The <code>ATMOS_PRO_ERRORS_ENABLED=false</code> environment override also disables reporting
and takes precedence over component settings. Edition pins do not suppress this
new behavior. Reporting failures preserve the command's exit code, with a
two-second delivery timeout and a shared two-second shutdown flush.</p>
<p>The CLI contract covers successful ingestion and authentication rejection; Pro's
provider verification and persisted-tag assertions are tracked in
<a href="https://github.com/cloudposse/atmos/issues/3219" target="_blank" rel="noopener noreferrer" class="">issue #3219</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/atmos-pro-exception-reporting#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-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/settings/pro#automatic-exception-reporting">reporting configuration and tag precedence</a>
for details, and <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">open an issue</a> with
feedback about exception reporting.</p>]]></content:encoded>
            <category>Feature</category>
            <category>Atmos Pro</category>
        </item>
        <item>
            <title><![CDATA[Consistent Toolchain Paths and Stable Version Declarations]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/toolchain-project-paths-and-declarations</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/toolchain-project-paths-and-declarations</guid>
            <pubDate>Thu, 24 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[CI should install the artifacts reviewed and committed with a project. Ordinarily, Atmos verifies artifacts against the lockfile's recorded checksums, but it can still accept and record a new artifact when a tool or platform entry is missing.]]></description>
            <content:encoded><![CDATA[<p>CI should install the artifacts reviewed and committed with a project. Ordinarily, Atmos verifies artifacts against the lockfile's recorded checksums, but it can still accept and record a new artifact when a tool or platform entry is missing.</p>
<p>Enable <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/toolchain#frozen-installs-in-ci"><code>toolchain.frozen_lock_file: true</code></a> in CI and security-sensitive environments to reject those missing entries and prevent lockfile writes. That way, you can prepare and review lockfile updates before running CI.</p>
<p>This update makes project configuration consistent across invocation directories and keeps automatic installs from changing declared dependencies. The same project paths and declarations apply whether a developer or CI runs the command.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/toolchain-project-paths-and-declarations#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Relative toolchain paths could follow the directory where you invoked Atmos. A command run from a component directory could therefore look for a different version manifest or use a different installation directory than the same command run from the project base.</p>
<p>Automatic installation also used the declaration-writing behavior of an explicit install command. Running an infrastructure command could leave a change in <code>.tool-versions</code>, even though you had not asked to change the project's dependencies.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/toolchain-project-paths-and-declarations#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p><a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/toolchain#configuration-options">Toolchain paths</a> now resolve from the configured project base, and automatic installs leave declared versions unchanged.</p>
<table><thead><tr><th>Behavior</th><th>Before</th><th>Now</th></tr></thead><tbody><tr><td>Relative toolchain paths</td><td>Could resolve from the invocation directory.</td><td>Resolve from the configured project base, including the default <code>.tool-versions</code> path.</td></tr><tr><td>Automatic dependency installation</td><td>Could add entries to <code>.tool-versions</code>.</td><td>Installs the dependency without rewriting declarations.</td></tr><tr><td>Atmos version switching</td><td>Could use earlier toolchain settings instead of the active project configuration.</td><td>Uses the active configuration, including selected profiles and project lockfile settings.</td></tr><tr><td>Toolchain path environment overrides</td><td><code>ATMOS_TOOLCHAIN_FILE_PATH</code> and <code>ATMOS_TOOLCHAIN_INSTALL_PATH</code> were not applied.</td><td>Override configured paths for explicit installs, automatic dependencies, and Atmos version switching.</td></tr></tbody></table>
<p>For example, with <code>/work/infra</code> as the configured project base, Atmos reads <code>/work/infra/.tool-versions</code> even when invoked from <code>/work/infra/components/vpc</code>. A configured <code>install_path: .tools</code> resolves to <code>/work/infra/.tools</code> from either directory. The same rule applies to relative <code>versions_file</code> and <code>lock_file</code> settings.</p>
<p>Binaries still use shared XDG cache storage by default. When Atmos installs a version of itself outside a project, it now keeps installation metadata there too, unless you explicitly override the installation path.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/toolchain-project-paths-and-declarations#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>Existing projects get the path and declaration fixes without adding configuration. Continue running your usual Atmos commands; when they need to install a tool automatically, the project's declarations remain unchanged. Use explicit <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/toolchain/install">toolchain management commands</a> when you intend to add or change those declarations.</p>
<p>Use the <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/toolchain#environment-variables">toolchain environment overrides</a> to select a different manifest or installation directory without editing project configuration. For example, <code>ATMOS_TOOLCHAIN_INSTALL_PATH=/shared/atmos-tools atmos toolchain install</code> installs binaries in the supplied directory even when invoked outside the project.</p>
<p>Automatic installs can still update <strong>resolved artifact metadata</strong> in the existing <code>toolchain.lock.yaml</code>: they record missing version or platform entries after successful installation, preserve matching entries, and fail on checksum mismatches. The distinction is between declaring a dependency and recording the artifact used to satisfy it. See <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/toolchain#automatic-installation-and-lockfiles">automatic installation and lockfiles</a> for details.</p>
<h3 class="anchor anchorTargetStickyNavbar_cA1_" id="compatibility">Compatibility<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/toolchain-project-paths-and-declarations#compatibility" class="hash-link" aria-label="Direct link to Compatibility" title="Direct link to Compatibility" translate="no">​</a></h3>
<p>If you relied on toolchain paths relative to the invocation directory, adjust them relative to the project base or use absolute paths. These behavior fixes apply to every <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/edition">config edition</a>; pinning an older edition does not restore the earlier path or declaration-writing behavior.</p>
<p>The existing lockfile defaults still depend on your edition. Editions before <code>2026-08-05</code> retain <code>use_lock_file: false</code>; set it explicitly to enable ordinary lockfile use. Frozen mode remains opt-in and requires verification regardless of that setting.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/toolchain-project-paths-and-declarations#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Try running your existing commands from a project subdirectory and check that automatic installs leave <code>.tool-versions</code> unchanged. Share any unexpected behavior in <a href="https://github.com/cloudposse/atmos/discussions" target="_blank" rel="noopener noreferrer" class="">GitHub Discussions</a>.</p>]]></content:encoded>
            <category>Enhancement</category>
            <category>Bug Fix</category>
        </item>
        <item>
            <title><![CDATA[Derive a scaffold field once with type: computed]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-computed-fields</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-computed-fields</guid>
            <pubDate>Wed, 23 Sep 2026 12:00:00 GMT</pubDate>
            <description><![CDATA[A scaffold template's spec.fields[] questionnaire is great at collecting answers, but not every]]></description>
            <content:encoded><![CDATA[<p>A scaffold template's <code>spec.fields[]</code> questionnaire is great at collecting answers, but not every
value a template needs is really an answer. Some values are just a function of other answers —
"the primary region, defaulting to the only region when there's just one" — and until now, every
file that needed that value had to re-derive it itself, with the same <code>{{ if .Config.primary_region_select }}...{{ end }}</code>
snippet copied into each one.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-computed-fields#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Templating and scaffolding tools all hit the same shape of problem eventually: a value the
generated output needs isn't something the user should be prompted for at all — it's derived from
answers they already gave. Ask for a list of regions, then only ask for a primary region when
there's more than one; when there's exactly one, it's the primary by definition, no prompt needed.
That derivation logic is simple once, but a scaffold template has no single place to put it. It
gets pasted into every file that references the value, and every copy has to independently stay
in sync with the same conditional. Miss one, or get the fallback logic subtly wrong in one file,
and that file quietly disagrees with the rest of the generated project.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-computed-fields#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>A new <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate#computed-fields"><code>type: computed</code></a> field declares a value
once — either derived from other answers via a <code>value:</code> Go-template expression, or a plain
literal (string, number, boolean, list, or map) used as-is — and is never itself prompted for or
settable with <code>--set</code>. A string is only treated as an expression when it actually contains a
template action; a plain string like <code>hello</code> is a literal too, same as any other type:</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">spec</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">fields</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"> regions</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"> multiselect</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">us</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">east</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"> us</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">west</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> eu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">west</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 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"> primary_region_select</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"> select</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"> answers.regions</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">when</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)">"size(answers.regions) &gt; 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">    </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"> primary_region</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"> computed</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">value</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)">"{{ ternary answers.primary_region_select (index answers.regions 0) (gt (len answers.regions) 1) }}"</span></span><br></div></code></pre></div></div>
<p><code>primary_region</code> derives its value exactly once, and <code>.Config.primary_region</code> is then usable
everywhere <code>.Config</code> is — file content, <code>target:</code> path templates, and <code>matrix:</code> axes — with no
per-file fallback logic to keep in sync. Computed fields evaluate in declaration order, after
every regular field's answer is already final, so a computed field can reference any regular
field regardless of where it's declared, and any <em>earlier</em>-declared computed field's own result.</p>
<p>A computed field's <code>value:</code> doesn't have to be an expression at all — a plain literal works too,
useful for a small hand-authored reference table shared across every file in the template:</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 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"> provider_version_pins</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"> computed</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">value</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">aws</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)">"~&gt; 5.0"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token key atrule">azurerm</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)">"~&gt; 3.0"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token key atrule">google</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)">"~&gt; 5.0"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span></span><br></div></code></pre></div></div>
<p><code>provider_version_pins</code> is stored exactly as written, with no template rendering, and is
reachable the same way as any other computed field: <code>.Config.provider_version_pins</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-computed-fields#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 a <code>type: computed</code> field to any existing <code>scaffold.yaml</code>, following the shape above, and
reference its name from <code>.Config</code> in any file the template generates:</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 scaffold generate </span><span class="token operator" style="color:rgb(127, 219, 202)">&lt;</span><span class="token plain">template</span><span class="token operator" style="color:rgb(127, 219, 202)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:rgb(127, 219, 202)">&lt;</span><span class="token plain">target</span><span class="token operator" style="color:rgb(127, 219, 202)">&gt;</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(214, 222, 235)">regions</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">us-east-1,us-west-2</span><br></div></code></pre></div></div>
<p>See the <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate#computed-fields">Computed Fields</a> section of the
<code>atmos scaffold generate</code> docs for the full set of validation rules (<code>value:</code> is required on a
computed field and rejected on every other type; <code>required:</code>/<code>default:</code> are both rejected on a
computed field) and the ordering constraints that keep a computed field's dependencies resolvable.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-computed-fields#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-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate#computed-fields"><code>atmos scaffold generate</code></a> docs for the
full reference, or <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">open an issue</a> with feedback.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[Skip or duplicate a whole directory with glob spec.files[].path]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-directory-glob</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-directory-glob</guid>
            <pubDate>Fri, 18 Sep 2026 12:00:00 GMT</pubDate>
            <description><![CDATA[A scaffold template's spec.files[] entries have always matched one discovered file at a time —]]></description>
            <content:encoded><![CDATA[<p>A scaffold template's <code>spec.files[]</code> entries have always matched one discovered file at a time —
every file that needed gating or duplicating got its own entry, one <code>path:</code> per file. That's fine
for a handful of files. It breaks down the moment the thing you want to skip or duplicate is a
whole directory: a legacy docs tree gated behind an opt-in answer, or a <code>components/</code> tree that
needs to exist once per environment, region, or tenant. Either case meant repeating the same
<code>when:</code> or the same <code>matrix:</code> on every file inside the directory, one entry per file, kept in sync
by hand as the directory grew.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-directory-glob#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>The <code>matrix:</code> field already expands a single declared file into one generated file per selected value —
pick three environments, get three files, from one template file. But real templates aren't
single files; they're whole directories. A <code>components/</code> tree with a dozen resources that needs
to exist under every environment couldn't be matrixed as a unit — only file by file, one
<code>spec.files[]</code> entry per file, each with its own repeated <code>matrix:</code> and <code>target:</code>. Skipping a
directory recursively (docs that only ship when an answer opts in, a cloud-specific subtree that
only applies to one provider) had the same problem in miniature: one <code>when:</code>-gated entry per file,
duplicated across every file the directory contained.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-directory-glob#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>The <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate#glob-paths-and-directory-level-matrix"><code>spec.files[].path</code></a>
field can now be a glob pattern instead of a literal path — <code>*</code>, <code>?</code>, <code>[...]</code>, <code>**</code> for any depth, and
<code>{a,b}</code> brace expansion — matched against every file the template discovers. One entry now covers
an entire directory:</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">spec</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">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">path</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)">"docs/legacy/**"</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">when</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)">"answers.include_legacy_docs"</span></span><br></div></code></pre></div></div>
<p>The <code>when:</code> field still evaluates exactly as it does for a single file — it just now applies to every file
the glob matches, at any depth, recursively, with no per-file repetition. When more than one
entry's <code>path:</code> matches the same file, the <em>last</em> one declared wins, the same precedence
<code>.gitignore</code>/<code>CODEOWNERS</code> use: write broad patterns first, specific overrides after.</p>
<p>Combine a glob <code>path:</code> with <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate#dynamic-file-generation"><code>matrix:</code></a>
and <code>target:</code> to duplicate an entire directory once per combination, the same way a single file
already could:</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">spec</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">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">path</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)">"components/**"</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">target</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)">"environments/{{ .matrix.env }}/{{ .file.RelPath }}"</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">matrix</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">env</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"> staging</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><br></div></code></pre></div></div>
<p>Since a glob can match many files, <code>target:</code> needs to know <em>which</em> matched file an output came
from — <code>.file.RelPath</code> is that file's own path with the glob's literal prefix stripped (so
<code>components/vpc/main.tf</code> becomes <code>vpc/main.tf</code>), available in <code>target:</code> and the file's own content
alongside <code>.matrix.&lt;axis&gt;</code>. A <code>components/</code> directory with <code>vpc/main.tf</code> and <code>eks/main.tf</code>
produces six files across three environments — each preserving its own relative position under
every environment.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-directory-glob#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>The <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/examples/scaffolding-directory-matrix">scaffolding-directory-matrix example</a> is a minimal,
runnable template — a two-resource <code>components/</code> directory duplicated once per selected
environment:</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 builtin class-name" style="color:rgb(255, 203, 139)">cd</span><span class="token plain"> examples/scaffolding-directory-matrix</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos scaffold generate example ./my-project </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(214, 222, 235)">environments</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">dev,staging</span><br></div></code></pre></div></div>
<p>This generates four files: <code>environments/dev/vpc/main.tf</code>, <code>environments/dev/eks/main.tf</code>, and
the same pair under <code>staging/</code> — two full copies of <code>components/</code>, one per selected environment,
without listing <code>vpc/main.tf</code> and <code>eks/main.tf</code> individually in <code>scaffold.yaml</code>. Add a glob
<code>path:</code> to any <code>spec.files[]</code> entry in your own templates — with <code>when:</code> alone to skip a
directory, or with <code>matrix:</code> and <code>.file.RelPath</code> in <code>target:</code> to duplicate one.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-directory-glob#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-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate#glob-paths-and-directory-level-matrix"><code>atmos scaffold generate</code></a>
docs for the full reference, or <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">open an issue</a> with
feedback.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[Bring your own model: OpenRouter, DeepSeek, and Z.AI for Atmos AI]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/more-ai-providers</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/more-ai-providers</guid>
            <pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The AI model landscape moves faster than any single vendor's roadmap. A model that was the obvious]]></description>
            <content:encoded><![CDATA[<p>The AI model landscape moves faster than any single vendor's roadmap. A model that was the obvious
choice last quarter is often outclassed - or undercut on price by an order of magnitude - by one you
hadn't heard of this quarter. Locking your infrastructure assistant to one vendor's API means you
either overpay or miss out, and for teams outside the US, a US-only provider list can be a
non-starter entirely.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/more-ai-providers#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Atmos AI let you talk to your infrastructure through a fixed set of API providers. If you wanted to
try a cheaper or non-US model - route through an aggregator, run DeepSeek directly, or use a GLM
model from Z.AI - you were out of luck unless you were willing to point the generic OpenAI provider
at a hand-copied base URL and hope the defaults lined up. There was no first-class way to say "use
OpenRouter" and get a sensible model, API-key variable, and endpoint out of the box.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/more-ai-providers#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>Atmos AI adds three OpenAI-compatible API providers you can select by name:</p>
<ul>
<li class=""><strong>OpenRouter</strong> (<code>openrouter</code>) - a router that fronts hundreds of models behind one API key. Switch
models by changing the <code>model</code> slug (<code>anthropic/claude-sonnet-4-5</code>, <code>openai/gpt-4o</code>,
<code>deepseek/deepseek-chat</code>, ...) without touching anything else.</li>
<li class=""><strong>DeepSeek</strong> (<code>deepseek</code>) - the DeepSeek API directly, including <code>deepseek-reasoner</code> for the
reasoning model. Low cost for a lot of everyday infrastructure questions.</li>
<li class=""><strong>Z.AI</strong> (<code>zai</code>) - Zhipu's GLM models over their OpenAI-compatible endpoint.</li>
</ul>
<p>Each one behaves like every other Atmos AI provider: set an API key with the <code>!env</code> function, and
optionally override the model, <code>base_url</code>, or token limits. Because they are OpenAI-compatible, they
work everywhere the existing providers do - <code>atmos ai ask</code>, <code>atmos ai chat</code>, and the <code>--ai</code> flag.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/more-ai-providers#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 the provider under <code>ai.providers</code> in <code>atmos.yaml</code> and select it as the default:</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">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">default_provider</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> openrouter</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">openrouter</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">model</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)">"deepseek/deepseek-chat"</span><span class="token plain">   </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># any provider-prefixed slug</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">api_key</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"> </span><span class="token string" style="color:rgb(173, 219, 103)">"OPENROUTER_API_KEY"</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">deepseek</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">model</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)">"deepseek-chat"</span><span class="token plain">            </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># or "deepseek-reasoner"</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">api_key</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"> </span><span class="token string" style="color:rgb(173, 219, 103)">"DEEPSEEK_API_KEY"</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">zai</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">model</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)">"glm-5.3"</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">api_key</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"> </span><span class="token string" style="color:rgb(173, 219, 103)">"ZAI_API_KEY"</span></span><br></div></code></pre></div></div>
<p>Then ask away:</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 builtin class-name" style="color:rgb(255, 203, 139)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(214, 222, 235)">OPENROUTER_API_KEY</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">sk-or-</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 ai ask </span><span class="token string" style="color:rgb(173, 219, 103)">"What stacks and components do we have?"</span><br></div></code></pre></div></div>
<p>See the full list of options on the <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/ai/providers">AI providers configuration page</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/more-ai-providers#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>The provider list will keep growing as the model landscape shifts. If there's an OpenAI-compatible
provider you want to see as a first-class name in Atmos, open an issue or a pull request on
<a href="https://github.com/cloudposse/atmos" target="_blank" rel="noopener noreferrer" class="">cloudposse/atmos</a> - adding one is a small, well-templated change.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[Use opencode as your Atmos AI provider]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/opencode-cli-provider</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/opencode-cli-provider</guid>
            <pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[If you already drive your infrastructure work through a terminal coding agent, paying for a]]></description>
            <content:encoded><![CDATA[<p>If you already drive your infrastructure work through a terminal coding agent, paying for a
separate AI API key just to ask Atmos a question is redundant. You've authenticated the agent
once, picked your model provider there, and you'd rather Atmos reuse that setup than make you
manage a second set of credentials.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/opencode-cli-provider#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Atmos AI could reuse a locally installed coding-agent CLI - Claude Code, OpenAI Codex, GitHub
Copilot - instead of an API key, but the popular open-source <a href="https://opencode.ai/" target="_blank" rel="noopener noreferrer" class="">opencode</a>
agent wasn't one of them. opencode users had to fall back to configuring a raw API provider,
which meant a second credential to manage and gave up opencode's own model selection and MCP
setup.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/opencode-cli-provider#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>Atmos AI adds <strong>opencode</strong> as a CLI provider. Point Atmos at it and every <code>atmos ai</code> command runs
through your existing opencode installation and whichever model provider you've authenticated
there - no API key in <code>atmos.yaml</code>:</p>
<ul>
<li class="">Reuses your opencode auth and model configuration (<code>opencode auth login</code>).</li>
<li class=""><strong>Full MCP pass-through</strong>: MCP servers you declare in <code>atmos.yaml</code> are handed to opencode
automatically, with auth-requiring servers wrapped in <code>atmos auth exec</code> and the Atmos toolchain
on <code>PATH</code>. Atmos writes a temporary config and points opencode at it via <code>OPENCODE_CONFIG</code>, so
your own <code>opencode.json</code> is never touched.</li>
<li class="">Participates in auto-detection: with <code>ai.enabled: true</code> and no <code>default_provider</code>, Atmos finds
the <code>opencode</code> binary on your <code>PATH</code> and uses it.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/opencode-cli-provider#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>Select it as the default provider (or let auto-detection find it):</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">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">default_provider</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> opencode</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">opencode</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 - opencode's provider/model slug; defaults to opencode's own default</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">model</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)">"anthropic/claude-sonnet-4-5"</span></span><br></div></code></pre></div></div>
<p>Then ask away - opencode handles the model call and any MCP tools:</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 ai ask </span><span class="token string" style="color:rgb(173, 219, 103)">"Which components changed in the dev stack?"</span><br></div></code></pre></div></div>
<p>See the <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/ai/providers">AI providers configuration page</a> for the full CLI-provider
reference, including the MCP pass-through behavior.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/opencode-cli-provider#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>opencode joins Claude Code, OpenAI Codex, and GitHub Copilot as bring-your-own-subscription CLI
providers. If there's another local coding agent you'd like Atmos to drive, open an issue or a pull
request on <a href="https://github.com/cloudposse/atmos" target="_blank" rel="noopener noreferrer" class="">cloudposse/atmos</a>.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[Faster Vendoring with Concurrent Downloads]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/concurrent-vendoring</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/concurrent-vendoring</guid>
            <pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Waiting for each component download to finish before the next begins adds up in]]></description>
            <content:encoded><![CDATA[<p>Waiting for each component download to finish before the next begins adds up in
large repositories. Atmos vendoring now prepares independent packages concurrently
and shows their progress together, while keeping destination writes in declaration
order.</p>
<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">Concurrent vendoring and cleanup</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="castActions_M13G"><div class="container_zGFV"><div class="group_ncGU" role="group" aria-label="Share this demo"><button type="button" class="primary_hpkh" title="Copy a link to this demo" aria-live="polite"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon_P_nE" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line></svg><span>Share</span></button><button type="button" class="caret_pPxC" aria-expanded="false" aria-label="More share options" title="More share options"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon_P_nE" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><polyline points="6 9 12 15 18 9"></polyline></svg></button></div></div><div class="container_EXko"><button type="button" class="trigger_WxG7" aria-expanded="false" aria-label="Download cast"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon_LbC3" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg><span>Download</span><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon_LbC3" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><polyline points="6 9 12 15 18 9"></polyline></svg></button></div></div></div>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/concurrent-vendoring#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>A repository can contain many component sources, mixins, and targets. Fetching
these one at a time leaves the network idle between jobs and makes a large update
hard to follow. Overlapping destinations also mean downloads cannot simply copy
files whenever they finish.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/concurrent-vendoring#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p><a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/vendor/pull">Vendor pull</a> prepares up to four packages at once and
installs them in declaration order. Local sources wait for earlier writes before
being read. <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/vendor/vendor-update">Vendor update</a> checks upstream
versions concurrently and preserves the order and formatting of manifest edits.</p>
<p>The shared progress display shows active phases, download percentages when the total
size is known, retries, and completed results. A ready package is waiting for its turn
to install. The overall bar advances during downloads with known sizes and when
packages become ready, with equal weight for preparation and installation. The
completed count advances only after processing finishes. CI receives plain result
lines, and structured update reports stay on stdout.</p>
<p>The <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/vendor/vendor-clean">vendor clean</a> command displays relative paths
and preserves every lock entry when removing vendored files. Recorded versions,
checksums, and provenance remain available for the next pull. Fully cleaned packages
reinstall without drift warnings; partial deletion and modified files still trigger checks.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/concurrent-vendoring#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 plain">atmos vendor pull --max-concurrency </span><span class="token number" style="color:rgb(247, 140, 108)">8</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"> --max-concurrency </span><span class="token number" style="color:rgb(247, 140, 108)">8</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"> --max-concurrency </span><span class="token number" style="color:rgb(247, 140, 108)">8</span><br></div></code></pre></div></div>
<p>Set <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/vendor#concurrency"><code>vendor.max_concurrency</code></a> in <code>atmos.yaml</code>
or use <code>ATMOS_VENDOR_MAX_CONCURRENCY</code>. Explicit flags take precedence over the
environment and configuration. Set one worker for serial execution.</p>
<p>Projects with an <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/edition">edition pin</a> before <code>2026-09-15</code> keep
one worker by default. All editions receive the progress display, and explicit
concurrency settings override the pin.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/concurrent-vendoring#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Try the commands on your component catalog and share feedback in
<a href="https://github.com/cloudposse/atmos/discussions" target="_blank" rel="noopener noreferrer" class="">Atmos GitHub Discussions</a>.</p>]]></content:encoded>
            <category>Enhancement</category>
            <category>DX</category>
        </item>
        <item>
            <title><![CDATA[Quieter Workflow Output and Daily Experimental Warnings]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/quieter-workflow-notices</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/quieter-workflow-notices</guid>
            <pubDate>Mon, 14 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Workflows and custom commands can invoke Atmos many times, repeating startup banners and experimental warnings before each step. Those repeated notices make it harder to find the output that matters. Atmos now shows each experimental feature's warning once every 24 hours by default and suppresses repeated startup banners in child invocations.]]></description>
            <content:encoded><![CDATA[<p>Workflows and custom commands can invoke Atmos many times, repeating startup banners and experimental warnings before each step. Those repeated notices make it harder to find the output that matters. Atmos now shows each experimental feature's warning once every 24 hours by default and suppresses repeated startup banners in child invocations.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/quieter-workflow-notices#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>An experimental warning is useful when you first use a feature. Seeing it again for every component in a workflow adds noise, especially alongside repeated Atmos version, CI, and Pro status messages.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/quieter-workflow-notices#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 <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/settings/experimental">experimental mode</a> <code>warn-daily</code> gives each feature its own 24-hour timer. A toolchain warning does not suppress the first warning for devcontainers or an experimental setting. Commands in the same experimental family share a timer, and CI commands and CI hooks share the CI feature's timer.</p>
<p>Atmos stores readable feature names and timestamps in its shared local cache. The timers apply across invocations and projects using that cache. Clearing the cache makes warnings eligible again; an unavailable cache never blocks the command. Concurrent suppression is best effort on Windows.</p>
<p>Startup banners appear at the top-level invocation and are suppressed in child Atmos calls. Markdown output also follows Atmos's explicit theme and color profile without automatic terminal-style probing.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/quieter-workflow-notices#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>The new default requires no configuration for unpinned projects. To choose it explicitly:</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">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">experimental</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> warn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">daily</span></span><br></div></code></pre></div></div>
<p>Projects pinned to a <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/edition">config edition</a> before <code>2026-09-14</code> retain <code>warn</code> as the default. An explicit <code>settings.experimental</code> value or <code>ATMOS_EXPERIMENTAL</code> takes precedence over the edition default.</p>
<p>To show experimental warnings on each top-level invocation, set <code>experimental: warn</code>. Child command and setting notices are now suppressed in this mode too, independently of the edition pin. CI hooks retain their existing <code>warn</code> behavior. The <code>error</code> and <code>disable</code> modes remain enforced on every invocation, including nested calls, regardless of cached warnings.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/quieter-workflow-notices#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-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/settings/experimental">experimental settings reference</a> for all modes, or <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">report unexpected output</a>.</p>]]></content:encoded>
            <category>Enhancement</category>
            <category>DX</category>
        </item>
        <item>
            <title><![CDATA[Update generated projects without a Git history to lean on]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-strategy-rendered</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-strategy-rendered</guid>
            <pubDate>Fri, 11 Sep 2026 12:00:00 GMT</pubDate>
            <description><![CDATA[Bringing a generated project or component forward when its template changes means computing a]]></description>
            <content:encoded><![CDATA[<p>Bringing a generated project or component forward when its template changes means computing a
three-way merge: what changed in the template since you last generated, layered onto whatever
you've customized locally. That merge needs a <em>base</em> — a snapshot of what the template looked like
at the point you started from — and the obvious place to find one is the project's own commit
history. But not every generated project has intact history to read: it might not be a Git
repository at all, its history might have been squashed or rewritten by a different tool, or it
might simply be old enough that the base commit no longer exists on any reachable branch. Any of
those and <code>--update</code> had nothing to work with.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-strategy-rendered#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p><a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/init"><code>atmos init --update</code></a> and
<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate"><code>atmos scaffold generate --update</code></a> read the merge base directly
from the target directory's own Git history, at whichever ref was pinned when the project was
first generated. That works well when the target is a Git repository with intact history — but it
also means <code>--update</code> fails outright the moment it isn't: no Git repo, a rewritten or squashed
history, or a base commit that's since been garbage-collected all leave the merge with no base to
compare against.</p>
<p>It has a second, quieter cost even when history <em>is</em> intact: because the pinned base ref never
advances, the gap between "what the template looked like at that pin" and "what it looks like now"
only grows with every successive update — so does the conflict surface.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-strategy-rendered#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p><a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate"><code>--update-strategy</code></a> chooses where that merge base comes from,
independently of <code>--merge-strategy</code> (how a conflict resolves) and <code>--merge-driver</code> (which merge
algorithm runs):</p>
<ul>
<li class=""><strong><code>tracked</code></strong> (default, unchanged) — the merge base is read from the target's own Git history,
exactly as before.</li>
<li class=""><strong><code>rendered</code></strong> — the merge base is a fresh, pristine re-render of the template itself, at the ref
that produced what's currently on disk, using that generation's own recorded answers. There's no
Git read involved at all, so it works whether or not the target is (or still is) a Git
repository — and because it re-renders from the last update rather than the original pin, the
base never drifts further than one update cycle behind.</li>
</ul>
<p><code>rendered</code> needs a <code>scaffold.yaml</code>-driven template, since it relies on the answers Atmos already
records in <code>.atmos/scaffold.yaml</code> from the prior generation to reproduce that render faithfully. A
plain <code>--set</code>-only template has no such record to replay, so <code>rendered</code> isn't available for those
yet — use <code>tracked</code> there.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-strategy-rendered#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"># Everyday updates: tracked (the default) keeps reading from Git history.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos scaffold generate my-template ./my-project </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</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"># No Git history to lean on, or you just want the merge base to stay current</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"># with the last update instead of the original pin.</span><span class="token plain"></span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos scaffold generate my-template ./my-project </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</span><span class="token plain"> --update-strategy</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">rendered</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos init </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">--update</span><span class="token plain"> --update-strategy</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">rendered</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/scaffold-update-strategy-rendered#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-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/scaffold/generate"><code>atmos scaffold generate</code></a> and
<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/init"><code>atmos init</code></a> docs for the full flag reference. Have feedback on this
feature? <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">Open an issue</a> or join the conversation in
the <a href="https://cloudposse.com/slack" target="_blank" rel="noopener noreferrer" class="">Cloud Posse community Slack</a>.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[Terraform init now runs only when it needs to]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/smart-terraform-init</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/smart-terraform-init</guid>
            <pubDate>Fri, 11 Sep 2026 12:00:00 GMT</pubDate>
            <description><![CDATA[Running terraform init is necessary the first time you touch a working directory, and again]]></description>
            <content:encoded><![CDATA[<p>Running <code>terraform init</code> is necessary the first time you touch a working directory, and again
after a real change — a new provider, an updated module, a different backend. Repeating that same
work before every single command, whether or not anything changed, adds real time to a workflow:
provider downloads, backend re-initialization, module resolution, all over again for a component
that's identical to how it was a few seconds ago.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/smart-terraform-init#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>That's exactly what Atmos did. Every Terraform subcommand — <code>plan</code>, <code>apply</code>, <code>shell</code>, <code>destroy</code>,
and even the read path behind <code>!terraform.output</code> and <code>atmos.Component</code> — started with a full
<code>terraform init -reconfigure</code>, unconditionally:</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 demo </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> dev</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"># Initializing provider plugins...</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"># Initializing the backend...</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"># ...apply completes...</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">atmos terraform output demo </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> dev</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"># Initializing provider plugins...   &lt;- nothing changed, but init runs again</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"># Initializing the backend...</span><br></div></code></pre></div></div>
<p>Nothing about <code>demo</code> changed between those two commands, but the second one pays the full init
cost anyway. On a slow connection, or with a component that pulls in a lot of providers, that
turns a fast edit-plan-apply loop into a slow one. <a href="https://github.com/cloudposse/atmos/issues/620" target="_blank" rel="noopener noreferrer" class="">Issue #620</a>
asked Atmos to be smarter about this — Terragrunt-style Auto-Init, where init only re-runs when it
actually needs to. <a href="https://github.com/cloudposse/atmos/issues/1263" target="_blank" rel="noopener noreferrer" class="">Issue #1263</a> asked for
something related: a way to have Atmos run <code>init -upgrade</code> automatically when a provider
constraint changes, instead of requiring <code>-upgrade</code> to be typed by hand after every version bump.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/smart-terraform-init#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 fingerprints the inputs that actually affect <code>terraform init</code> — the component's root
Terraform/OpenTofu files, the lock file, the CLI configuration, the resolved binary, and relevant
environment variables — and compares that fingerprint against the one recorded after the last
successful init. When nothing has changed, and the working directory still looks initialized,
Atmos skips init entirely. Applying a component and then reading one of its outputs no longer
performs two full inits.</p>
<p><code>-reconfigure</code> and <code>-upgrade</code> get the same treatment instead of being added unconditionally:
<code>-reconfigure</code> only goes on when the backend configuration actually changed (or on the first
init, or after a working directory is re-provisioned), and <code>-upgrade</code> only goes on when Terraform
or OpenTofu itself reports that an upgrade is required — the behavior <a href="https://github.com/cloudposse/atmos/issues/1263" target="_blank" rel="noopener noreferrer" class="">#1263</a>
asked for.</p>
<p>None of this trusts the fingerprint blindly. If a skip turns out to have been wrong — a nested
module changed, or <code>.terraform</code> was altered by hand — Terraform or OpenTofu fails with a
diagnostic like <em>"Backend initialization required"</em> or <em>"Required plugins are not installed"</em>
before it ever touches state. Atmos recognizes that class of diagnostic, runs the init that should
have run, and retries the command once. The one gap this doesn't close is a change inside a
nested local module, which isn't part of the fingerprint — that's caught by the same retry path
rather than avoided up front, and it's a limitation Terragrunt's own Auto-Init shares.</p>
<p><strong>Behavior change, automatically protected by <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/edition">editions</a>:</strong> init no
longer runs unconditionally, and <code>-reconfigure</code>/<code>-upgrade</code> are no longer added to every init, by
default. If your project is pinned to an <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/edition">edition</a> from before
2026-09-12, you see byte-for-byte the same behavior Atmos always had — no config changes needed.
Unpinned projects, and anything pinned on or after that date, get the new defaults automatically.
See <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/config-editions">Config Editions</a> for how pinning works.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/smart-terraform-init#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>Three new settings under <code>components.terraform.init</code>, all defaulting to <code>auto</code>:</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">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">init</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">mode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> auto         </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># auto | always | never</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">reconfigure</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> auto  </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># auto | always | never</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">upgrade</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> auto       </span><span class="token comment" style="color:rgb(99, 119, 119);font-style:italic"># auto | always | never</span></span><br></div></code></pre></div></div>
<p><code>mode</code> controls whether init runs at all: <code>auto</code> skips it when nothing relevant changed, <code>always</code>
restores the previous behavior, <code>never</code> disables the ordinary implicit init — but <code>terraform workspace select/new</code> still forces a reconfigured init regardless, since it always needs one;
<code>--skip-init</code> is the flag that suppresses init unconditionally, including for <code>workspace</code>.
<code>reconfigure</code> and <code>upgrade</code> control the two flags the same way, independently.</p>
<p><code>mode</code> and <code>upgrade</code> are <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/edition">edition</a>-protected: pin <code>edition: "2026-09-11"</code> or earlier and both roll back to their pre-this-PR behavior (<code>always</code> and <code>never</code>
respectively) with no other config changes. <code>reconfigure</code> isn't — see the note on
<code>init_run_reconfigure</code> below.</p>
<p>Each setting also has a matching flag and environment variable for one-off overrides:</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 vpc </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> dev --init-mode</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">always</span><br></div><div class="token-line" style="color:#d6deeb"><span class="token plain">atmos terraform apply vpc </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> dev --init-reconfigure</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">always</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"> dev --init-upgrade</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token plain">always</span><br></div></code></pre></div></div>
<p>The existing <code>init_run_reconfigure</code> boolean keeps working: <code>false</code> maps to <code>init.reconfigure: never</code>, and the previous default <code>true</code> now maps to <code>init.reconfigure: auto</code> rather than
<code>always</code>. Unlike <code>mode</code>/<code>upgrade</code>, this one isn't edition-protected — pinning an earlier edition
doesn't restore it, because <code>init.reconfigure</code> has to stay unset internally for the legacy
<code>init_run_reconfigure</code> mapping to keep working at all. Set <code>init.reconfigure: always</code> explicitly
to keep the exact previous behavior.</p>
<p>See <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/components/terraform#configuration-reference">Terraform Configuration</a> for
the full setting reference, and <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/terraform/init#automatic-initialization">Automatic Initialization</a>
for how the skip decision and recovery path work.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/smart-terraform-init#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Have feedback on this feature? <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">Open an issue</a> or join
the conversation in the <a href="https://cloudposse.com/slack" target="_blank" rel="noopener noreferrer" class="">Cloud Posse community Slack</a>.</p>]]></content:encoded>
            <category>Feature</category>
            <category>DX</category>
        </item>
        <item>
            <title><![CDATA[Test Your Infrastructure After Deployment]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/test-steps</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/test-steps</guid>
            <pubDate>Fri, 11 Sep 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Run post-deployment checks with a test tree, progress, and failure-only output.]]></description>
            <content:encoded><![CDATA[<p>A successful deployment still needs checks that the application is healthy.
Running those checks as ordinary commands can bury failures in successful logs
or stop before the remaining tests run. The new <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/steps/type/test">test step</a>
collects the results, keeps passing output quiet, and reveals each failed check's logs.</p>
<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">Post-deployment tests</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="castActions_M13G"><div class="container_zGFV"><div class="group_ncGU" role="group" aria-label="Share this demo"><button type="button" class="primary_hpkh" title="Copy a link to this demo" aria-live="polite"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon_P_nE" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line></svg><span>Share</span></button><button type="button" class="caret_pPxC" aria-expanded="false" aria-label="More share options" title="More share options"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon_P_nE" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><polyline points="6 9 12 15 18 9"></polyline></svg></button></div></div><div class="container_EXko"><button type="button" class="trigger_WxG7" aria-expanded="false" aria-label="Download cast"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon_LbC3" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg><span>Download</span><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon_LbC3" aria-hidden="true" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><polyline points="6 9 12 15 18 9"></polyline></svg></button></div></div></div>
<p><a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/examples/tests">View the full example</a></p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/test-steps#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Post-deployment checks need a clear result for every test, including independent
checks that can still run after another fails. Shell wrappers and CI-specific
reporting make that behavior harder to reuse locally and across deployments.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/test-steps#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>Atmos supports <code>type: test</code> in workflows, custom commands, and lifecycle hooks.
Tests continue by default, while a tree with green/red dots and a bottom progress
bar shows the results. Nested <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/steps/type/parallel">parallel</a> and
<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/steps/type/matrix">matrix</a> groups share the same report.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/test-steps#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>Attach a test step to an <code>after.terraform.apply</code> hook with <code>kind: step</code> and
<code>on_failure: fail</code> to make checks part of the deployment result. Use <code>output: all</code>
when debugging, or <code>fail.mode: fail_fast</code> when remaining checks should stop after
an error. CI receives a static tree with the same failure details.</p>
<p>See the <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/steps/type/test">test step reference</a> for configuration and
failure behavior.</p>
<p>The local example runs without stacks. Running bare <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli"><code>atmos</code></a> now displays
usage and available commands, including custom commands, without requiring stack
configuration.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/test-steps#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Try the <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/examples/tests">local example</a> and share feedback in
<a href="https://github.com/cloudposse/atmos/discussions" target="_blank" rel="noopener noreferrer" class="">GitHub Discussions</a>.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[Right-size CI runners with real Terraform resource data]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-resource-usage-metrics</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-resource-usage-metrics</guid>
            <pubDate>Thu, 10 Sep 2026 13:00:00 GMT</pubDate>
            <description><![CDATA[Every CI runner — a GitHub-hosted tier or a self-hosted pool — has to be sized before a single job runs]]></description>
            <content:encoded><![CDATA[<p>Every CI runner — a GitHub-hosted tier or a self-hosted pool — has to be sized before a single job runs
on it. Get it wrong small and jobs queue or get OOM-killed on a memory-hungry provider plugin; get it
wrong large and every job pays for idle capacity it never touches. Nothing in a pipeline's output tells
you which side of that line you're on.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-resource-usage-metrics#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Right-sizing a runner pool means knowing what a job actually costs to run, and Terraform is usually the
most expensive step in the pipeline. But teams size runners by guessing, then watching for OOM kills or
timeouts and bumping the tier — because nothing reports what a <code>plan</code> or <code>apply</code> actually consumed. That
guessing game repeats for every new component, every provider version bump, and every runner generation,
whether the pipeline runs on plain GitHub Actions, Atmos alone, or Atmos Pro.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-resource-usage-metrics#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p><code>terraform plan</code>, <code>apply</code>, and <code>deploy</code> now measure the actual resource cost of the run: the terraform
process itself and everything it spawns — provider plugins and any other child processes — not just the
negligible overhead of the Atmos CLI wrapper around it. When each component's command finishes, Atmos
prints a one-line summary identifying which component and stack it covers — important in a
multi-component <code>--all</code>/<code>--affected</code> run, where this line prints once per component:</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">▶ Completed vpc (dev) in 45.2s | CPU: 12.3s user, 4.1s sys | Peak memory (largest process): 512 MB</span><br></div></code></pre></div></div>
<p>At the end of the whole invocation, Atmos also prints one aggregate summary covering everything that ran:</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">▶ Total for this invocation in 3m12.4s | CPU: 48.9s user, 16.2s sys | Peak memory (largest process): 780 MB</span><br></div></code></pre></div></div>
<p>The same, more accurate numbers now flow into the execution data Atmos Pro receives for CI runs, and — when
<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/ci">Native CI</a> is active — into the GitHub Actions job summary itself, right next to the
resource-change badges:</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">📊 Resource usage: 45.2s wall · 12.3s user / 4.1s sys CPU · 512.0 MB peak memory (largest process)</span><br></div></code></pre></div></div>
<p>Instead of guessing at a runner tier and adjusting after the fact, size a pool from real CPU-time and
peak-memory numbers per component, visible directly in the run UI. The memory figure is the largest single
process observed, not a simultaneous sum across Terraform and every provider plugin running alongside it —
a lower bound worth catching an obviously undersized runner with, not the exact ceiling to provision to.
Re-check the sizing whenever a provider version bump or a new component changes the actual footprint.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-resource-usage-metrics#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>Both summary lines are on by default — no setup required. If you'd rather not see them (for example, in
a scripted context where you don't want the extra output), turn them off with one setting:</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">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">metrics</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)">false</span></span><br></div></code></pre></div></div>
<p>This only controls local terminal output; it never affects what Atmos Pro receives. See the
<a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/configuration/settings/metrics">Metrics settings</a> docs for details.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/terraform-resource-usage-metrics#get-involved" class="hash-link" aria-label="Direct link to Get Involved" title="Direct link to Get Involved" translate="no">​</a></h2>
<p>Have feedback on this feature? <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">Open an issue</a> or join the
conversation in the <a href="https://cloudposse.com/slack" target="_blank" rel="noopener noreferrer" class="">Cloud Posse community Slack</a>.</p>]]></content:encoded>
            <category>Feature</category>
        </item>
        <item>
            <title><![CDATA[Preview and Deploy Native Helm Value Overrides]]></title>
            <link>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-cli-value-overrides</link>
            <guid>https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-cli-value-overrides</guid>
            <pubDate>Wed, 09 Sep 2026 12:00:00 GMT</pubDate>
            <description><![CDATA[An urgent image rollback, a temporary feature flag, or a one-off chart setting should not require]]></description>
            <content:encoded><![CDATA[<p>An urgent image rollback, a temporary feature flag, or a one-off chart setting should not require
editing a stack manifest just to make one deployment. Yet a preview is only useful when it renders
the exact values that the later deployment will use. When temporary values live in a shell wrapper
or are applied only at deploy time, teams cannot reliably see the change before it reaches a
cluster.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-problem">The Problem<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-cli-value-overrides#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem" translate="no">​</a></h2>
<p>Native Helm components already resolve chart values from inherited stack configuration, component
value files, and inline values. Before this update, there was no Helm-compatible command-line
override surface for those resolved values. Operators had to commit a temporary configuration
change, use a separate wrapper around Helm, or accept that a <code>diff</code> did not necessarily match the
subsequent deployment.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="the-fix">The Fix<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-cli-value-overrides#the-fix" class="hash-link" aria-label="Direct link to The Fix" title="Direct link to The Fix" translate="no">​</a></h2>
<p>Native Helm now accepts repeatable Helm-compatible <code>-f</code>/<code>--values</code>, <code>--set</code>, <code>--set-string</code>,
<code>--set-file</code>, <code>--set-json</code>, and <code>--set-literal</code> flags on <code>template</code>/<code>render</code>, <code>diff</code>/<code>plan</code>, and
<code>apply</code>/<code>deploy</code>. The overrides apply only to the current invocation and take precedence over the
resolved component values; they never modify stack configuration.</p>
<p>The new <code>atmos helm values</code> command prints the final, masked value map as formatted YAML. It lets
you inspect the value set that a preview or deployment will consume, including temporary command
line overrides, without contacting Kubernetes.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="how-to-use-it">How to Use It<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-cli-value-overrides#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>Use the same override arguments for inspection, preview, and deployment:</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 helm values monitoring </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> plat-ue2-dev </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 parameter variable" style="color:rgb(214, 222, 235)">-f</span><span class="token plain"> incident-values.yaml </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 parameter variable" style="color:rgb(214, 222, 235)">--set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(214, 222, 235)">image.tag</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token number" style="color:rgb(247, 140, 108)">2026.09</span><span class="token plain">.09</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">atmos helm </span><span class="token function" style="color:rgb(130, 170, 255)">diff</span><span class="token plain"> monitoring </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> plat-ue2-dev </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 parameter variable" style="color:rgb(214, 222, 235)">-f</span><span class="token plain"> incident-values.yaml </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 parameter variable" style="color:rgb(214, 222, 235)">--set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(214, 222, 235)">image.tag</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token number" style="color:rgb(247, 140, 108)">2026.09</span><span class="token plain">.09</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">atmos helm apply monitoring </span><span class="token parameter variable" style="color:rgb(214, 222, 235)">-s</span><span class="token plain"> plat-ue2-dev </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 parameter variable" style="color:rgb(214, 222, 235)">-f</span><span class="token plain"> incident-values.yaml </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 parameter variable" style="color:rgb(214, 222, 235)">--set</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(214, 222, 235)">image.tag</span><span class="token operator" style="color:rgb(127, 219, 202)">=</span><span class="token number" style="color:rgb(247, 140, 108)">2026.09</span><span class="token plain">.09</span><br></div></code></pre></div></div>
<p>Atmos layers command-line value files and each supported <code>--set</code> variant over the component's
resolved values using Helm's normal parsing and precedence rules. That includes nested paths,
list indexes, typed values, string and literal handling, JSON input, and file-backed values.</p>
<h2 class="anchor anchorTargetStickyNavbar_cA1_" id="get-involved">Get Involved<a href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/changelog/native-helm-cli-value-overrides#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-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/helm/usage#runtime-value-overrides">native Helm command reference</a> for
the complete override reference and the <a class="" href="https://pr-3263.atmos-docs.ue2.dev.plat.cloudposse.org/cli/commands/helm/values"><code>values</code></a> command guide.
Have feedback? <a href="https://github.com/cloudposse/atmos/issues" target="_blank" rel="noopener noreferrer" class="">Open an issue</a> or join the
<a href="https://cloudposse.com/slack" target="_blank" rel="noopener noreferrer" class="">Cloud Posse community Slack</a>.</p>]]></content:encoded>
            <category>Feature</category>
            <category>Experimental</category>
        </item>
    </channel>
</rss>