Skip to content

CLI Reference

Complete reference for every C3X command, flag, and output format. All commands support the global flags listed at the bottom of this page.

c3x estimate

Parse Terraform configurations and estimate monthly cloud costs. This is the primary command for most workflows.

c3x estimate --path /path/to/terraform

Flags

FlagDescriptionDefault
--pathPath to a Terraform root module directory..
--formatOutput format: text, markdown, json, junit, html, csv, or sarif. Goes to stdout, redirect with > file to save.text
--usagePath to a usage file for variable-cost resources.c3x-usage.yml
--budgetMaximum allowed monthly cost in USD. Exits with code 1 if exceeded.none
--save-baselineAfter the estimate, write the JSON to this path for use as a c3x diff baseline.none
--what-ifOverride a resource attribute for what-if analysis. Can be specified multiple times. Format: <resource address>.<attr>=value, e.g. module.web.aws_instance.this[0].instance_type=m7i.large.none
--offlineUse only the local pricing database. No network calls are made.false
--show-skippedAfter the breakdown, list resources that were parsed but couldn't be priced, with the reason.false
--no-cacheBypass the on-disk price cache (every lookup hits pricing.c3x.dev).false
--varVariable override: name=value (repeatable; HCL or bare string).none
--var-filePath to a .tfvars / .tfvars.json file (repeatable; applied after auto-tfvars).none
--currencyDisplay currency (USD, EUR, GBP, JPY, …); USD rates converted via Frankfurter.USD
--regionDefault region when the IaC source doesn't declare one.none
--pricing-endpointOverride the pricing GraphQL endpoint.pricing.c3x.dev
--pricing-tokenBearer token for a self-hosted pricing API with API_KEY set. Also reads $C3X_PRICING_TOKEN.none
--cache-pathSQLite file for the on-disk price cache.XDG cache dir
--show-deltaWhen the input is a Terraform plan, show only what the plan changes instead of the full post-apply estimate.false
--no-remote-modulesNever fetch remote Terraform modules. Useful when estimating untrusted input or running without network access.false
--allow-file-functionsEvaluate file(), templatefile(), and fileset(), reading only inside the project directory. Ignored with --no-remote-modules. Also C3X_ALLOW_FILE_FUNCTIONS=true. Leave it off for untrusted input.false
--inline-demoEstimate a small built-in example instead of reading --path. Handy for a first run or a smoke test.false

Examples

# Basic estimate
c3x estimate --path .

# JSON output to file
c3x estimate --path . --format json > estimate.json

# Budget gate in CI
c3x estimate --path . --budget 5000

# What-if: change instance type
c3x estimate --path . --what-if 'aws_instance.web.instance_type=m6i.2xlarge'

# Offline mode (after 'c3x pricing sync')
c3x estimate --path . --offline

# Multiple tfvars files
c3x estimate --path . --var-file prod.tfvars --var-file secrets.tfvars

# Display in another currency
c3x estimate --path . --currency EUR

c3x diff

Compare the current estimate against a saved baseline JSON (produced by c3x estimate --save-baseline on the base branch). Useful for understanding the cost impact of a change.

c3x diff --path . --baseline base.json

Flags

FlagDescriptionDefault
--baselinePath to a saved baseline JSON (from c3x estimate --save-baseline). Required.none
--pathTerraform input: directory, .tf, .hcl, or plan JSON..
--budget-deltaFail with exit code 1 when the project delta exceeds this monthly amount (0 disables).0
--formatOutput format: text, markdown, json, junit, html, csv, or sarif.text

Examples

# Save a baseline (e.g. from main), then diff the PR branch against it
c3x estimate --path . --save-baseline base.json
c3x diff --path . --baseline base.json

# JSON diff with a delta gate (fail if monthly cost rises > $500)
c3x diff --path . --baseline base.json --format json --budget-delta 500

c3x top

Rank the resources in an estimate by monthly cost, highest first. Use it to find what actually drives a bill, or to generate a list of destroy targets for shutting down expensive development environments on a schedule.

c3x top --path . --limit 10

Flags

