Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ledger-book

Put your bank statements and invoices in a folder. Get proper books out.

That is the whole aim. You should not have to learn double-entry accounting, a ledger syntax, or anything about how this works. You drop files in inbox/, and the profit and loss, the balance sheet and the trial balance appear — with every figure traceable to the document it came from.

Everything stays on your own machine. No account, no upload, no subscription.

make setup
make demo          # invents a company and books it, so you can see it work
make web           # http://127.0.0.1:8765

Then, when you want your own:

ledgerbook init            # writes books/ — four files, about 20 lines to edit
$EDITOR books/config.toml  # your business, your banks
ledgerbook inbox           # drop your statements in inbox/ first

How you actually use it

1.  Put files in  inbox/          bank statements, invoices, receipts,
                                  screenshots — any name, any format
2.  make inbox                    or drag them into the web page
3.  make report                   profit and loss, balance sheet,
                                  trial balance

That is it. Step 2 works out which account each statement belongs to, checks it against the bank's own closing balance, files it, links your invoices to the payments that paid them, and writes the books.

Where everything lives

Two folders, and you only interact with one of them.

inbox/     you drop things here
books/     everything you own — created by `ledgerbook init`

ledgerbook/, tests/ and docs/ are the software. Nothing of yours is ever written into them.

What you write, and what is written for you

This is the important table. You only ever touch the top three.

