← スキル一覧に戻る

tfc-plan-json
by laurigates
Claude Code plugins for development workflows
⭐ 2🍴 0📅 2026年1月24日
SKILL.md
model: haiku created: 2025-12-16 modified: 2025-12-16 reviewed: 2025-12-16 name: tfc-plan-json description: Download and analyze structured Terraform plan JSON output from Terraform Cloud. Use when analyzing resource changes, diffing infrastructure, or programmatically inspecting plan details. Requires TFE_TOKEN environment variable. allowed-tools: Bash, Read
Terraform Cloud Plan JSON
Download and analyze structured plan JSON output from Terraform Cloud runs for detailed resource change analysis.
Prerequisites
export TFE_TOKEN="your-api-token" # User or team token with admin workspace access
export TFE_ADDRESS="app.terraform.io" # Optional
Core Commands
Download Plan JSON
#!/bin/bash
set -euo pipefail
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
BASE_URL="https://${TFE_ADDRESS:-app.terraform.io}/api/v2"
RUN_ID="${1:?Usage: $0 <run-id> [output-file]}"
OUTPUT="${2:-plan.json}"
# Download with redirect following (API returns 307)
curl -Lsf --header "Authorization: Bearer $TOKEN" \
-o "$OUTPUT" \
"$BASE_URL/runs/$RUN_ID/plan/json-output"
echo "Plan JSON saved to: $OUTPUT"
Download via Plan ID
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
PLAN_ID="plan-xyz789"
curl -Lsf --header "Authorization: Bearer $TOKEN" \
-o plan.json \
"https://app.terraform.io/api/v2/plans/$PLAN_ID/json-output"
Analysis Commands
Resource Change Summary
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq '{
terraform_version: .terraform_version,
format_version: .format_version,
summary: {
create: [.resource_changes[] | select(.change.actions | contains(["create"]))] | length,
update: [.resource_changes[] | select(.change.actions | contains(["update"]))] | length,
delete: [.resource_changes[] | select(.change.actions | contains(["delete"]))] | length,
replace: [.resource_changes[] | select(.change.actions | contains(["delete", "create"]))] | length,
read: [.resource_changes[] | select(.change.actions | contains(["read"]))] | length,
no_op: [.resource_changes[] | select(.change.actions == ["no-op"])] | length
}
}'
List Resources Being Created
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq -r '.resource_changes[] | select(.change.actions | contains(["create"])) | .address'
List Resources Being Destroyed
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq -r '.resource_changes[] | select(.change.actions | contains(["delete"])) | .address'
List Resources Being Updated
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq -r '.resource_changes[] | select(.change.actions | contains(["update"])) | .address'
Resources Being Replaced
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq -r '.resource_changes[] | select(.change.actions | contains(["delete", "create"])) |
"\(.address) (replace due to: \(.action_reason // "unknown"))"'
Detailed Resource Changes
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq '.resource_changes[] | select(.change.actions != ["no-op"]) | {
address: .address,
actions: .change.actions,
before: .change.before,
after: .change.after
}'
Show What's Changing in a Specific Resource
RESOURCE="aws_instance.web"
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq --arg addr "$RESOURCE" '
.resource_changes[] | select(.address == $addr) | {
address: .address,
actions: .change.actions,
before: .change.before,
after: .change.after,
after_unknown: .change.after_unknown
}'
Provider Versions Used
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq '.configuration.provider_config | to_entries | map({
provider: .key,
version: .value.version_constraint
})'
Output Values
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq '.output_changes | to_entries | map({
name: .key,
actions: .value.actions,
sensitive: .value.after_sensitive
})'
Variables Used
curl -Lsf --header "Authorization: Bearer $TFE_TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output" | \
jq '.variables | keys'
Complete Analysis Script
#!/bin/bash
set -euo pipefail
TOKEN="${TFE_TOKEN:?TFE_TOKEN not set}"
RUN_ID="${1:?Usage: $0 <run-id>}"
PLAN=$(curl -Lsf --header "Authorization: Bearer $TOKEN" \
"https://app.terraform.io/api/v2/runs/$RUN_ID/plan/json-output")
echo "=== Plan Analysis for $RUN_ID ==="
echo ""
echo "Terraform Version: $(echo "$PLAN" | jq -r '.terraform_version')"
echo ""
echo "Resource Changes:"
echo " Create: $(echo "$PLAN" | jq '[.resource_changes[] | select(.change.actions | contains(["create"]))] | length')"
echo " Update: $(echo "$PLAN" | jq '[.resource_changes[] | select(.change.actions | contains(["update"]))] | length')"
echo " Delete: $(echo "$PLAN" | jq '[.resource_changes[] | select(.change.actions | contains(["delete"]))] | length')"
echo " Replace: $(echo "$PLAN" | jq '[.resource_changes[] | select(.change.actions | contains(["delete", "create"]))] | length')"
echo ""
echo "Resources to Create:"
echo "$PLAN" | jq -r '.resource_changes[] | select(.change.actions | contains(["create"])) | " - " + .address'
echo ""
echo "Resources to Destroy:"
echo "$PLAN" | jq -r '.resource_changes[] | select(.change.actions | contains(["delete"])) | " - " + .address'
echo ""
echo "Resources to Update:"
echo "$PLAN" | jq -r '.resource_changes[] | select(.change.actions | contains(["update"])) | " - " + .address'
Plan JSON Structure
The plan JSON output follows Terraform's JSON plan format:
{
"format_version": "1.2",
"terraform_version": "1.5.0",
"planned_values": { ... },
"resource_changes": [
{
"address": "aws_instance.web",
"mode": "managed",
"type": "aws_instance",
"name": "web",
"provider_name": "registry.terraform.io/hashicorp/aws",
"change": {
"actions": ["create"],
"before": null,
"after": { ... },
"after_unknown": { ... },
"before_sensitive": false,
"after_sensitive": { ... }
}
}
],
"output_changes": { ... },
"configuration": { ... },
"variables": { ... }
}
Change Actions
["create"]- Resource will be created["delete"]- Resource will be destroyed["update"]- Resource will be updated in-place["delete", "create"]- Resource will be replaced["read"]- Data source will be read["no-op"]- No changes
Important Notes
- Requires Terraform 0.12+ for JSON output support
- Returns 204 No Content if plan hasn't completed yet
- Follow redirects - API returns HTTP 307 to temporary download URL
- Temporary URL - Download URL is valid for ~1 minute
- Admin access required - Need admin permissions on the workspace
Error Handling
204 No Content
Plan hasn't completed yet. Check run status first.
401 Unauthorized
Token lacks admin workspace access or is invalid.
404 Not Found
Run doesn't exist or you don't have permission.
See Also
tfc-run-logs: Get plan/apply logs (human-readable)tfc-run-status: Quick status check for a runtfc-list-runs: List recent runs in a workspace
スコア
総合スコア
50/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です