Use the browser dashboard
finfocus --web serves the overview, actual-cost, recommendations, and what-if
estimate experiences as a local web page. It uses the same engine, plugin
routing, calculations, filtering, sorting, formatting, and recommendation
scoring as the CLI and terminal UI, so the browser shows the same numbers.
This guide covers the common tasks. For every flag, view, and status code, see the Web UI reference. For why the server is built the way it is, see Web UI design.
Before you begin
Section titled “Before you begin”- Install the plugins your resources need (
finfocus plugin listshows what is installed). The browser adds no pricing of its own. - Have a Pulumi project, or exported Pulumi preview or state files. Terraform state is not supported by the browser dashboard.
- Use a browser on the same machine that runs
finfocus. The server listens only on127.0.0.1and has no option to listen on another interface.
Open the dashboard for a Pulumi project
Section titled “Open the dashboard for a Pulumi project”Run FinFocus from the directory that contains your Pulumi program:
cd <your-pulumi-project>finfocus --webFinFocus detects the project, the current stack, and its state the same way
finfocus overview does. It prints the session URL on stdout and opens your
default browser on it. The page fills in progressively while plugins answer.
The URL contains a session token, so keep it private.
To use a stack other than the current one, add --stack:
finfocus --web --stack dev--project-dir still controls only configuration resolution. Source detection
always starts from the working directory.
Open several stacks
Section titled “Open several stacks”With one stack, the page names it in the header and in a single tab, so you
can always see which stack’s costs are on screen. That is the stack --stack
names, or the workspace’s selected stack (pulumi stack select) when you leave
--stack out. A plan or state file and Terraform show no tab.
To compare stacks in one page, give --stack a list:
finfocus --web --stack dev,prodYou can also repeat the flag: --stack dev --stack prod. The page shows a tab
for each stack, in the order you gave, and the header names the one you are
looking at. Select a tab with the mouse, or focus the tab bar and use Left,
Right, Home, and End. Each tab has its own Overview, Cost,
Recommendations, and every other view, and nothing is added up across stacks.
A stack loads when you first open its tab, so a list of five stacks does not start five sets of plugins at once. Returning to a tab shows what it already loaded.
If a stack cannot load, its tab says failed and its view shows the same
message a single stack would. The other tabs keep working. Restart the
dashboard to retry a failed stack.
Every name must be a stack of the project in the working directory. An unknown
name stops the command with exit code 2 and lists the stacks the project has. A
list needs the project’s own stacks, so it cannot be combined with
--pulumi-json or --pulumi-state.
Run without opening a browser
Section titled “Run without opening a browser”On a machine with no graphical browser, or when you want to choose the browser yourself, suppress the automatic open:
finfocus --web --no-browserOpen the printed http://127.0.0.1:<port>/?token=<token> URL yourself. If
FinFocus cannot start a browser, it logs a warning and keeps serving, so the
printed URL still works.
Pin the port
Section titled “Pin the port”The operating system picks a free port unless you set one:
finfocus --web --port 8484A port that is already in use stops the launch with an error naming the port.
Pick another port, or omit --port.
Use exported Pulumi files
Section titled “Use exported Pulumi files”When you generate sources yourself, for example in a script, pass them explicitly:
pulumi stack export > state.jsonpulumi preview --json > plan.jsonfinfocus --web --pulumi-state state.json --pulumi-json plan.jsonAn explicit source takes precedence over auto-detection. A preview file also loads by itself outside a Pulumi project:
finfocus --web --pulumi-json plan.jsonInside a detected project, a preview-only launch still exports the project’s
current state for the overview. Pass --pulumi-state to supply that state
yourself.
Narrow the data
Section titled “Narrow the data”The companion flags work as they do on finfocus overview:
# Actual costs for September (YYYY-MM-DD or RFC3339)finfocus --web --from 2026-09-01 --to 2026-09-30
# Query one installed plugin onlyfinfocus --web --adapter aws-public
# Only AWS resourcesfinfocus --web --filter provider=awsThese flags are valid only together with --web, and only on the root
finfocus command. Sources and dates are fixed for the session and cannot be
changed from the page. Restart the session to change them. The only file the
page reads is the optional spend CSV on the Forecast view.
Unlock an encrypted stack
Section titled “Unlock an encrypted stack”If the stack uses a passphrase secrets provider, the overview opens an Encrypted stack dialog. Enter the passphrase and choose Unlock. A wrong passphrase shows an inline error and lets you try again.
With several stacks, each encrypted stack asks for its own passphrase in its
own tab, marked locked. Unlocking one stack does not unlock another. If you
switch to a locked stack from another view, such as Cost, a notice above the
view links to that stack’s Overview, where the prompt appears. A stack that
failed to load shows the same kind of notice.
FinFocus hands the passphrase only to the pulumi subprocess environment. It
never puts it in a response, an event, or a log line, and never saves it.
Preview pending changes
Section titled “Preview pending changes”When the session starts from state only, choose Run preview in the overview
to run pulumi preview on demand, like the p key in the terminal UI. The
overview shows the elapsed time and updates pending changes when the preview
finishes. Only one preview runs at a time. A resource’s detail panel lists its
dependents under Blast radius; after the preview it includes the
dependents the plan creates, changes or deletes. The terminal
overview shows the same section.
The Blast radius table keeps its summary and column headings in view while
a long list scrolls, and it fits a narrow window without scrolling sideways.
The Status column spells out new, deleting, replacing, updating and
component, so no state depends on color. Each dependent is a link: press
Enter on it (reach it with Tab) to open that resource’s detail, then choose
Back to the earlier resource, or Close detail to return to the row you
started from.
There is no general refresh. To fetch fresh actual costs, stop the session and launch it again.
Choose a What-If resource
Section titled “Choose a What-If resource”The What-If picker hides Pulumi provider and stack bookkeeping by default. It also hides resources confirmed non-billable by available, agreeing plugin pricing metadata. Show all resources restores the complete safe source list, within your launch filters. An eligible selected resource and its unsaved edits stay selected when you toggle it, provided the source properties are unchanged. If a preview changes those properties during the toggle, What-If reloads the editor and baseline from the updated source. A failed resource-list refresh shows a separate error and preserves the current estimate.
Zero baseline, zero rate, or zero actual spend does not establish non-billability. Unsupported resources, missing region or SKU, pricing errors, and unknown billability remain available for estimation. Metadata is used only when already available for the effective pricing providers; listing resources never triggers new pricing probes. A positive projected baseline helps choose the initial resource without affecting which resources are visible.
If only known non-billable resources remain, the picker explains the empty list
and offers Show all resources. Planned resources and existing launch filters
still apply. Interactive plan estimation uses the same default eligibility
policy; explicit cost estimate --provider ... --resource-type ... remains
available for inspecting a specific type.
Forecast from past spend
Section titled “Forecast from past spend”Open Forecast to project monthly cost. The default is the plugins’ growth
models, the same as finfocus cost forecast. To fit past spend instead,
choose Statistical (ARIMA) and pick a CSV of date,value rows, one per
consecutive day or month, exported from your billing console. The file stays
on your machine; the page reads it and sends the text to the local server.
Add a Growth cap such as 1.25 to keep every month within 25% of the
current one, or Steps such as 2027-06-01=500 for a known change. For a
spike that will not repeat, add an Exclude range such as
2025-12-01:2025-12-31. The model order and confidence appear in the summary,
and any warning the CLI would print appears under the table.
Open another tab or reconnect
Section titled “Open another tab or reconnect”Open the printed URL again to start another tab or browser profile. The URL stays valid until the server stops. Reloading a page recovers the current load state instead of restarting the load.
If the page reports that a valid session cookie is required, the browser has no session for this server. Open the URL printed in the terminal.
Edit configuration
Section titled “Edit configuration”Open Config in the header. The page lists each known setting, the value that is in effect, and whether that value came from the built-in default, the global file, the project file, or the environment.
Choose Project or Global, edit the values, and choose Review
changes. The preview names each change and writes nothing. Confirm
updates only that tier’s config.hujson. Cancel leaves the file as it was.
Comments and keys the page does not edit stay in the file.
A secret is shown as set or not set. The field starts empty. Leave it blank to keep the stored value, or type a replacement. The page does not show the stored secret and does not write the masked placeholder back to the file.
The running dashboard keeps the configuration it loaded at startup. The new values apply to the next launch and to command-line runs. Alert destinations, routing, and analyzer settings are visible and are not editable on this page.
Install and configure plugins
Section titled “Install and configure plugins”Open Plugins in the header. The page lists every built-in catalog plugin and any installed plugin that came from outside the catalog.
Choose Install, Update, or Remove. The confirmation names the plugin, the version, the source repository, and the security level. Nothing is downloaded until you confirm. Progress then shows each phase, including bytes received when the download reports a size. A second operation on the same plugin is refused until the first one finishes. Try it again afterward.
A plugin installed from outside the catalog can be validated, configured, and removed. Install and update stay on the catalog entries. The page does not accept a download URL. Custom registry addresses stay on the command line.
Validate checks the installed files and that the plugin starts. It does not certify the plugin.
Plugin settings use the same Project or Global choice as Config. Review the changes, then save. A secret field starts empty. Leave it blank to keep the stored secret. The page never shows the stored secret. Saved settings apply the next time that plugin is launched. The dashboard opens plugins again after a successful install, update, remove, or settings save. A plugin process that was already running keeps the environment it started with until that reopen.
An environment variable that is already set for the dashboard process takes precedence over the project file, the global file, and the plugin’s default. Set a secret that way when you do not want it written to a file.
When Pulumi ESC supplies a plugin setting, the Status cell reads
from ESC (<reference>). The help text names that environment and says it
overrides the shell and both configuration files. The value stays hidden.
Watch the logs
Section titled “Watch the logs”The dashboard can show the log lines that FinFocus and its plugins write while the session runs. The view is off by default. Turn it on for one run with an environment variable:
FINFOCUS_WEB_LOGS=1 finfocus --webOr turn it on for every run:
finfocus config set web.logs.enabled trueThe environment variable wins over the setting, so FINFOCUS_WEB_LOGS=0
turns the view off for one run even when the setting is true. A value other
than 1, true, 0, or false stops the launch with a validation error.
Open Logs in the header. Earlier lines from the initial load are already
there, oldest first, and new lines follow. For debug lines, add --debug or
set FINFOCUS_LOG_LEVEL=debug before you launch.
To narrow what you see:
- Select source chips to show only
coreor specific plugins, or use the All sources / Core / Plugins select. - Choose a minimum level, such as
warn+. - Type text in the filter box. It matches the message and field values, not field names. Turn on Regex to use a regular expression.
- Press Pause to stop following the newest line while you read. The status line counts the lines that arrive meanwhile. Press Resume to follow again.
- Press Clear to empty the view. This does not touch the log file.
- Press Download NDJSON to save the rows currently shown, after filters, as a file with one JSON object per line.
For the same data in a terminal, run finfocus logs. It
reads the log file once, with the same filters and the same redaction.
What the log view shows
Section titled “What the log view shows”- Credential-like field names and Pulumi secret values in fields are replaced
with
[redacted], in the page and in the downloaded file. The free-text message is shown as written, because it cannot be inspected reliably. Plugins should never log credentials in a message. - Log lines can contain resource names and file paths. The view is served only
on
127.0.0.1behind the session token, like the rest of the dashboard. - The server holds the newest 5000 entries in memory, and the page shows the newest 2000 rows. Older entries are dropped. The viewer writes nothing to disk, and the entries disappear when the session ends. The log file keeps receiving the same lines it does with the view off.
Serve behind a proxy
Section titled “Serve behind a proxy”finfocus --web always listens on 127.0.0.1. To open it from another
device on your tailnet, run a reverse proxy on the same machine, such as
tailscale serve, and tell FinFocus the public name the proxy uses:
finfocus --web --no-browser --port 8765 --allowed-host dash.example.ts.nettailscale serve --bg --https=443 http://127.0.0.1:8765Open https://dash.example.ts.net/?token=<token> with the token from the
printed URL. The session cookie is marked Secure because the proxy sends
X-Forwarded-Proto: https.
--allowed-hostis repeatable and matches the exact name. Wildcards, IP addresses, and values with a scheme or path are refused at startup. A port is optional; without one, the HTTPS default (443) is assumed. Any otherHostis still refused with 403.- Each request must still carry the token cookie, so the proxy needs no special setup.
Sign in with your tailnet identity
Section titled “Sign in with your tailnet identity”To skip the token, name the tailnet users who may open the dashboard:
finfocus --web --no-browser --port 8765 \ --allowed-host dash.example.ts.net \ --trusted-proxy --allowed-user alice@example.comA request is admitted without the token only when it comes from the same
machine, for an allowed host, with exactly one Tailscale-User-Login header
that names an allowed user (case-insensitive). --trusted-proxy needs at
least one --allowed-host and one --allowed-user, and --allowed-user
needs --trusted-proxy. FinFocus prints a warning to stderr, then the token
URL and the proxy URL on stdout.
Warning: Identity mode removes the token as a barrier against other users and processes on the same machine. Any local process can reach the loopback port and send the header itself. Use it only on a machine whose local users you trust.
- Tailscale Serve sets
Tailscale-User-Loginfor tailnet traffic only and strips client-supplied copies. Tailscale Funnel traffic and tagged devices carry no login, so use the token URL there. - Not yet verified live: whether Serve forwards the tailnet
Hostunchanged (if it rewrites it, list the rewritten name) and whether the live event stream survives Serve without buffering.
Stop the session
Section titled “Stop the session”Closing the browser tab does not stop FinFocus. Press Ctrl+C in the terminal
that launched it to shut down the server and its plugins.
Troubleshooting
Section titled “Troubleshooting”| Message | Cause and fix |
|---|---|
--port is only valid with --web (any companion flag) |
A companion flag was given without --web. Add --web. Exit code 2. |
--web and --mcp are mutually exclusive |
Run the web dashboard and the MCP server as separate processes. Exit code 2. |
unknown flag: --web |
--web was put on a subcommand, such as finfocus overview --web. Use finfocus --web. |
no Pulumi project found in current or parent directories |
Run from the Pulumi project directory, or pass --pulumi-json. |
port <n> on 127.0.0.1 is unavailable |
Another process holds the pinned port. Choose another --port or omit it. |
valid session cookie required; open the URL printed in the terminal |
Open the printed URL, not the bare address. |
invalid session token; open the URL printed in the terminal |
The token belongs to an earlier session. Use the URL from the current run. |
| No Logs link in the header | Logs are off by default. Set FINFOCUS_WEB_LOGS=1 or web.logs.enabled to true and relaunch. |
| No cost data | Check that the needed plugins are installed: finfocus plugin list. |
Limitations
Section titled “Limitations”- Pulumi only.
--terraform-stateis not a--webflag. - A stack list needs a Pulumi project. There are no totals or comparisons across stacks; each tab is independent.
- Loopback listener only. There is no option to listen on a non-loopback address and no built-in TLS. To reach the dashboard from other devices, put an HTTPS proxy on the same machine in front of it (Serve behind a proxy).
- The browser cannot dismiss, snooze, or undismiss recommendations. Use
finfocus cost recommendations dismissand its siblings. - Run preview is offered even when the session already has preview data,
and state-only sessions do not show the terminal UI’s
Projected*marker (#1751).
Related
Section titled “Related”- Web UI reference: flags, views, controls, and HTTP behavior
- Web UI design: the security model and how the dashboard shares the CLI engine
- logs command: the same log data from the terminal
- overview command: the terminal equivalent
- CLI Commands Reference