Blog · Claude × Data analysis

How to use Claude for data analysis — without re-uploading every time

Published July 24, 2026 · 8 min read

Claude is a genuinely good data analyst. The hard part was never the analysis — it's the data getting there, and staying there. Drop a CSV into a claude.ai conversation and you'll get a clean read of it in seconds: the outlier flagged, the segment that's dragging the average, the SQL to reproduce it. Then the conversation ends, and the next time you need that same answer you're exporting the same file again. This guide covers both halves: what the upload workflow is actually good at, and how to give Claude a standing connection to your data so recurring analysis stops being a re-upload ritual.

What Claude can already do with a table of numbers

It's worth being precise about where the capability sits, because the ceiling isn't where most people assume.

  • It reads tabular data properly. Not just "summarize this" — it will notice that your conversion rate jumped because the denominator changed, not the numerator.
  • It writes and debugs real analysis code. SQL with window functions, a pandas pivot, a quick chart. And it iterates when the first query returns something implausible.
  • It knows the metric traps. That CTR isn't CVR, that averaging an average is usually wrong, that a spike in impressions with flat clicks means you started ranking for junk.
  • It explains itself. The reason a model beats a dashboard for exploratory work is that you can ask "why?" and get a chain of reasoning rather than another chart.

None of that is the bottleneck. The bottleneck is reach: Claude analyzes what you can put in front of it, and how you put it there decides whether the analysis is a one-off or a habit.

Two surfaces, two different ceilings

People searching for how to use claude.ai for data analytics are usually on one of two surfaces, and they fail differently.

claude.ai with file uploads

You upload a CSV or spreadsheet into the conversation and ask questions in plain language. This is excellent for what it is: zero setup, no install, good for a file someone emailed you or a one-time question about last quarter. The ceiling is structural — the data is a snapshot you carried in by hand. Nothing connects back to Search Console, GA4 or your ad accounts, so a weekly question means a weekly export. And each new conversation starts from zero: the definitions you agreed on last time ("revenue means net of refunds") don't carry over.

Claude Code in your terminal

Claude Code can already reach your filesystem and run any command. That solves the "carried in by hand" problem for files on disk — see CSV analysis with Claude Code for that path specifically. But your marketing and product numbers mostly aren't files on disk. They're behind OAuth flows and rate-limited APIs, and wiring each one up by hand is a small engineering project you'd rather not maintain.

The fix: give Claude a queryable backend, not more files

The move that changes the workflow is to stop feeding Claude data and start giving it a place to query data. That's what TableBI is — a data backend built to be driven by a CLI-native agent, around three verbs:

  1. Pipe — connect each source once with a browser OAuth round-trip. Search Console, GA4, Meta Ads and Google Ads connect live; anything else arrives as CSV and is normalized into the same definitions. Data lands at two altitudes: metrics, one cross-channel table where spend is spend and clicks are clicks regardless of platform, and raw, the lossless per-platform tables underneath.
  2. Ask — read-only SQL against either altitude, from the terminal. Cross-channel questions hit the unified definitions; forensic questions hit raw.
  3. Pin — freeze any analysis into a live dashboard at a public read-only URL that keeps refreshing as sources sync.

Worth being explicit about: TableBI hosts no LLM. The backend serves deterministic numbers from a SQL engine; the reasoning happens inside your own Claude session, under your account and your data policy. Inference cost on our side is $0 because your agent is the brain.

Setting it up

Install the CLI, then plant the skill so Claude Code knows the tool exists and when to reach for it:

terminal
# install the CLI, then teach your agent to drive it
npm i -g @tablebi/cli
tablebi login
tablebi install

tablebi install drops a skill into ~/.claude/skills. After that you don't type commands at all — "connect my Search Console" or "which channel lost the most conversions last month?" is enough, and the agent picks the commands itself. Connecting each source is one OAuth round-trip:

terminal
# live sources — browser opens for OAuth, then data syncs in
tablebi connect gsc --site sc-domain:example.com
tablebi connect ga4
tablebi connect meta_ads
tablebi connect google_ads

# files land in the same definitions instead of a one-off upload
tablebi connect csv --file tiktok-export.csv --platform tiktok_ads

Every session then opens with a single rehydration call — definitions, connected sources, freshness, and the command cheatsheet in one JSON blob the agent holds in context. This is the piece that replaces "re-explaining your data model every conversation":

terminal
tablebi context --json

What the analysis actually looks like

Cross-channel questions run against the unified metrics table, with definition macros — roas, ctr, cpa, cvr, aov — so the arithmetic is never re-derived by hand:

