Automated Receipt Processing and Expense Reports with AI
Turn a folder of scanned receipts into categorized, renamed files and a polished Excel report—with one command. No data entry required.
"What if you could drop receipts into a folder, say 'process my receipts,' and get back organized files plus a complete expense report with monthly subtotals?"
Drop a stack of PDFs into a folder. Say “process my receipts.” Get back: every file renamed with date, vendor, and amount. Categorized by GL account. Flagged as expense or depreciate. Duplicates caught. Excel report generated with monthly subtotals. Ready to send to accounting.
That’s not a workflow diagram. That’s what Claude Code actually does—right now, with vision, file operations, and intelligent categorization working together.
The Problem
Anyone who submits expense reports knows the pain:
-
Manual data entry hell — Each receipt requires typing vendor, amount, date, category. For 50 receipts, that’s an hour of mind-numbing work where one typo means reconciliation nightmares.
-
Inconsistent file naming — Your Dropbox is a graveyard of
IMG_4521.pdf,scan_dec_maybe.pdf, andreceipt (3).pdf. Good luck finding that Starbucks receipt from October when the auditor asks. -
Category guessing games — Is that Home Depot purchase office supplies or equipment? Does the $800 monitor expense or depreciate? Every receipt requires a mental lookup against accounting rules you half-remember.
Small business owners lose 2-3 hours per week on receipt processing. Finance teams processing employee expenses multiply that by headcount. It’s death by a thousand paper cuts.
What Claude Code Actually Does
This isn’t OCR plus a spreadsheet. It’s an intelligent system that sees receipts, understands context, and executes the entire workflow:
Vision-Based Extraction Claude reads each PDF visually—not just OCR text, but understanding layout, logos, and context. It distinguishes a receipt from a contract. It finds the total even when buried in a complex layout. It reads airport codes and maps them to cities.
Smart Categorization A configurable GL chart maps keywords to accounts. “Starbucks” → Travel - Meals. “United Airlines” → Travel - Airfare. “MacBook” → Computer Equipment. But it goes deeper: a $1,200 monitor gets flagged for depreciation while a $45 keyboard expenses immediately.
Duplicate Detection Hash-based fingerprinting catches the same receipt scanned twice. Before processing, the system checks vendor + amount + date against previously processed receipts. Duplicates get skipped with a message showing when and where it was already processed.
File Organization
Every receipt gets renamed to a consistent format: 2024-12-15_Starbucks_12.45.pdf. Files move from inbox to processed folder. No more hunting through random filenames.
Report Generation Excel report with monthly subtotals, expense vs. depreciate breakdown, GL account summary—formatted and ready for accounting.
How It Works
The Orchestration
When you trigger receipt processing, Claude Code coordinates multiple operations:
// Receipt processing orchestration
async function processReceipts(sourceFolder: string) {
// Discover all PDFs waiting to be processed
const pdfs = await Glob.find(`${sourceFolder}/*.pdf`);
const processed: Receipt[] = [];
const skipped: SkippedFile[] = [];
for (const pdf of pdfs) {
// Read PDF with vision - Claude SEES the receipt
const content = await Read.file(pdf);
// Classify: Is this actually a receipt?
const classification = classifyDocument(content);
if (!classification.isReceipt) {
skipped.push({ file: pdf, reason: classification.reason });
continue;
}
// Extract key fields using vision
const extracted = extractReceiptData(content);
// Check for duplicates before processing
const duplicate = await checkDuplicate(
extracted.vendor,
extracted.amount,
extracted.date
);
if (duplicate) {
skipped.push({
file: pdf,
reason: `Duplicate of ${duplicate.previousFile} (processed ${duplicate.processedDate})`
});
continue;
}
// Categorize against GL chart
const category = await categorizeExpense(extracted, glChart);
// Generate standardized filename
const newFilename = `${extracted.date}_${sanitize(extracted.vendor)}_${extracted.amount}.pdf`;
// Move and rename file
await moveFile(pdf, `${processedFolder}/${newFilename}`);
// Register hash to prevent future duplicates
await registerProcessedReceipt(extracted, newFilename);
processed.push({ ...extracted, ...category, filename: newFilename });
}
// Generate Excel report with monthly subtotals
const reportPath = await generateExcelReport(processed, {
includeMonthlySubtotals: true,
includeSummary: true
});
return { processed, skipped, reportPath };
}
Intelligent Categorization
The GL chart matching goes beyond simple keyword lookup:
// Smart categorization with amount-based rules
function categorizeExpense(receipt: Receipt, glChart: GLChart): Category {
const searchText = `${receipt.vendor} ${receipt.items.join(' ')}`.toLowerCase();
let bestMatch = null;
let bestScore = 0;
for (const [code, account] of Object.entries(glChart)) {
let score = 0;
for (const keyword of account.keywords) {
if (searchText.includes(keyword)) {
score++;
}
}
if (score > bestScore) {
bestScore = score;
bestMatch = account;
}
}
if (!bestMatch) {
return { glAccount: '9999 Uncategorized', expenseType: 'Manual Review' };
}
// Apply amount-based depreciation rules
let expenseType = bestMatch.defaultExpenseType;
if (bestMatch.depreciateThreshold) {
// "Depreciate if >$500" rules
if (receipt.amount >= bestMatch.depreciateThreshold) {
expenseType = 'Depreciate';
} else {
expenseType = 'Expense';
}
}
return {
glAccount: `${bestMatch.code} ${bestMatch.name}`,
expenseType
};
}
Duplicate Detection
The hash system prevents reprocessing while allowing legitimate same-day purchases:
// Hash-based duplicate detection
function generateReceiptHash(vendor: string, amount: number, date: string): string {
// Normalize inputs for consistent matching
const vendorNorm = sanitizeVendorName(vendor).toLowerCase();
const amountNorm = amount.toFixed(2);
const dateNorm = parseDate(date); // Handles multiple formats
const content = `${vendorNorm}|${amountNorm}|${dateNorm}`;
return sha256(content).substring(0, 16);
}
function checkDuplicate(vendor: string, amount: number, date: string): DuplicateInfo | null {
const hash = generateReceiptHash(vendor, amount, date);
const db = loadHashDatabase(); // Simple JSON file
if (db[hash]) {
return {
hash,
previousFile: db[hash].filename,
processedDate: db[hash].processedDate
};
}
return null;
}
The Output
Renamed Files
Before:
~/Dropbox/scans/
IMG_4521.pdf
receipt_dec.pdf
scan (2).pdf
starbucks_maybe.pdf
united_boarding.pdf
After:
~/Dropbox/scans/processed/
2024-12-10_AppleStore_1299.00.pdf
2024-12-12_OfficeDepot_48.37.pdf
2024-12-13_Marriott_189.00.pdf
2024-12-14_UnitedAirlines_450.00.pdf
2024-12-15_Starbucks_12.45.pdf
Excel Report
┌─────────────────────────────────────────────────────────────────────────┐
│ Receipt Processing Report │
│ Generated: 2024-12-28 15:30 │
├──────────────────────────────────────────────────────────────────────────┤
│ Vendor │ Location │ Amount │ GL Account │ Type │
├──────────────────────────────────────────────────────────────────────────┤
│ Office Depot │ Chicago │ $48.37 │ 5100 Office Supply │ Expense│
│ Marriott │ NYC │ $189.00 │ 5210 Travel-Lodging │ Expense│
│ │ │ │ │ │
│ ▸ November 2024 Subtotal │ $237.37 │ │ │
├──────────────────────────────────────────────────────────────────────────┤
│ Apple Store │ SF │$1,299.00 │ 6100 Computer Equip │ Deprec │
│ United Airlines │ ORD │ $450.00 │ 5200 Travel-Airfare │ Expense│
│ Starbucks │ Chicago │ $12.45 │ 5220 Travel-Meals │ Expense│
│ │ │ │ │ │
│ ▸ December 2024 Subtotal │$1,761.45 │ │ │
├──────────────────────────────────────────────────────────────────────────┤
│ SUMMARY │
│ Total Receipts: 5 │
│ Total Amount: $1,998.82 │
│ │
│ BY MONTH: │
│ November 2024: $237.37 │
│ December 2024: $1,761.45 │
│ │
│ BY TYPE: │
│ Expense Total: $699.82 │
│ Depreciate Total: $1,299.00 │
└──────────────────────────────────────────────────────────────────────────┘
Terminal Summary
=================================================================
RECEIPT PROCESSING COMPLETE
=================================================================
Processed: 5 receipts
Skipped: 2 files
Total Amount: $1,998.82
Expense: $699.82
Depreciate: $1,299.00
Processed Receipts:
--------------------------------------------------
2024-11-12 | Office Depot | $48.37 | 5100
2024-11-13 | Marriott | $189.00 | 5210
2024-12-10 | Apple Store | $1,299.00 | 6100
2024-12-14 | United Airlines | $450.00 | 5200
2024-12-15 | Starbucks | $12.45 | 5220
Skipped Files:
--------------------------------------------------
contract-v2.pdf: Not a receipt - legal document
old_starbucks.pdf: Duplicate of 2024-12-15_Starbucks_12.45.pdf
Excel Report: ~/Desktop/receipts_2024-12-28.xlsx
=================================================================
What Makes This Different
vs. Expensify/Concur Those tools require per-receipt interaction—snap, categorize, submit. This processes a batch in one command. No app switching, no per-receipt tapping, no subscription per user.
vs. Generic OCR OCR extracts text. It doesn’t understand that “ORD” means Chicago, that $1,200 on a monitor should depreciate, or that a document without a total isn’t a receipt. Claude’s vision understands context.
vs. Manual Processing 50 receipts manually: ~60 minutes of data entry plus organization. Same receipts with this system: ~2 minutes of processing time, zero data entry.
What You Get
| Metric | Before | After | Impact |
|---|---|---|---|
| Time per batch (50 receipts) | 60 min | 2 min | 97% reduction |
| Naming consistency | Chaos | 100% standardized | Instant searchability |
| Categorization accuracy | Variable | Rules-based, auditable | Consistent GL mapping |
| Duplicate processing | Common | Zero | No double-entries |
| Report generation | Manual Excel work | Automatic | Ready for accounting |
Going Further
This foundation enables:
- Vendor Memory — Store vendor patterns in semantic memory. “When I buy from Apple, it’s usually equipment. Starbucks near ORD is travel meals.”
- Email Pipeline — Forward receipts to a dedicated address, auto-extract attachments, process overnight.
- Accounting Integration — Push categorized data directly to QuickBooks, Xero, or your ERP.
- Spending Analytics — Monthly trend analysis, anomaly detection, budget vs. actual dashboards.
The hardest part isn’t the technology—it’s encoding your business rules correctly. Which purchases count as travel vs. office supplies? What’s your depreciation threshold? How do you handle foreign currency? These decisions require understanding your specific accounting requirements, not just generic receipt reading.
See It In Action
Watch the full workflow—from raw PDFs to organized files and Excel report:
