Ledger CLI: Plain-Text Double-Entry Accounting for People Who Live in a Terminal
Double-entry accounting system with a command-line reporting interface
At a glance
- What is it?
- Ledger reads a text file of transactions and prints reports, with no database and no stored state. It is a fit for engineers who want their books in version control, and a poor fit for anyone who wants a GUI, sync, or a mobile app.
- Who is it for?
- Adopt Ledger if you are comfortable in a shell, want your journal in a text file under version control, and need scriptable reports rather than a GUI. Do not adopt it if you need bank sync, multi-device storage, or a mobile client; the README describes a command-line program that reads files and prints output, nothing more.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem Ledger solves, and who actually has it
Most accounting software stores your books in a proprietary database and gives you the reports the vendor decided to build. Ledger inverts that. The README states that Ledger "uses text files for input" and that "there is no other database or stored state." Your journal is a plain file on disk. Every report is generated on demand by reading that file, so the report set is limited by the query language and the command-line options, not by a product roadmap.
That design targets a specific person: someone who is already at a UNIX shell, who wants their financial records diffable and reviewable the way source code is, and who would rather write a query than click through a wizard. The README is blunt about the trade-off, noting the command-line interface "may put off some users, since there is no flashy UI." If a graphical interface or a phone app is a requirement, this is the wrong tool and no amount of configuration changes that.
The second audience is automation. Because output is "generally plain text," a journal can be the input to a script that generates HTML, a graph, or anything else. The README mentions generating a graph or HTML instead of text, though it does not document the exact flags for those outputs in the excerpt available.
How Ledger turns a journal file into a report
The data flow is short and worth stating plainly. You write a file containing account names and transactions. You invoke the binary with options that name the input file and the report you want. Ledger parses the file, applies the requested report, and writes text to standard output.
The README's own first example shows the shape of this:
./ledger -f test/input/sample.dat regHere `-f` names the input file and `reg` selects the register report. There is no server, no daemon, and no state carried between invocations. Each run re-reads the file. That means correctness depends entirely on the file being well formed, and it means a malformed journal produces an error at report time rather than at entry time.
Double-entry bookkeeping is the accounting model underneath: each transaction records balanced postings across accounts. Ledger does not invent that model, it implements it over text. The practical consequence is that the file is the source of truth, and any tool that can read text can read your books.
Installing Ledger from source, and a first register report
The README's quick path assumes dependencies are already present. It clones the repository and runs the `acprep` script, which the README describes as doing "a lot more of the footwork" than plain `cmake` and make:
git clone [email protected]:ledger/ledger.git
cd ledger && ./acprep updateThe README notes that `acprep update` updates to the latest, configures, and makes. If configure fails, it points you at `CMakeFiles/CMakeOutput.log` and `CMakeFiles/CMakeError.log`. You can then run `make check` to confirm the build and `make install` to install it.
Build dependencies for the current main branch include CMake 3.16.2 or greater, Boost 1.72, Gmp 6.1.2, Mpfr 4.0.2, and utfcpp 3.2.3. ICU, gettext, libedit, Python 3.10, and Gpgmepp are listed as optional. The README also provides a helper, `./acprep dependencies`, and platform-specific package lists for macOS, Ubuntu, Debian, and Fedora.
If you would rather not build anything, the README documents a Docker image:
docker run --rm -v "$PWD"/test/input:/data dcycle/ledger:1 -f /data/sample.dat regThat command mounts the repository's test input directory into the container and runs the same register report against `sample.dat`. After a source build, the README's first real command is the one shown above, `./ledger -f test/input/sample.dat reg`, and the output is a register listing of the postings in that sample file. Note that Python support, needed for features such as `--import`, is off by default and must be explicitly enabled.
Where Ledger stops being the right answer
The absence of stored state is both the feature and the limitation. Ledger does not hold a database, so it does not reconcile anything for you, does not fetch transactions from a bank, and does not maintain a running balance outside the file. If your journal is wrong, the reports are wrong, and Ledger has no opinion about which of the two entries in a transaction is the mistaken one.
Build cost is a real constraint. The dependency table lists CMake, Boost, Gmp, Mpfr, and utfcpp as required, and the README devotes separate sections to Homebrew, MacPorts, Conda, Ubuntu, Debian, and Fedora package lists. That is a heavier install than a single binary download, and the README itself notes that some features require building with Python support.
The project's own release history shows a gap worth knowing about: v3.3.2 is dated 2023-03-30, and the next releases, v3.4.0 and v3.4.1, are dated 2025-10-22 and 2025-10-26. Anyone pinning to the 3.3.x line should be aware that the 3.4.x series arrived more than two years later. The repository is not archived and the last push was on 2026-09-22.
Finally, the README does not document rollback or undo. If you edit a journal badly, recovery is your problem, which is an argument for keeping the file in version control from the start.
Ledger against a spreadsheet or a hosted accounting service
The obvious alternative for a small set of books is a spreadsheet. A spreadsheet gives you a grid, formulas, and a visual total, and it requires no compiler. The difference in approach is that a spreadsheet has no built-in notion of double entry: nothing stops an unbalanced row, and the balance is whatever your formulas happen to compute. Ledger enforces the accounting model at parse time and generates reports from the file, but it gives you no grid and no cells to click.
The other alternative is a hosted accounting service with a web interface. Those handle bank feeds, collaboration, and access from a browser or phone. Ledger does none of that. What it offers instead is that the data is a text file you own, that reports are reproducible commands, and that the whole thing runs offline. The README's claim that there are "few alternatives" for "unparalleled reporting access" is the project's own framing, and it is accurate in the narrow sense that the report surface is a query language rather than a fixed set of screens. It is not a claim about ease of use, and the README does not make one.
Licence and the cost of staying current
The repository's licence metadata is reported as NOASSERTION, while the README carries a BSD badge linking to the BSD-3-Clause text. Those two signals do not agree, and the discrepancy is worth resolving against `LICENSE.md` in the repository before you rely on either. This is a description of what the metadata says, not legal advice; if the licence terms matter to your organisation, read the file itself.
Upgrade cost is mostly build cost. There is no package manager step in the README for the main branch, so moving to a new release means repeating the `acprep update` cycle and re-checking dependencies, which the README lists with minimum versions. The optional components are where this bites: Python support must be enabled deliberately, and Gpgmepp, ICU, gettext, and libedit are each optional, so a build that works on one machine may lack a feature another machine has. The release cadence is not regular. Between v3.3.2 in March 2023 and v3.4.0 in October 2025 there were no releases listed, so planning an upgrade around a predictable schedule is not realistic.
Editorial conclusion
Adopt Ledger if you are comfortable in a shell, want your journal in a text file under version control, and need scriptable reports rather than a GUI. Do not adopt it if you need bank sync, multi-device storage, or a mobile client; the README describes a command-line program that reads files and prints output, nothing more. Before committing real books, verify three things: that your platform's dependency set builds the current main branch, that the optional Python bindings you need are enabled, and that the account structure in your journal matches how you actually want reports grouped. The README does not document a rollback path for a bad journal edit, so keep the file in git from day one.
Frequently asked questions
Where do I download Ledger?
The README does not point to a binary download. It documents building from source by cloning the repository and running ./acprep update, and it also documents a Docker image, dcycle/ledger:1, for users who have Docker installed.
Does Ledger store my transactions in a database?
No. The README states that Ledger uses text files for input and that there is no other database or stored state. Each invocation reads the file and generates the requested report.
What is the first Ledger command to try after building it?
The README suggests ./ledger -f test/input/sample.dat reg, which runs the register report against the sample journal shipped in the repository's test input directory.
Do I need Python to build Ledger?
Python 3.10 is listed as an optional dependency, and the README states that Python support is off by default and must be explicitly enabled. Some features, such as --import, require building with Python support.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ledger-ledger)