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:8765Then, 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/ first1. 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.
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.
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.
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.
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 accountantEach 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.
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.
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
...
make web # opens http://127.0.0.1:8765
ledgerbook web --port 9000It 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.mapgets written. - Statements — profit and loss, balance sheet, trial balance, by date range.
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.
ledgerbook init
$EDITOR books/config.toml # your business, your banks — about 20 lines
make inboxFive 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).
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/reportsEvery 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
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.
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.
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.
MIT © 2026 Vahini Technologies <info@vahinitech.com>