File Who writes it What it is
books/config.toml you, once Your business name, your bank accounts, your currency. ledgerbook init puts a commented one there.
books/accounts.ledger you, occasionally Your list of accounts — "Contractors", "Software", "Rent". Add one when you need one.
books/payee.map you, as you go "Anything saying CLOUDSPAN is a Hosting cost." One line, and it applies to every matching payment forever. The web page writes these for you.
books/receipts.map auto (you may edit) Which invoice explains which payment. Written for you when the reference can be read.
books/statements/ auto Your originals, filed and never modified.
books/receipts/ auto Your invoices, filed by supplier.
books/statements/_normalized/ auto — do not edit Every bank's format turned into one shape.
books/journal/** auto — do not edit The actual double-entry books. Rewritten on every run; every file says so on line one.
books/main.ledger auto — do not edit The index ledger reads.

Keeping a second set of books — a side business, a partner's — is ledgerbook --books other-books <command>, or LEDGERBOOK_HOME. The inbox moves with it.

If you change something in a generated file, the next run overwrites it. To change how something is booked, add a line to payee.map — or click it in the web page — and it applies to every matching row, past and future.

Built on ledger-cli

The accounting engine is ledger-cli — free, open source, around since 2003, and used by people who care a great deal about their books being right. Version 3.x (developed against 3.4.1).

ledger-book does not reimplement accounting. It does the part ledger-cli deliberately leaves to you: reading your bank's file, checking it, classifying it, joining your invoices to it, and writing the journal files ledger-cli then reports on.

Your books end up as plain text you own. If you ever stop using this, the journal is still there and still readable — by ledger-cli, by hledger, or by you in a text editor.

Reports

Each statement comes out separately, because that is how they are read and sent on.

ledgerbook report                      # all of them, on screen
ledgerbook report --only pnl           # just the profit and loss
ledgerbook report --only balance       # just the balance sheet
ledgerbook report --only trial         # just the trial balance
ledgerbook report --only handover      # just the notes underneath
ledgerbook report --year 2026          # one financial year
ledgerbook report --entity owner       # the owner's books, not the business's
ledgerbook report --out books/reports  # one .csv per statement, for your accountant

Each statement is written as its own file, in three formats:

books/reports/
  vahini-trial-FY2026.xlsx    .csv   .pdf
  vahini-pnl-FY2026.xlsx      .csv   .pdf
  vahini-balance-FY2026.xlsx  .csv   .pdf
  vahini-handover-FY2026.xlsx .csv   .pdf

Separate files rather than one workbook of tabs, because they get sent on one at a time. The .xlsx is the deliverable — most accountants in India work in Tally and will import a spreadsheet — and the .pdf is the copy nobody can edit. --format csv writes just one kind.

Every figure is a number with a display format, never pre-formatted text, so selecting a column and reading the sum gives the right answer.

On your letterhead

Fill in [letterhead] in books/config.toml once — legal name, address, phone, email, PAN, CIN, and a logo — and every report carries it: as a letterhead on the PDF, at the top of each spreadsheet, and above each report on screen. Your GSTIN comes from [tax]; one copy of it is enough.

Acme Robotics Private Limited
14 Residency Road
Bengaluru, Karnataka 560025
+91 80 4000 1234  ·  accounts@acme.example
GSTIN 29AABCH1234K1ZN  ·  PAN AABCA1234K
─────────────────────────────────────────────────────────
Balance Sheet
FY 2026

Every field is optional and every one is printed exactly as written. Nothing is invented, and the shipped template leaves it blank on purpose: an address that is not yours, on a document that leaves the building, is worse than no address at all.

Each file also carries a footer saying what produced it and which version of ledger did the accounting — a figure nobody can reproduce a year later is a figure nobody can defend.

The handover, under every report

A trial balance that foots proves the arithmetic and nothing else. So every report ends with four short lists — and they go in the workbook as their own sheet, because it is the one your accountant reads first.

  SETTLED              182 payments read, 19 with their invoice attached
  NEEDS YOU            what is flagged, what the inbox could not place,
                       and the one command that clears each
  MISSING              periods with no statement, and payments over
                       5,000 with no evidence — named, biggest first
  FOR YOUR ACCOUNTANT  every figure resting on an assumption rather
                       than a document, and every decision with a tax
                       consequence this will not make for you

The point of the last one: a flagged transaction is included in every figure above it. It is recorded, not decided.

Acme Robotics Pvt Ltd
FY 2026

Profit and Loss
──────────────────────────────────────────────────────────────
  Account                                                 Amount
· Income
  Income:Sales                                       8,38,170.12
· Total income                                       8,38,170.12
· Expenses
  Expenses:Contractors                               5,41,299.33
  ...

The web page

make web              # opens http://127.0.0.1:8765
ledgerbook web --port 9000

It binds to your own machine only — nothing is served outward and nothing is fetched from the internet.

Three pages:

  • Overview — drag your statements and invoices straight in. See what was filed, what was linked, what needs you.
  • Review — everything the tool could not classify, grouped by reason, with the bank's own words beside it. Type what it is, pick an account, and it rebuilds. That is how payee.map gets written.
  • Statements — profit and loss, balance sheet, trial balance, by date range.

What it refuses to do

Import a statement that doesn't add up. Every row is checked against the running balance. If it doesn't reach the closing figure your bank printed, nothing is saved and it tells you which row is wrong.

Ignore a missing statement. If March's statement isn't there, it says so instead of quietly absorbing the difference.

Guess which invoice paid which bill. Invoices are matched on the bank's reference number. If two payments are the same amount on the same day — which happens constantly — it shows you both and lets you choose.

Guess which of your accounts a statement belongs to. Two accounts at the same bank export identical columns, and both balance chains tie, so the numbers cannot say. Three things can: the folder you dropped it in (inbox/business/), a marks = ["<your account number>"] line in config.toml, and whether its opening balance continues a statement already filed. They are not ranked and they do not vote — if they disagree, one of them is wrong, and the file waits for you.

Pretend it knows. Anything it can't classify is booked, flagged, and counted. An unfiled transaction you can see is recoverable; a confidently misfiled one is not.

Your own books

ledgerbook init
$EDITOR books/config.toml   # your business, your banks — about 20 lines
make inbox

Five readers cover most bank exports — csv, xlsx, xls, pdf, text — driven by a small column map. Multiple currencies, and number formats for however your part of the world writes them (12,34,567.89, 1,234,567.89, 1.234.567,89).

GST

If you are registered, invoices are their own input — books/sales.csv and books/purchases.csv — with the fields a return actually asks for, because an account name cannot tell you the place of supply.

ledgerbook gst                      # sales and purchase registers, HSN
ledgerbook gst --only gstr1         # summary, GSTR-3B, outstanding, liability
ledgerbook gst --out books/reports

Every row is checked before it is booked: the GSTIN checksum, CGST/SGST against IGST by place of supply, that the rate is a real slab, that the amounts match the rate, and that the total is taxable plus tax. All five mistakes produce a journal that parses and a return that is wrong.

Working papers, not returns. → docs/gst.md

→ docs/configuring.md · docs/adding-a-bank.md · docs/design.md · docs/gst.md · docs/privacy.md

Privacy

Everything of yours is in books/, and books/ is gitignored — one rule rather than a dozen, because a dozen is how something gets missed. Nothing leaves your machine. make demo invents a company so the project can be run and tested without anybody's real banking, and the test suite fails the build if real-looking data appears in the source.

Where it fits

Use beancount, hledger or paisa if you want a query language, portfolio analytics or personal-finance dashboards — they are excellent and mature.

ledger-book is the layer above a plain-text ledger, for the part before the charts: turning a pile of bank statements and invoices into books you can trust and hand to an accountant.

Status

Alpha. The books are checked hard — balance chains, closing assertions, the owner-loan mirror — but it is young. Keep your statements. Bug reports welcome; please don't attach real ones.

Licence

MIT © 2026 Vahini Technologies <info@vahinitech.com>

Releases

Sponsor this project

Packages

Used by

Contributors

Languages