$npx -y skills add PaulRBerg/agent-skills --skill spreadsheetsUse when CSV, TSV, or Excel (.xlsx) is the primary input/output: inspect, transform, validate, convert, recalc formulas, or create/fix spreadsheets. Do not trigger when tabular data is incidental.
| 1 | # Spreadsheets |
| 2 | |
| 3 | Handle tabular data with exact values, minimal diffs, local privacy, atomic writes, and structural validation. |
| 4 | |
| 5 | ## Invariants |
| 6 | |
| 7 | 1. Keep precision-sensitive amounts as strings and compute with `decimal.Decimal` or DuckDB `DECIMAL(38, 18)`, never |
| 8 | binary floats. |
| 9 | 2. Touch only requested rows, columns, formulas, and formatting. Existing file conventions override house defaults. |
| 10 | 3. For newly authored text tables, prefer TSV, UTF-8 without BOM, LF, one trailing newline, lowercase `snake_case` |
| 11 | headers, ISO dates, `.` decimals, and `-` nulls. |
| 12 | 4. Read unknown text tables with BOM-tolerant UTF-8; never write a BOM. |
| 13 | 5. Write in place atomically through a sibling temporary file, validate it, then replace the target. |
| 14 | 6. Escape external cells beginning with `=`, `+`, or `@`; a bare `-` null is exempt. Formula-prefix cells in trusted |
| 15 | authored data are observations, not proof of injection. |
| 16 | 7. Keep transaction, bank, exchange, and tax data local. Redact samples unless raw rows were explicitly requested. |
| 17 | |
| 18 | ## Factual Profiling |
| 19 | |
| 20 | Resolve helper paths from this `SKILL.md`. Profile unknown data before choosing a transformation tool: |
| 21 | |
| 22 | ```sh |
| 23 | uv run "<skill-dir>/scripts/profile.py" <file> --redact-samples |
| 24 | ``` |
| 25 | |
| 26 | The JSON output has `schema_version: 2`. It reports structural facts, header quality, cardinality/statistics when qsv is |
| 27 | available, frequency facts, formula-prefix cells, workbook metadata, and local tool availability. It contains no tool |
| 28 | recommendations and does not infer identifiers from uniqueness. Choose the tool from the requested transformation, |
| 29 | provenance, output format, and preservation requirements. |
| 30 | |
| 31 | Use `--external-data` only when the cells came from an external or otherwise untrusted source and will be written to a |
| 32 | formula-capable consumer. With that flag, formula-prefix cells affect `status`; without it, legitimate formulas such as |
| 33 | `=SUM(...)` remain factual observations and do not fail the profile. |
| 34 | |
| 35 | ## Tool Routing |
| 36 | |
| 37 | | Need | Tool | |
| 38 | | ------------------------------------------ | --------------------------------------------------- | |
| 39 | | Fast structural preview/validation | `uv run scripts/peek.py <file> --redact-samples` | |
| 40 | | Factual local quality profile | `uv run scripts/profile.py <file> --redact-samples` | |
| 41 | | Counts, stats, frequencies, select, dedupe | `qsv` | |
| 42 | | Joins, pivots, aggregation, conversion | DuckDB with `all_varchar = true` | |
| 43 | | Exact custom transforms | `uv run` Python, stdlib `csv`, `decimal.Decimal` | |
| 44 | | Any `.xlsx`/`.xlsm` input or output | Read `references/xlsx.md` first | |
| 45 | | Exact transformation/validation recipes | Read `references/recipes.md` only when needed | |
| 46 | |
| 47 | Prefer `qsv --cache-threshold 0` where supported. When qsv stdout must remain TSV, use `-o out.tsv`; stdout otherwise |
| 48 | defaults to CSV. |
| 49 | |
| 50 | ## Workflow |
| 51 | |
| 52 | 1. Inspect with `peek.py --redact-samples`; add `profile.py` when cardinality, formula prefixes, metadata, or available |
| 53 | tooling matters. For a no-shape-change edit, save the peek JSON. For intentional row/schema changes, record the |
| 54 | expected width and invariants. |
| 55 | 2. Decide whether formula-prefix cells are dangerous from provenance and output context. Decide the smallest tool that |
| 56 | preserves values and formatting. Avoid pandas unless necessary; if used, load every column as strings. |
| 57 | 3. Apply the transformation atomically. For idempotent appends with legitimate duplicate rows, use multiset difference |
| 58 | rather than set deduplication. |
| 59 | 4. Validate: |
| 60 | - unchanged shape: `peek.py --strict --expect-like <before-report>`; |
| 61 | - changed shape: `peek.py --strict --expect-columns <n>` plus task-specific counts/keys; |
| 62 | - authored house TSV: add `--house`; |
| 63 | - formulas: `uv run scripts/recalc.py <file.xlsx>` and require success. |
| 64 | 5. Report paths, row/column effects, validation, and any workbook features that could not be preserved. |
| 65 | |
| 66 | For human output, lead with `### 📊 Spreadsheet — ✅ updated` only after the write and required validation pass, or |
| 67 | `### 📊 Spreadsheet — 🔎 inspected, no files written` for read-only work. On required validation failure, use |
| 68 | `### 📊 Spreadsheet — ⛔ not deliverable`. Do not paste private profile JSON or decorate cells, headers, formulas, |
| 69 | paths, commands, or diagnostics. |
| 70 | |
| 71 | ## prb-finance |
| 72 | |
| 73 | Never hand-edit generated `.pool.tsv`, `.annual.tsv`, or Markdown reports. After source edits, run `just tsv-check`, |
| 74 | then `just cli::write-changed`. Cap private output to counts and file references unless raw rows were re |