# beancount: plain-text double-entry accounting with a real parser underneath

> A command-line accounting system that reads transaction records from a text file, checks them against double-entry rules, and generates balance sheets, income statements and an HTML web interface.

**beancount/beancount** — Beancount: Double-Entry Accounting from Text Files.

- Repository: https://github.com/beancount/beancount
- Website: http://beancount.github.io/
- Stars: 6,070 · Forks: 473
- Language: Python
- License: GPL-2.0
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/beancount-beancount

## Three versions, and which one to install

The README names three versions and is unusually direct about each one, which saves anyone who finds an old blog post a lot of confusion.

Version 3, on the `v3` branch, has been the stable release since June 2024 and the README says to use it. It is a trimmed version of v2, with most of the tools that branch carried moved out into independent projects on GitHub. Version 2, on the `v2` branch, was the previous stable release, in maintenance mode from 2020 to 2024, and the README calls it frozen and obsolete. It was the complete rewrite of the original, and it introduced the grammar and constraints that still define the format. Version 1, on the `v1` branch, is where development stopped in 2013, and the README says not to use it.

The default branch is `master`, which is worth noticing: it is not `v3`. Anyone cloning without thinking gets the development line, and the README is where the version table lives, not the branch list.

What the software does is stated twice in slightly different words. The README calls it a double-entry bookkeeping computer language that lets you define financial transaction records in a text file, read them in memory, and generate a variety of reports, with a web interface. The project metadata in `pyproject.toml` adds two details the README leaves out: an SQL-like query language for filtering and aggregating the data, and scaffolding for automating the conversion of external data into your own input file.

## The grammar is compiled, not interpreted

The build system tells you more about the implementation than any amount of prose would. `pyproject.toml` names `mesonpy` as the build backend and lists what the build itself requires:

```toml
[build-system]
build-backend = "mesonpy"
requires = [
    'flex-bin ; sys_platform == "linux" or sys_platform == "darwin"',
    'bison-bin ; sys_platform == "linux" or sys_platform == "darwin"',
    'winflexbison-bin>=2.5.25.1 ; sys_platform == "win32"',
    "meson-python >= 0.14.0",
    "meson >= 1.2.1",
]
```

Flex and Bison are the classic Unix lexer and parser generators, and they are conditioned per platform: `flex-bin` and `bison-bin` on Linux and macOS, `winflexbison-bin` on Windows. So the package is not pure Python. There is a compiled parser extension, and the Makefile confirms it by copying a built shared object into place:

```bash
$(NINJA) -C $(MESON_BUILD_DIR)/
cp $(MESON_BUILD_DIR)/_parser*.so beancount/parser/
```

The `Makefile` builds into a directory keyed by Python version, `build/$(PYTAG)`, with the tag computed as `cp` plus the major and minor version, which is how it keeps several interpreters from colliding. It also has a `ctest` target that runs the suite through Meson, and a `grind` target that runs `valgrind --leak-check=full` against `bean-sandbox`, which is the kind of memory checking you only bother with in a parser.

Practical consequence: installing beancount needs a C toolchain, not just a Python environment. The runtime dependency list is short, `click >=7.0`, `python-dateutil >=2.6.0` and `regex >=2022.9.13`, and Python 3.9 or newer is required, but the build requirements are the part that trips up a locked-down environment.

## Console scripts that name the workflow

The `[project.scripts]` table in `pyproject.toml` is a compact map of what the tool expects you to do. It starts with `bean-check` pointing at `beancount.scripts.check:main`, then `bean-doctor` at `beancount.scripts.doctor:main`, then `bean-example` at `beancount.scripts.example:main` and `bean-format` at the formatter module. The Makefile references further commands such as `bean-dump-lexer`, for dumping lexer output in a form comparable across languages, and `bean-sandbox`, which is the interpreter used for the memory check.

The naming makes the intended loop obvious. `bean-example` scaffolds a working file, `bean-format` rewrites yours into canonical form, `bean-check` verifies it, and `bean-query` is the interface to the SQL-like query language described in the project metadata. `bean-doctor` is the odd one out and worth explaining: it exists to diagnose a ledger that will not load, which in practice means the balance assertions failed or an account is referenced that was never opened.

The example directory backs this up with material to read rather than only run. It contains `examples/simple/`, `examples/tutorial/`, `examples/ingest/` and `examples/vesting/`, plus `examples/example.beancount` and a `README` inside `examples/` itself. The `ingest` and `vesting` directories are the interesting ones for a new user, since equity vesting and bank statement import are exactly the two cases where people write their own import scripts badly.

The README also points at a documentation site, beancount.github.io, and an index of source documents, and notes that documentation authoring happens on Google Docs with access granted on request. That detail is a small signal about the project's centre of gravity: it is a tool with a long history and a single principal author, not a foundation project.

## What v3 removed, and where those pieces went

The single most consequential line in the README is that v3 is trimmed down from v2 and most of the tools the v2 branch included have been moved to their own independent projects on GitHub. Anyone upgrading from a v2-era setup hits this immediately, because the commands they used are no longer in the package.

