Skip to content
Back to skills

Iac Plan

ASecurity

Preview an Infrastructure-as-Code change WITHOUT applying it. Runs `bin/iac-plan.sh`, which detects the repo's IaC tool (terraform, opentofu, aws-cdk, pulumi, helm, kubernetes, kustomize, ansible), shells out to the user's already-authenticated CLI, and renders a normalized add/change/destroy summary. READ-ONLY — it never mutates infrastructure. TRIGGER when the user says "terraform plan", "preview my infra change", "what will this deploy", "cdk diff", "pulumi preview", "show me the terraform...

  • 6 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 5, 2026
developmentrustgoshellkubernetesawsterraformbackend

Works with

  • cli

Security analysis

A100/100

Scanned September 5, 2026

npx -y skills add thettwe/nyann --skill iac-plan --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Iac Plan?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Iac Plan
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/thettwe-iac-plan/badge)](https://www.skillsdirectory.com/skills/thettwe-iac-plan)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: iac-plan
description: >
  Preview an Infrastructure-as-Code change WITHOUT applying it. Runs
  `bin/iac-plan.sh`, which detects the repo's IaC tool (terraform,
  opentofu, aws-cdk, pulumi, helm, kubernetes, kustomize, ansible),
  shells out to the user's already-authenticated CLI, and renders a
  normalized add/change/destroy summary. READ-ONLY — it never mutates
  infrastructure. TRIGGER when the user says "terraform plan",
  "preview my infra change", "what will this deploy", "cdk diff",
  "pulumi preview", "show me the terraform diff", "dry-run the infra
  change", "what would terraform/tofu/cdk/pulumi do", "plan the
  infrastructure", "kubectl diff", "helm diff", "what does this
  deploy change", "/nyann:plan".
  DISAMBIGUATION — fire ONLY for IaC plan intent on a detected infra
  repo. Do NOT trigger on the bare word "plan": this is NOT project
  planning, NOT sprint/roadmap planning, NOT `sc:*` task planning, NOT
  Claude's ExitPlanMode / "make a plan" for code work. "plan a feature",
  "plan my week", "let's plan the refactor" → ignore. Require an
  infra signal (a tool name like terraform/tofu/cdk/pulumi/helm/kubectl,
  OR the word "infra"/"infrastructure"/"deploy", OR a detected
  `iac.tool` in the stack descriptor). With no infra signal, do NOT
  trigger. To apply the change after previewing, that's `/nyann:apply`
  (the iac-apply skill) — iac-plan never applies.
---

# iac-plan

Wraps `bin/iac-plan.sh`. It detects the repo's `iac.tool`, dispatches
to the per-tool adapter (`bin/iac-plan/<tool>.sh`), captures whatever
machine-readable plan the tool offers, and emits a normalized **IacPlan**
JSON on stdout (schema: `schemas/iac-plan.schema.json`). This skill is
READ-ONLY: it previews, it never applies. To apply, hand off to
`/nyann:apply`.

## 1. Confirm this is an IaC repo before running

iac-plan is only meaningful on an infrastructure repo. Before invoking,
satisfy yourself there's an infra signal — a tool name in the request
(terraform / tofu / cdk / pulumi / helm / kubectl / kustomize /
ansible), an explicit "infra"/"deploy" intent, OR a detected `iac.tool`
in the stack descriptor (`bin/detect-stack.sh --path <cwd>` →
`.iac.tool`). If there's no infra signal, this is the wrong skill — see
DISAMBIGUATION in the frontmatter and do not run.

## 2. Scope: whole target or a single unit

By default iac-plan previews the whole target root (`unit:"."`). When
the user names a specific module/stack/chart/overlay/playbook (or the
repo is a monorepo with multiple units), scope it with `--unit`:

```
bin/iac-plan.sh --target <cwd> [--unit <repo-rel-path>]
```

`--unit` is a **repo-relative** path resolved under the target with a
traversal guard — a path that escapes the target is refused (see step
4). Omit it to plan the root.

## 3. Invoke

```
bin/iac-plan.sh --target <cwd> [--unit <repo-rel-path>]
```

The script emits one IacPlan JSON object on stdout. It runs the cloud
CLI only inside the adapter (which the operator invoked by asking for a
plan) — detection itself is pure filesystem work and never auto-runs a
cloud CLI behind the user's back. nyann handles no credentials: the
adapter inherits whatever auth the user's CLI already has.

