Xlsx toolkit
Skill decebal/curated-claude-skills/skills/stack-agnostic/xlsx-toolkit
Read, write, convert, diff, and analyze .xlsx (Excel) files with a single Rust binary built on umya-spreadsheet. Use when the user wants to inspect an unknown spreadsheet, extract sheet data to CSV/JSON, generate an xlsx report (with headers, formulas, freeze panes, autofilter, column widths), compare two workbooks, or measure column fill coverage (e.g. "what's actually populated in this spreadsheet?"). Triggers on: read xlsx, parse xlsx, convert xlsx to csv, generate xlsx, write excel file, diff two spreadsheets, coverage of a spreadsheet, what's in this .xlsx, summarize this excel file.From its SKILL.md
npx -y skills add decebal/curated-claude-skills --skill xlsx-toolkitAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.4 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
xlsx-toolkit
Single Rust binary with five subcommands, built on umya-spreadsheet (read+write) and clap. The skill directory is a cargo project — source in src/, binary at bin/xlsx-toolkit.
First-time setup
Invoke via the shim, which picks a prebuilt for the current platform or builds from source on first use:
~/.claude/skills/xlsx-toolkit/bin/xlsx-toolkit --help
The skill ships a prebuilt only for aarch64-apple-darwin. On any other platform the shim runs cargo build --release once and caches the result in target/release/. Subsequent runs go straight to the cached binary — no cargo overhead.
Optional alias if you'll use this often:
alias xlsx-toolkit='~/.claude/skills/xlsx-toolkit/bin/xlsx-toolkit'
macOS Gatekeeper: if the bundled binary arrived with a com.apple.quarantine xattr (downloaded .skill), the shim strips it automatically. If macOS still blocks it ("unidentified developer"), run xattr -dr com.apple.quarantine ~/.claude/skills/xlsx-toolkit/bin and retry.
The rest of this file assumes you can invoke the binary as xlsx-toolkit. If the alias isn't set, use the full path.
When to use what
| Task | Subcommand |
|---|---|
| "What's in this xlsx?" / unknown workbook | inspect |
| Dump a sheet (or all sheets) to CSV/TSV | to-csv |
| Build a new xlsx from a JSON spec | write |
| Compare two workbooks | diff |
| Per-column fill % / data quality | coverage |
For anything else, read references/patterns.md — it covers formulas vs cached values, dates, merged cells, multi-row headers, hidden sheets, write-side details, and how to drop down to the umya-spreadsheet API when the subcommands don't fit.
Workflow
- Always inspect first. Run
xlsx-toolkit inspect <file>before doing anything else. It prints sheet names, dimensions, headers, formula count, merged ranges, and a sample. Without this, you'll guess wrong about what's in the workbook. - Convert to CSV when piping to other tools.
to-csv --sheet NAMEto stdout is the right move when feeding data tojq,grep,awk,csvkit, etc. Don't try to parse xlsx with shell. - For new workbooks, prefer
writeover hand-rolling. It handles freeze panes, autofilter, column widths, and formulas through a JSON spec. If the layout is unusual, fall back to writing a small cargo binary against the patterns inreferences/patterns.md. - Coverage is the data-quality lens. Use
coverageto find columns that are mostly empty (often imported-but-unused fields) or to confirm a migration populated what it should. The HubSpot data-model coverage doc in this monorepo is exactly this shape.
Quick examples
Inspect
xlsx-toolkit inspect ./data.xlsx --sample 5
xlsx-toolkit inspect ./data.xlsx --json | jq '.details[].headers'
xlsx-toolkit inspect ./data.xlsx --sheet Contacts
Convert
# One sheet → stdout (pipe to anything)
xlsx-toolkit to-csv ./data.xlsx --sheet Contacts | head
# All sheets → sibling .csv files next to the source
xlsx-toolkit to-csv ./data.xlsx
# TSV
xlsx-toolkit to-csv ./data.xlsx --sheet Contacts --delimiter $'\t'
Write
cat > /tmp/spec.json <<'EOF'
{
"sheets": [{
"name": "Report",
"headers": ["Item", "Qty", "Price", "Total"],
"rows": [
["apples", 3, 1.5, { "v": 0, "f": "B2*C2" }],
["bread", 2, 4.25, { "v": 0, "f": "B3*C3" }]
],
"freeze_header": true,
"autofilter": true,
"column_widths": [12, 6, 8, 10]
}]
}
EOF
xlsx-toolkit write --spec /tmp/spec.json --out report.xlsx
# Or pipe the spec on stdin:
cat /tmp/spec.json | xlsx-toolkit write --out report.xlsx
Cell values: plain JSON string | number | boolean | null for static data, or { "v": <value>, "f": "FORMULA", "t": "n|s|b" } for formulas / explicit types. Set the value AND the formula together — the cached v is what other tools see until Excel re-evaluates.
Diff
# Positional row diff (row N vs row N) across shared sheets
xlsx-toolkit diff before.xlsx after.xlsx
# Key-based: match rows by a header column value (stable across reorderings)
xlsx-toolkit diff before.xlsx after.xlsx --key "Property"
# Restrict to one sheet, JSON output
xlsx-toolkit diff before.xlsx after.xlsx --sheet Contacts --json
Coverage
# Per-column fill % on every sheet
xlsx-toolkit coverage ./data.xlsx
# Only columns with ≥50% fill
xlsx-toolkit coverage ./data.xlsx --threshold 0.5 --sheet Contacts
Output conventions
- Human-readable goes to stdout; pass
--json(where supported) for machine output. - Status lines from
writeandto-csv(file-writes) go to stderr, so stdout stays clean for piping. - All subcommands exit non-zero on usage errors and propagate
anyhowerrors with context on failure.
When NOT to use this
- Inside a Rust crate that already depends on
umya-spreadsheetorcalamine. Use the in-tree dep directly — don't shell out to global binaries for production logic. - For
.xls(old binary format) — umya is xlsx-only. Convert first (libreoffice --headless --convert-to xlsx file.xls) or read it elsewhere. - For
.xlsmmacros — umya reads the data but doesn't preserve macros on write. Don't round-trip a macro-enabled workbook throughwrite. - For 100k+ row workbooks — umya is fine but loads everything into memory. If memory is tight, dump to CSV and stream from there, or write a one-off using
calamine(much faster reader, read-only).
Project layout
~/.claude/skills/xlsx-toolkit/
├── SKILL.md
├── Cargo.toml
├── .gitignore ← /target/ and *.skill ignored
├── references/
│ └── patterns.md ← gotchas, advanced usage, umya API notes
├── src/
│ ├── main.rs ← clap entry point
│ └── commands/
│ ├── mod.rs
│ ├── common.rs ← shared read/walk helpers
│ ├── inspect.rs
│ ├── to_csv.rs
│ ├── write.rs
│ ├── diff.rs
│ └── coverage.rs
├── bin/
│ ├── xlsx-toolkit ← shell shim, dispatches to prebuilt or cargo build
│ └── aarch64-apple-darwin/
│ └── xlsx-toolkit ← shipped prebuilt (~4 MB)
└── target/release/xlsx-toolkit ← cargo-built fallback (gitignored)
To add another platform: rustup target add <triple>, cargo build --release --target <triple>, then copy target/<triple>/release/xlsx-toolkit to bin/<triple>/xlsx-toolkit. The shim picks it up automatically. For Linux targets from a Mac, use cross (cross build --release --target x86_64-unknown-linux-gnu) to get the right glibc.
What ships with it: 13 files
34.8 KB alongside SKILL.md, 2 of them executable
bin/
- xlsx-toolkitruns1.5 KB
references/
- patterns.md6.4 KB
src/
- commands/common.rs1.9 KB
- commands/coverage.rs3.1 KB
- commands/diff.rs6.9 KB
- commands/inspect.rs2.8 KB
- commands/mod.rs96 B
- commands/to_csv.rs2.5 KB
- commands/write.rs5.8 KB
- main.rs2.2 KB
- Cargo.toml364 B
- .gitignore17 B
- package.shruns1.2 KB