Skip to content

overview Command

Display a unified cost dashboard combining Pulumi state and plan data with actual costs, projected costs, drift analysis, and recommendations.

Terminal window
finfocus overview [options]

All flags are optional. When --pulumi-state and --pulumi-json are omitted, the command auto-detects your Pulumi project and stack from the current directory.

Tip: Running finfocus with no arguments inside a Pulumi project directory automatically launches the overview — no subcommand needed.

Flag Description Default
--pulumi-state Path to Pulumi state JSON (skips auto-detection) Auto-detected
--pulumi-json Path to Pulumi preview JSON (skips auto-detection) Auto-detected
--stack, -s Pulumi stack name for auto-detection (ignored with --pulumi-state/--pulumi-json) Current stack
--from Start date (YYYY-MM-DD or RFC3339) 1st of current month
--to End date (YYYY-MM-DD or RFC3339) Now
--adapter, -a Restrict to a specific adapter plugin All plugins
--output Output format: table, json, ndjson table
--filter, -f Resource filters (repeatable) -
--plain Force non-interactive plain text output false
--color, --force-color Style the plain table when stdout is not a terminal. Does not open the TUI. The two names are the same switch false
--no-color Disable ANSI styling. Wins over --color and --force-color false
--high-contrast Accepted for consistency with the other output commands. overview has no budget box to recolor, so it changes nothing false
--yes, -y Skip confirmation prompts false
--cache-ttl Root flag. Seconds to keep plugin cost results. An explicit value wins, then FINFOCUS_CACHE_TTL, then config. 0 disables the cache config
--no-pagination Disable pagination (plain mode only) false
--exit-on-threshold Exit non-zero when a budget threshold is exceeded false
--exit-code Exit code for a threshold breach (0-255) 1
--notify Send budget notifications for exceeded thresholds. Unset uses FINFOCUS_NOTIFY false
--state-only Skip pulumi preview (faster, no pending change detection). Mutually exclusive with --pulumi-json false
--budget-scope Filter budget scopes: global, provider, tag, type All

When no --pulumi-state or --pulumi-json flags are provided, finfocus overview locates your Pulumi project automatically:

  1. Walks up from the current directory to find Pulumi.yaml.
  2. Runs pulumi stack export to fetch the current state JSON.
  3. Runs pulumi preview --json to fetch the pending-change plan.
  4. Uses --stack to select a non-default stack (e.g., --stack production).

Use --pulumi-state / --pulumi-json to skip these Pulumi CLI calls and provide pre-exported files directly — useful in CI/CD when you manage the export step yourself.

Section titled “Auto-detect from current directory (recommended)”
Terminal window
finfocus overview

Walks up from the current directory to find Pulumi.yaml, exports the current stack state, and runs pulumi preview automatically. Opens an interactive TUI with progressive data loading.

Terminal window
finfocus overview --state-only

Skips pulumi preview entirely, reducing overview time from ~18s to ~3s. Shows cost data from the current stack state without detecting pending infrastructure changes. In the TUI, the p key is still available to run preview on demand.

Terminal window
finfocus overview --stack production

Same as above but selects the production stack instead of the current default.

Terminal window
finfocus overview --pulumi-state state.json --pulumi-json plan.json

Opens an interactive TUI with progressive data loading. Resources appear as they are enriched with cost data. Use this when you manage the pulumi stack export and pulumi preview --json steps yourself.

Terminal window
finfocus overview --pulumi-state state.json --pulumi-json plan.json

Shows resources with pending changes and their cost impact.

Terminal window
finfocus overview --pulumi-state state.json --plain --yes

Renders an ASCII table suitable for piping or CI/CD environments.

Terminal window
finfocus overview --pulumi-state state.json --output json --yes

Produces structured JSON with metadata, resources, summary, and errors.

Terminal window
finfocus overview --pulumi-state state.json --output ndjson --yes

One JSON object per line, suitable for streaming processors.

Terminal window
finfocus overview --pulumi-state state.json --from 2025-01-01 --to 2025-01-31
Terminal window
finfocus overview --cache-ttl 300 --pulumi-state state.json

Enables a 5-minute cache. The first run enriches all resources via plugin calls and stores results locally. Subsequent runs within the TTL window show (cached) in the adapter field and complete faster.

Terminal window
finfocus overview --pulumi-state state.json --filter provider=aws --yes
Terminal window
finfocus overview --pulumi-state state.json --filter type=aws:ec2/instance:Instance --yes

When running in a terminal (TTY) without --plain, the overview launches an interactive dashboard built with Bubble Tea.

