No description
  • Python 50.2%
  • Zig 38.2%
  • TypeScript 5.6%
  • JavaScript 3.9%
  • Vim Script 1.3%
  • Other 0.8%
Find a file
2026-04-05 01:37:27 -07:00
evolution/proposals Add native Python bridge and expand CLI 2026-04-04 19:38:33 -07:00
nvim/beanz Reach upstream Python parity and add editor surfaces 2026-04-04 21:22:47 -07:00
obsidian-plugin Reach upstream Python parity and add editor surfaces 2026-04-04 21:22:47 -07:00
python Unify Python packaging under beanz 2026-04-05 01:37:27 -07:00
src Reach full upstream beanquery execution parity 2026-04-05 00:58:45 -07:00
tests Reach full upstream beanquery execution parity 2026-04-05 00:58:45 -07:00
third_party Add upstream beanquery compatibility harness 2026-04-04 23:47:19 -07:00
tools Reach full upstream beanquery execution parity 2026-04-05 00:58:45 -07:00
vscode-extension Reach upstream Python parity and add editor surfaces 2026-04-04 21:22:47 -07:00
wasm Reach upstream Python parity and add editor surfaces 2026-04-04 21:22:47 -07:00
.gitignore Reach upstream Python parity and add editor surfaces 2026-04-04 21:22:47 -07:00
beanz-format.json Initial beanz import 2026-04-03 21:23:47 -07:00
build.zig Add native Python bridge and expand CLI 2026-04-04 19:38:33 -07:00
build.zig.zon Initial beanz import 2026-04-03 21:23:47 -07:00
CONSTITUTION.md Add native Python bridge and expand CLI 2026-04-04 19:38:33 -07:00
flake.lock Initial beanz import 2026-04-03 21:23:47 -07:00
flake.nix Initial beanz import 2026-04-03 21:23:47 -07:00
README.md Unify Python packaging under beanz 2026-04-05 01:37:27 -07:00

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 beanz binary 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/treeify parity

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:

  • check and lint are aliases.
  • query runs a native bean-query-style executor over the loaded workspace and is also exposed through LSP (beanz/query) and MCP (query_ledger).
  • doctor list-options and doctor print-options alias doctor options.
  • format accepts Beancount width flags for compatibility, but current formatting is driven by beanz-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 / 76 modules passing
  • Beanquery execution suite: 303 / 303 captured 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-check
  • bean-query
  • bean-format
  • bean-doctor

Current compatibility also includes the internal BeanQuery-facing modules needed by downstream code that imports the Python API directly:

  • beanquery.connect, Connection, Cursor, Column
  • beanquery.query.run_query
  • beanquery.numberify
  • beanquery.query_compile, query_env, query_render, hashable
  • beanquery.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 beanz as 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/beancount
  • upstream/zig
  • upstream/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 storage
  • src/tokenizer.zig: zero-copy lexer
  • src/parse.zig: syntax builder
  • src/lower.zig: typed lowering
  • src/check.zig: balance/assertion checking
  • src/edit.zig: editor/workspace state
  • src/cli.zig: batch CLI surface
  • src/native.zig: native C ABI for Python
  • src/wasm.zig: wasm host API
  • python/: native Python compatibility package
  • nvim/: native Neovim plugin
  • vscode-extension/: VS Code extension
  • obsidian-plugin/: Obsidian plugin
  • tools/: fixture extraction, smoke tests, and reports

Governance

Non-trivial architectural changes should land with a BZP-XXXX proposal.