Agent Skill · Infracost

infracost-scan

Analyze infrastructure as code (IaC) projects to estimate cloud costs, identify savings opportunities, and flag FinOps policy violations. This skill should be used when asking about the cost of a cloud project, how to optimize costs, or when there are specific questions about FinOps policies or tagging compliance in an IaC codebase. The skill uses the Infracost CLI and its plugins to perform the analysis, so it requires the user to have those set up and authenticated. The output is a detailed cost report that highlights key insights and recommendations for cost optimization.

Provider: Infracost Path in repo: plugins/infracost/skills/scan/SKILL.md

Skill body

Infracost Cost Estimation

Analyze infrastructure as code (IaC) projects to estimate cloud costs, identify savings opportunities, and flag FinOps policy violations.

Supported IaC types: Terraform, CloudFormation, Terragrunt. CDK is not yet directly supported.

Setup

Important: Verify the Infracost CLI is installed and the user is authenticated before running any scans.

  1. Check the CLI is on the path:

    infracost --version
    

    If this fails, inform the user that they need to install the Infracost CLI by following the instructions at https://www.infracost.io/docs/features/get_started/.

  2. Check the user is logged in:

    infracost auth whoami
    

    If this reports that the user is not authenticated, ask them to run infracost auth login in a separate terminal window and let you know once it completes. Do not attempt to run the login command yourself — it is interactive.

Usage

Run the scan command, pointing to your IaC files or a repository root:

# Single CloudFormation template
infracost scan /path/to/cloudformation.yaml

# Terraform project directory
infracost scan /path/to/terraform/

# Repository root (auto-discovers all IaC projects in nested directories)
infracost scan /path/to/repo

Output

By default, scan prints a human-readable summary table to stdout (projects, resources, monthly cost, FinOps and tagging policy counts, guardrails, budgets, diagnostics) followed by a “What’s next?” section that suggests context-aware inspect commands you can run to dive deeper. Diagnostics and warnings go to stderr.

For the full machine-readable JSON output, pass the global --json flag:

# Human-readable summary (default)
infracost scan /path/to/repo

# Full JSON output (large; redirect to a file for big repos)
infracost scan --json /path/to/repo > /tmp/scan.json

--json is a global flag — it works on scan, price, and inspect and also switches log output to JSON.

For a compact, token-efficient text format suitable for piping into LLM prompts or other agentic tooling, pass --llm instead of --json. It carries the same data model in roughly 30–40% fewer tokens, with arrays of uniform records rendered as tabular rows so they grep cleanly.

Both --json and --llm outputs include a top-level summary block with pre-computed totals (total_monthly_cost, total_potential_monthly_savings, distinct failing-resource counts per policy class, per-class policy counts, guardrails triggered, budgets over). Read the summary first — most “how many X are failing?” or “what’s the total Y?” questions can be answered from it without walking projects[] yourself.

Inspecting Results

After analyzing, use the inspect command to explore the results instead of parsing raw JSON. Scan results are cached automatically, so inspect picks them up with no extra arguments — you do not need to redirect scan output or pass --file unless you saved a JSON file yourself.

Important: The inspect command reads cached results and you DO NOT NEED to write any scripts to handle JSON yourself. Just run inspect with the appropriate flags.

# Scan first (caches the result)
infracost scan /path/to/repo

# Then drill in — no --file needed
infracost inspect [flags]

# Or, if you saved JSON yourself with --json, point inspect at it
infracost inspect --file /tmp/scan.json [flags]

Available flags (combine as needed):

Views

Aggregations

Resource selection

Output projection (replaces piping through cut / awk '{print $N}')

Available fields per view (use with --fields):

For “how many distinct resources fail X policy” questions, prefer --summary --fields distinct_failing_finops_resources / distinct_failing_tagging_resources over enumerating the failing-resource list and piping through sort -u | wc -l or awk. The summary already de-dupes addresses across multiple policies.

Format

--group-by dimensions

Resource-context dimensions (aggregate the resource list):

Anchor dimensions (each routes to its own collector):

Compatibility rules (validated up-front):

The same mutual-exclusion rule applies to the drill-in flags: --policy, --budget, and --guardrail cannot be used together — pick one.

Use native flags before reaching for jq / python / cut

Many common queries that look like they need --json | jq or a python3 -c heredoc have dedicated inspect flags. Reach for these first:

Question Use this Not this
Total monthly cost? infracost inspect --summary --fields monthly_cost infracost scan --json \| jq '.summary.total_monthly_cost'
How many failing FinOps policies? infracost inspect --summary --fields failing_policies infracost inspect --failing --group-by policy \| sort -u \| wc -l
How many resources fail FinOps policies? infracost inspect --summary --fields distinct_failing_finops_resources ... --policy "X" --addresses-only \| sort -u \| wc -l per policy
How many resources fail tagging policies? infracost inspect --summary --fields distinct_failing_tagging_resources ... --policy "X" --addresses-only \| sort -u \| wc -l per policy
Total potential savings? infracost inspect --total-savings jq '[..monthly_savings] \| add'
Top N savings opportunities? infracost inspect --top-savings N jq 'sort_by(.savings)' \| head
Resources missing the team tag? infracost inspect --missing-tag team jq 'select(.tags.team == null)'
Just the addresses for a view? infracost inspect --policy "X" --addresses-only ... \| awk '{print $1}'
Custom column projection? infracost inspect --top-savings 10 --fields address,monthly_savings ... \| awk '{print $1, $5}'orcut -f1,5

These flags exist because they capture intent in a structured way the CLI logs as telemetry — when you reach for a flag instead of an ad-hoc pipeline, we can see which patterns are common and decide what to support natively next.

Worked examples

# Setup: populate the cache.
infracost scan /path/to/repo

