DEV Community

Cover image for LocalLedger AI: Open-Source Bookkeeping with Human-Verified AI
Abishethvarman V
Abishethvarman V

Posted on AI-assisted

LocalLedger AI: Open-Source Bookkeeping with Human-Verified AI

Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle Submission 💸

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle

What I Built

LocalLedger AI is a bookkeeping assistant for freelancers and small businesses. It imports receipts, reads the text on the computer where it runs, and waits for a person to confirm every amount before that amount becomes part of the ledger. It also writes invoices, tracks payments already received, and exports CSV.

The person who would pay for this is a freelancer who keeps a folder of receipt photos and a spreadsheet, and does not want those files sent to a hosted model. A bookkeeper charging for monthly cleanup would pay for the same reason: the client's names, addresses, and prices stay on the laptop. The app does not connect to a bank and does not collect payments. It is a record, not a payment processor or a tax adviser.

Demo

The ledger is local. These screenshots are a fictional Northwind Supplies receipt, not a customer's documents.

Demo Video

The landing page:

LocalLedger AI landing page

A new ledger starts empty. The figures are not sample data until you ask for them:

Empty dashboard

  1. Upload a text PDF receipt. PyMuPDF reads the vendor, date, currency, subtotal, tax, total, and receipt number. The fields stay editable until you approve them.

Review screen with extracted receipt fields and OCR text

  1. Change the total from 1080.00 to 1075.00. The app shows that subtotal plus tax no longer matches, and it does not rewrite the numbers.

Amount mismatch kept for the reviewer to confirm

  1. Approve the expense. Only then does it appear in the expense list and in the default CSV.

Approved Northwind expense in the list

  1. Upload the same file again. The matching file hash is explained, and a second expense is not created.

Exact duplicate warning in the receipt inbox

  1. Issue an invoice with two lines and different tax rates. The server calculates LKR 3,600.00 in minor units and downloads a PDF.

Issued invoice with server totals

  1. Open the category report and the dashboard. Amounts in different currencies are listed separately. This receipt is dated March 2026, so "all dates" is selected.

Expenses by category

Dashboard totals from the approved expense and the outstanding invoice

The same path is scripted in scripts/run_demo.py. It uses a temporary data directory and does not call a commercial AI API. On this machine the script completed with the local model switched off. The screenshots are in docs/screenshots.

Code

Abishethvarman/LocalLedger.AI

LocalLedger AI

Your receipts. Your records. Your computer.

LocalLedger AI is a local bookkeeping assistant for freelancers and small businesses. It imports receipts, reads what it can on your machine, and waits for you to confirm every amount before that amount becomes part of the ledger. It also creates invoices, reports, and CSV exports. It does not connect to a bank, collect payments, or call a paid AI API.

What it does

  1. You upload a JPEG, PNG, WebP, or PDF.
  2. The app stores the original file, hashes it, and reads embedded PDF text. Images and scanned PDFs use Tesseract when it is installed.
  3. A deterministic parser pulls vendor, date, currency, amounts, and reference from that text. Missing or ambiguous fields stay empty.
  4. You correct the fields and approve the expense. Until then it is excluded from totals, reports, and the default CSV export.
  5. You can create invoices, record payments you…

The license is MIT. Setup, OCR, and Ollama instructions are in the README.

How I Built It

The app is a local FastAPI service with SQLite, and a React interface. Money is stored as integer minor units. Invoice totals are calculated on the server. A client cannot edit a stored total independently of the line items.

Text PDFs are read with PyMuPDF. Photos and scans use Tesseract when it is installed. A deterministic parser then looks for vendor, date, currency, amounts, and a reference. If a field is missing or ambiguous, it stays empty. The parser does not fill a missing date with today, and it does not guess a currency from the computer's location.

Ollama is the open-weight piece. It is optional, loopback-only unless that guard is deliberately turned off, and it has no hosted fallback. A suggestion is kept only when the model quotes text that is actually on the receipt, and only for a field the parser left blank. The suggestion is still marked for review. Approving it is what makes it a ledger record.

I verified the core flow with pytest: 71 passed, 1 skipped. The skip is image OCR, because Tesseract is not installed on this Windows machine. The running demo used Python 3.12 and did not have Ollama started.

Why Does Open Innovation Matter?

A receipt is a worse thing to send to a metered API than a chat message. It has a name, an address, a tax amount, and sometimes an account fragment. A closed API would price that upload per document and keep a copy I do not control. LocalLedger is useful at zero document fees, including when the laptop has no model installed: PDF text and manual review still work.

When a model is installed, I can swap it in Settings. The ledger does not change. A closed provider's price change or model retirement would not take the bookkeeping data with it.

The part a closed API is worse at is refusal. If the receipt does not say the date, the field stays blank. If subtotal, tax, and total disagree, the app shows the disagreement. The model is not allowed to invent the missing number from general knowledge.

My Agent Session

Session with DevRelay

{% agent_session SESSION_SLUG %}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)