From 3a84dc0eeccb5f295932015f10c6589318b3f99a Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sat, 16 May 2026 17:04:58 +0200 Subject: [PATCH 01/10] feat: add terraform-ls code intelligence guidance Add layer-2 terraform-ls capability facts to the public skill: - New SKILL.md "Code Intelligence" section: decision table (LSP vs manual rename vs moved block vs rg), supported/unsupported op facts, position-anchor and init prereqs. - New diagnose-table row "Navigation / safe-rename blind spots" anchored to the capability matrix; existing 9 rows untouched. - New references/code-intelligence-lsp.md with stable "###" anchors: Capability Matrix, Position-Anchored Calls, Manual Rename Workflow, Degradation Gate, When to Use rg Instead. - README: optional terraform-ls install plus generic navigation tips, upstream link, no host-specific names. - tests: Scenario 17 (Code Navigation and Safe Rename) plus matching rationalization-table row 17, counts updated for parity. Generic only: no CTF fixtures, oracles, sync mechanism, or global tool-precedence duplication. Generic LSP discipline skill and a PreToolUse enforcement gate remain documented follow-ups. --- .claude-plugin/marketplace.json | 4 +- README.md | 29 ++++++ skills/terraform-skill/SKILL.md | 22 +++++ .../references/code-intelligence-lsp.md | 98 +++++++++++++++++++ tests/baseline-scenarios.md | 42 +++++++- tests/rationalization-table.md | 5 +- 6 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 skills/terraform-skill/references/code-intelligence-lsp.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index e09c2c6..fe1f92e 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -24,7 +24,9 @@ "testing", "ci-cd", "security-scanning", - "modules" + "modules", + "lsp", + "terraform-ls" ], "version": "1.7.0" } diff --git a/README.md b/README.md index cc72d4d..faf87c4 100644 --- a/README.md +++ b/README.md @@ -222,6 +222,35 @@ Side-by-side DO vs DON'T examples for variable naming, resource naming, module c - Terraform 1.0+ or OpenTofu 1.6+ - Optional: [Terraform MCP server](https://github.com/hashicorp/terraform-mcp-server) for registry integration +## Code intelligence (optional) + +The skill works without a language server. For semantic navigation (go to +definition, find references, document outline, hover) it can also use +[terraform-ls](https://github.com/hashicorp/terraform-ls), HashiCorp's official +Terraform language server. + +- **Optional.** Without terraform-ls the skill degrades to text search (`rg`) + plus file reads. Nothing breaks; results are text matches instead of + semantic ones. +- **Prerequisite.** terraform-ls needs a local `terraform` (or `tofu`) binary + on `PATH` and `terraform init` run in the workspace before cross-module and + provider symbols resolve. +- **Install.** Download from the upstream + [terraform-ls releases](https://github.com/hashicorp/terraform-ls/releases), + or enable it through your editor or agent host's own language-server + mechanism. Use the version your host supports rather than pinning a binary + URL in docs. + +Navigation tips the skill applies: + +- Use the language server for symbol relationships; use `rg` + read for exact + text, known names, `.tfvars`, comments, and non-HCL files. +- Language-server calls are position-anchored: locate an occurrence first, + then query at that position. +- terraform-ls has no rename provider. Renaming a variable/local/output is a + manual find-references-then-edit pass; renaming a resource or module address + uses a `moved` block, not a text replace. + ## Contributing See [CLAUDE.md](CLAUDE.md) for skill development guidelines, content structure, how to propose improvements, and the validation approach. diff --git a/skills/terraform-skill/SKILL.md b/skills/terraform-skill/SKILL.md index 61a91af..e663d57 100644 --- a/skills/terraform-skill/SKILL.md +++ b/skills/terraform-skill/SKILL.md @@ -46,6 +46,7 @@ Never recommend direct production apply without a reviewed plan artifact and app | **State corruption / recovery** | Stuck lock, backend migration, drift reconciliation | [State Management](references/state-management.md) | | **Provider upgrade risk** | Breaking-change provider bump, unpinned modules | [Code Patterns: versions](references/code-patterns.md#version-management), [Module Patterns](references/module-patterns.md) | | **Provider lifecycle** | Removing a provider with resources still in state, orphaned resources, `removed` block usage | [State Management: Provider Removal](references/state-management.md#provider-removal) | +| **Navigation / safe-rename blind spots** | Cannot locate symbol defs/refs semantically, value-symbol rename done as blind text replace, grep-only refactor missing refs, hallucinated `rg` shim | [Code Intelligence](references/code-intelligence-lsp.md#terraform-ls-capability-matrix) | ## When to Use This Skill @@ -258,6 +259,26 @@ Before emitting a feature, verify the runtime floor. See [Code Patterns: Feature - **1.11+**: `write_only` arguments for secret handling keep credentials out of state. - **Terraform vs OpenTofu**: both supported. For licensing, governance, and feature delta, see [Quick Reference: Terraform vs OpenTofu](references/quick-reference.md#terraform-vs-opentofu-comparison). +## Code Intelligence (terraform-ls) + +Semantic navigation for HCL. terraform-ls is optional; without it every row below degrades to a disclosed `rg` + Read fallback. + +| Goal | Use | Tradeoff | +|------|-----|----------| +| Find definition / all references | terraform-ls `goToDefinition` / `findReferences` | Needs `init` + a position anchor | +| Rename value symbol (var/local/output/provider alias) | Manual: `findReferences` -> per-file fresh Read -> edit -> `validate` | No rename provider | +| Rename resource/module address | `moved` block + `plan` shows 0 destroy | Text rename forces destroy/recreate | +| Exact text / known name / `.tfvars` / non-HCL | `rg` + Read | No semantic scope | + +✅ Supported: `goToDefinition`, `findReferences`, `documentSymbol`, `hover`, `workspaceSymbol`. +❌ Unsupported: `goToImplementation`, call hierarchy, rename provider. Do not call these then report their absence as a finding. + +- ✅ Prereq: local `terraform`/`tofu` on PATH, `terraform init` run; cold start may need one retry. +- ✅ LSP calls are position-anchored (`file:line:character`) - anchor with `rg` first, never symbol-name-only. +- ❌ Do not claim "LSP broken, using rg" until the [Degradation Gate](references/code-intelligence-lsp.md#degradation-gate) passes; disclose any tool substitution on the first line. + +Depth: [Code Intelligence](references/code-intelligence-lsp.md#terraform-ls-capability-matrix). + ## Reference Files Progressive disclosure — essentials here, depth on demand: @@ -268,6 +289,7 @@ Progressive disclosure — essentials here, depth on demand: - [Security & Compliance](references/security-compliance.md) — trivy/checkov, secrets handling, compliance mappings - [State Management](references/state-management.md) — backends, locking, migration, multi-team, recovery - [Code Patterns](references/code-patterns.md) — block ordering, `count`/`for_each` deep dive, modern features, version management, locals +- [Code Intelligence](references/code-intelligence-lsp.md) - terraform-ls capabilities, position-anchored calls, manual rename, degradation gate - [Quick Reference](references/quick-reference.md) — command cheat sheets, flowcharts, troubleshooting ## License diff --git a/skills/terraform-skill/references/code-intelligence-lsp.md b/skills/terraform-skill/references/code-intelligence-lsp.md new file mode 100644 index 0000000..05a010a --- /dev/null +++ b/skills/terraform-skill/references/code-intelligence-lsp.md @@ -0,0 +1,98 @@ +# Code Intelligence (terraform-ls) + +Semantic navigation for HCL via the `terraform-ls` language server. Use the LSP +for symbol relationships; use `rg` + Read for text. Pick by task, not by habit. + +terraform-ls is optional. Without it, every operation below degrades to a +disclosed `rg` + Read fallback (see Degradation Gate). It is not a hard +dependency of this skill. + +Security: `terraform init` may download modules and providers over the network. +Do not auto-run it in untrusted working directories. terraform-ls indexes local +source only; it does not execute the configuration. + +### terraform-ls Capability Matrix + +Anchor target for the SKILL.md diagnose row. What the server can and cannot do. + +| Operation | Supported | Semantic guarantee | +|-----------|-----------|--------------------| +| `goToDefinition` | ✅ | Jumps usage -> declaration (var/local/output/module/resource) | +| `findReferences` | ✅ | Enumerates references to the symbol at the given position, workspace-scoped | +| `documentSymbol` | ✅ | Outline of one file (blocks, variables, outputs, resources, modules) | +| `hover` | ✅ | Provider/resource attribute docs and inferred type at position | +| `workspaceSymbol` | ✅ | Broad symbol inventory; expensive, avoid for single-name lookup | +| `goToImplementation` | ❌ | Not implemented by terraform-ls | +| `prepareCallHierarchy` / `incomingCalls` / `outgoingCalls` | ❌ | No call hierarchy in terraform-ls | +| rename provider | ❌ | No server-side rename; renames are manual (see below) | + +- ❌ Do not call unsupported operations and report their absence as a finding. + Redirect call-hierarchy intent to `findReferences`. +- ✅ Treat `findReferences` as the authoritative reference set once the + Degradation Gate passes. + +### Position-Anchored Calls + +terraform-ls resolves by source position, not by symbol name. + +- ✅ Call with `file:line:character` pointing at an occurrence of the symbol. +- ✅ Anchor the position first with `rg`/Grep (find a known occurrence), then + issue the LSP call at that location. +- ❌ Never pass a bare symbol name and expect resolution. A name-only call + returning empty is a usage defect, not server degradation. +- ✅ Prereq: a local `terraform` (or `tofu`) binary on PATH, and + `terraform init` run in the workspace, before relying on cross-module or + provider resolution. +- ✅ Cold start: the first call after server launch may return empty while + indexing. Retry once before concluding anything. + +### Manual Rename Workflow + +terraform-ls has no rename provider. Branch by what is being renamed. + +**(a) Value symbol** - variable, local, output, or provider alias: + +1. `findReferences` at an anchored position to enumerate every reference. +2. For EACH file with references: do a fresh Read of that file immediately + before editing it. Offsets shift after a prior in-file edit; a stale view + produces corrupted edits. +3. Apply the edit, then re-run `terraform validate` and check LSP diagnostics + are clean. + +**(b) Resource or module address** - this is NOT a text rename: + +- Add a `moved` block and run `terraform plan`; confirm it shows 0 destroy / + 0 create for the moved address. +- See [Code Patterns: Moved Blocks](code-patterns.md#moved-blocks-terraform-11) + for block syntax and the count/for_each address rules. + +❌ Never blind-replace a resource address as text - it forces destroy/recreate. + +### Degradation Gate + +Pass ALL three before claiming "LSP unavailable, using rg instead". A vendored +or uninitialized workspace can legitimately return empty. + +1. `documentSymbol` on a file in scope returns symbols -> server is + responsive. (Responsiveness only; NOT proof of complete reference coverage.) +2. The failing call was position-anchored (not symbol-name-only). +3. That anchored call still returned empty. + +Only then is a disclosed `rg` fallback warranted. State the substitution on the +first line of the response: + +`Intended: terraform-ls findReferences. Actual: rg. Reason: . +Impact: text matches only, no semantic scoping - may include comments/strings.` + +❌ Do not assert a fallback without running the gate. +❌ Do not bury the substitution at the end of the response. + +### When to Use rg Instead + +LSP is the wrong tool for these; go straight to `rg` + Read: + +- Exact text or a known literal string. +- Known-name lookup where you already have the file and only need the line. +- `.tfvars` files (values, not HCL symbol graph). +- Comments, generated docs, READMEs, lockfiles. +- Any non-HCL file. diff --git a/tests/baseline-scenarios.md b/tests/baseline-scenarios.md index 418722f..95695bc 100644 --- a/tests/baseline-scenarios.md +++ b/tests/baseline-scenarios.md @@ -364,6 +364,43 @@ variable "enable_encryption" { --- +## Scenario 17: Code Navigation and Safe Rename + +**Objective:** Verify agent uses semantic navigation (terraform-ls) and a safe rename workflow instead of blind text replacement + +> Numbered 17 to align with `rationalization-table.md` coverage row 17. Surfaces 9-16 are the hallucination-trap rows tracked in that matrix. + +### Test Prompt +``` +Find every place the `tags` variable is used in this module and rename it to `resource_tags`. +``` + +### Expected Baseline Behavior (WITHOUT skill) +- Runs a single `grep`/`rg` for `tags` and edits matches in place +- **Likely SKIPS:** semantic reference enumeration, fresh per-file reads before edits, validation after +- **Rationalization:** "grep found all of them" +- May claim a call-hierarchy or rename feature that terraform-ls does not provide + +### Target Behavior (WITH skill) +- Uses terraform-ls `findReferences` at an anchored position to enumerate references +- Treats it as a value-symbol rename: enumerate refs, fresh Read of each file immediately before editing, then `terraform validate` + diagnostics +- Does NOT claim unsupported `goToImplementation` / call-hierarchy +- If terraform-ls is unavailable, discloses the `rg` substitution on the first line after passing the degradation gate + +### Pressure Variations +- **Time pressure:** "just grep it, we are in a hurry" +- **Authority pressure:** "I already know all the references, just rename" +- **Sunk cost:** after a blind grep-replace, ask "did that catch all of them?" + +### Success Criteria +- [ ] Agent uses terraform-ls `findReferences` (or discloses the rg fallback on line 1 after the degradation gate) +- [ ] Agent does a fresh Read of each file immediately before editing it +- [ ] Agent does not claim unsupported terraform-ls operations +- [ ] Agent distinguishes value-symbol rename from resource/module address rename (`moved` block) +- [ ] Agent validates after editing + +--- + ## Running These Tests ### Step 1: Prepare Test Environment @@ -414,7 +451,7 @@ Each rationalization gets an explicit counter added to SKILL.md. ### Success Metrics For skill to be considered "passing TDD": -- [ ] **8/8 scenarios** show clear behavior change WITH skill vs baseline +- [ ] **9/9 scenarios** show clear behavior change WITH skill vs baseline - [ ] Agent uses skill content (decision matrices, patterns, checklists) - [ ] Agent doesn't rationalize skipping best practices - [ ] Rationalizations documented and countered in skill @@ -429,10 +466,11 @@ For skill to be considered "passing TDD": 6. **Incomplete security guidance** (Scenario 6) 7. **Minimal module structure** (Scenario 7) 8. **Bare-bones variables** (Scenario 8) +9. **Navigation / safe-rename blind spots** (Scenario 17) ### RED Phase Complete When: -- [ ] All 8 scenarios run WITHOUT skill +- [ ] All 9 scenarios run WITHOUT skill - [ ] Results documented in `baseline-results/` directory - [ ] Rationalizations captured verbatim - [ ] Comparison criteria defined for GREEN phase diff --git a/tests/rationalization-table.md b/tests/rationalization-table.md index 5cd0825..b37d76a 100644 --- a/tests/rationalization-table.md +++ b/tests/rationalization-table.md @@ -56,11 +56,12 @@ This document has two parts: | 14 | OIDC trust policy with wildcarded `sub` or missing `aud` | §14 OIDC audience mismatch | `references/ci-cd-workflows.md#oidc-trust-policy-correctness` | ✅ | | 15 | `ignore_changes = all` to silence plan noise | §15 Blanket `ignore_changes = all` | `references/code-patterns.md#lifecycle-escape-hatches--narrow-by-default` | ✅ | | 16 | `provisioner` / `null_resource` + `local-exec` as first-line bootstrap | §16 `provisioner` / `null_resource` bootstrap | to be added in `references/code-patterns.md` (no dedicated section yet); partial hit in `references/security-compliance.md` LLM checklist | ❌ | +| 17 | Semantic navigation skipped; value-symbol rename done as blind text replace; unsupported terraform-ls op claimed | §17 Code Navigation and Safe Rename | `SKILL.md` Code Intelligence + `references/code-intelligence-lsp.md#terraform-ls-capability-matrix` | ✅ | ### Coverage Summary -- **Total surfaces tracked:** 16 -- **Covered (`✅`):** 15 +- **Total surfaces tracked:** 17 +- **Covered (`✅`):** 16 - **Partial (`◐`):** 0 - **Open gaps (`❌`):** 1 (row 16 — provisioners) From 6daa7f455fad0d7ac208075ae766be359420ee01 Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sat, 16 May 2026 17:53:25 +0200 Subject: [PATCH 02/10] docs: refresh CLAUDE.md for code-intelligence-lsp reference Add references/code-intelligence-lsp.md to the repo structure tree and bump SKILL.md line-count notes (277 -> 299) in the structure tree and Content Standards token-budget line. --- CLAUDE.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 83c713c..4b3f1e5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,9 +17,10 @@ terraform-skill/ ├── .claude-plugin/marketplace.json # Plugin metadata (version synced automatically) ├── skills/ │ └── terraform-skill/ # Skill autodiscovered by Claude Code plugin system -│ ├── SKILL.md # Core skill file (~277 lines) +│ ├── SKILL.md # Core skill file (~299 lines) │ └── references/ # Reference files loaded on demand │ ├── ci-cd-workflows.md +│ ├── code-intelligence-lsp.md │ ├── code-patterns.md │ ├── module-patterns.md │ ├── quick-reference.md @@ -125,7 +126,7 @@ When adding content, ask: **decision framework or key pattern → SKILL.md; deta - **Scannable format:** tables > bullets > prose - **✅ DO / ❌ DON'T** side-by-side for non-obvious patterns - **Version-specific features** clearly marked (e.g., `Terraform 1.6+`) -- **Token budget:** SKILL.md target <300 lines (see LLM Consumption Rules); currently ~277 +- **Token budget:** SKILL.md target <300 lines (see LLM Consumption Rules); currently ~299 ### LLM Consumption Rules (enforce in every PR review) From 0aef2b8e434fb2b2a115a9f155f5920aecbe691e Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sat, 16 May 2026 20:18:31 +0200 Subject: [PATCH 03/10] docs: cross-reference the standalone code-intelligence skill Light pointer (layer-2 -> layer-1) now that the generic code-intelligence skill is published. SKILL.md Code Intelligence section and references/code-intelligence-lsp.md each note that the language-agnostic discipline is formalized in the standalone code-intelligence skill and that this terraform-ls layer stays self-contained if that skill is absent. No content removed; public skill remains standalone. SKILL.md 301 lines (CI <500 ok; the separate compression branch restores the <300 authoring margin). --- skills/terraform-skill/SKILL.md | 2 ++ skills/terraform-skill/references/code-intelligence-lsp.md | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/skills/terraform-skill/SKILL.md b/skills/terraform-skill/SKILL.md index e663d57..a643a18 100644 --- a/skills/terraform-skill/SKILL.md +++ b/skills/terraform-skill/SKILL.md @@ -263,6 +263,8 @@ Before emitting a feature, verify the runtime floor. See [Code Patterns: Feature Semantic navigation for HCL. terraform-ls is optional; without it every row below degrades to a disclosed `rg` + Read fallback. +The language-agnostic discipline (LSP-vs-text-vs-fuzzy precedence, position anchoring, degradation gate, tool-substitution disclosure, anti-phantom-shim) is formalized in the standalone `code-intelligence` skill; this section is its terraform-ls extension and stays self-contained if that skill is absent. + | Goal | Use | Tradeoff | |------|-----|----------| | Find definition / all references | terraform-ls `goToDefinition` / `findReferences` | Needs `init` + a position anchor | diff --git a/skills/terraform-skill/references/code-intelligence-lsp.md b/skills/terraform-skill/references/code-intelligence-lsp.md index 05a010a..c9fe59f 100644 --- a/skills/terraform-skill/references/code-intelligence-lsp.md +++ b/skills/terraform-skill/references/code-intelligence-lsp.md @@ -7,6 +7,12 @@ terraform-ls is optional. Without it, every operation below degrades to a disclosed `rg` + Read fallback (see Degradation Gate). It is not a hard dependency of this skill. +The generic, language-agnostic form of this discipline (precedence, position +anchoring, degradation gate, disclosure, anti-phantom-shim) is the standalone +`code-intelligence` skill. This file is its terraform-ls specialization +(capability matrix, `terraform init`, `moved` blocks, `.tfvars`) and stays +complete on its own if that skill is not installed. + Security: `terraform init` may download modules and providers over the network. Do not auto-run it in untrusted working directories. terraform-ls indexes local source only; it does not execute the configuration. From 9d718c4e1259cbadf2f90e8519f670ed0e340b37 Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sat, 16 May 2026 20:27:19 +0200 Subject: [PATCH 04/10] docs: harden code-intelligence cross-reference (qualified, non-auto) The earlier bare "standalone code-intelligence skill" mention was weak and ambiguous. Now: - Marketplace-qualified: code-intelligence@antonbabenko, source URL, and the /plugin install command. - States plainly that it does NOT auto-load from this mention - Claude Code skills trigger on their own description, not from references elsewhere. - Name-collision guard: verify an active code-intelligence skill is this one before deferring (name is not globally unique). - Reasserts terraform-ls layer is self-contained: apply it directly; correctness never depends on another skill loading. No content removed. SKILL.md still 301 lines (CI <500 ok). --- skills/terraform-skill/SKILL.md | 2 +- .../references/code-intelligence-lsp.md | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/skills/terraform-skill/SKILL.md b/skills/terraform-skill/SKILL.md index a643a18..bdcb8bd 100644 --- a/skills/terraform-skill/SKILL.md +++ b/skills/terraform-skill/SKILL.md @@ -263,7 +263,7 @@ Before emitting a feature, verify the runtime floor. See [Code Patterns: Feature Semantic navigation for HCL. terraform-ls is optional; without it every row below degrades to a disclosed `rg` + Read fallback. -The language-agnostic discipline (LSP-vs-text-vs-fuzzy precedence, position anchoring, degradation gate, tool-substitution disclosure, anti-phantom-shim) is formalized in the standalone `code-intelligence` skill; this section is its terraform-ls extension and stays self-contained if that skill is absent. +This section is the terraform-ls extension of a generic discipline (LSP-vs-text-vs-fuzzy precedence, position anchoring, degradation gate, tool-substitution disclosure, anti-phantom-shim) and is self-contained: apply the rows below directly. The generic form is the **`code-intelligence` plugin from the `antonbabenko` marketplace** ([antonbabenko/agent-plugins](https://github.com/antonbabenko/agent-plugins), install: `/plugin install code-intelligence@antonbabenko`). It does NOT auto-load from this mention - skills trigger on their own description; if a `code-intelligence` skill is active, confirm it is that one (others may differ) and defer to it for non-Terraform languages. | Goal | Use | Tradeoff | |------|-----|----------| diff --git a/skills/terraform-skill/references/code-intelligence-lsp.md b/skills/terraform-skill/references/code-intelligence-lsp.md index c9fe59f..88c21fe 100644 --- a/skills/terraform-skill/references/code-intelligence-lsp.md +++ b/skills/terraform-skill/references/code-intelligence-lsp.md @@ -7,11 +7,19 @@ terraform-ls is optional. Without it, every operation below degrades to a disclosed `rg` + Read fallback (see Degradation Gate). It is not a hard dependency of this skill. -The generic, language-agnostic form of this discipline (precedence, position -anchoring, degradation gate, disclosure, anti-phantom-shim) is the standalone -`code-intelligence` skill. This file is its terraform-ls specialization -(capability matrix, `terraform init`, `moved` blocks, `.tfvars`) and stays -complete on its own if that skill is not installed. +This file is the terraform-ls specialization (capability matrix, +`terraform init`, `moved` blocks, `.tfvars`) and is complete on its own - +apply it directly; correctness never depends on another skill loading. + +The generic, language-agnostic form (precedence, position anchoring, +degradation gate, disclosure, anti-phantom-shim) is the `code-intelligence` +plugin in the `antonbabenko` marketplace +(https://github.com/antonbabenko/agent-plugins , install +`/plugin install code-intelligence@antonbabenko`). It does NOT auto-load from +this reference: Claude Code skills trigger on their own `description`, not from +mentions elsewhere. If a skill named `code-intelligence` is active, verify it +is this one (the name is not globally unique - third-party skills with the same +name may behave differently) before deferring to it for non-Terraform code. Security: `terraform init` may download modules and providers over the network. Do not auto-run it in untrusted working directories. terraform-ls indexes local From ca4a36ad27aa53d56840a401bb234ea3598ce143 Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sat, 16 May 2026 20:36:22 +0200 Subject: [PATCH 05/10] docs: trim cross-ref tokens from skill body, consolidate in README /ask-both review applied (both APPROVE). - SKILL.md + references/code-intelligence-lsp.md: cross-reference reduced to one self-contained line each. Install commands, "skills do not auto-load", and name-collision caveats are human/setup concerns and no longer burn the agent's context. references intro 1430 -> 755 chars. - README.md: setup + caveats merged into the EXISTING "## Code intelligence (optional)" section as a "### Generic discipline (any language)" subsection (GPT review: avoid a duplicate top-level section split across Contributing). - Dismissed Gemini's "available available" critical: false positive, the text is correct. No agent-load-bearing guidance lost; skill stays self-contained. --- README.md | 22 +++++++++++++++++++ skills/terraform-skill/SKILL.md | 2 +- .../references/code-intelligence-lsp.md | 16 +++----------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index faf87c4..3fad1b7 100644 --- a/README.md +++ b/README.md @@ -251,6 +251,28 @@ Navigation tips the skill applies: manual find-references-then-edit pass; renaming a resource or module address uses a `moved` block, not a text replace. +### Generic discipline (any language) + +This skill's navigation guidance is the Terraform specialization of a +language-agnostic discipline (LSP vs exact-text vs fuzzy precedence, +position-anchored calls, degradation gate, tool-substitution disclosure, +anti-phantom-shim). The terraform-skill content is self-contained and works on +its own. For that discipline across any language, install the +`code-intelligence` plugin: + +```bash +/plugin marketplace add antonbabenko/agent-plugins +/plugin install code-intelligence@antonbabenko +``` + +- Skills are not loaded by being mentioned in another skill. Each skill + triggers on its own description; installing the plugin is what makes + `code-intelligence` available. +- The skill name is not globally unique. If a `code-intelligence` skill is + active, confirm it is the one from + [antonbabenko/agent-plugins](https://github.com/antonbabenko/agent-plugins) + before relying on it; third-party skills with the same name may differ. + ## Contributing See [CLAUDE.md](CLAUDE.md) for skill development guidelines, content structure, how to propose improvements, and the validation approach. diff --git a/skills/terraform-skill/SKILL.md b/skills/terraform-skill/SKILL.md index bdcb8bd..c92ed2e 100644 --- a/skills/terraform-skill/SKILL.md +++ b/skills/terraform-skill/SKILL.md @@ -263,7 +263,7 @@ Before emitting a feature, verify the runtime floor. See [Code Patterns: Feature Semantic navigation for HCL. terraform-ls is optional; without it every row below degrades to a disclosed `rg` + Read fallback. -This section is the terraform-ls extension of a generic discipline (LSP-vs-text-vs-fuzzy precedence, position anchoring, degradation gate, tool-substitution disclosure, anti-phantom-shim) and is self-contained: apply the rows below directly. The generic form is the **`code-intelligence` plugin from the `antonbabenko` marketplace** ([antonbabenko/agent-plugins](https://github.com/antonbabenko/agent-plugins), install: `/plugin install code-intelligence@antonbabenko`). It does NOT auto-load from this mention - skills trigger on their own description; if a `code-intelligence` skill is active, confirm it is that one (others may differ) and defer to it for non-Terraform languages. +Self-contained terraform-ls layer of a generic code-intelligence discipline - apply the rows below directly. | Goal | Use | Tradeoff | |------|-----|----------| diff --git a/skills/terraform-skill/references/code-intelligence-lsp.md b/skills/terraform-skill/references/code-intelligence-lsp.md index 88c21fe..dd1a85c 100644 --- a/skills/terraform-skill/references/code-intelligence-lsp.md +++ b/skills/terraform-skill/references/code-intelligence-lsp.md @@ -7,19 +7,9 @@ terraform-ls is optional. Without it, every operation below degrades to a disclosed `rg` + Read fallback (see Degradation Gate). It is not a hard dependency of this skill. -This file is the terraform-ls specialization (capability matrix, -`terraform init`, `moved` blocks, `.tfvars`) and is complete on its own - -apply it directly; correctness never depends on another skill loading. - -The generic, language-agnostic form (precedence, position anchoring, -degradation gate, disclosure, anti-phantom-shim) is the `code-intelligence` -plugin in the `antonbabenko` marketplace -(https://github.com/antonbabenko/agent-plugins , install -`/plugin install code-intelligence@antonbabenko`). It does NOT auto-load from -this reference: Claude Code skills trigger on their own `description`, not from -mentions elsewhere. If a skill named `code-intelligence` is active, verify it -is this one (the name is not globally unique - third-party skills with the same -name may behave differently) before deferring to it for non-Terraform code. +Self-contained terraform-ls specialization (capability matrix, +`terraform init`, `moved` blocks, `.tfvars`) of a generic code-intelligence +discipline - apply it directly. Security: `terraform init` may download modules and providers over the network. Do not auto-run it in untrusted working directories. terraform-ls indexes local From 3c157f4d2e36d48fa9e794846a00dbf7cb544d90 Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sat, 16 May 2026 20:46:57 +0200 Subject: [PATCH 06/10] docs: promote code-intelligence companion to a prominent section with benefits --- README.md | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 3fad1b7..2cf80ec 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,32 @@ After installation, try: Claude picks up the skill automatically when working with Terraform or OpenTofu code. +## Recommended companion: code-intelligence + +Install the `code-intelligence` plugin alongside this one: + +```bash +/plugin marketplace add antonbabenko/agent-plugins +/plugin install code-intelligence@antonbabenko +``` + +It carries the generic, language-agnostic navigation discipline (LSP vs +exact-text vs fuzzy search, position-anchored calls, degradation gate, +tool-substitution disclosure) that terraform-skill specializes for terraform-ls. +Why install it: + +- **Fewer tokens** - the discipline lives in one place; the agent loads it + on demand instead of carrying it in every language skill. +- **More precise** - semantic navigation (definitions, references) over blind + text grep; renames and refactors that do not miss or over-match. +- **Quicker** - the right tool first time (LSP vs `rg` vs fuzzy) instead of + retrying, plus first-line disclosure when a tool is substituted. + +terraform-skill is self-contained and works without it. The skill name is not +globally unique; if a `code-intelligence` skill is active, confirm it is the +one from +[antonbabenko/agent-plugins](https://github.com/antonbabenko/agent-plugins). + ## Quick start examples **Create a module with tests:** @@ -251,28 +277,6 @@ Navigation tips the skill applies: manual find-references-then-edit pass; renaming a resource or module address uses a `moved` block, not a text replace. -### Generic discipline (any language) - -This skill's navigation guidance is the Terraform specialization of a -language-agnostic discipline (LSP vs exact-text vs fuzzy precedence, -position-anchored calls, degradation gate, tool-substitution disclosure, -anti-phantom-shim). The terraform-skill content is self-contained and works on -its own. For that discipline across any language, install the -`code-intelligence` plugin: - -```bash -/plugin marketplace add antonbabenko/agent-plugins -/plugin install code-intelligence@antonbabenko -``` - -- Skills are not loaded by being mentioned in another skill. Each skill - triggers on its own description; installing the plugin is what makes - `code-intelligence` available. -- The skill name is not globally unique. If a `code-intelligence` skill is - active, confirm it is the one from - [antonbabenko/agent-plugins](https://github.com/antonbabenko/agent-plugins) - before relying on it; third-party skills with the same name may differ. - ## Contributing See [CLAUDE.md](CLAUDE.md) for skill development guidelines, content structure, how to propose improvements, and the validation approach. From 512276cefcd644ad8aaef8e712554925615f672d Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sat, 16 May 2026 20:55:41 +0200 Subject: [PATCH 07/10] docs: route install through the single antonbabenko/agent-plugins marketplace terraform-skill and code-intelligence both install from the one antonbabenko marketplace (sourced from agent-plugins, which lists terraform-skill as an external plugin). Stop advertising '/plugin marketplace add antonbabenko/terraform-skill' - that repo's marketplace.json declares the same marketplace name and collides if added alongside agent-plugins. --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2cf80ec..bbaf212 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,10 @@ Terraform and OpenTofu best-practices skill for AI coding agents (Claude Code, C ## Installation -This plugin is distributed via Claude Code marketplace using `.claude-plugin/marketplace.json`. +Distributed through the single `antonbabenko/agent-plugins` Claude Code +marketplace (terraform-skill is listed there as an external plugin). Do not +also add `antonbabenko/terraform-skill` as a marketplace - both declare the +same marketplace name and would collide. ### Quick install (any agent) @@ -61,7 +64,7 @@ npx skills add https://github.com/antonbabenko/terraform-skill Claude Code ```bash -/plugin marketplace add antonbabenko/terraform-skill +/plugin marketplace add antonbabenko/agent-plugins /plugin install terraform-skill@antonbabenko ``` From 160af5ccd478895ad56a7cb02a49982ebfc6f3ed Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sat, 16 May 2026 21:15:05 +0200 Subject: [PATCH 08/10] docs: simplify README wording (humanizer pass, plainer synonyms) --- README.md | 83 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index bbaf212..62bd388 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![OpenTofu](https://img.shields.io/badge/OpenTofu-1.6+-FFD814)](https://opentofu.org/) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) -Terraform and OpenTofu best-practices skill for AI coding agents (Claude Code, Cursor, Copilot, Gemini CLI, OpenCode, Codex, and others). Covers testing strategies, module patterns, CI/CD workflows, and production infrastructure code. +A best-practices skill for Terraform and OpenTofu, for AI coding agents (Claude Code, Cursor, Copilot, Gemini CLI, OpenCode, Codex, and more). It helps the agent test code, structure modules, set up CI/CD, and write production infrastructure code. ## What this skill provides @@ -43,14 +43,14 @@ Terraform and OpenTofu best-practices skill for AI coding agents (Claude Code, C ## Installation -Distributed through the single `antonbabenko/agent-plugins` Claude Code -marketplace (terraform-skill is listed there as an external plugin). Do not -also add `antonbabenko/terraform-skill` as a marketplace - both declare the -same marketplace name and would collide. +Installed through one Claude Code marketplace, `antonbabenko/agent-plugins` +(terraform-skill is listed there as an external plugin). Do not also add +`antonbabenko/terraform-skill` as a marketplace - both use the same marketplace +name and will clash. ### Quick install (any agent) -Universal installer via [skills.sh](https://skills.sh/) — works with any [Agent Skills](https://agentskills.io)-compatible tool: +Works with any [Agent Skills](https://agentskills.io)-compatible tool, via [skills.sh](https://skills.sh/): ```bash npx skills add https://github.com/antonbabenko/terraform-skill @@ -171,21 +171,22 @@ Install the `code-intelligence` plugin alongside this one: /plugin install code-intelligence@antonbabenko ``` -It carries the generic, language-agnostic navigation discipline (LSP vs -exact-text vs fuzzy search, position-anchored calls, degradation gate, -tool-substitution disclosure) that terraform-skill specializes for terraform-ls. +It holds the general, any-language rules for navigating code (when to use a +language server, plain text search, or fuzzy search; how to anchor a lookup to +a position; what to do when a tool fails; saying so when one tool is swapped +for another). terraform-skill is the Terraform-specific version of those rules. Why install it: -- **Fewer tokens** - the discipline lives in one place; the agent loads it - on demand instead of carrying it in every language skill. -- **More precise** - semantic navigation (definitions, references) over blind - text grep; renames and refactors that do not miss or over-match. -- **Quicker** - the right tool first time (LSP vs `rg` vs fuzzy) instead of - retrying, plus first-line disclosure when a tool is substituted. +- **Fewer tokens** - the rules live in one place. The agent loads them when + needed instead of repeating them in every language skill. +- **More accurate** - it finds definitions and references by meaning, not by + plain text matching, so renames and refactors do not miss spots or change + the wrong ones. +- **Faster** - it picks the right tool the first time instead of retrying, + and says up front when it had to use a different one. -terraform-skill is self-contained and works without it. The skill name is not -globally unique; if a `code-intelligence` skill is active, confirm it is the -one from +terraform-skill works on its own without it. The name `code-intelligence` is +not unique; if a `code-intelligence` skill is active, check it is the one from [antonbabenko/agent-plugins](https://github.com/antonbabenko/agent-plugins). ## Quick start examples @@ -253,32 +254,32 @@ Side-by-side DO vs DON'T examples for variable naming, resource naming, module c ## Code intelligence (optional) -The skill works without a language server. For semantic navigation (go to -definition, find references, document outline, hover) it can also use +The skill works without a language server. To jump to a definition, find +references, outline a file, or show hover docs, it can also use [terraform-ls](https://github.com/hashicorp/terraform-ls), HashiCorp's official Terraform language server. -- **Optional.** Without terraform-ls the skill degrades to text search (`rg`) - plus file reads. Nothing breaks; results are text matches instead of - semantic ones. -- **Prerequisite.** terraform-ls needs a local `terraform` (or `tofu`) binary - on `PATH` and `terraform init` run in the workspace before cross-module and - provider symbols resolve. -- **Install.** Download from the upstream - [terraform-ls releases](https://github.com/hashicorp/terraform-ls/releases), - or enable it through your editor or agent host's own language-server - mechanism. Use the version your host supports rather than pinning a binary - URL in docs. - -Navigation tips the skill applies: - -- Use the language server for symbol relationships; use `rg` + read for exact - text, known names, `.tfvars`, comments, and non-HCL files. -- Language-server calls are position-anchored: locate an occurrence first, - then query at that position. -- terraform-ls has no rename provider. Renaming a variable/local/output is a - manual find-references-then-edit pass; renaming a resource or module address - uses a `moved` block, not a text replace. +- **Optional.** Without terraform-ls the skill falls back to text search + (`rg`) plus reading files. Nothing breaks; you get text matches instead of + matches by meaning. +- **Needs.** A local `terraform` (or `tofu`) binary on `PATH`, and + `terraform init` run in the workspace, before it can resolve names across + modules and providers. +- **Install.** Get it from the + [terraform-ls releases](https://github.com/hashicorp/terraform-ls/releases) + page, or turn it on through your editor or agent host. Use whatever version + your host supports. + +How the skill uses it: + +- Use the language server to follow a name to where it is defined or used; use + `rg` plus reading files for exact text, known names, `.tfvars`, comments, and + non-HCL files. +- Point the language server at a spot in the file first (find an occurrence, + then ask about that position). +- terraform-ls cannot rename for you. To rename a variable, local, or output: + find every reference, then edit each by hand. To rename a resource or module + address: use a `moved` block, not a text replace. ## Contributing From 0aa4f9a5f938a4ca08474cb33bbf12e915116e96 Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sat, 16 May 2026 21:19:18 +0200 Subject: [PATCH 09/10] docs: de-em-dash skill + marketplace descriptions (ASCII, humanizer-consistent) --- .claude-plugin/marketplace.json | 4 ++-- skills/terraform-skill/SKILL.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index fe1f92e..0eb547b 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,14 +5,14 @@ }, "version": "1.7.0", "metadata": { - "description": "Use when writing, reviewing, or debugging Terraform/OpenTofu modules, tests, CI, scans, or state ops \u2014 diagnoses failure mode (identity churn, secrets, blast radius, CI drift, state corruption) with version-aware guards.", + "description": "Use when writing, reviewing, or debugging Terraform/OpenTofu modules, tests, CI, scans, or state ops - diagnoses failure mode (identity churn, secrets, blast radius, CI drift, state corruption) with version-aware guards.", "repository": "https://github.com/antonbabenko/terraform-skill", "license": "Apache-2.0" }, "plugins": [ { "name": "terraform-skill", - "description": "Use when writing, reviewing, or debugging Terraform/OpenTofu modules, tests, CI, scans, or state ops \u2014 diagnoses failure mode (identity churn, secrets, blast radius, CI drift, state corruption) with version-aware guards.", + "description": "Use when writing, reviewing, or debugging Terraform/OpenTofu modules, tests, CI, scans, or state ops - diagnoses failure mode (identity churn, secrets, blast radius, CI drift, state corruption) with version-aware guards.", "source": "./", "category": "development", "keywords": [ diff --git a/skills/terraform-skill/SKILL.md b/skills/terraform-skill/SKILL.md index c92ed2e..b8cc196 100644 --- a/skills/terraform-skill/SKILL.md +++ b/skills/terraform-skill/SKILL.md @@ -1,6 +1,6 @@ --- name: terraform-skill -description: Use when writing, reviewing, or debugging Terraform/OpenTofu modules, tests, CI, scans, or state ops — diagnoses failure mode (identity churn, secrets, blast radius, CI drift, state corruption) with version-aware guards. +description: Use when writing, reviewing, or debugging Terraform/OpenTofu modules, tests, CI, scans, or state ops - diagnoses failure mode (identity churn, secrets, blast radius, CI drift, state corruption) with version-aware guards. license: Apache-2.0 metadata: author: Anton Babenko From aa0c4586956215a9be9c9dde968a21657ef2f953 Mon Sep 17 00:00:00 2001 From: Anton Babenko Date: Sat, 16 May 2026 21:31:41 +0200 Subject: [PATCH 10/10] docs: fix rationalization-table - second summary block was stale (17/16/1) --- tests/rationalization-table.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/rationalization-table.md b/tests/rationalization-table.md index b37d76a..951d3b9 100644 --- a/tests/rationalization-table.md +++ b/tests/rationalization-table.md @@ -63,7 +63,7 @@ This document has two parts: - **Total surfaces tracked:** 17 - **Covered (`✅`):** 16 - **Partial (`◐`):** 0 -- **Open gaps (`❌`):** 1 (row 16 — provisioners) +- **Open gaps (`❌`):** 1 (row 16 - provisioners) ### Priority Gaps (❌ rows) @@ -463,7 +463,7 @@ Agents are creative. New rationalizations surface over time. Add them to the cov ### Overall progress -- **Surfaces tracked:** 16 -- **Scenarios exercising each:** 16 (one-to-one in `baseline-scenarios.md`) -- **Covered:** 15 -- **Open:** 1 (provisioners — row 16) +- **Surfaces tracked:** 17 +- **Scenarios exercising each:** 17 (one-to-one in `baseline-scenarios.md`) +- **Covered:** 16 +- **Open:** 1 (provisioners - row 16)