FlagDescriptionDefault
--limitHow many resources to list. 0 lists every priced resource.10
--formatOutput format: text (ranked table with each resource's share of the total), targets (-target= flags), or json.text
--pathTerraform input: directory, .tf, .hcl, or plan JSON..
--regionDefault region when the IaC source does not declare one.provider block
--offlineUse the offline pricing stub instead of calling the pricing API.false

Shutting down expensive environments

The targets format emits one -target=<address> flag per line, which word-splits straight into a destroy:

# Tear down the five costliest resources in a dev environment
tofu destroy $(c3x top --limit 5 --format targets)

# Same with Terraform
terraform destroy $(c3x top --limit 5 --format targets)

C3X only prints the list. It never destroys anything itself, so review the output before piping it into a destroy: -target is a blunt instrument, and tearing down a resource that others depend on can break the rest of the environment.

Two details make the list safe to feed to Terraform. Addresses are canonical Terraform addresses, so resources inside modules come out as module.frontend.aws_instance.web rather than a display label Terraform would reject. And free resources are never listed, so a --limit list is not padded with IAM roles and route table associations that save nothing when destroyed.

Examples

# What is driving this bill?
c3x top --path . --limit 10

# Every priced resource, most expensive first
c3x top --path . --limit 0

# Structured output for tooling
c3x top --path . --format json | jq '.resources[] | {address, monthly_cost}'

# Rank a Terraform plan instead of a directory
c3x top --path plan.json --limit 5

c3x recommend

Analyze your Terraform configuration and suggest cost optimization opportunities such as right-sizing instances, switching to reserved pricing, or removing unused resources.

c3x recommend --path .

Flags

FlagDescriptionDefault
--pathPath to the Terraform root module directory..
--formatOutput format: text, markdown, or json.text

Examples

# Table output
c3x recommend --path .

# JSON output for programmatic use
c3x recommend --path . --format json

c3x comment

Post a cost estimate as a comment on a pull request or merge request. Supports GitHub, GitLab, Bitbucket, and Azure Repos.

Comment layout and cost delta

The comment leads with a one-line summary and tucks the per-resource breakdown into a collapsible details block, so a large estimate does not flood the discussion thread. Pass --expand to post the full breakdown always-expanded instead. Every comment opens with the c3x mark and the heading C3X cost estimate, and ends with a one-line footer noting that the figures are public list prices before discounts. On GitHub Actions, the C3X Action runs this command for you.

When --path points at a Terraform plan JSON, C3X derives the cost change automatically and the summary leads with the dollar delta, for example Monthly cost increased by $314.82 (+30.3%), followed by a baseline / new / change table. No baseline file and no base-branch checkout are needed: a plan already carries both the prior and planned state of every resource. For a directory of .tf files, or a plan where everything is newly created, the comment shows the absolute monthly total instead. Passing --baseline overrides this and diffs against that saved baseline.

Shared flags

These work on every forge subcommand below.

FlagDescription
--comment-tagNamespace the comment marker so multiple runs on one PR keep separate comments, for example one per environment or Terraform directory. Also reads $C3X_COMMENT_TAG.
--recreateDelete the previous C3X comment and post a fresh one at the bottom of the thread, instead of updating it in place.
--expandPost the full breakdown expanded instead of the collapsible summary layout.
--baselineDiff against a saved baseline JSON (from c3x estimate --save-baseline) rather than the plan's own prior state.
--strictExit with code 3 when any part of the estimate rests on an assumption. The comment is posted first, so reviewers see the caveats.

Subcommands

c3x comment github

c3x comment github --path . --token $GITHUB_TOKEN
FlagDescription
--pathPath to the Terraform root module directory.
--tokenGitHub API token with permission to write PR comments.
--ownerRepository owner. Auto-detected in CI environments.
--repoRepository name. Auto-detected in CI environments.
--prPull request number. Auto-detected in CI environments.
--comment-tagNamespace the comment marker so multiple runs on one PR keep separate comments (e.g. one per environment or directory). Also reads $C3X_COMMENT_TAG.
--recreateDelete the previous C3X comment and post a fresh one at the bottom, instead of updating it in place.

c3x comment gitlab

c3x comment gitlab --path . --token $GITLAB_TOKEN
FlagDescription
--pathPath to the Terraform root module directory.
--tokenGitLab API token with permission to write MR comments.
--base-urlGitLab API base URL for self-managed instances. Auto-detected from CI_API_V4_URL, defaults to gitlab.com.
--mrMerge request IID. Auto-detected in CI environments.
--projectGitLab project ID or path. Auto-detected in CI environments.
--comment-tagNamespace the comment marker so multiple runs on one MR keep separate comments (e.g. one per environment or directory). Also reads $C3X_COMMENT_TAG.
--recreateDelete the previous C3X comment and post a fresh one at the bottom, instead of updating it in place.

c3x comment bitbucket

c3x comment bitbucket --path . --user $BITBUCKET_USERNAME --token $BITBUCKET_APP_PASSWORD
FlagDescription
--pathPath to the Terraform root module directory.
--tokenBitbucket app password with permission to write PR comments. Also reads $BITBUCKET_APP_PASSWORD.
--base-urlBitbucket server URL for self-hosted instances.
--prPull request ID. Auto-detected in CI environments.
--repoRepository in workspace/repo format. Auto-detected in CI environments.
--workspaceBitbucket workspace. Auto-detected from $BITBUCKET_REPO_FULL_NAME in Pipelines.
--userBitbucket username paired with the app password. Also reads $BITBUCKET_USERNAME.

c3x comment azuredevops

c3x comment azuredevops --path . --token $SYSTEM_ACCESSTOKEN
FlagDescription
--pathPath to the Terraform root module directory.
--tokenAzure DevOps access token.
--prPull request ID. Auto-detected in CI environments.
--repoAzure Repos URL. Auto-detected in CI environments.
--orgAzure DevOps organisation. Auto-detected from $SYSTEM_TEAMFOUNDATIONCOLLECTIONURI in Pipelines.

c3x pricing sync

Download cloud pricing data to a local SQLite database for offline use. See the Self-Hosted & Offline guide for details.

c3x pricing sync --providers aws,azure,gcp --regions us-east-1

Flags

FlagDescriptionDefault
--providersComma-separated list of providers to sync: aws, azure, google.aws,azure
--concurrencyHow many price fetches to run in parallel while warming the cache.4
--cache-pathPath to the local pricing cache file.Platform cache directory (XDG)

c3x pricing stats / where / clear

Inspect and manage the on-disk price cache.

c3x pricing where   # print the cache file path
c3x pricing stats   # row counts: total, live, stale
c3x pricing clear   # delete every cached row

These take no additional flags (besides --cache-path). Use c3x pricing sync (above) to populate the cache for offline use.

c3x usage sync

Measure usage (quantities such as GB stored) from your own cloud account and write it to a generated usage file, c3x-usage.synced.yml, which every pricing command reads. This is not c3x pricing sync, which caches prices (rates). Estimates never call a cloud API; only this command does, run by you with your credentials, making read-only calls. It refuses to run in untrusted-input mode (C3X_NO_REMOTE_MODULES). See the usage file for how the generated file and yours combine.

terraform show -json > state.json
c3x usage sync --state state.json   # writes c3x-usage.synced.yml
c3x estimate                        # reads it, no flags needed

Today it measures AWS S3 bucket storage (standard_storage_gb, from CloudWatch BucketSizeBytes), which needs cloudwatch:GetMetricData. Credentials come from the AWS SDK's default chain. A resource whose real name or region cannot be established is skipped and listed, never guessed, and a run that measures nothing leaves the existing file unchanged.

Flags

FlagDescriptionDefault
--pathTerraform directory, file or plan JSON to read resources from..
--stateTerraform state JSON (terraform show -json) to read real resource names and regions from. Without it, a literal name in configuration is used.none
--providerCloud provider to read metrics from.aws
--daysLength of the window to measure usage over, in days.30
--outFile to write. Never the hand-written usage file.synced_usage_path, else c3x-usage.synced.yml
--regionRegion for resources that have none of their own.none
--strictExit non-zero if any resource could not be synced.false
--var-file, --varTerraform variable files and values, as for c3x estimate.none

c3x doctor

Run pre-flight checks and exit non-zero if any fail, usable as a CI gate. Verifies the embedded catalog parses, pricing.c3x.dev responds, the cache directory is writable, and user config resolves. When a synced usage file is configured or present, it also checks that AWS credentials resolve for c3x usage sync.

c3x doctor

# Only report failures, for a quiet CI gate
c3x doctor --quiet

Pass --quiet to suppress the per-check output and print only failures, which keeps CI logs short while still failing the job on a problem.

c3x supported-resources

List every Terraform / CloudFormation resource kind c3x can estimate, with its pricing status: LIVE (queried from pricing.c3x.dev), STATIC (inline rate), or FREE (no per-resource charge).

c3x supported-resources --provider aws --status live
c3x supported-resources --format json

c3x policy eval

Evaluate Rego policies against an estimate or diff to gate merges on cost rules. Exits non-zero on a policy deny. Point --policy at a .rego file or directory, and either --path (compute a fresh estimate) or --estimate (a saved JSON).

c3x policy eval --policy ./policies --path .

c3x configure

First-run setup wizard. Prompts for the settings most users pin once (currency, format, region, pricing endpoint) and writes them to ~/.config/c3x/config.toml (XDG-aware). Re-running pre-fills from the current values. Project-level overrides go in a .c3x.toml in your repo.

c3x configure

# Write defaults without prompting (for provisioning scripts and images)
c3x configure --non-interactive

--non-interactive skips the prompts and writes the resolved defaults straight to the config file, which is what you want when baking an image or provisioning a CI runner.

c3x version

Print the c3x version and build info.

c3x version

Global Flags

These flags are available on every C3X command.

FlagDescriptionDefault
-v, --verboseIncrease log verbosity. Repeatable: -v info, -vv debug, -vvv adds source locations.none
--versionPrint the c3x version and exit.none

Examples

# Debug logging
c3x estimate --path . -vv

# Disable color (c3x respects the NO_COLOR environment variable)
NO_COLOR=1 c3x estimate --path .