This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Beanfmt is a fast beancount file formatter with CJK double-width character support. It provides a Rust library, CLI binary, Python bindings (via PyO3/maturin, managed by uv), and WASM bindings (via wasm-bindgen). The VSCode extension uses bun for Node package management.
All commands are available via just (see justfile for details):
just # List all available recipes
just build # Build library
just build-cli # Build CLI binary
just build-python # Build Python extension (uv + maturin)
just build-wasm # Build WASM module
just build-vscode # Build VSCode extension (WASM + TypeScript)
just package-vscode # Package .vsix
just test # Run all tests
just test-file name # Run a specific test file
just clippy # Run clippy lints
just fmt # Format code
just fmt-check # Check formatting
just check # Run all checks (fmt, clippy, test)
just clean # Clean build artifactsThe formatting pipeline in lib.rs::format() processes input line-by-line through three stages:
- Sort (
sort.rs) — optionally reorder entries by date - Parse (
line.rs) — regex-based parser classifies each line into aLineenum variant (TransactionHeader, Posting, Balance, Open, Close, Price, MetaItem, Comment, etc.) - Normalize + Align — per-variant formatting:
normalize.rs— standardizes indentation, thousands separators, brace spacing, comment formattingalign.rs— column-aligns currencies and costs usingunicode-widthfor CJK-aware display width calculation
Key design points:
Optionsstruct (options.rs) is the single configuration object shared across all targetsrecursive.rs(gated behindcli/pythonfeatures) — BFS traversal ofincludedirectives with glob expansion- Features
pythonandwasmare mutually exclusive (enforced by compile_error!) - All regex patterns use
LazyLockfor one-time compilation - The
line.rsparser uses zero-copy&strslices via theLine<'a>enum