Beanfmt
A fast beancount file formatter with CJK double-width character support and smart date-based sorting.
Features
- Column-aligned currencies and costs with CJK-aware display width
- Thousands separator normalization (add, remove, or keep)
- Brace spacing control for cost annotations
- Smart date-based sorting (asc/desc) with
timemetadata intra-day ordering, timeless entry positioning, and directive-type sort barriers - Recursive formatting of
included files (with glob support) - Multi-platform: CLI, Python library, WASM module, and VSCode extension
Installation
CLI
Python
VSCode Extension
Search for beanfmt in the VSCode Marketplace, or install from the command line:
From Source
Note:
pythonandwasmfeatures are mutually exclusive.
Usage
CLI
# Format from stdin
|
# Format a file (print to stdout)
# Format in-place
# Recursively format all included files in-place
# Custom alignment columns
# Add thousands separators and sort by date
Options
| Flag | Default | Description |
|---|---|---|
--indent <N> |
4 |
Number of spaces for indentation |
--currency-column <N> |
70 |
Target column for currency alignment |
--cost-column <N> |
75 |
Target column for cost/price alignment |
--thousands <MODE> |
keep |
Thousands separator: add, remove, or keep |
--spaces-in-braces / --no-spaces-in-braces |
off | Add spaces inside cost braces { ... } |
--fixed-cjk-width / --no-fixed-cjk-width |
on | CJK double-width alignment |
--sort [MODE] / --no-sort |
off |
Sort entries by date: asc (default if bare --sort), desc, off |
--sort-timeless <POS> |
begin |
Where to place timeless entries within a day: begin, end |
--sort-exclude <TYPES> |
(none) | Comma-separated directive types to exclude from sorting; excluded directives act as sort barriers. Values: transaction, balance, open, close, price, pad, note, document, event, custom, query, commodity |
--recursive |
off | Follow and format included files |
-w, --write |
off | Write output back to file (in-place) |
--no-config |
off | Skip loading configuration files |
Configuration File
Beanfmt supports TOML configuration files with a three-layer merge priority (low → high):
- Built-in defaults
- Global config:
$XDG_CONFIG_HOME/beanfmt/config.toml(defaults to~/.config/beanfmt/config.toml) - Project config:
.beanfmt.tomlorbeanfmt.toml(searched upward from the current directory) - CLI arguments (highest priority)
Example .beanfmt.toml:
= 2
= 60
= 65
= "add"
= true
= true
= "asc" # "asc", "desc", "off", or true/false
= "keep" # "begin", "end", or "keep"
= ["open", "close"] # excluded types act as sort barriers
All fields are optional. Unspecified fields inherit from the next lower priority layer. Use --no-config to skip all configuration file loading. See beanfmt.toml for a full reference with comments.
Config file support varies by target:
| Target | Global config | Project config | Notes |
|---|---|---|---|
| CLI | Auto | Auto | --no-config to disable |
| Python | No | Opt-in via config=True |
load_project_config() for manual loading |
| VSCode | No (user settings serve this role) | Auto (within workspace) | Explicit settings override config file |
Python
# Format a string
=
# Format a file
=
# Format with project config (.beanfmt.toml auto-discovery)
=
# Format with a specific config file
=
# Config + kwargs override (kwargs win over config file values)
=
# Load and inspect project config
=
=
# Reusable options
=
=
# Recursive formatting — returns list of (path, content) tuples
=
The config parameter on format_file and format_recursive accepts None (default, no config loading), True (auto-discover .beanfmt.toml from the file's directory upward), False (same as None), or a string path to a specific config file. Individual kwargs always override config file values. The config and options parameters are mutually exclusive.
WASM
import from "beanfmt";
// Format with default options
const output = ;
// Format with full options
const output = ;
VSCode
Install the extension, then configure in settings.json:
"[beancount]": {
"editor.defaultFormatter": "beanfmt.beanfmt-beancount-formatter",
"editor.formatOnSave": true
}
The extension automatically reads .beanfmt.toml or beanfmt.toml from the workspace (searching from the file's directory up to the workspace root). Explicit VSCode settings override config file values; unset settings fall back to the config file, then to built-in defaults.
Available settings:
| Setting | Default | Description |
|---|---|---|
beanfmt.indent |
4 |
Number of spaces for indentation |
beanfmt.currencyColumn |
70 |
Currency alignment column |
beanfmt.costColumn |
75 |
Cost/price alignment column |
beanfmt.thousandsSeparator |
"keep" |
"add", "remove", or "keep" |
beanfmt.spacesInBraces |
false |
Spaces inside cost braces |
beanfmt.fixedCJKWidth |
true |
CJK double-width alignment |
beanfmt.sort |
"off" |
Sort entries by date: "asc", "desc", "off" |
beanfmt.sortTimeless |
"keep" |
Timeless entry position within a day: "begin", "end", "keep" |
beanfmt.sortExclude |
[] |
Directive types to exclude from sorting (act as sort barriers) |
License
MIT