This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
Receipt Sloth turns a folder of receipt text files and exported emails into something I can stop thinking about. It reads the merchant, date, total, and currency, picks a spending category, and copies each receipt into a dated folder with a readable name. It also writes a CSV and a monthly summary.
The little job I wanted to automate is the gap between "I'll keep this receipt" and "I'll actually file it." A folder full of scan (2).txt files is easy to create and easy to ignore.
Gemma runs locally through Ollama. The default keeps the originals. A dry run shows every destination before anything is written, duplicates are skipped, and missing dates or totals go into needs-review/. The sloth still has to look at those.
This version handles text, Markdown, and .eml emails. Photos and PDFs need text extraction first. All receipts in the demo are fictional.
Demo
Watch the real terminal demo, MP4.
The recording shows a rules preview, an actual Gemma run, the resulting folder tree, and the spending summary. Commands were typed automatically; every command really executed. The video preserves the recorded timing. No hosted application or paid API is involved.
Code
RostyslavDzhohola
/
receipt-sloth
Lazy, offline receipt sorter powered by local Gemma (Ollama), with a no-model fallback
receipt-sloth
A messy receipt folder goes in. Dated folders, readable filenames, a CSV, and a monthly spending summary come out. Local Gemma reads text and email receipts so you can put off the filing, rather than put off the receipts.
Built for DEV's Hacktoberfest Week 3: Slow and Steady, entering Best Use of Gemma. This new project started and finished on October 20, 2026, during the October 19–25 entry window. There are no post-deadline commits as of this release. Any commits after October 25, 2026 at 11:59 PM PDT must be identified here.
Watch the terminal video or view the animated recording. The DEV submission draft is ready for publication by Ros's publishing bot.
Try it without installing anything
Python 3.9 or newer. The app and tests use only the standard library. No Python packages, API keys, accounts, or paid services are needed.
git clone https://github.com/RostyslavDzhohola/receipt-sloth.git
cd…Source and setup instructions. The original application and fictional fixtures are MIT licensed. The project started and finished on October 20, 2026, inside this challenge's build window.
Python 3.9 or newer is enough to try the rules engine. There are no third-party Python dependencies.
git clone https://github.com/RostyslavDzhohola/receipt-sloth.git
cd receipt-sloth
python3 -m receipt_sloth samples/ --engine rules --dry-run
How I Built It
The app asks gemma4:e2b-it-qat, served by local Ollama, for a JSON object with five fields. A small validation layer checks the result before the sorter touches a file. A rules engine supplies missing fields and keeps the app useful when Ollama is unavailable.
On a Mac with Ollama installed and running:
ollama pull gemma4:e2b-it-qat
python3 -m receipt_sloth samples/ --engine gemma
The real Gemma runs worked. That is separate from the unit tests, which use a fake HTTP server. The release passes 71 tests on Python 3.9, 3.11, and 3.15, including malformed model replies, unsafe output paths, and reports surviving repeated move runs.
The evaluation uses small, hand-labelled fictional fixtures. An all-fields-correct result needs merchant, date, total, currency, and category to match. The same coding agent wrote the engines and receipts, so these numbers are a sanity check, not a benchmark.
| Evaluation | Rules | Gemma with validation and fallback | Raw Gemma |
|---|---|---|---|
| Original frozen sample set, 11 receipts | 10/11 | 11/11 | 10/11 |
| Original frozen holdout, 6 receipts | 5/6 | 5/6 | 5/6 |
| Reviewed release, same samples | 10/11 | 10/11 | 10/11 |
| Reviewed release, same holdout | 5/6 | 5/6 | 5/6 |
The original engines were frozen at commit 9c6fe3c before the first holdout score. Once the failures informed fixes, that set stopped being unseen. The later scores are regression checks. Full labels, per-field scores, and raw replies are in the repository.
The fresh release evaluation completed all 19 local model requests with zero request failures. Two sample documents needed rules backfill. Both the grocery list and the holdout newsletter were correctly kept for review; the original frozen version had mistakenly accepted the newsletter.
One failure is a useful reason to keep the guard. On a pizzeria receipt, Gemma invented a 30.33 EUR total where the page said 27.80 EUR. It also read an ambiguous October date as March. The amount check rejected the invented total. The rules parser could not read the Italian TOTALE label, so the receipt went to review.
There is a cost to being cautious. Gemma repaired an OCR date, 1O/09/26, but the parser could not independently read that date. The release sends it to review, which lowers the sample score from 11/11 to 10/11. I prefer an extra item to inspect over a quietly invented filing date. A wrong number that happens to appear elsewhere on the receipt can still pass validation, so the CSV deserves a human check.
Why Does Open Innovation Matter?
A receipt contains more than a price. It can say where someone went, when they went there, and what they bought. Local inference lets the sorting happen without sending that text to an API provider.
Gemma's downloadable weights make that possible on a laptop. Ollama serves the model locally, and the app only accepts loopback endpoints, bypasses proxies, and refuses redirects. After the initial model download, the workflow runs without internet access. There is no per-receipt API bill, though it still uses your own hardware and electricity.
The Python code, extraction prompt, validation, and labels are all inspectable. Someone can change the categories, inspect a raw reply, or try another downloaded local model against the same fixtures. A closed API would make offline operation depend on somebody else's service.
Gemma is Google's open-weight model, and Ollama is MIT licensed. The installed gemma4:e2b-it-qat artifact reports Apache License 2.0 through Ollama's model metadata; the repository includes that reported license. Model weights are downloaded separately. No non-trivial application code was copied from an earlier project.
My Agent Session
The app was built by AI coding agents, Claude Opus 5.5 then Codex GPT-6.1-Sol, orchestrated in T3 Code, for me, Ros. They implemented the app, ran local Gemma, reviewed the code, fixed the valid findings, and prepared this entry. That help is part of the process, including this write-up.
The session logs can be shared on request after a privacy review. No public session link is included here. The code, test cases, saved raw model replies, and terminal recordings are available now so readers can check the result.
The Lazy Payoff
The demo files three unique receipts, skips one duplicate, and leaves one grocery list for review. The larger sample folder exercises multiple currencies, email exports, an unreadable date, and repeated runs. That is what has actually been exercised, not a claim about weeks of personal use.
For a folder of 30 receipts, saving 20 seconds of manual naming and filing per receipt would be about 10 minutes. That is an estimate, not a measured user study, and review time reduces the saving. The payoff I care about is simpler: one command does the routine copying and naming, and the awkward cases wait in one obvious place.
Prize Categories
Best Use of Gemma.





Top comments (0)