https://github.com/robinvdvleuten/beancount
Fast, lightweight Beancount parser, formatter and editor written in Go
https://github.com/robinvdvleuten/beancount
accounting beancount cli finance go ledger plaintext plaintext-accounting solidjs
Last synced: 5 months ago
JSON representation
Fast, lightweight Beancount parser, formatter and editor written in Go
- Host: GitHub
- URL: https://github.com/robinvdvleuten/beancount
- Owner: robinvdvleuten
- License: gpl-2.0
- Created: 2022-10-06T17:36:49.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2026-01-12T14:40:09.000Z (5 months ago)
- Last Synced: 2026-01-12T21:13:15.032Z (5 months ago)
- Topics: accounting, beancount, cli, finance, go, ledger, plaintext, plaintext-accounting, solidjs
- Language: Go
- Homepage:
- Size: 1.19 MB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: COPYING
- Agents: AGENTS.md
Awesome Lists containing this project
README
# beancount

A fast, lightweight [Beancount](https://beancount.github.io/) parser and formatter written in Go.
[](https://github.com/robinvdvleuten/beancount/releases)
[](https://github.com/robinvdvleuten/beancount/actions?query=workflow%3Abuild)
[](https://github.com/robinvdvleuten/beancount/blob/main/COPYING)
[](https://pkg.go.dev/github.com/robinvdvleuten/beancount)
[](https://goreportcard.com/report/robinvdvleuten/beancount)
## What is it?
[Beancount](https://beancount.github.io/) is a double-entry bookkeeping system that uses plain text files to track personal or business finances. It allows you to maintain your accounting ledger as readable text files, making it easy to version control, search, and programmatically manipulate your financial data. The Beancount file format uses a simple, human-readable syntax to record transactions, accounts, and other financial directives.
This project is a Go implementation of a Beancount file parser, formatter, and validator. While the official Beancount implementation is written in Python and includes a full accounting engine with balance calculations, reports, queries, and a web interface, this Go version focuses on parsing, formatting, and ledger validation. It's designed to be fast and lightweight, making it ideal for tooling, text editors, build pipelines, or any situation where you need to validate Beancount files without the overhead of the full accounting system.
## Features
This implementation currently supports:
- **Parsing**: Full parsing of Beancount file syntax
- **Formatting**: Auto-align currencies, numbers, and accounts
- **Validation**: Balance checks, account lifecycle, assertions
- **Inventory**: Lot-based tracking with cost basis (FIFO/LIFO)
- **Includes**: Recursive loading of modular Beancount files
- **CLI Interface**: Simple command-line tools for common operations
**Note**: This implementation includes ledger validation with transaction balancing, account management, and inventory tracking. It does not include reporting, queries, or a web interface like the official Python implementation.
## Compatibility
This Go implementation is stricter than the official Python Beancount parser in some areas:
- Arithmetic expressions in amounts must be enclosed in parentheses: `(155.74 + 304.58) USD` instead of `155.74 + 304.58 USD`
- Amount values must include both a number and currency: `100.00 USD` (not just `100.00`)
## Installation
### Packages & Binaries
If you use Brew, you can simply install the package:
```sh
brew install robinvdvleuten/tap/beancount
```
Or download a binary from the [releases](https://github.com/robinvdvleuten/beancount/releases)
page. Linux (including ARM) binaries are available, as well as Debian, RPM AND APK
packages.
### Build From Source
Alternatively you can also build `beancount` from source. Make sure you have a
working Go environment (Go 1.24 or higher is required). See the
[install instructions](https://golang.org/doc/install.html).
To install beancount, simply run:
```sh
go install github.com/robinvdvleuten/beancount
```
## Usage
### Check a Beancount file
Validate a Beancount file with full ledger checks:
```sh
beancount check example.beancount
```
Or read from stdin (omit filename or use `-`):
```sh
echo "2024-01-01 open Assets:Checking USD" | beancount check
```
This command validates:
- Transaction balance across all currencies
- Account open/close dates are respected
- Balance assertions match actual balances
- All referenced accounts exist
Example error output:
```
example.beancount:15: Transaction does not balance: (-500.00 USD)
2020-01-15 * "Grocery shopping"
Assets:Checking 1000.00 USD
Expenses:Food 500.00 USD
1 validation error(s) found
```
### Format a Beancount file
Format a Beancount file with automatic alignment:
```sh
beancount format example.beancount
# Specify currency column position
beancount format --currency-column 60 example.beancount
# Customize account name and number widths
beancount format --prefix-width 50 --num-width 12 example.beancount
```
Or read from stdin (omit filename or use `-`):
```sh
echo "2024-01-01 open Assets:Checking USD" | beancount format
```
### Telemetry
Use the global `--telemetry` flag to see detailed timing breakdowns for any command:
```sh
beancount --telemetry check example.beancount
beancount --telemetry format example.beancount
```
This displays a hierarchical breakdown of where time is spent during execution:
```
✓ Check passed
check example.beancount: 125ms
├─ loader.load example.beancount: 85ms
│ └─ loader.parse: 85ms
│ ├─ parser.lexing: 75ms
│ ├─ parser.parsing: 8ms
│ ├─ parser.push_pop: ~1ms
│ └─ parser.sorting: 245µs
├─ loader.load accounts.beancount: 35ms
│ └─ loader.parse: 35ms
│ ├─ parser.lexing: 30ms
│ ├─ parser.parsing: ~4ms
│ ├─ parser.push_pop: 823µs
│ └─ parser.sorting: 156µs
├─ ast.merging: ~2ms
└─ ledger.processing (1523 directives): ~3ms
```
The telemetry output is written to stderr, making it easy to separate from command results.
## Programmatic Usage
This library can be used programmatically in your Go applications to parse, manipulate, and generate Beancount files.
### Parsing Beancount Files
Load and parse a Beancount file:
```go
import (
"context"
"github.com/robinvdvleuten/beancount/loader"
)
// Load a single file
ldr := loader.New()
ast, err := ldr.Load(context.Background(), "example.beancount")
if err != nil {
log.Fatal(err)
}
// Load with recursive include resolution
ldr = loader.New(loader.WithFollowIncludes())
ast, err = ldr.Load(context.Background(), "main.beancount")
```
### Building Transactions Programmatically
Create Beancount transactions using the builder API:
```go
import "github.com/robinvdvleuten/beancount/ast"
// Create a transaction with the functional options pattern
date, _ := ast.NewDate("2024-01-15")
checking, _ := ast.NewAccount("Assets:Checking")
groceries, _ := ast.NewAccount("Expenses:Groceries")
txn := ast.NewTransaction(date, "Grocery shopping",
ast.WithFlag("*"),
ast.WithPayee("Whole Foods"),
ast.WithTags("food", "weekly"),
ast.WithPostings(
ast.NewPosting(groceries, ast.WithAmount("125.43", "USD")),
ast.NewPosting(checking), // Balancing posting
),
)
```
### Formatting Output
Format transactions back to Beancount syntax:
```go
import (
"context"
"os"
"github.com/robinvdvleuten/beancount/formatter"
)
// Create a formatter
fmtr := formatter.New()
// Format a single transaction
fmtr.FormatTransaction(txn, os.Stdout)
// Format an entire AST
fmtr.Format(context.Background(), ast, sourceContent, os.Stdout)
```
### Complete Example
See the [CSV Importer example](_examples/csv_importer/) for a complete working example that demonstrates:
- Reading CSV files with Go's `encoding/csv`
- Building transactions programmatically with the builder API
- Automatic expense categorization
- Error handling and validation
- Formatting output
Run the example:
```sh
cd _examples/csv_importer
go run main.go transactions.csv
```
For more details on the builder API, see the [package documentation](https://pkg.go.dev/github.com/robinvdvleuten/beancount/ast).
## Contributing
Everyone is encouraged to help improve this project. Here are a few ways you can help:
- [Report bugs](https://github.com/robinvdvleuten/beancount/issues)
- Fix bugs and [submit pull requests](https://github.com/robinvdvleuten/beancount/pulls)
- Write, clarify, or fix documentation
- Suggest or add new features
To get started with development:
```
git clone https://github.com/robinvdvleuten/beancount.git
cd beancount
go test ./...
```
Before submitting a pull request, please make sure to run
`go fmt` on any Go source files you touched so the code stays consistent.
Feel free to open an issue to get feedback on your idea before spending too much time on it.
## License
Copyright (c) Robin van der Vleuten
Licensed under the GNU General Public License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.