Home · Data Analysis · xlsx
xlsx
Anthropic's spreadsheet skill: live formulas only, a professional formatting standard, and a mandatory LibreOffice recalculation pass before any workbook ships.
Score
“The first skill in our tests whose edge over the baseline is binary rather than a matter of taste: identical formula logic on both sides, but only the with-skill workbook shipped values a reader could actually see, because the skill mandates the recalculation pass nobody runs unprompted. Caveats: it needs LibreOffice installed, and the licence is proprietary.”
Both workbooks had correct formulas. Only one shipped values anyone could read: the baseline's totals were all None until we recalculated a copy ourselves.
Sub-scores & evidence
| Task completion | Data + Summary sheets as briefed, 5/5 summary cells are live formulas referencing Data, and after the recalc pass the cached totals are exact: $787.50 / $982.50 / $1,082.50 / $1,002.50, grand total $3,855.00. | 12/12 |
| Beats the no-skill baseline | As shipped, the baseline had 0/5 readable summary values (cached value None in every formula cell) against the skill version's 5/5. It also added a Revenue helper column the brief didn't ask for and used the default Calibri instead of a mandated font. Its formula logic, once recalculated, was equally correct — the gap is the shipping state, not the maths. | 8/10 |
| Self-verification in output | The run followed the skill's own checks: expected totals computed before the grid was built (North pre-check $787.50), then scripts/recalc.py reported status success, total_formulas 5, total_errors 0. | 5/5 |
| Failure behaviour | No failure case was injected this round. recalc.py's refusal to destroy external links is designed behaviour, documented and read in audit, but not exercised by this test. | 2/3 |
The only skill we have tested with a hard ship gate: never deliver while the recalculation check reports errors. The JSON contract for that check is specified to the exit code.
Sub-scores & evidence
| Clear steps | A task-routing table up front (create/edit → openpyxl, bulk → pandas, quick look → markitdown), then requirements, recalc procedure and gotchas. Organised by topic rather than as one numbered pipeline. | 5/6 |
| Inputs & outputs defined | 'Follow the user's spec literally. Exact tab names, exact column headers' — and the recalc output contract names every JSON key (status, total_formulas, total_errors, error_summary). | 4/4 |
| Checks & verification | Mandatory recalculation after any formula work, error locations named per cell, plus the warning that a green recalc proves formulas evaluate, not that they are right — so spot-check 2–3 formulas against expected values first. | 4/4 |
| Stop conditions | 'Zero formula errors. Never ship while recalc.py reports errors_found.' recalc.py itself refuses to run when external links would be destroyed, unless --force is passed. | 3/3 |
| Failure recovery | Timeout handling with a re-run instruction, a distinct error-JSON shape for 'nothing was recalculated', and the trap spelled out: errors_found exits 0, so a clean exit is not a clean workbook. | 3/3 |
A single dense 99-line file. No layered reference documents — the depth lives in the shipped scripts, which never enter context.
Sub-scores & evidence
| Leanness | SKILL.md is 99 lines / 8,598 bytes — about 2,150 tokens in the always-loaded layer. | 5/5 |
| Progressive disclosure | No reference files to load on demand; everything sits in the core file. Acceptable at 99 lines, and the heavy material is code (scripts/recalc.py, the office toolkit), not prose competing for context. | 3/5 |
| Organisation & naming | Routing table, output requirements, recalculation, formula survival, openpyxl gotchas, financial models, dependencies — in the order an agent hits them. | 3/3 |
| No padding | Every paragraph is a rule, a format spec or a named failure mode. Nothing decorative. | 2/2 |
The best description we have tested: five file extensions, the user's casual phrasings, and — alone in this set — an explicit list of when NOT to fire.
Sub-scores & evidence
| What it does | Open, read, edit, fix, create and convert across .xlsx, .xlsm, .xltx, .csv and .tsv, plus cleaning messy tabular data into proper spreadsheets. | 4/4 |
| When to use | 'Use this skill any time a spreadsheet file is the primary input or output' — one testable condition, stated first. | 4/4 |
| User-word keywords | Covers casual references explicitly: 'even casually (like "the xlsx in my downloads")'. | 3/3 |
| When NOT to use | Names five exclusions: a Word document, an HTML report, a standalone Python script, a database pipeline, or a Google Sheets API integration as the primary deliverable — 'even if tabular data is involved'. | 3/3 |
| Naming & voice | Single-word functional name; description written as instructions to the agent, third person. | 1/1 |
No network code anywhere in the toolkit. One mechanism needs naming plainly: office/soffice.py compiles an embedded C socket shim with gcc and LD_PRELOADs it into LibreOffice when a sandbox blocks AF_UNIX sockets. Readable source, scoped to the soffice process.
Sub-scores & evidence
| Least privilege | Scripts operate on the files passed to them plus temp directories, and subprocess is used only for soffice, gcc, git and timeout — no shell=True anywhere. One point off for the runtime-compiled LD_PRELOAD shim: interposition code, however well-scoped, is more machinery than the task strictly needs. | 3/4 |
| Declared tool scope | A Dependencies section names openpyxl, pandas, markitdown and LibreOffice; there is no allowed-tools field in the frontmatter and versions are unpinned. | 2/3 |
| Sensitive-action confirmation | The one destructive path is guarded: recalc.py lists the exact cells whose external links would be destroyed and refuses without --force. SKILL.md likewise warns that saving a data_only workbook permanently replaces formulas with literals. | 3/3 |
Written by someone who has shipped broken workbooks and catalogued how. The formula-survival section alone — which functions LibreOffice cannot evaluate, and why — is worth the install.
Sub-scores & evidence
| Examples & templates | Concrete fragments throughout (the '=SUM(B2:B9)' pattern, a model source citation with journal and page, exact format strings and RGB codes) but no complete worked workbook to imitate. | 2/3 |
| Scripts & instruction precision | recalc.py's contract is documented to the level of JSON keys, a 100-location cap per error type, and exit-code semantics. The function whitelist/blacklist gives reasons: XLOOKUP is banned because spilling functions have no spill metadata in an openpyxl-written file, so only the top-left cell gets a value — silently. | 3/3 |
| Dependencies stated | A dedicated Dependencies section: openpyxl, pandas, markitdown via pip, and LibreOffice (soffice) as a system dependency, with its sandbox helper named. | 2/2 |
| Concrete instructions | Exact specs, not vibes: currency $#,##0;($#,##0);-, percentages stored as fractions (0.15 renders 15.0%; storing 15 renders 1500.0%), blue text (0,0,255) for hardcoded inputs, green for cross-sheet links. | 2/2 |
Best for / not for
Best for
- Workbooks other people and tools must read — the cached-value trap is the commonest silent spreadsheet failure
- Financial models and recurring reports where totals must stay live formulas, never pasted numbers
- Teams who want one enforceable shipping standard: formulas, font, formats, zero errors
Not for
- Machines without LibreOffice — the mandatory recalculation step, and the guarantee it buys, cannot run
- Google Sheets deliverables — the description itself excludes them
- Projects that need open-source licensing; this one is proprietary Anthropic terms
What it does
xlsx is not a recipe collection. It is a set of shipping rules for spreadsheets, plus one mandated tool. The rules: formulas are never hardcoded results (=SUM(B2:B9), not the Python-computed total); one professional font throughout; every assumption and hardcoded number documented where the reader will see it; an existing file’s own conventions override everything, down to writing only in its designated input cells. Behind the rules sits a formula-survival guide for the skill’s own verification runtime — which functions LibreOffice evaluates, which six post-2007 functions only work with an _xlfn. prefix, and why XLOOKUP is banned outright (spilling functions in an openpyxl-written file fill only the top-left cell, and the error check still reports zero errors).
The mandated tool is scripts/recalc.py. openpyxl writes formulas with no cached values, so until something recalculates the file, every formula cell reads back as None to pandas, to load_workbook(data_only=True) and to most previewers. recalc.py drives LibreOffice headless to compute every formula, rewrites the file in place, and returns a JSON verdict — success or errors_found, with error locations named per cell. The skill is blunt about the workflow: never ship while it reports errors. It ships as part of a shared office toolkit of about 1 MB — XML validators and ~40 XSD schemas shared with the docx and pptx skills — of which recalc.py is the only piece this skill actually calls.
How the live test went
The brief was identical on both sides: a 12-row sales CSV turned into a workbook with a Data sheet (the raw rows) and a Summary sheet (revenue by region, live formulas, finance-team formatting). Ground truth was fixed before either run: North $787.50, South $982.50, East $1,082.50, West $1,002.50, grand total $3,855.00.
The with-skill run followed the file literally: Arial throughout, SUMPRODUCT formulas against the Data sheet, the prescribed $#,##0;($#,##0);- currency format, expected totals computed before the grid was built, then the recalc pass — status success, 5 formulas, 0 errors. All five Summary values are cached in the shipped file and exact.
The baseline was no fool. It wrote live formulas too (a Revenue helper column on Data, SUMIF in Summary), and when we recalculated a copy of it ourselves, every total came out exact. But as shipped, all 17 of its formula cells have cached value None. Open that file with pandas or most preview tools and the Summary is five blank cells under correct-looking headers. That is precisely the failure the recalc mandate exists to catch, and it is invisible if you only ever open the file in Excel, which recalculates on load and forgives it.
Where it falls short
The recalc guarantee has a hard dependency: no LibreOffice, no verification. soffice was installed in our test environment (and the toolkit’s helper goes as far as compiling a socket shim to make LibreOffice run in sandboxes that block AF_UNIX), but on a machine without it, recalc.py returns an error JSON and the skill’s central promise is unachievable — the instructions offer no fallback verification path. The prescribed currency format also drops cents from the display ($#,##0 renders $787.50 as $788; the stored value keeps the cents), which suits the $mm models the conventions were written for and suits a 12-row sales summary less. The licence is proprietary Anthropic terms, like its pdf sibling — not Apache-2.0. And the trigger’s strength cuts both ways: with no size limit stated anywhere, a two-row CSV and a 40-sheet financial model get the same full rulebook, including the financial-model colour conventions, unless the user pushes back.
Live A/B test — the evidence
One standard task, run twice: turn a 12-row sales CSV (date, region, product, units, unit price) into a professional workbook — a Data sheet with the raw rows and a Summary sheet with revenue totals by region, as live Excel formulas referencing Data, never pasted values. Ground truth fixed in advance: North $787.50, South $982.50, East $1,082.50, West $1,002.50, grand total $3,855.00.
With the skill
Approach: The skill followed literally: openpyxl with Arial throughout, SUMPRODUCT formulas (on the skill's preferred-function list), its prescribed currency format, then the mandatory scripts/recalc.py pass under LibreOffice
- 5/5 Summary cells are live formulas referencing the Data sheet
- Cached totals exact as shipped: $787.50 / $982.50 / $1,082.50 / $1,002.50 / $3,855.00 — recalc.py reported status success, 0 errors
- Data sheet holds exactly the five raw CSV columns; expected totals were pre-checked before the grid was built
Without the skill (baseline)
Approach: A competent from-scratch build: pandas to read the CSV, openpyxl to write, a Revenue helper column on Data with SUMIF totals in Summary — and no recalculation step
- Formula logic equally correct — a recalculated copy of the baseline reproduces all four totals and the grand total exactly
- As shipped, every one of its 17 formula cells has cached value None: pandas, data_only readers and most previewers see blanks
- Default Calibri instead of a mandated font, and Data gained a helper column the brief did not ask for
| Objective count | With skill | Baseline |
|---|---|---|
| Formula cells in Summary | 5 | 5 |
| Region totals correct (formula logic) | 4/4 | 4/4 |
| Cached values readable as shipped | 5/5 | 0/5 |
| Grand total as a live formula | Yes — =SUM(B2:B5) | Yes — =SUM(B2:B5) |
| Body font | Arial | Calibri (default) |
| Summary number format | $#,##0;($#,##0);- | "$"#,##0.00 |
Same maths, different shipping state. The baseline's workbook is one recalculation away from correct — and nothing in a normal workflow takes that step, so as delivered, its Summary reads as five blank cells. The skill's entire value in this test is a mandated verification pass plus the conventions around it.
Full outputs: Source CSV used in the test · With-skill workbook · Baseline workbook
Trigger tests
| Prompt | Expected | Result |
|---|---|---|
| “Turn this sales CSV into an Excel workbook with totals by region” | trigger | Triggers — a tabular file in, a spreadsheet out: the exact centre of the description. |
| “Fix the broken formulas in Q3-model.xlsx and reformat the totals row” | trigger | Triggers — an existing .xlsx referenced by name, with edit and fix work named in the description. |
| “Clean up this messy TSV export and give me a proper spreadsheet” | trigger | Triggers — restructuring messy tabular data into a proper spreadsheet is called out as its own trigger case. |
| “Write a Python script that loads this CSV into Postgres every night” | skip | Skips — a database pipeline is in the description's explicit Do-NOT-trigger list, even though a spreadsheet file is the input. |
| “Build an HTML dashboard from the numbers in this spreadsheet” | skip | Skips — the primary deliverable is an HTML report, a named exclusion. The spreadsheet being the input does not change that. |
Desk-simulated against the skill's description matching rules; noted as simulated wherever the score depends on it.
Security screen
✓ Pass
Credential theft / exfiltration
✓ Pass
Remote code download & execute
✓ Pass
Data sent to unrelated third parties
✓ Pass
Hidden instructions (incl. invisible Unicode)
✓ Pass
Obfuscated payloads
✓ Pass
Privilege escalation requests
Screening only — not a security certification. We read every Python file in the toolkit: no network calls, no credential or environment access beyond building the LibreOffice environment, no shell=True. The embedded C shim in office/soffice.py is plain readable source, compiled locally with gcc only when AF_UNIX sockets are blocked; nothing is downloaded and nothing leaves the machine. Industry context: Snyk's ToxicSkills scan of 3,984 public skills found security flaws in 36.82% of them.
Install
Claude Code (plugin)
/plugin marketplace add anthropics/skills /plugin install document-skills@anthropic-agent-skills
Any agent (skills CLI)
npx skills add anthropics/skills --skill xlsx
Cursor / Codex (manual)
# copy the xlsx folder into: .cursor/skills/xlsx/ # Cursor project .agents/skills/xlsx/ # shared agents folder # then: pip install openpyxl pandas markitdown # and install LibreOffice — recalc.py needs soffice on PATH
Alternatives
pdf (Anthropic)
The sibling document skill, scored 84/A on this site. Same proprietary licence and the same division of labour: tested recipes for the file format, verified against a baseline. Pick by the file you actually have to ship.
No skill — openpyxl / pandas alone
What our baseline did. The libraries are not the gap: the baseline's formulas were correct. What you give up is the mandated recalculation pass, the function-survival rules for LibreOffice, and the formatting standard — the parts that decide whether the file is right when someone else opens it.
Frequently asked questions
Is the xlsx skill safe?
In our screening on 2026-10-23, xlsx passed all six security red lines (credential theft, remote code execution, data exfiltration, hidden instructions, obfuscated payloads, privilege abuse) and scored 8/10 on the safety dimension. Screening is not a certification — re-screen after major updates.
What is the xlsx skill used for?
Anthropic's spreadsheet skill: live formulas only, a professional formatting standard, and a mandatory LibreOffice recalculation pass before any workbook ships.
How do I install the xlsx skill?
For Claude Code, add the marketplace and install the plugin set that contains it. With the skills CLI: npx skills add anthropics/skills --skill xlsx. For Cursor or Codex, copy the xlsx folder into .cursor/skills/ or .agents/skills/. Full commands are in the Install section of this page.
How good is the xlsx skill?
xlsx scored 91/100 (grade S) in our live test on 2026-10-23: The first skill in our tests whose edge over the baseline is binary rather than a matter of taste: identical formula logic on both sides, but only the with-skill workbook shipped values a reader could actually see, because the skill mandates the recalculation pass nobody runs unprompted. Caveats: it needs LibreOffice installed, and the licence is proprietary.
Tested 2026-10-23 in an agent environment following the skill's own instructions — not inside the Cursor desktop app. Scores follow the Skills List methodology v1: red lines veto regardless of score; install counts and stars never count toward quality. More in Data Analysis.