Key Action
Up / k Move cursor up
Down / j Move cursor down
Enter Open resource detail view
Escape Return to list / clear filter
s Cycle sort field (Cost, Name, Type, Delta)
/ Enter filter mode
p In state-only mode, run pulumi preview and apply pending changes to the open table
PgUp / PgDn Navigate pages (when >250 resources)
e Toggle expansion of a cluster row (Kubernetes workloads)
Right Expand a cluster row
Left Collapse a cluster row
q / Ctrl+C Quit

The dashboard opens immediately and shows a progress banner while fetching cost data from plugins. Resources update in-place as data arrives.

Press Enter on a resource to see a detailed breakdown including:

  • Actual cost (MTD) with breakdown by category
  • Projected cost (monthly) with breakdown
  • Cost drift analysis with extrapolation
  • Optimization recommendations with estimated savings

Rows for Kubernetes cluster resources (EKS, GKE, AKS) expand into workload rows. The cluster row shows a ▸ marker when collapsed and ▾ when expanded; children render indented beneath it.

Two data sources feed the expansion:

  • Projected: workloads declared in the same Pulumi stack (kubernetes:apps/v1:Deployment, StatefulSet, DaemonSet, kubernetes:batch/v1:Job, CronJob) nest under the cluster row and keep their individually priced projected cost.
  • Live: when a usage-source plugin and an allocator plugin are installed (e.g. finfocus plugin install kubernetes), the cluster is expanded from live allocation data grouped by namespace, including idle capacity. Live rows re-allocate node cost already shown by other rows, so they are excluded from the summary totals.

When both are available, live data wins: the projected workload rows are hidden and a † footnote reports how many were suppressed. The summary resource count still includes the hidden rows and does not count the live namespace rows.

The usage-source plugin is asked for these kubeconfig contexts in order, and the first one it answers is used:

  1. The overview.cluster_contexts config mapping (cluster name or full URN to context). When a mapping exists, it is the only context tried.
  2. The cluster’s name property, its full ARN (the context name that aws eks update-kubeconfig writes), and the name segment of its ARN.
  3. The current context, for single-cluster stacks only (footnoted as assumed).

Set a mapping with finfocus config set overview.cluster_contexts.<cluster> <context>. A cluster with no answering context keeps its projected view. Clusters that are being deleted, or whose cost lookup failed, are not expanded.

Projected grouping needs exactly one cluster in the stack. A stack with more than one cluster keeps its declared workload rows flat, because core cannot tell which cluster a workload is deployed to. Live expansion still runs for each cluster that has a name, ARN, or mapping.

In JSON and NDJSON output the rows stay flat: children carry parentUrn and expansionSource (live or projected), and the cluster row carries childUrns in display order. Live namespace rows use the type finfocus:k8s/namespace:Allocation and URNs of the form <clusterURN>#ns/<namespace>.

The overview command displays budget health information differently depending on the output mode.

Mode Budget Shown Details
Interactive TUI Footer bar + detail view Color-coded health badge, spend/limit, utilization %. Press Enter for per-budget breakdown with forecasts and triggered alerts
Plain (--plain) Not rendered Budget enforcement available via --exit-on-threshold
JSON (--output json) budgets array in output Full budget health objects with utilization, forecasted spend, triggered thresholds
NDJSON (--output ndjson) Not included NDJSON is resource-scoped; budgets are stack-scoped
Flag Description Applies To
--exit-on-threshold Exit non-zero when budget threshold exceeded Plain, JSON
--exit-code Exit code when threshold exceeded (0-255) Plain, JSON
--notify Send budget notifications for exceeded thresholds Plain, JSON, NDJSON
--budget-scope Filter budget scopes (global, provider, tag, type) All modes

Why is budget status missing in plain or NDJSON mode?

Section titled “Why is budget status missing in plain or NDJSON mode?”

Plain mode focuses on the resource table for piping and CI/CD use. Use --exit-on-threshold for budget enforcement in non-interactive environments. NDJSON emits one object per resource and budgets are stack-scoped, so they do not fit the per-line streaming model. Use --output json or the interactive TUI to see full budget details.

ASCII table with the following columns:

