- Python 50.2%
- Zig 38.2%
- TypeScript 5.6%
- JavaScript 3.9%
- Vim Script 1.3%
- Other 0.8%
| evolution/proposals | ||
| nvim/beanz | ||
| obsidian-plugin | ||
| python | ||
| src | ||
| tests | ||
| third_party | ||
| tools | ||
| vscode-extension | ||
| wasm | ||
| .gitignore | ||
| beanz-format.json | ||
| build.zig | ||
| build.zig.zon | ||
| CONSTITUTION.md | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
beanz
beanz is a zero-copy Beancount reimplementation in Zig.
The project is shaped around the Zig compiler's parser architecture:
- immutable AST over externally-owned source
- zero-copy token spans
- explicit parse/lower/check phases
- mergeable per-file units
- editor-first workspace state for LSP, MCP, Neovim, VS Code, Obsidian, and native host APIs
The first deployment target is replacing Beancount inside local repos without depending on upstream Python runtime.
Status
What is working now:
- parser, lowering, formatter, checker, LSP, MCP, native Neovim host
- WebAssembly host for Obsidian/mobile integration
- single
beanzbinary for CLI, LSP, MCP, and Neovim - native shared library at
zig-out/lib/libbeanz_native.* - initial Python compatibility package in
python/backed by the native library, not the CLI
What is not complete yet:
- full upstream Beancount Python API/data-model parity
- full upstream checker/loader/plugin semantics
- direct CPython binary extension module
- full upstream
bean-doctor/treeifyparity
Toolchain
This repo is pinned to Zig master through Mitchell Hashimoto's Zig overlay.
nix develop
Core verification:
zig build test
zig build native
zig build wasm
zig build install
python3 tools/report_parser_fixture_progress.py
Current parser fixture target remains:
272 / 272 static extracted parser fixtures passing
CLI
The main binary is beanz.
beanz parse ledger.beancount
beanz check ledger.beancount
beanz lint ledger.beancount
beanz query ledger.beancount 'select distinct account, count(*) as count group by account order by account desc'
beanz format --check ledger.beancount
beanz format -i ledger.beancount
beanz doctor parse --json ledger.beancount
beanz doctor snapshot --json ledger.beancount
beanz lsp
beanz mcp --file ledger.beancount
beanz nvim
Notes:
checkandlintare aliases.queryruns a native bean-query-style executor over the loaded workspace and is also exposed through LSP (beanz/query) and MCP (query_ledger).doctor list-optionsanddoctor print-optionsaliasdoctor options.formataccepts Beancount width flags for compatibility, but current formatting is driven bybeanz-format.json.
Native Python
The Python compatibility layer is in python/ and loads the native shared library in-process through ctypes.
Build the shared library first:
zig build native
Then run the Python tests:
PYTHONPATH=python/src python3 -m unittest discover -s python/tests
Optional upstream compatibility suite:
python3 tools/run_upstream_python_suite.py --sync-only
python3 tools/run_upstream_python_suite.py --no-sync --limit 10
python3 tools/run_upstream_python_suite.py --no-sync --summary-only
python3 tools/run_upstream_beanquery_suite.py --sync-only
python3 tools/run_upstream_beanquery_suite.py --no-sync --summary-only
python3 tools/report_compat_progress.py --include-upstream-python --include-upstream-beanquery
Current upstream compatibility baselines:
- Python API suite:
76 / 76modules passing - Beanquery execution suite:
303 / 303captured cases passing
Quick smoke:
PYTHONPATH=python/src python3 - <<'PY'
from beancount.loader import load_string
entries, errors, options = load_string("""
2013-05-18 open Assets:Cash USD
2013-05-18 open Expenses:Food USD
2013-05-19 * "Coffee"
Assets:Cash -4 USD
Expenses:Food 4 USD
""".strip() + "\n", filename="example.beancount")
print(len(entries), len(errors), sorted(options.keys()))
PY
The Python distribution is beanz, but it vends the upstream-facing module and CLI names:
beancount.*beanquery.*beanz.*bean-checkbean-querybean-formatbean-doctor
Current compatibility also includes the internal BeanQuery-facing modules needed by downstream code that imports the Python API directly:
beanquery.connect,Connection,Cursor,Columnbeanquery.query.run_querybeanquery.numberifybeanquery.query_compile,query_env,query_render,hashablebeanquery.sources.beancount,beanquery.sources.test
The wheel includes Provides-Dist/Obsoletes-Dist metadata for beancount and beanquery, but current pip installers do not treat that as a hard conflict or automatic replacement. In practice, this means:
- use
beanzas the installed Python distribution name - treat Nix/system packaging as the place to enforce replacement/conflict rules
- keep the module names and CLI names compatible inside the single distribution
For older local Python environments that still stumble on modern editable-install paths, python/setup.py develop is included as a compatibility bridge.
Editor Surfaces
LSP
beanz lsp
Native Neovim
The repo ships a native Neovim plugin under nvim/beanz/. The host is Zig, not Lua.
Smoke tests:
bash tools/run_nvim_plugin_smoke.sh
bash tools/run_nvim_completion_smoke.sh
bash tools/run_nvim_syntax_smoke.sh
VS Code
The repo includes a bundled VS Code extension in vscode-extension/ that launches beanz lsp and renders account state in a sidebar.
Obsidian
The mobile-safe Obsidian plugin lives in obsidian-plugin/ and uses the wasm host. The installable bundle is produced under built/obsidian-plugin/beanz/.
Reference Trees
The workspace is bootstrapped around three local references:
upstream/beancountupstream/zigupstream/zig-overlay
third_party/beancount-python/ is vendored as the spec/reference tree for fixtures, command/API parity work, and compatibility evaluation.
third_party/beanquery-python/ is vendored as the query-language spec/reference tree for optional compatibility evaluation.
Repository Layout
src/ast.zig: compact AST/token storagesrc/tokenizer.zig: zero-copy lexersrc/parse.zig: syntax buildersrc/lower.zig: typed loweringsrc/check.zig: balance/assertion checkingsrc/edit.zig: editor/workspace statesrc/cli.zig: batch CLI surfacesrc/native.zig: native C ABI for Pythonsrc/wasm.zig: wasm host APIpython/: native Python compatibility packagenvim/: native Neovim pluginvscode-extension/: VS Code extensionobsidian-plugin/: Obsidian plugintools/: fixture extraction, smoke tests, and reports
Governance
- Constitution: CONSTITUTION.md
- Proposals: evolution/proposals/README.md
Non-trivial architectural changes should land with a BZP-XXXX proposal.