Skip to content

Repository files navigation

BeanBeaver

Beanbeaver turns bank statements and grocery receipts into your Beancount ledger.

Two modes

  1. Import credit card and chequing statements into Beancount
  2. Parse scanned grocery receipts into itemized expenses.

You can use either mode on its own, but using both brings the synergy of semi-automatic matching bank statements and grocery receipts.

Example

Input: T&T receipt

Output: Itemized Beancount Record

TUI (recommended)

bb-tui is the ratatui dashboard that is becoming the primary UI. It starts the OCR container and the receipt upload server for you, shows the scanned/approved receipt queues, and drives review, imports, and matching from one screen.

pixi run bb-tui

The legacy bb CLI below still works but is being deprecated in favor of the TUI.

CLI Usage

Install

Recommended: Pixi

pixi install
pixi run maturin-develop
pixi run bb --help

Standard Python editable install:

python -m pip install --upgrade pip
python -m pip install -e ".[dev,test]"
maturin develop
python -m pip install -e ".[dev,test]"
bb --help

The Rust/PyO3 extension is required for receipt parsing and matching.

Import Statement

bb import  # auto-detects type (prompts if ambiguous)

It scans your default Downloads folder and matches the bank.

Parse receipt

1. Set up OCR

By default Beanbeaver runs receipt OCR in-process — no container needed. Download the model weights once:

bb fetch-models

This fetches the PP-OCRv5 ONNX models (~100 MB) into a per-user cache; from then on bb serve and the TUI run OCR natively. Force a backend any time with OCR_BACKEND=native|container.

Higher line-item accuracy (optional container): the PaddleOCR container (https://github.com/Endle/beanbeaver-ocr) reaches somewhat higher itemization accuracy. Run it and set OCR_BACKEND=container:

docker run --name beanbeaver-ocr -p 8001:8000 ghcr.io/endle/beanbeaver-ocr:latest
# Or podman on Linux
podman run --replace --name beanbeaver-ocr --network=slirp4netns -p 8001:8000 ghcr.io/endle/beanbeaver-ocr:latest

2. Load receipt

If the receipt is on the mobile, we can run

bb serve

Then we use iOS shortcut or other tools to sent the receipt to this endpoint:

curl -X POST "http://<LAN_IP>:8080/beanbeaver" -F file=@receipt.jpg

The server always saves a draft stage into the receipt's own directory (receipts/<receipt-dir>/stages/) for later manual review.

On success the endpoint returns a JSON body that the iOS Shortcut can surface as a notification:

{
  "status": "success",
  "summary": "Loblaws · 2026-05-16 · $32.70 · 8 items",
  "parsed": {
    "merchant": "Loblaws",
    "date": "2026-05-16",
    "date_is_placeholder": false,
    "total": "32.70",
    "subtotal": "29.10",
    "tax": "3.60",
    "item_count": 8,
    "warnings": []
  },
  "draft_filename": "review_stage_1.receipt.json"
}

On failure the body carries an error_code (ocr_unreachable, ocr_error, parse_failed, internal_error) and a human-readable summary you can show directly on the phone so you know whether to reshoot. Keep bb serve bound to localhost or your LAN — the response includes parsed merchant/date/amount.

3. Edit receipt

bb edit

It appends a review stage to the receipt's stages/ directory, promoting the receipt from scanned to approved. Files never move between status trees — status is derived from the latest stage file.

There are also helpers

bb list-approved
bb list-scanned
bb edit
bb re-edit

Match Phase

Here comes the fun part.

bb match

It will match beancount records (from credit card statements) with approved receipts.

Notes:

  • Each receipt chain lives in one directory: receipts/<receipt-dir>/ with source/, ocr/, stages/, and rendered/ subdirectories.
  • Status comes from the latest file under stages/: scanned means OCR+parser succeeded but the draft is unreviewed and may contain errors; approved means the draft has been reviewed and edited by a human; matched means it has been paired with a ledger transaction.
  • bb edit requires an interactive TTY.

Development

Recommended local commands:

pixi run lint
pixi run test
pixi run test-e2e-cached

Core CI now targets Linux, macOS, and Windows for lint and non-E2E tests. Container-backed OCR flows remain Linux-first in practice.

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages