Photo: Unsplash
The Spreadsheet Killer — Local AI Data Analysis on Your Mac
Last month I asked my Mac: “How much did we spend on food delivery in the first quarter, split by month, and how does that compare to last year?” Thirty seconds later I had the answer, a tidy table, and a mild sense of shame about the numbers. The data was my bank’s CSV export. The intelligence was a local LLM. Nothing — not one transaction — left my machine.
This post is the setup, the crucial mental model that makes it actually work, and the honest assessment of what “spreadsheet killer” really means. Spoiler on that last one: the title is three-quarters true, and I’ll show you exactly which quarter survives.
The rule everything depends on: LLMs write code, they don’t do math
Here’s the mistake that makes people abandon this workflow on day one: pasting a CSV into a chat window and asking the model to “calculate total spending by category.” The model will produce confident numbers, and some of them will be wrong.
Why: an LLM is a text predictor, not a calculator. Adding 847 transaction amounts is not text prediction — it’s arithmetic, and a transformer doing token-by-token arithmetic over a wall of pasted numbers is roughly as reliable as you doing the same sum in your head while someone reads it aloud once. It will drop rows, transpose digits, and round creatively, all while sounding certain.
But the same model is excellent at a different task: writing the pandas code that does the arithmetic. Python computes the sum perfectly every time; the LLM’s job is translating your plain-English question into that code. The division of labor is the entire trick:
- You: ask the question in natural language
- LLM: writes the analysis code
- Python/pandas: executes it with boring, perfect precision
- You: read results, ask the follow-up
Every “code interpreter” product, including OpenAI’s, works exactly this way internally. We’re building the local, private version.
The setup: fifteen minutes, all free
You need Python with pandas, a local model server, and a place to run code. My stack on both the M2 Ultra and the M3 Pro MacBook:
brew install uv
uv tool install jupyterlab --with pandas --with matplotlib
ollama pull qwen2.5-coder:14b
Qwen 2.5 Coder 14B is the sweet spot for this job — code-specialized, runs comfortably in 18 GB+ of RAM at ~40 tok/s on my MacBook, and its pandas is genuinely idiomatic. On 16 GB Macs use qwen2.5-coder:7b; on a big Mac Studio, the 32B version writes noticeably cleverer groupbys.
Then pick your loop, in ascending order of comfort:
Option A — the manual loop (zero extra tools). Chat with the model in the terminal, paste its code into JupyterLab, run, paste back errors or results. Crude, surprisingly effective, and it teaches you what the automation does.
Option B — Jupyter with an AI assistant. Install jupyter-ai (pip install jupyter-ai, point it at Ollama) and you get a chat panel inside JupyterLab plus magic commands like %%ai in cells. The model sees your notebook context; you stay in one window.
Option C — a code-interpreter-style loop. Tools like Open Interpreter (uv tool install open-interpreter, configure it against http://localhost:11434/v1) close the loop fully: the model writes code, executes it, reads errors, and self-corrects. Convenient — but it’s running generated code unattended, so I use it in a directory containing only copies of the data, never originals. Auto-executed df.to_csv is fine; you want to be sure nothing creative happens to files you care about.
I live in Option B. The friction of pressing Run on each cell doubles as a review step.
The prompt patterns that actually work
The phrasing is the skill, and there’s one rule above all: say “write pandas code to…” — never “calculate…” The first triggers code generation; the second invites the model to attempt mental math.
Start every session by giving the model the data’s shape, not the data:
I have a CSV at expenses.csv with columns: Date (DD.MM.YYYY),
Description (string, Czech), Amount (negative = spending, decimal
comma), Category (string, often empty), Counterparty account.
About 2,400 rows covering 24 months.
Write pandas code to load it correctly (parse dates, handle the
decimal comma), then show monthly total spending as a table.
Note what that prompt does: it warns about the decimal comma and DD.MM.YYYY dates — every Czech bank export (mine come from Fio and Air Bank) uses both, and naive pd.read_csv silently mangles them. One line of context, hours of debugging saved: the model correctly emits decimal=',' and dayfirst=True.
Then ask follow-ups exactly like you’d ask an analyst:
- “Write code to find all recurring monthly charges — same counterparty, similar amount, appearing in 6+ consecutive months — and list them with annual cost.” (This is the famous forgotten-subscription detector. It found a 199 CZK/month service I’d stopped using in 2024.)
- “Categorize transactions by keyword in Description — make a mapping dict I can edit — then plot category share by quarter.”
- “Compare Q1 2026 vs Q1 2025 by category, show absolute and percentage change, sort by biggest increase.”
For business data the same patterns scale up: I’ve pointed this loop at an invoicing export and asked for cohort summaries — “write pandas code to group customers by first-purchase month and show revenue retention by cohort over the following 12 months.” That’s a pivot table that takes most people an afternoon in Excel; the model wrote a working version in one shot and a correct version after one follow-up (“exclude refunds”).
When code errors out, paste the traceback verbatim with the word “fix.” The 14B Coder model resolves its own pandas errors on the first retry maybe 80% of the time.
The honest title check: what actually got killed
Time to audit my own clickbait. Did this kill spreadsheets? No — and watch the boundary, because it’s crisp:
What it killed: formula-wrangling. Nested VLOOKUPs, SUMIFS with five conditions, the pivot table that needs rebuilding every month, the 40 minutes on a forum learning array-formula syntax for a question you’ll ask once. That entire skill — translating a question into spreadsheet incantations — is now the model’s job, and the model is better at it than almost everyone. I have not written a complex formula since this setup landed.
What survives, deservedly: Numbers and Excel still win for quick tables — ten rows of holiday budget don’t need a Jupyter kernel. They win for shared editing — sending a colleague a .xlsx beats sending a notebook, every time, and that’s not changing soon. And they win for eyeballing — clicking into a cell to check one value beats writing df.loc for it. My actual workflow is a loop: analyze in pandas, then df.to_excel("report.xlsx") for anything a human besides me needs to touch.
So: the analysis layer of spreadsheets is dead to me. The table layer is immortal. Three-quarters killed, as promised.
The privacy win is the quiet headline
Step back and notice what didn’t happen anywhere above: no upload. Cloud AI data analysis is genuinely good now — and it involves handing a third party your complete bank transaction history: every merchant, every salary deposit, every pharmacy visit, every donation. That’s among the most sensitive datasets a person owns; it’s a profile of your entire life with timestamps. The same applies to your company’s revenue export.
The local loop gives you the identical natural-language experience with zero disclosure. The CSV goes from ~/Downloads to a pandas DataFrame in unified memory and back to a chart on your screen. On a sufficiently specced Mac, the privacy-convenience tradeoff that defined cloud AI simply doesn’t apply to this workload — Qwen Coder writes the same groupby either way.
Try it tonight with one file: export the last 12 months from your bank, open JupyterLab, and ask for monthly spending by category — remembering the magic words, “write pandas code to…” The first session takes twenty minutes including setup. The second one takes ninety seconds, and somewhere in that output there’s a subscription you forgot you were paying for. Mine was hiding in row 1,847.