The reason is visible in the repository layout. The current tree carries `beancount/` for the library, `bin/` for entry points, `docs/`, `examples/`, `experiments/`, `etc/`, `tools/` and the site files `index.html` and `style.css`, plus `meson.build` and `meson.options`. There is no single bundled tools directory that used to hold every report generator and web component. The `experiments/` directory is a good clue about the direction of travel: work in progress lives apart from the stable package.

There are also three legacy files at the root that describe the state of play: `CHANGES` for the change log, `TODO` for what is planned, and `COPYING` for the licence. The GitHub repository publishes no formal releases, so `CHANGES` is the version history rather than a tag list, which means reading it is the way to find out what changed in a given version.

For a team that relied on a specific v2 tool, the practical move is to work out which project now owns it before migrating the ledger, because the v3 change alone will not tell you. The README does not name the successor projects, so that mapping has to be done by searching their names.

## Licence, authorship and the shape of the project

Copyright runs from 2007 to 2025 and belongs to Martin Blais, who is also the listed author in `pyproject.toml` and the maintainer of the documentation. The licence is stated twice and consistently: the README says the code is distributed under GNU GPLv2 only, and the project metadata says `GPL-2.0-only`. `COPYING` holds the text.

GPL-2.0 on a tool you run as a command is not the constraint people assume it is. It matters if you redistribute beancount inside another product or offer it as a hosted accounting service. It does not stop a company from using it to check its own books, which is the normal case.

The donation section is worth reading for a different reason: it explains why there is no feature roadmap with sponsors on it. The author's stated position is that he never asks for money, that his intent is to build something useful to himself first and then to others in the simplest and most durable manner, and that this is a labour of love where a desire for perfection and minimalism runs without much constraint. That is a candid description of a project whose priorities are set by one person.

The last push was on 2026-08-23, so the code is being worked on now. The mailing list is on Google Groups, and the README also points at the Ledger mailing list for more general command-line accounting discussion, which is a useful cross-reference if you are deciding between the two tools rather than using both.

## Where beancount sits against Ledger

Ledger is the other plain-text accounting tool, and the README mentions its mailing list without ever competing with it head on, so the comparison is worth making explicitly.

The difference starts with implementation. Ledger's original is written in C and has a fast parsing model, while beancount is a Python system with a compiled flex and Bison parser and a much larger standard library of reports and a query language. Beancount treats the file as data you can query with SQL-like expressions, which suits a user who wants to ask the ledger questions rather than only print statements.

The other difference is history and compatibility. The original beancount version 1 was intended to be similar to and partially compatible with Ledger, and the README says so. Version 2 was a complete rewrite that introduced a new grammar and a set of constraints, and version 3 narrowed the package further. So compatibility with Ledger is a property of the abandoned first version, not of the one you should install.

Where beancount is the wrong tool is more specific than the usual answer. If you need a double-entry file that a Ledger user can open unchanged, beancount v3 will not give you that. If you want a system that reads a spreadsheet or a CSV without a parser, it will not help either, since the import scaffolding is something you build. And if you want multi-currency handling with the bookkeeping conventions of a particular jurisdiction already worked out, that is configuration work in both tools and neither removes it.

## Conclusion

beancount suits anyone who already thinks in debits and credits and wants a ledger that diffs in git, which rules out most people buying their first accounting package. Install v3 rather than v2, since v2 has been frozen since 2024 and the tooling that used to ship inside it now lives in separate projects you will have to find. Expect a real build on first install: `flex-bin` and `bison-bin` appear as build requirements in `pyproject.toml`, because the grammar is compiled rather than parsed at runtime. Start with the tutorial files under `examples/tutorial/` and run `bean-check` on the result before you import a year of bank data.

## FAQ

### What is beancount?

A command-line double-entry accounting system that takes financial transaction records in a text file, loads them into memory, and generates reports such as balance sheets and income statements from them. The project metadata also describes an SQL-like query language for filtering and aggregating that data, a web interface that renders reports to HTML, and scaffolding for automating conversion of external data into your own file. It is written in Python with a compiled parser and is licensed GPL-2.0.

### How do I use beancount?

Start from the examples in the repository rather than a blank file: `examples/simple/`, `examples/tutorial/`, `examples/ingest/` and `examples/vesting/` are all present, and `bean-example` generates a starting point. Then run `bean-check` on the file to verify it balances, `bean-format` to canonicalise it, and `bean-query` when you want to ask the data questions. Installation details are on the documentation site rather than in the README.

### Which version of beancount should I install?

Version 3, on the `v3` branch, which has been stable since June 2024. Version 2 was frozen and made obsolete after maintenance mode from 2020 to 2024, and version 1 stopped development in 2013. Be aware that the default branch is `master`, not `v3`, and that v3 is a trimmed package whose former tools now live in separate projects.

## Sources

- [beancount/beancount on GitHub](https://github.com/beancount/beancount)
- [Issues](https://github.com/beancount/beancount/issues)
- [License: GPL-2.0](https://github.com/beancount/beancount/blob/master/LICENSE)
- [Project website](http://beancount.github.io/)
- [README](https://github.com/beancount/beancount/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/beancount-beancount