## 4. Branch on `status` — this drives everything

| `status` | Meaning | What to do |
|---|---|---|
| `planned` | A plan ran and produced a summary. | Render the summary (step 5). Only this status leads to an apply offer. |
| `skipped` | The CLI, backend, or credentials were absent — **no plan ran** (exit 0). | Surface `.message` verbatim (e.g. "terraform CLI not installed", "no backend configured"). Do NOT offer apply — there's nothing to apply. Tell the user what's missing. |
| `refused` | A precondition failed (exit 1) — unknown tool, or `--unit` escaped the target. | Surface `.message`. This is bad input, not a missing tool. Fix the input (correct the unit path, confirm the repo's tool) and retry. |

`skipped` is a *success* outcome of "I couldn't run a plan here", not an
error — never present it as a failure, and never offer apply after it.

## 5. Render the summary (status: planned)

Read these fields off the IacPlan and show them back plainly:

- `.tool` — which tool produced the plan.
- `.unit` — the unit that was planned (`.` = root).
- `.summary.add` / `.summary.change` / `.summary.destroy` — the resource
  action counts. Show them as e.g. **"+3 add, ~1 change, -2 destroy"**.
- `.destructive` — whether this plan would destroy/replace a resource.
- `.destructive_known` — confidence in that verdict (see below).
- `.message` — a one-line summary; relay it.
- `.raw_path` — absolute path to the raw tool output, written **outside
  the repo** (never committed). Offer it if the user wants the full
  diff; do not paste raw plan contents into chat unprompted (it may
  contain resource addresses / config values).

### Structured vs advisory tools — say which you're looking at

- **Structured** (terraform, opentofu, aws-cdk, pulumi):
  `destructive_known:true`. The add/change/destroy counts are real, and
  `destructive` = (`summary.destroy > 0`). Trust the numbers.
- **Advisory** (helm, kubernetes, kustomize, ansible):
  `destructive_known:false`, all summary counts `0`, and `destructive`
  is conservatively **true**. These tools only emit a text diff in
  v1.13.0 — nyann cannot count destruction from it, so it treats the
  change as **potentially destructive** (fail-safe). Tell the user the
  counts are 0 because they're *unknown*, not because the change is
  safe, and point them at `.raw_path` to read the actual diff.

## 6. Destructive plan → ask before offering apply

When `.destructive` is `true` (a structured plan with `destroy > 0`, OR
any advisory plan), do NOT casually suggest applying. **You MUST call
the `AskUserQuestion` tool** (not plain text) to surface the stakes
before any apply path is even offered:

```json
{
  "questions": [
    {
      "question": "This plan is destructive — it would destroy or replace real infrastructure. What next?",
      "header": "Destructive plan",
      "multiSelect": false,
      "options": [
        { "label": "Stop here (Recommended)", "description": "Just show the preview. Nothing is applied. Review the diff and decide later." },
        { "label": "Proceed to apply", "description": "Hand off to /nyann:apply, which will require an explicit destroy confirmation before mutating." }
      ]
    }
  ]
}
```

For an **advisory** destructive plan, add that the destroy count is
unknown (`destructive_known:false`) — the tool gave only a text diff, so
"destructive" here means "could not be proven safe." Recommend reading
`.raw_path` before proceeding.

If the user picks "Proceed to apply", hand off to `/nyann:apply` (step
7) — never apply from this skill.

## 7. Non-destructive plan → offer apply, don't auto-run it

When `.destructive` is `false` (only possible for a structured tool with
`destroy == 0`), it's safe to offer the apply step. State the
add/change counts and ask if they want to apply via `/nyann:apply`.
Still don't run apply from here — iac-plan is preview-only by contract.

## When to hand off

- "Now apply it" / "go ahead and deploy" / "run the apply" →
  `/nyann:apply` (iac-apply skill). It re-runs this plan, requires an
  explicit `--apply`, and gates destructive changes behind an extra
  confirmation. Never apply from iac-plan.
- "plan a feature" / "plan my sprint" / "make a plan for the refactor"
  → NOT this skill. This is code/project planning, not IaC. See
  DISAMBIGUATION.
- "scan for infra drift" / "are my modules pinned" → `/nyann:doctor`
  (it runs `iac-drift-scan.sh`, a filesystem-only IaC audit — no cloud
  CLI, no plan).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.