tfstackplan
tfstackplan CLI helper extension for managing Terraform state operations, plan visibility, and agentic workflows
Open source Open in the app JSON README (API)
About
tfstackplan CLI helper extension for managing Terraform state operations, plan visibility, and agentic workflows
Details
- Kind
- Plugins
- Topic
- Cloud & DevOps
- Publisher
- fluent-health
- Origin
- gemini
- Category
- ferramentas
- Version
- 0.19.0
- Stars
- 2
- Last push
- 2026-09-02T06:52:07Z
- Repository state
- ativo
- Language
- Go
- License
- Apache-2.0
- Added
- 2026-08-30 14:13:39
- Updated
- 2026-08-30 14:13:39
- Origin id
fluent-health/terraform-stack-plan
README
# tfstackplan > Your monorepo just opened **8 Terraform plans** on this one PR. > Your reviewer has gone very quiet. <p align="center"> <img src="docs/images/hero-reviewer.jpg" alt="An engineer at dusk, cold coffee in hand, a '127 files changed' sign glowing in the window" width="760"> <br><sub><i>He's reviewing the networking stack.</i></sub> </p> `tfstackplan` turns the N `plan.json` files a monorepo spits out per PR into a single comment a human can actually read — then, if you're brave, gates the apply behind a button someone has to consciously press. Terramate makes a Terraform monorepo *runnable*. `tfstackplan` makes it **reviewable, governable, and safe** inside GitHub's PR workflow. It closes the four gaps a raw `terramate run` in CI leaves wide open — and it has **four faces**, one per gap: | Face | The gap it closes | In one line | | --- | --- | --- | | [**`render`**](docs/guide/04-render.md) | **Review** | N unreadable `plan.json` → one scannable PR comment | | [**`serve`**](docs/guide/07-serve.md) | **Governance** | no approval story → live gates + privilege-backed apply | | [**`run`**](docs/guide/06-run.md) | **Observability** | CI logs are a black hole → live DAG UI, per-stack logs, check runs | | [**`state`**](docs/guide/08-state.md) | **Management** | cross-stack refactors are scary → declarative state moves | > Terramate runs your stacks. GitHub shrugs and posts the logs. `terraform > apply` does exactly what you told it to, which is the problem. `tfstackplan` > is the adult in the room. `render` is **fully standalone** — point it at a directory of plans and you get a comment. You never have to touch `run` / `serve` / `state`. The other three layer a control plane on top, while Terraform keeps executing in *your* CI under *your* identities. New here? Start with **[the guide](docs/index.md)** — it reads in order, from *why this exists* to *every flag there is*. --- ## What it looks like A run over eight stacks with classification on, rendered the way GitHub shows it in a PR comment: a scannable summary table, then a per-stack drill-down. Each resource is its own row inside an indented blockquote bar, so it's always clear which stack and resource you're reading. Small changes show expanded; big ones collapse to a row you click to open. <!-- tfstackplan:nonprod --> ### Terraform plan — nonprod (8 stacks changed) | Stack | Add | Change | Destroy | Replace | Categories | | --- | ---: | ---: | ---: | ---: | --- | | platform/nonprod | 0 | 4 | 0 | 0 | 🔐 iam | | service-projects/app-dev | 4 | 3 | 0 | 0 | ✅ safe | | data/warehouse | 0 | 0 | 6 | 0 | 💣 destructive | | networking/shared-vpc | 0 | 5 | 0 | 2 | 💣 destructive | | observability/grafana | 5 | 6 | 0 | 0 | ✅ safe | <details open><summary>📁 <b>platform/nonprod</b> · 🔐 iam · 4 change</summary> > > <details open><summary>✏️ google_project_iam_member.data_engineers<br> 1 changed</summary> > > ```diff > ~ role = "roles/viewer" → "roles/editor" > ``` > > </details> </details> <details open><summary>📁 <b>data/warehouse</b> · 💣 destructive · 6 destroy</summary> > > <details open><summary>➖ google_bigquery_dataset.legacy_events<br> 2 attrs</summary> > > ```diff > - location = "us-central1" > - name = "legacy_events" > ``` > > </details> </details> That whole block is **live Markdown, not a screenshot** — it renders natively on GitHub and you can paste it anywhere. The first line of the real output is an invisible HTML-comment marker (`<!-- tfstackplan:nonprod -->`) that CI uses to upsert one comment per environment. The full anatomy — folding rules, aligned diffs, structured-value rendering, state-op rows — lives in **[the render chapter](docs/guide/04-render.md)**. More worked outputs (big plans, the byte budget kicking in, state ops) are in **[`examples/`](examples/)**. --- ## 60-second quickstart `render` is offline and standalone — no `terraform`, no posting, no config required. Give it a directory of plans laid out to mirror your stack tree. ```bash # 1. install go install github.com/Fluent-Health/terraform-stack-plan/cmd/tfstackplan@latest # 2. for each stack, capture a plan as JSON next to where it lives terraform plan -out plan.bin && terraform show -json plan.bin > out/<stack>/tfplan.json # 3. render every stack under out/ into one comment tfstackplan render --plans-dir out/ \ --title "Terraform plan — nonprod" \ --marker tfstackplan:nonprod \ --output report.md ``` `report.md` is the comment you saw above. With no config, classification is off and the tool degrades gracefully — add a `.tfstackplan.hcl` when you want categories, links, and budgets. Then have your CI post `report.md`; `render` writes Markdown, your CI does the posting. The full path from here — classification, then the control plane — is laid out in **[the guide](docs/index.md)**. --- ## The four faces **[`render`](docs/guide/04-render.md) — the review gap.** A pure, offline renderer: many `plan.json` files in, one reviewer-friendly Markdown comment out, with optional classification. It never runs `terraform` and never posts. Use it entirely on its own. **[`run`](docs/guide/06-run.md) — the observability gap.** The CI driver. It wraps your `terramate script run`, detects the changed stacks, runs plan/apply/verify, renders + classifies in-process, and reports the execution lifecycle to the control plane — so a CI run stops being a wall of interleaved logs. **[`serve`](docs/guide/07-serve.md) — the governance gap.** The control plane: a live dependency-DAG UI, approval gates, one GitHub check run per environment, and SSE-tailed per-stack logs. > `terraform apply` across 8 stacks, straight from CI, with no one watching, is > a perfectly reasonable thing to do. `serve` is for the other 100% of cases. **[`state`](docs/guide/08-state.md) — the management gap.** Declarative cross-stack Terraform state moves, applied as part of the normal apply — so refactoring resources between stacks stops being a hand-run, fingers-crossed operation. --- ## Where do I go now? The docs read as a sequence — **[start at the index](docs/index.md)** — but if you know what you want: - **Why does this exist?** → [The gaps](docs/guide/01-the-gaps.md) · [Mental model](docs/guide/02-mental-model.md) - **I just want a comment.** → [Quickstart](docs/guide/03-quickstart.md) · [`render`](docs/guide/04-render.md) · [Classification](docs/guide/05-classification.md) - **I want a control plane.** → [`run`](docs/guide/06-run.md) · [`serve`](docs/guide/07-serve.md) · [CI integration](docs/guide/09-ci-integration.md) - **I'm moving resources between stacks.** → [`state`](docs/guide/08-state.md) - **Just give me every flag.** → [Reference](docs/reference/index.md) · [CLI](docs/reference/cli.md) · [Configuration](docs/reference/configuration.md) - **How is it built?** → [Architecture](docs/architecture/) · [`DESIGN.md`](docs/DESIGN.md) --- ## Install ```bash go install github.com/Fluent-Health/terraform-stack-plan/cmd/tfstackplan@latest # or go build -o tfstackplan ./cmd/tfstackplan ``` Prebuilt binaries (linux/darwin · amd64/arm64) are on the [Releases](https://github.com/Fluent-Health/terraform-stack-plan/releases) page, which also ships a multi-arch, distroless **Cloud Run container** (entrypoint `serve`). The binary is fully static — pure-Go SQLite, no cgo — and embeds its assets, so the image needs no runtime files. This repo is also **its own [asdf](https://asdf-vm.com) plugin** (hook scripts in [`bin/`](./bin), no separate plugin repo): ```bash asdf plugin add tfstackplan https://github.com/Fluent-Health/terraform-stack-plan.git asdf install tfstackplan latest # or a pinned version asdf set tfstackplan latest # writes .tool-versions ``` Full install detail — toolchain notes, container, deployment — is in [Reference → Install & deploy](docs/reference/install-and-deploy.md). --- ## Agentic Workflows, Extensions & Workspace Skills `tfstackplan` publishes a comprehensive, cross-runtime **Workspace Agent Skill** directly in this repository under `skills/tfstackplan/SKILL.md`. This skill governs the entire lifecycle and CLI surface of `tfstackplan` (lint, plan, state refactoring, watch status, claims, and applies), instructing future coding agents on how to operate this codebase with maximum safety and TDD discipline. ### Loading in Claude Code (Marketplace & Plugins) We package `tfstackplan` as a standard Claude Code plugin. You can load this plugin directly from GitHub or subscribe to our marketplace feed: 1. **Install directly as a Claude Plugin:** ```bash /plugin add https://github.com/Fluent-Health/terraform-stack-plan ``` 2. **Add as a Marketplace Catalog:** ```bash /plugin marketplace add https://raw.githubusercontent.com/Fluent-Health/terraform-stack-plan/main/.claude-plugin/marketplace.json ``` *Claude Code will automatically detect `.claude-plugin/plugin.json` and load the configured `./skills` on demand when your session context matches the skill's frontmatter description, executing these instructions natively via the Claude `Skill` tool.* ### Loading in Gemini CLI You can install this repository's agent skill and extensions globally or link them locally during development: 1. **Install globally as a Gemini Extension:** ```bash gemini extensions install https://github.com/Fluent-Health/terraform-stack-plan ``` 2. **Link the skill locally:** ```bash gemini skills link ./skills/tfstackplan ``` *Once loaded, Gemini CLI will automatically trigger and follow this skill whenever you ask the model to validate, plan, or restructure Terraform state.* ### Manual / Cross-Runtime Loading Both Claude Code and Gemini CLI support the open [Agent Skills](https://agentskills.io) standard, enabling cross-runtime interoperability: 1. **Create the global skill directory:** ```bash mkdir -p ~/.agents/skills/tfstackplan ``` 2. **Symlink or copy the skill file:** ```bash ln -s "$(pwd)/skills/tfstackplan/SKILL.md" ~/.agents/skills/tfstackplan/SKILL.md ``` --- ## When *not* to use this Honesty up front saves everyone a wasted afternoon: - **One root module, one plan per PR.** If `terraform plan` already produces a single readable diff, you don't need a *multi*-plan renderer. Reach for [`tfplan2md`](https://github.com/oocx/tfplan2md) or [`terraform-plan-summary`](https://github.com/dineshba/terraform-plan-summary). - **You want the tool to run `terraform` for you.** `render` doesn't; its inputs are pre-existing `plan.json` files. (`run` *does* drive Terraform via Terramate — that's a different face.) - **You want it to post comments for you.** `render` writes Markdown; your CI posts it. (`serve` posts its own check runs, but that's the control plane, not the renderer.) - **You need static-analysis rollups** (Checkov / Trivy / SARIF). Not today; possibly later. --- ## Related tools Yes, it's another Terraform tool. We're as surprised as you are. The difference is the **multi-plan** part — taking the many plans a monorepo emits per PR and making them one reviewable, gate-able, observable thing: - [`tfplan2md`](https://github.com/oocx/tfplan2md) — single-plan Markdown renderer; the inspiration for the per-stack diff style. - [Atlantis](https://www.runatlantis.io/) — PR-comment-driven Terraform CI; renders per-project, tied to its own workflow. - [`terraform-plan-summary`](https://github.com/dineshba/terraform-plan-summary) — single-plan summary table; no multi-plan support. --- ## Contributing Contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). For security issues, follow [SECURITY.md](SECURITY.md) rather than opening a public issue. ## License Licensed under the Apache License, Version 2.0 — see [LICENSE](LICENSE). --- Built and maintained by [Fluent Health](https://github.com/Fluent-Health).