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/terraformFlags
| Flag | Description | Default |
|---|---|---|
--path | Path to a Terraform root module directory. | . |
--format | Output format: text, markdown, json, junit, html, csv, or sarif. Goes to stdout, redirect with > file to save. | text |
--usage | Path to a usage file for variable-cost resources. | c3x-usage.yml |
--budget | Maximum allowed monthly cost in USD. Exits with code 1 if exceeded. | none |
--save-baseline | After the estimate, write the JSON to this path for use as a c3x diff baseline. | none |
--what-if | Override 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 |
--offline | Use only the local pricing database. No network calls are made. | false |
--show-skipped | After the breakdown, list resources that were parsed but couldn't be priced, with the reason. | false |
--no-cache | Bypass the on-disk price cache (every lookup hits pricing.c3x.dev). | false |
--var | Variable override: name=value (repeatable; HCL or bare string). | none |
--var-file | Path to a .tfvars / .tfvars.json file (repeatable; applied after auto-tfvars). | none |
--currency | Display currency (USD, EUR, GBP, JPY, …); USD rates converted via Frankfurter. | USD |
--region | Default region when the IaC source doesn't declare one. | none |
--pricing-endpoint | Override the pricing GraphQL endpoint. | pricing.c3x.dev |
--pricing-token | Bearer token for a self-hosted pricing API with API_KEY set. Also reads $C3X_PRICING_TOKEN. | none |
--cache-path | SQLite file for the on-disk price cache. | XDG cache dir |
--show-delta | When the input is a Terraform plan, show only what the plan changes instead of the full post-apply estimate. | false |
--no-remote-modules | Never fetch remote Terraform modules. Useful when estimating untrusted input or running without network access. | false |
--allow-file-functions | Evaluate 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-demo | Estimate 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 EURc3x 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.jsonFlags
| Flag | Description | Default |
|---|---|---|
--baseline | Path to a saved baseline JSON (from c3x estimate --save-baseline). Required. | none |
--path | Terraform input: directory, .tf, .hcl, or plan JSON. | . |
--budget-delta | Fail with exit code 1 when the project delta exceeds this monthly amount (0 disables). | 0 |
--format | Output 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 500c3x 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 10Flags
| Flag | Description | Default |
|---|---|---|
--limit | How many resources to list. 0 lists every priced resource. | 10 |
--format | Output format: text (ranked table with each resource's share of the total), targets (-target= flags), or json. | text |
--path | Terraform input: directory, .tf, .hcl, or plan JSON. | . |
--region | Default region when the IaC source does not declare one. | provider block |
--offline | Use 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 5c3x 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
| Flag | Description | Default |
|---|---|---|
--path | Path to the Terraform root module directory. | . |
--format | Output format: text, markdown, or json. | text |
Examples
# Table output
c3x recommend --path .
# JSON output for programmatic use
c3x recommend --path . --format jsonc3x 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.
| Flag | Description |
|---|---|
--comment-tag | Namespace 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. |
--recreate | Delete the previous C3X comment and post a fresh one at the bottom of the thread, instead of updating it in place. |
--expand | Post the full breakdown expanded instead of the collapsible summary layout. |
--baseline | Diff against a saved baseline JSON (from c3x estimate --save-baseline) rather than the plan's own prior state. |
--strict | Exit 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| Flag | Description |
|---|---|
--path | Path to the Terraform root module directory. |
--token | GitHub API token with permission to write PR comments. |
--owner | Repository owner. Auto-detected in CI environments. |
--repo | Repository name. Auto-detected in CI environments. |
--pr | Pull request number. Auto-detected in CI environments. |
--comment-tag | Namespace the comment marker so multiple runs on one PR keep separate comments (e.g. one per environment or directory). Also reads $C3X_COMMENT_TAG. |
--recreate | Delete 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| Flag | Description |
|---|---|
--path | Path to the Terraform root module directory. |
--token | GitLab API token with permission to write MR comments. |
--base-url | GitLab API base URL for self-managed instances. Auto-detected from CI_API_V4_URL, defaults to gitlab.com. |
--mr | Merge request IID. Auto-detected in CI environments. |
--project | GitLab project ID or path. Auto-detected in CI environments. |
--comment-tag | Namespace the comment marker so multiple runs on one MR keep separate comments (e.g. one per environment or directory). Also reads $C3X_COMMENT_TAG. |
--recreate | Delete 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| Flag | Description |
|---|---|
--path | Path to the Terraform root module directory. |
--token | Bitbucket app password with permission to write PR comments. Also reads $BITBUCKET_APP_PASSWORD. |
--base-url | Bitbucket server URL for self-hosted instances. |
--pr | Pull request ID. Auto-detected in CI environments. |
--repo | Repository in workspace/repo format. Auto-detected in CI environments. |
--workspace | Bitbucket workspace. Auto-detected from $BITBUCKET_REPO_FULL_NAME in Pipelines. |
--user | Bitbucket username paired with the app password. Also reads $BITBUCKET_USERNAME. |
c3x comment azuredevops
c3x comment azuredevops --path . --token $SYSTEM_ACCESSTOKEN| Flag | Description |
|---|---|
--path | Path to the Terraform root module directory. |
--token | Azure DevOps access token. |
--pr | Pull request ID. Auto-detected in CI environments. |
--repo | Azure Repos URL. Auto-detected in CI environments. |
--org | Azure 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-1Flags
| Flag | Description | Default |
|---|---|---|
--providers | Comma-separated list of providers to sync: aws, azure, google. | aws,azure |
--concurrency | How many price fetches to run in parallel while warming the cache. | 4 |
--cache-path | Path 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 rowThese 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 neededToday 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
| Flag | Description | Default |
|---|---|---|
--path | Terraform directory, file or plan JSON to read resources from. | . |
--state | Terraform state JSON (terraform show -json) to read real resource names and regions from. Without it, a literal name in configuration is used. | none |
--provider | Cloud provider to read metrics from. | aws |
--days | Length of the window to measure usage over, in days. | 30 |
--out | File to write. Never the hand-written usage file. | synced_usage_path, else c3x-usage.synced.yml |
--region | Region for resources that have none of their own. | none |
--strict | Exit non-zero if any resource could not be synced. | false |
--var-file, --var | Terraform 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 --quietPass --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 jsonc3x 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 versionGlobal Flags
These flags are available on every C3X command.
| Flag | Description | Default |
|---|---|---|
-v, --verbose | Increase log verbosity. Repeatable: -v info, -vv debug, -vvv adds source locations. | none |
--version | Print 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 .