# Counts and totals (single --summary call answers most "how many" questions):
infracost inspect --summary                                                   # full summary block
infracost inspect --summary --fields failing_policies                         # just the count, bare value
infracost inspect --summary --fields failing_policies,failing_tagging_policies,resources
infracost inspect --summary --fields distinct_failing_tagging_resources       # distinct resources failing tagging
infracost inspect --summary --fields distinct_failing_finops_resources        # distinct resources failing finops
infracost inspect --total-savings                                             # one number

# "List the top N highest-savings opportunities" (no jq, no awk):
infracost inspect --top-savings 5 --fields address,monthly_savings

# "Which resources fail the tagging policy?":
infracost inspect --missing-tag team                        # default: one address per line
infracost inspect --missing-tag team --fields address,type  # with type column

# "All resources failing a specific policy" (preserves full list, no truncation):
infracost inspect --policy "Required Tags" --addresses-only

# Composable filter (multiple predicates, AND'd):
infracost inspect --filter "tag.team=missing,provider=aws" --fields address,monthly_cost

Anti-patterns

Do not:

Drill-down workflow

Always start with a summary or high-level grouping, then offer to drill deeper. The inspect command supports a progressive drill-down:

Policies

  1. Start broad--summary or --group-by=policy to see what’s failing
  2. Pick a policy--policy "Use GP3" to list the failing resources for that policy, with file locations
  3. Pick a resource--policy "Use GP3" --resource "aws_ebs_volume.data" to see full issue detail with a code snippet

When presenting results, always offer the user a list of policies or resources they can drill into next. For example:

You have 3 failing FinOps policies. Would you like to drill into one?

  1. Use GP3 — 2 failing resources
  2. Use Graviton — 5 failing resources
  3. Required Tags — 12 failing resources

After showing a policy overview, offer to drill into specific resources:

Use GP3 has 2 failing resources. Want to see the detail for one?

  1. aws_ebs_volume.data — modules/storage/main.tf:10
  2. aws_ebs_volume.logs — modules/logging/main.tf:25

The resource detail view includes a code snippet showing the relevant lines from the source file — use this to explain what needs to change and suggest a fix.

Important: When the user asks about a specific resource (e.g., “show me the issue with the lambda”, “what’s wrong with the RDS instance?”), always drill down to the resource level using --policy <name> --resource <address> and include the code snippet in your response. Don’t just describe the issue — show it with the snippet so the user can see exactly what needs to change.

Guardrails

When the summary shows triggered guardrails (e.g., Guardrails: 2 (1 triggered)), drill into them:

  1. List all--group-by=guardrail to see all guardrails with their status and monthly cost
  2. Pick one--guardrail "Cost increase > $100" to see detail: whether it triggered, the total monthly cost, and configured thresholds

Present triggered guardrails prominently — they may block the PR. For example:

1 guardrail triggered. The total monthly cost of $500 exceeded the “Cost increase > $100” threshold. Would you like to see the detail?

Budgets

Important context: Budget costs represent actual org-wide cloud spend from cloud billing data — they are NOT computed from the IaC scan and are NOT affected by the changes in the current PR. Budgets are shown on a PR because the PR touches resources with matching tags, but the dollar amounts reflect what the org has already spent across all repos and resources with those tags. Do not describe budget costs as “estimated” or imply the PR caused them.

When the summary shows budgets over limit (e.g., Budgets: 3 (1 over)), drill into them:

  1. List all--group-by=budget to see all budgets with their name, status, actual spend, and limit
  2. Pick one--budget "Production budget" to see full detail: tag scope, limit, actual spend, remaining/over, custom message, matching resources from the scan, and potential savings from FinOps policies on those resources

The budget detail view shows:

Important: The savings shown are estimates from the IaC scan. They may not directly reduce the org-wide budget spend — for example, if the resources are newly created and haven’t been deployed yet, or if the savings depend on usage changes. Present savings as “areas to investigate” rather than guaranteed reductions.

Present over-budget items clearly with the dollar amount over. For example:

1 of 3 budgets is relevant to this change (matched by resource tags): | Budget | Status | Actual Spend | Limit | |——–|——–|———|——-| | Production budget | under | $500 | $1,000 (50% left) | | Frontend Q2 | OVER | $400 | $300 | | Backend annual | under | $200 | $5,000 (96% left) |

Frontend Q2 is $100 over its org-wide budget. Let me drill in for detail…

(runs --budget "Frontend Q2")

The budget detail shows 3 resources matching team=frontend tags in this scan. There are also FinOps policy violations on some of these resources (Use GP3: up to $30/mo, Use Graviton: up to $45/mo) — addressing these could help reduce spend over time.

Note: Actual spend is based on cloud billing data across the organization. Savings estimates are from the IaC scan and may not directly translate to budget reductions.

When a budget is over, always drill in with --budget <name> to check for related FinOps violations — they highlight areas where spend on matching resources could potentially be reduced.

Presenting scan results

Make the output engaging with emojis, tables, and graphs where appropriate.

Summarize the costs of the cloud resources, focusing on the following:

Diffing Against a Baseline

To compare cost changes between branches, use git worktree and capture each scan’s JSON output:

# Create a worktree for the baseline
git worktree add /tmp/infracost-baseline origin/main

# Run against both and capture full JSON for diffing
infracost scan --json /path/to/repo > /tmp/head.json
infracost scan --json /tmp/infracost-baseline/path/to/repo > /tmp/base.json

# Clean up
git worktree remove /tmp/infracost-baseline

Compare the two JSON files to identify cost differences introduced by the current branch.

Presenting Results

Always present cost analysis in an engaging, actionable way tailored to what the data shows. Don’t just dump raw numbers — tell a story with the data:

Important Guidelines