Claude Code dashboard: pin your agent's analysis to a live URL
"Claude Code dashboard" means two different things, so here's the fork up front. If you want a dashboard of Claude Code — token burn, per-session cost, which model your agent has been hammering — that lives in the Anthropic Console and the community usage monitors, and the next section points you there. If you want Claude Code to produce a dashboard — live charts over your Search Console, GA4, Meta Ads and Google Ads numbers that a teammate can open in a browser on Monday — the bottom line is one command: tablebi pin turns SQL your agent already wrote into a public, read-only, self-refreshing URL. No React app to scaffold, no screenshot ritual, no BI seat to buy.
Which Claude Code dashboard are you looking for?
The monitoring intent is the quick one to serve. Claude Code's own usage — API spend, model mix, token consumption over time — is what the Anthropic Console reports, and the ecosystem has terminal-native usage monitors that chart burn rate live while you work. If that's what you searched for, you're set; nothing below is about metering the agent.
This article is about the other direction, the one that also gets searched as claude code analytics dashboard: the agent as the analyst, and a dashboard of your business data as its output. That direction has a real gap in it. Claude Code can compute nearly anything about your marketing or product numbers, but a computation that lives in a terminal session dies with the terminal session. Dashboards are how analysis survives contact with the rest of the team — and dashboards are exactly where coding agents have been weakest.
Why dashboards are the weak spot of coding agents
Ask a coding agent for a dashboard today and you get one of two failure modes:
- The static artifact. A chart PNG, an HTML file with the numbers baked in, a markdown table in the transcript. It was correct at the moment it rendered and it decays from there — next week's version means re-running the session, and nobody else can see it without you.
- The hand-rolled app. The agent happily scaffolds a React dashboard: a chart library, a data-fetching layer, API credentials for four platforms, somewhere to deploy, some notion of a refresh job. You asked for a chart; you now own a small product. It's expensive in tokens the day it's built and more expensive the day the auth silently breaks.
The root mismatch: what the agent is genuinely great at is analysis — deciding what's worth watching and expressing it as a query. Rendering, hosting, refresh and access control are infrastructure, and infrastructure is precisely the thing you don't want an agent re-inventing once per report.
The pin model: a widget is a title plus a query
TableBI — the data backend for your Claude Code — splits the job along exactly that line. The agent decides what to watch and writes the SQL; the backend renders it, hosts it and keeps it fresh. A dashboard is declared in a single command, one flag per widget:
# a widget is "Title=SQL" — add ::line for a line chart, default is a table tablebi pin --title "…" \ --widget "Daily clicks::line=SELECT …" \ --widget "Top campaigns=SELECT …"
That's the entire authoring model. No layout DSL, no chart-config JSON, no component library — a title, two colons if you want a line chart, and a query. Widgets run against the same two altitudes every TableBI query uses: facts, the cross-channel table with unified definitions, or the per-platform raw tables (search_console_raw, ga4_raw, meta_ads_raw, google_ads_raw) when you need numbers exactly as a platform reported them. The querying side — the definition macros, the trust block, when to use which altitude — is covered in depth in Claude Code analytics.
Because a widget is nothing but SQL, the backend can re-run it whenever data syncs. That's the property that makes the page live instead of a snapshot — and it costs the agent nothing to maintain.
From ask to pin, end to end
Prerequisites, compressed (the full multi-source walkthrough is in Claude Code for marketing): install the CLI, teach the agent, connect a source or two.
npm i -g @tablebi/cli
tablebi login
tablebi install
# connect whatever the dashboard should watch — OAuth opens in the browser
tablebi connect gsc --site sc-domain:example.com
tablebi connect google_ads
Inside a Claude Code session the workflow is explore-then-freeze. You (or the agent, unprompted) poke at the data with tablebi ask until there's a view worth keeping:
# explore first — is the trend even interesting? tablebi ask "SELECT date, SUM(clicks) AS clicks FROM facts WHERE date >= (SELECT MAX(date) FROM facts) - 28 GROUP BY date ORDER BY date"
One idiom worth noticing: the date window anchors to (SELECT MAX(date) FROM facts) - 28 — the newest synced row — rather than the wall clock. Queries are precompiled and validated, and current_date is rejected by design: a widget windowed off the clock renders an empty right edge whenever a source lags a day, while a widget windowed off the data always shows the latest 28 days that actually exist.
When the view is worth keeping, freeze it:
tablebi pin --title "Search and spend overview" \ --widget "Daily clicks (28d)::line=SELECT date, SUM(clicks) AS clicks FROM facts WHERE date >= (SELECT MAX(date) FROM facts) - 28 GROUP BY date ORDER BY date" \ --widget "Top campaigns by spend=SELECT campaign, SUM(cost) AS spend, roas(SUM(conversion_value), SUM(cost)) AS roas FROM facts WHERE date >= (SELECT MAX(date) FROM facts) - 28 GROUP BY campaign ORDER BY spend DESC LIMIT 10" ✓ published → https://dk.tablebi.com/d/dsh_… (public, read-only, self-refreshing)
The URL lives at your workspace's subdomain, and it is the deliverable. In practice you rarely type any of this by hand: with the skill installed, "pin that as a dashboard" in plain English is enough, and the agent composes the command from the queries it just ran.
What the public URL gives viewers
A pinned dashboard has deliberately narrow semantics, and they're worth spelling out because they're what make the URL safe to hand to anyone:
- Read-only. Viewers see rendered widgets. They can't edit queries, run new ones, or touch the connected accounts — the page exposes results, not access.
- Self-refreshing. Syncs run on a schedule and are additionally triggered when someone opens the dashboard, so the Monday visitor gets Monday's numbers without anyone re-running an analysis. Sources lag by different amounts by nature — Search Console finalizes data days behind an ads platform — and the freshness metadata reflects that instead of hiding it.
- No accounts. It's a URL. Nobody installs anything or signs into anything to look at it.
- A feedback path built in. Each widget carries an "ask" button: a viewer can copy a ready-made question about that exact widget to send back to you, instead of the classic "can you explain the dashboard?" email with no context attached. The page footer notes it's powered by TableBI — and if your viewers are paying clients, the workflow around that is its own topic, covered in the client reporting guide.
Underneath all of it sits the property that matters: every number on the page came out of a deterministic SQL engine, from a query you can read. There is no model in the serving path to paraphrase your data.
A live example you can open right now
Below is a real pinned dashboard, not a mockup — an SEO portfolio overview over live Search Console data, three widgets, published with exactly the command shape above. Scroll it, open it in a tab, come back next week; it will have refreshed itself: