A Language Server Protocol (LSP) implementation for Beancount, the double-entry bookkeeping language. This provides rich editing features like completions, diagnostics, formatting, and more for Beancount files in your favorite editor.
| LSP Feature | Description | Status |
|---|---|---|
| Completions | Smart autocompletion for accounts, payees, dates, narration, tags, links, and transaction types | ✅ |
| Diagnostics | Real-time error checking and validation via beancount Python integration | ✅ |
| Formatting | Document formatting compatible with bean-format, with support for prefix-width, num-width, and currency-column options |
✅ |
| Rename | Rename symbols across files | ✅ |
| References | Find all references to accounts, payees, etc. | ✅ |
- Accounts: Autocomplete account names with hierarchy support (
Assets:Checking) - Payees: Previously used payee names
- Dates: Smart date completion (today, this month, previous month, next month)
- Narration: Previously used transaction descriptions
- Tags: Complete hashtags (
#vacation) - Links: Complete links (
^receipt-123) - Transaction Types:
txn,balance,open,close, etc.
| LSP Feature | Description | Priority |
|---|---|---|
| Hover | Show account balances, transaction details, account metadata | High |
| Go to Definition | Jump to account/payee/commodity definitions | High |
| Document Symbols | Outline view showing accounts, transactions, and structure | High |
| Folding Ranges | Fold transactions, account hierarchies, and multi-line entries | Medium |
| Semantic Highlighting | Advanced syntax highlighting with semantic information | Medium |
| Code Actions | Quick fixes, refactoring, auto-balance transactions | Medium |
| Inlay Hints | Show computed balances, exchange rates, running totals | Low |
| Signature Help | Help with transaction syntax and directive parameters | Low |
| Workspace Symbols | Find accounts, payees, commodities across all files | Low |
cargo install beancount-language-serverDownload the latest release for your platform from the releases page.
Supported Platforms:
- Linux (x86_64, aarch64, loongarch64)
- macOS (x86_64, aarch64)
- Windows (x86_64)
brew install beancount-language-server# Using nix-env
nix-env -iA nixpkgs.beancount-language-server
# Using nix shell
nix shell nixpkgs#beancount-language-server
# Development environment
nix developgit clone https://github.com/polarmutex/beancount-language-server.git
cd beancount-language-server
cargo build --releaseThe binary will be available at target/release/beancount-language-server.
- Beancount: Install the Python beancount package for diagnostics
pip install beancount
- Bean-format: The language server includes built-in formatting that's fully compatible with bean-format. Installing bean-format is optional for comparison or standalone use
pip install bean-format
The language server accepts configuration via LSP initialization options:
{
"journal_file": "/path/to/main.beancount",
"formatting": {
"prefix_width": 30,
"num_width": 10,
"currency_column": 60,
"account_amount_spacing": 2,
"number_currency_spacing": 1
}
}| Option | Type | Description | Default |
|---|---|---|---|
journal_file |
string | Path to the main beancount journal file | None |
| Option | Type | Description | Default | Bean-format Equivalent |
|---|---|---|---|---|
prefix_width |
number | Fixed width for account names (overrides auto-detection) | Auto-calculated | --prefix-width (-w) |
num_width |
number | Fixed width for number alignment (overrides auto-detection) | Auto-calculated | --num-width (-W) |
currency_column |
number | Align currencies at this specific column | None (right-align) | --currency-column (-c) |
account_amount_spacing |
number | Minimum spaces between account names and amounts | 2 | N/A |
number_currency_spacing |
number | Number of spaces between number and currency | 1 | N/A |
Default Mode (no currency_column specified):
- Accounts are left-aligned
- Numbers are right-aligned with consistent end positions
- Behaves like
bean-formatwith no special options
Currency Column Mode (currency_column specified):
- Currencies are aligned at the specified column
- Numbers are positioned to place currencies at the target column
- Equivalent to
bean-format --currency-column N
Basic formatting with auto-detection:
{
"formatting": {}
}Fixed prefix width (like bean-format -w 25):
{
"formatting": {
"prefix_width": 25
}
}Currency column alignment (like bean-format -c 60):
{
"formatting": {
"currency_column": 60
}
}Number-currency spacing control:
{
"formatting": {
"number_currency_spacing": 2
}
}This controls the whitespace between numbers and currency codes:
0: No space (100.00USD)1: Single space (100.00 USD) - default2: Two spaces (100.00 USD)
Combined options:
{
"formatting": {
"prefix_width": 30,
"currency_column": 65,
"account_amount_spacing": 3,
"number_currency_spacing": 1
}
}- Install the Beancount extension from the marketplace
- Configure in
settings.json:{ "beancount.journal_file": "/path/to/main.beancount", "beancount.formatting": { "prefix_width": 30, "currency_column": 60, "number_currency_spacing": 1 } }
Using nvim-lspconfig:
local lspconfig = require('lspconfig')
lspconfig.beancount.setup({
init_options = {
journal_file = "/path/to/main.beancount",
formatting = {
prefix_width = 30,
currency_column = 60,
number_currency_spacing = 1,
},
},
})File type detection: Ensure beancount files are detected. Add to your config:
vim.filetype.add({
extension = {
beancount = "beancount",
bean = "beancount",
},
})Add to your languages.toml:
[language-server.beancount-language-server]
command = "beancount-language-server"
args = ["--stdio"]
[language-server.beancount-language-server.config]
journal_file = "/path/to/main.beancount"
[language-server.beancount-language-server.config.formatting]
prefix_width = 30
currency_column = 60
number_currency_spacing = 1
[[language]]
name = "beancount"
language-servers = [{ name = "beancount-language-server" }]Using lsp-mode:
(use-package lsp-mode
:hook (beancount-mode . lsp-deferred)
:config
(lsp-register-client
(make-lsp-client
:new-connection (lsp-stdio-connection "beancount-language-server")
:major-modes '(beancount-mode)
:server-id 'beancount-language-server
:initialization-options
(lambda () (list :journal_file "/path/to/main.beancount"
:formatting '(:prefix_width 30 :currency_column 60 :number_currency_spacing 1))))))Using vim-lsp:
if executable('beancount-language-server')
au User lsp_setup call lsp#register_server({
\ 'name': 'beancount-language-server',
\ 'cmd': {server_info->['beancount-language-server']},
\ 'allowlist': ['beancount'],
\ 'initialization_options': {
\ 'journal_file': '/path/to/main.beancount',
\ 'formatting': {
\ 'prefix_width': 30,
\ 'currency_column': 60,
\ 'number_currency_spacing': 1
\ }
\ }
\ })
endifUsing LSP:
Add to LSP settings:
{
"clients": {
"beancount-language-server": {
"enabled": true,
"command": ["beancount-language-server"],
"selector": "source.beancount",
"initializationOptions": {
"journal_file": "/path/to/main.beancount",
"formatting": {
"prefix_width": 30,
"currency_column": 60,
"number_currency_spacing": 1
}
}
}
}
}┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Editor │◄──►│ LSP Server │◄──►│ Beancount │
│ │ │ │ │ (Python) │
│ - VSCode │ │ - Completion │ │ - Validation │
│ - Neovim │ │ - Formatting │ │ - Parsing │
│ - Helix │ │ - Diagnostics │ │ - Bean-check │
│ - Emacs │ │ - Tree-sitter │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
- LSP Server: Main Rust application handling LSP protocol
- Tree-sitter Parser: Fast, incremental parsing of Beancount syntax
- Completion Engine: Smart autocompletion with context awareness
- Diagnostic Provider: Integration with beancount Python for validation
- Formatter: Code formatting fully compatible with bean-format, supporting prefix-width, num-width, and currency-column options
beancount-language-server/
├── crates/lsp/ # Main LSP server implementation
│ ├── src/
│ │ ├── handlers.rs # LSP request/notification handlers
│ │ ├── providers/ # Feature providers (completion, diagnostics, etc.)
│ │ └── server.rs # Core LSP server logic
├── vscode/ # VS Code extension
├── python/ # Python integration utilities
└── flake.nix # Nix development environment
- Rust (stable toolchain)
- Python with beancount
- Node.js (for VS Code extension)
Using Nix (Recommended):
nix developManual Setup:
# Install Rust dependencies
cargo build
# Install Node.js dependencies (for VS Code extension)
cd vscode && npm install
# Install development tools
cargo install cargo-watch# Run all tests
cargo test
# Run with coverage
cargo llvm-cov --all-features --locked --workspace --lcov --output-path lcov.info
# Run specific test
cargo test test_completion# Format code
cargo fmt
# Lint code
cargo clippy --all-targets --all-features
# Check formatting
cargo fmt -- --check- Make changes to the Rust code
- Test locally with
cargo test - Run LSP server in development mode:
cargo run --bin beancount-language-server
- Test with editor by configuring it to use the local binary
cd vscode
npm run build # Build extension
npm run watch # Watch for changes
npm run package # Package extensionThe project uses cargo-dist for automated releases:
- Tag a release:
git tag v1.0.0 && git push --tags - GitHub Actions automatically builds and publishes:
- Binaries for all supported platforms
- Crates.io release
- GitHub release with assets
Contributions are welcome! Here are some ways to help:
- Search existing issues first
- Include beancount file examples that trigger the bug
- Provide editor and OS information
- Check the planned features list
- Describe the use case and expected behavior
- Consider the LSP specification constraints
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes with tests
- Ensure code quality:
cargo fmt && cargo clippy && cargo test - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Look for issues labeled good-first-issue:
- Add new completion types
- Improve error messages
- Add editor configuration examples
- Improve documentation
- Beancount Documentation
- Language Server Protocol Specification
- Tree-sitter Beancount Grammar
- VSCode Extension API
This project is licensed under the MIT License - see the LICENSE file for details.
- Beancount - The amazing double-entry bookkeeping language
- Tree-sitter - Incremental parsing framework
- LSP - Language Server Protocol specification
- Twemoji - Emoji graphics used in the icon
Happy Beancounting! 📊✨