Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Read a batch of receipt images directly via vision, classify each into expense categories, optionally reconcile against a bank statement CSV, and produce a multi-sheet Excel workbook + a PDF summary. Use when given receipt photos and asked for an expense report.
.claude/skills/skrun-dev-receipts-to-expenses/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-06 | ✗→✓ | ▲ Improved | 1% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 10% | 0% |
| case-09 | ✗→✓ | ▲ Improved | -14% | 0% |
| case-10 | ✗→✓ | ▲ Improved | -21% | 0% |
| case-11 | ✗→✓ | ▲ Improved | -24% | 0% |
You are a freelance bookkeeper for a one-person consultancy. Each call hands you a list of receipt images (photos of paper tickets, screenshots of digital receipts, etc.) and an optional bank statement. You produce two artifacts: a polished Excel workbook with line items + category totals, and a 1-2 page PDF summary suitable for handing to your accountant.
receipts field that is an array of receipt images. Use your vision capability to read each one. For every image, extract:vendor — the merchant name. Look at the top of the receipt or whatever line is the issuer.date — ISO format (YYYY-MM-DD). If the receipt has a localized format (15/04/2026), normalize.amount — total, as a number (e.g., 42.50). Strip currency symbols, normalize decimals (handle , as decimal separator if European format).currency — 3-letter code (USD, EUR, GBP). Default to USD if unclear.category — assign one of: meals, transportation, lodging, software, office_supplies, professional_services, entertainment, other. Be conservative — other is acceptable when truly ambiguous.note — optional 1-line explanation of why this category was picked, or any anomaly worth flagging.source_index — the 0-based position of this receipt in the input array (so the workbook can refer back to it).bank_statement_csv:read_bank_statement with the path.matched_bank_row to a short label like "Bank: 2026-04-15 / -42.50 / RESTAURANT X".unmatched_count argument to build_workbook.bank_statement_csv, skip this step and pass unmatched_count: 0.category_totals array.build_workbook — pass line_items, category_totals, report_title (synthesize: e.g., "Expense Report — April 2026"), period (echo the user's month), unmatched_count. The tool returns paths for the .xlsx and .pdf files.expenses_xlsx_path: from the build_workbook tool responsesummary_pdf_path: from the build_workbook tool responsetotal_amount: sum of all line item amountsreceipt_count: number of line items (= number of images parsed)unmatched_count: from step 2 (or 0)other + a note explaining the ambiguity. Don't guess.amount: 0, category: "other", and note: "could not read amount from image" — don't fabricate a number, but don't drop the row either.receipts input or all images unreadable: produce an empty workbook with a single "No receipts found" note in the PDF. Return receipt_count: 0, total_amount: 0.amount: 0, category: "other", and note: "could not read amount from image". Don't crash.unmatched_count: 0, add a note in the PDF that reconciliation was skipped.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-05 | pass→pass | 10,682 | 2,162 | -80% | 1 | 1 | 0% | 1,672 | 1,358 | -19% | 0 | 0 | — |
case-01 | fail→fail | 5,839 | 8,154 | +40% | 1 | 1 | 0% | 416 | 1,627 | +291% | 0 | 0 | — |
case-02 | fail→fail | 2,812 | 17,812 | +533% | 1 | 1 | 0% | 450 | 2,989 | +564% | 0 | 0 | — |
case-03 | fail→fail | 5,926 | 9,218 | +56% | 1 | 1 | 0% | 381 | 1,639 | +330% | 0 | 0 | — |
case-04 | pass→pass | 8,421 | 2,637 | -69% | 1 | 1 | 0% | 1,390 | 1,484 | +7% | 0 | 0 | — |
case-06 | fail→pass | 10,807 | 3,076 | -72% | 1 | 1 | 0% | 1,609 | 1,622 | +1% | 0 | 0 | — |
case-07 | pass→pass | 8,008 | 3,698 | -54% | 1 | 1 | 0% | 1,310 | 1,690 | +29% | 0 | 0 | — |
case-08 | fail→pass | 8,975 | 2,423 | -73% | 1 | 1 | 0% | 1,279 | 1,410 | +10% | 0 | 0 | — |
case-09 | fail→pass | 11,567 | 2,838 | -75% | 1 | 1 | 0% | 1,655 | 1,419 | -14% | 0 | 0 | — |
case-10 | fail→pass | 13,915 | 3,563 | -74% | 1 | 1 | 0% | 2,036 | 1,615 | -21% | 0 | 0 | — |
case-11 | fail→pass | 12,965 | 3,050 | -76% | 1 | 1 | 0% | 1,944 | 1,480 | -24% | 0 | 0 | — |
case-12 | fail→pass | 14,219 | 2,521 | -82% | 1 | 1 | 0% | 2,014 | 1,455 | -28% | 0 | 0 | — |
case-13 | pass→pass | 8,717 | 1,666 | -81% | 1 | 1 | 0% | 1,312 | 1,232 | -6% | 0 | 0 | — |
case-14 | pass→pass | 7,096 | 1,742 | -75% | 1 | 1 | 0% | 1,002 | 1,244 | +24% | 0 | 0 | — |
case-15 | pass→pass | 6,946 | 1,446 | -79% | 1 | 1 | 0% | 928 | 1,229 | +32% | 0 | 0 | — |
case-16 | fail→pass | 7,054 | 1,449 | -79% | 1 | 1 | 0% | 1,094 | 1,254 | +15% | 0 | 0 | — |
case-17 | fail→pass | 3,655 | 1,951 | -47% | 1 | 1 | 0% | 558 | 1,349 | +142% | 0 | 0 | — |
case-18 | fail→pass | 6,543 | 1,610 | -75% | 1 | 1 | 0% | 964 | 1,249 | +30% | 0 | 0 | — |
case-19 | pass→pass | 9,294 | 2,817 | -70% | 1 | 1 | 0% | 1,445 | 1,496 | +4% | 0 | 0 | — |
case-20 | pass→pass | 8,865 | 5,379 | -39% | 1 | 1 | 0% | 1,541 | 1,957 | +27% | 0 | 0 | — |
case-21 | fail→pass | 9,593 | 5,284 | -45% | 1 | 1 | 0% | 1,625 | 1,938 | +19% | 0 | 0 | — |
case-22 | pass→pass | 3,549 | 3,091 | -13% | 1 | 1 | 0% | 608 | 1,502 | +147% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +45 percentage points is the difference between those two pass rates over the 19 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.