claude code → tablebi
# where is the money going, and what is it returning?
tablebi ask "SELECT platform, SUM(cost) AS spend,
             roas(SUM(conversion_value), SUM(cost)) AS roas
             FROM facts WHERE date >= (SELECT MAX(date) FROM facts) - 30
             GROUP BY platform ORDER BY spend DESC"

Diagnostic questions drop to the raw altitude — the exact rows each platform reported, nothing averaged away:

claude code → tablebi
# which pages are getting seen but not clicked?
tablebi ask "SELECT page, SUM(impressions) AS imp, SUM(clicks) AS clicks,
             avg_position(SUM(position*impressions), SUM(impressions)) AS pos
             FROM search_console_raw
             WHERE date >= (SELECT MAX(date) FROM search_console_raw) - 28
             GROUP BY page HAVING SUM(impressions) > 100
             ORDER BY clicks / SUM(impressions) ASC LIMIT 20"

Note the date filter: (SELECT MAX(date) FROM …) - 28 rather than today's date. Sources finalize on their own clocks — Search Console lands roughly two to three days behind — so anchoring the window to the newest row you actually have is how you avoid a "traffic collapsed!" panic that's really just a reporting lag.

How Claude avoids being confidently wrong

This is the part that matters most when a model is doing the analyzing, and it's the part upload-a-CSV workflows structurally can't give you. Every answer ships with a trust block alongside the rows:

  • Freshness per source — what date each source has data through, how many days old that is, and whether it counts as stale. The agent can say "Meta is current, Search Console runs three days behind" instead of quietly comparing incomparable windows.
  • Caveats — the definitional landmines, in plain language. For example: a Search Console click and a GA4 session are different populations counted different ways, and shouldn't be expected to reconcile. Claude reads that and explains the gap rather than inventing a reason for it.

A model with no metadata will happily produce a confident number from a half-synced table. A model handed freshness and caveats will tell you which number not to trust yet. More on that design in Claude Code analytics.

Make the analysis outlive the session

The deepest limitation of chat-based analysis is that the work evaporates when the conversation closes. When an analysis is worth keeping, pin it instead of screenshotting it:

claude code → tablebi
tablebi pin --title "Weekly performance" \
  --widget "Daily clicks (28d)::line=SELECT date, SUM(clicks) AS clicks FROM facts …" \
  --widget "Spend by platform=SELECT platform, SUM(cost) AS spend FROM facts …"
✓ published → https://dk.tablebi.com/d/dsh_…  (public, read-only, self-refreshing)

You get a URL, not an artifact — it keeps refreshing as the sources sync. Here's a real one, live Search Console data across a portfolio of sites, pinned exactly this way:

When uploading a file is still the right call

Not every analysis needs infrastructure, and pretending otherwise would be selling you something. Stick with the upload workflow when:

  • It's genuinely one-off. A vendor sent a spreadsheet, you need one answer, you'll never open it again. Setting up a connector for that is overhead with no payoff.
  • The data isn't yours to connect. A client's export you were given a copy of, with no account access.
  • It's not tabular. A PDF, a pile of survey free-text, a contract. Reading and structuring unstructured input is exactly what a model should do directly.

The switch is worth making when the same question comes back. A weekly report, a channel you actually manage, anything a client expects on a schedule — that's when the export ritual starts costing more than the setup. And if your hesitation is about routing business numbers through a vendor's model, that concern is addressed by architecture here, not by policy: see chat with your data, without handing it to another model. For the marketing-specific version of this whole workflow, Claude Code for marketing covers it end to end.

FAQ

Can Claude do data analysis?

Yes. Claude reads tabular data, writes and debugs SQL and Python, spots outliers and explains what a trend implies. On claude.ai you hand it a file in the conversation; in Claude Code it works against your filesystem and any command line tool. The limit isn't reasoning — it's what data Claude can reach, and whether that reach survives the session.

How do I use claude.ai for data analytics?

Upload a CSV or spreadsheet into the conversation and ask in plain language. That's ideal for a one-off file. It doesn't give Claude a standing connection to Search Console, GA4 or your ad accounts, so recurring analysis means exporting and re-uploading every time, and each conversation starts from zero.

How is this different from uploading a CSV every time?

A data backend connects each source once via OAuth and keeps syncing it. Claude queries current data with read-only SQL instead of reading a snapshot you exported by hand. Nothing gets re-uploaded, definitions stay consistent across sessions, and any answer can be pinned as a live dashboard URL.

Does my data get sent to another model?

No. TableBI hosts no LLM — numbers come from a deterministic SQL engine, and the reasoning happens in your own Claude session under your own account and data policies. Inference cost on the backend is $0 because your agent is the brain.

Try it

Stop re-uploading. Give Claude a standing connection to your data.

terminal
npm i -g @tablebi/cli && tablebi install