overview Command
Display a unified cost dashboard combining Pulumi state and plan data with actual costs, projected costs, drift analysis, and recommendations.
For Pulumi projects, overview, cost projected, cost estimate, and
cost recommendations share one loading step that combines deployed state
with the preview. Unchanged deployed resources and preview-only creates appear
in the live inventory, and the preview takes precedence for resources present
in both. cost projected keeps its plan total and reports the full inventory
separately as the stack total. The terminal and web views use the same snapshot.
When a saved preview is supplied with --pulumi-json and the project’s state
cannot be read, overview continues with preview resources only. A warning
identifies the state-availability reason and the number of unchanged resources
omitted by the preview. Plain output writes the warning to stderr; the terminal
dashboard and web overview keep it visible alongside the results. Totals in this
fallback cover only the preview resources. Supply a readable --pulumi-state
export with the preview to include deployed resources.
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
finfocuswith no arguments inside a Pulumi project directory automatically launches the overview — no subcommand needed.
Options
Section titled “Options”| 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 |
--profile |
Workload hint for projected cost and recommendations: dev, prod, burst, or default. Overrides FINFOCUS_PROFILE and cost.profile |
no preference |
--budget-scope |
Filter budget scopes: global, provider, tag, type | All |
Auto-Detection
Section titled “Auto-Detection”When no --pulumi-state or --pulumi-json flags are provided, finfocus overview
locates your Pulumi project automatically. A Terraform directory is projected
with finfocus cost projected, which plans that directory or reads
--terraform-plan. Overview itself still loads a Pulumi project:
- Walks up from the current directory to find
Pulumi.yaml. - Runs
pulumi stack exportto fetch the current state JSON. - Runs
pulumi preview --jsonto fetch the pending-change plan. - Uses
--stackto 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.
Examples
Section titled “Examples”Auto-detect from current directory (recommended)
Section titled “Auto-detect from current directory (recommended)”finfocus overviewWalks 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.
Cost-only overview (skip preview)
Section titled “Cost-only overview (skip preview)”finfocus overview --state-onlySkips 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.
Specific stack with auto-detection
Section titled “Specific stack with auto-detection”finfocus overview --stack productionSame as above but selects the production stack instead of the current default.
Pre-exported files (CI/CD or offline)
Section titled “Pre-exported files (CI/CD or offline)”finfocus overview --pulumi-state state.json --pulumi-json plan.jsonOpens 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.
With pending changes from plan
Section titled “With pending changes from plan”finfocus overview --pulumi-state state.json --pulumi-json plan.jsonShows resources with pending changes and their cost impact.
Plain text table output
Section titled “Plain text table output”finfocus overview --pulumi-state state.json --plain --yesRenders an ASCII table suitable for piping or CI/CD environments.
JSON output for scripting
Section titled “JSON output for scripting”finfocus overview --pulumi-state state.json --output json --yesProduces structured JSON with metadata, resources, summary, and errors.
NDJSON streaming output
Section titled “NDJSON streaming output”finfocus overview --pulumi-state state.json --output ndjson --yesOne JSON object per line, suitable for streaming processors.
Custom date range
Section titled “Custom date range”finfocus overview --pulumi-state state.json --from 2025-01-01 --to 2025-01-31With caching enabled
Section titled “With caching enabled”finfocus overview --cache-ttl 300 --pulumi-state state.jsonEnables 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.
Filter by provider
Section titled “Filter by provider”finfocus overview --pulumi-state state.json --filter provider=aws --yesFilter by resource type
Section titled “Filter by resource type”finfocus overview --pulumi-state state.json --filter type=aws:ec2/instance:Instance --yesInteractive TUI
Section titled “Interactive TUI”When running in a terminal (TTY) without --plain, the overview launches an
interactive dashboard built with Bubble Tea.
To explore the same data in a browser instead, run finfocus --web from the
project directory. It takes the overview’s source, date, adapter, and filter
flags; see Use the browser dashboard.
Keyboard shortcuts
Section titled “Keyboard shortcuts”The list view shows a one-line hint under the status bar:
[w] web dashboard · finfocus --webOn a narrow terminal the hint shortens to [w] web, then disappears. It stays
on one line. The hint is not shown in plain text, JSON, or the detail view.
| 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 |
w |
Close the overview and start the browser dashboard (finfocus --web) |
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 |
r |
In the detail view, retry a cost-history load that failed |
q / Ctrl+C |
Quit |
Progressive loading
Section titled “Progressive loading”The dashboard opens immediately and shows a progress banner while fetching cost data from plugins. Resources update in-place as data arrives.
Resource detail view
Section titled “Resource detail view”Press Enter on a resource to see a detailed breakdown including:
- Actual cost (MTD) with breakdown by category
- Projected cost (monthly) with breakdown, and a
Pricingline such asSPOT · risk 0.12 · -62% vs on-demandwhen the plugin priced the resource as spot and supplied its on-demand price (spot savings unavailablereplaces the saving when it did not). The interactive list showsSPOTbeside the projected amount, the table and the dashboard list show the full label, and JSON rows carryprojectedCost.pricingCategory,projectedCost.spotInterruptionRisk,projectedCost.onDemandEquivalentMonthlyCost, andprojectedCost.spotSavingsPercent. - Cost drift analysis with extrapolation
- Optimization recommendations with estimated savings
- Stored cost history for this resource, loaded when the detail view opens.
The series comes from
cost history collectfor the stack named by the resource, not the state-file name. A missing history database leaves this section out. A read failure stays in the detail view; pressrto try again. On a short terminal, Up and Down scroll the detail view so the history section and the retry hint stay reachable. - Blast radius: the resources that depend on this one, directly or through other resources, as an indented tree with a count and a monthly total at the top. See Blast radius.
Blast radius
Section titled “Blast radius”The BLAST RADIUS section answers “what else is affected if this resource changes?” It reads the dependencies Pulumi records for each resource in the stack state and, after a preview, in the plan. It makes no plugin calls and needs no network.
- What counts as a dependent: any resource that depends on this one
directly or through a chain of other resources. Each is listed once, under
the shortest path. A resource also depends on the provider it was created
with and on the resources named in its
deletedWithandreplaceWithoptions, so a Kubernetes cluster lists the workloads deployed through the provider built from it, and a default provider lists every resource it manages. Pulumi records a dependency on a component as a dependency on its children, so a resource that depends on a component appears under each child. - The total: the summed projected monthly cost of the priced dependents that will exist. It leaves out dependents a preview deletes, dependents with no price, and components, which are listed so the tree stays connected but are not counted. A note under the total says how many were left out. When dependents use different currencies, the total is withheld.
- Markers:
[new],[updating],[replacing],[deleting]and[component]follow the cost.no pricemeans the plugin returned none;$0.00is a price. - Empty and unavailable: “nothing depends on this resource” means the resource is a leaf. “dependency information is not available” appears for Terraform and OpenTofu sources and for an empty state, which carry no dependency data.
- State-only runs: press
pto run a preview. Dependents that the plan creates, changes or deletes appear in the tree after it finishes.
finfocus --web shows the same section in the resource detail panel from the
same computation.
Kubernetes cluster expansion
Section titled “Kubernetes cluster expansion”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:
- The
overview.cluster_contextsconfig mapping (cluster name or full URN to context). When a mapping exists, it is the only context tried. - The cluster’s
nameproperty, its full ARN (the context name thataws eks update-kubeconfigwrites), and the name segment of its ARN. - 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>.
Budget Status
Section titled “Budget Status”The overview command displays budget health information differently depending on the output mode.
Visibility by Output Mode
Section titled “Visibility by 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 |
Budget Flags
Section titled “Budget Flags”| 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.
Output formats
Section titled “Output formats”Table (default)
Section titled “Table (default)”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 driftmy-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 USDA 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 |
When any projected row is spot, a Spot exposure: line follows the summary
with the spot cost, its share of the projected total, and the cost-weighted
interruption risk (for example 2000.00 USD (35.2% of 5678.90 USD), weighted risk 0.18). Rows with an unknown risk count as spot but are excluded from the
weighted risk, and the line names how many. It uses the projected (monthly)
amounts only, never the month-to-date column. The web overview shows the same
text in its totals bar.
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", "spot": { "spotCost": 2000.00, "totalCost": 5678.90, "spotShare": 0.3522, "weightedRisk": 0.18, "spotResources": 2, "riskUnknownResources": 0, "currency": "USD", "display": "2000.00 USD (35.2% of 5678.90 USD), weighted risk 0.18" } }, "budgets": [ { "budgetID": "global", "health": "WARNING", "utilization": 85.2, "limit": 5000.00, "currentSpend": 4260.00, "forecastedSpend": 5800.00 } ], "errors": [ ... ]}summary.spot is present only when a projected row is spot. weightedRisk is
absent when no spot row has a risk score, or when every spot row that has one
costs $0. spotShare is absent when the total is zero.
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.
NDJSON
Section titled “NDJSON”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",...}Exit codes
Section titled “Exit codes”| 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.
Filter syntax
Section titled “Filter syntax”Filters use key=value format and support:
provider=aws- Filter by cloud providertype=aws:ec2/instance:Instance- Filter by resource typestatus=active- Filter by resource status
Multiple filters are ANDed together.
Troubleshooting
Section titled “Troubleshooting”No cost data shown
Section titled “No cost data shown”Ensure plugins are installed and accessible. Run finfocus plugin list to verify.
The overview enrichment requires at least one plugin to fetch cost data.
Slow loading
Section titled “Slow loading”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.
Drift warnings
Section titled “Drift warnings”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.