Column Description
Resource Resource URN, truncated to the column width. The detail view shows the full URN
Type Pulumi resource type (for example aws:ec2/instance:Instance). The plain table shortens a value longer than 24 characters
Status Lifecycle state with an icon prefix (see below)
Actual(MTD) Month-to-date spend from the actual-cost plugin. Plain header is ACTUAL(MTD); the TUI header is Actual. - when the resource has no billing history
Projected Full-month estimate (730 hours) from the projected-cost plugin. Plain header is PROJECTED, or PROJECTED* in state-only mode. The TUI uses Projected and Projected*. - when there is no projection
Delta How this row changes the monthly bill. The plain table prints a positive amount as +$ and a negative amount as -$. Updating or replacing: new projected monthly cost minus the current projected cost, or minus the extrapolated actual when there is no baseline. Creating: the new projected cost. Deleting: minus the extrapolated actual being removed. Active: the drift delta when drift is shown, otherwise -
Drift% Calendar-month extrapolation of month-to-date spend compared with the projected monthly cost, scaled to the month’s length. It is the drift Delta divided by that scaled projection, so it is not the Delta column divided by the Projected column. - when drift is not shown (fewer than two days have elapsed, at or under 10%, or nothing to compare). A shown value is above 10% and ends with a warning mark
Recs Open recommendation count. N(-M) when M of them are dismissed. - when there are none
Warn Conditions for this resource, comma-separated in derivation order: drift, error, new. - when none apply. A shown drift stays in Drift% and is also listed here. The TUI column keeps that list when it fits, and otherwise shows the first name plus +N for the rest. estimate and stale are reserved and are not shown

Plain output (--plain) from the table renderer. Amounts are sample data, and the drift percentages assume a 30-day month. A type longer than the column is shortened, and the last row is the summary:

RESOURCE TYPE STATUS ACTUAL(MTD) PROJECTED DELTA DRIFT% RECS WARN
-------- ---- ------ ----------- --------- ----- ------ ---- ----
my-instance aws:ec2/instance:Inst... ✓ active $12.40 $15.00 +$6.20 +42% ⚠ 2 drift
my-bucket aws:s3/bucket:Bucket ✓ active $0.83 $1.00 - - - -
my-db aws:rds/instance:Inst... ✓ active $48.20 $50.00 -$8.40 -17% ⚠ 1 drift
SUMMARY prod 3 resources $61.43 USD $66.00 USD -$2.20 USD

A live terminal capture needs a Pulumi stack and a cost plugin. Use the sample above, or run finfocus overview --plain --yes in a project.

Status icons:

Icon Status Meaning
✓ active Resource exists and is running
+ creating Resource will be created by the pending plan
~ updating Resource will be updated by the pending plan
- deleting Resource will be deleted by the pending plan
↻ replacing Resource will be deleted and re-created

Structured JSON object:

{
"metadata": {
"stackName": "prod",
"region": "us-east-1",
"timeWindow": { "start": "...", "end": "..." },
"hasChanges": true,
"totalResources": 50,
"pendingChanges": 10,
"generatedAt": "..."
},
"resources": [ ... ],
"summary": {
"totalActualMTD": 1234.56,
"projectedMonthly": 5678.90,
"projectedDelta": 4444.34,
"potentialSavings": 500.00,
"currency": "USD"
},
"budgets": [
{
"budgetID": "global",
"health": "WARNING",
"utilization": 85.2,
"limit": 5000.00,
"currentSpend": 4260.00,
"forecastedSpend": 5800.00
}
],
"errors": [ ... ]
}

Each resource object includes warnings when a condition applies. The values are drift, error, and new, in that order. An empty list is omitted. NDJSON uses the same resource object.

error marks a failed cost fetch: the engine returned an error, or a plugin reported one for that resource, such as a timeout, a failed call, or a validation failure. The resource’s error object carries the message and type. A resource that no plugin has a price for, such as an IAM role, is not an error.

One JSON object per line, no metadata wrapper:

{"urn":"urn:pulumi:...","type":"aws:ec2:Instance","status":"active",...}
{"urn":"urn:pulumi:...","type":"aws:s3:Bucket","status":"creating",...}
Code Meaning
0 Success
1 Error (invalid input, plugin failure)
130 Interrupted (Ctrl+C)

Answering n at the pre-flight prompt prints Cancelled. and exits 0. Nothing is priced.

Filters use key=value format and support:

  • provider=aws - Filter by cloud provider
  • type=aws:ec2/instance:Instance - Filter by resource type
  • status=active - Filter by resource status

Multiple filters are ANDed together.

Ensure plugins are installed and accessible. Run finfocus plugin list to verify. The overview enrichment requires at least one plugin to fetch cost data.

The overview fetches cost data concurrently (up to 10 resources at a time). Large stacks with many resources may take longer. Use --filter to narrow scope.

A warning icon appears when the extrapolated monthly spend differs from projected cost by more than 10%. This helps identify resources with unexpected cost changes. Drift needs at least two elapsed days of data, counted from the start of the window or from the resource’s creation time if that is later. For a resource that existed all month, that is from the start of the third day.