{"id":35631447,"url":"https://github.com/rustledger/rustledger","last_synced_at":"2026-04-27T03:02:02.448Z","repository":{"id":331519829,"uuid":"1127502482","full_name":"rustledger/rustledger","owner":"rustledger","description":"Modern plain text accounting. Beancount compatible.","archived":false,"fork":false,"pushed_at":"2026-04-24T23:06:59.000Z","size":40730,"stargazers_count":210,"open_issues_count":0,"forks_count":17,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-24T23:13:51.067Z","etag":null,"topics":["accounting","beancount","cli","double-entry","finance","ledger","rust"],"latest_commit_sha":null,"homepage":"https://rustledger.github.io","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rustledger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":"CLA.md"},"funding":{"liberapay":"rustledger"}},"created_at":"2026-01-04T02:35:58.000Z","updated_at":"2026-04-24T23:00:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rustledger/rustledger","commit_stats":null,"previous_names":["rustledger/rustledger"],"tags_count":46,"template":false,"template_full_name":null,"purl":"pkg:github/rustledger/rustledger","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustledger%2Frustledger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustledger%2Frustledger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustledger%2Frustledger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustledger%2Frustledger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rustledger","download_url":"https://codeload.github.com/rustledger/rustledger/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustledger%2Frustledger/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32320683,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T23:26:28.701Z","status":"online","status_checked_at":"2026-04-27T02:00:06.769Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accounting","beancount","cli","double-entry","finance","ledger","rust"],"created_at":"2026-01-05T09:09:19.832Z","updated_at":"2026-04-27T03:02:02.440Z","avatar_url":"https://github.com/rustledger.png","language":"Rust","funding_links":["https://liberapay.com/rustledger"],"categories":["Alternative Implementations"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# rustledger\n\n**A blazing-fast Rust implementation of [Beancount](https://beancount.github.io/)**\n\nParse and validate your ledger faster than Python beancount.\n\n[![crates.io](https://img.shields.io/crates/v/rustledger)](https://crates.io/crates/rustledger)\n[![npm](https://img.shields.io/npm/v/@rustledger/wasm)](https://www.npmjs.com/package/@rustledger/wasm)\n[![Packaging status](https://repology.org/badge/tiny-repos/rustledger.svg)](https://repology.org/project/rustledger/versions)\n[![docs.rs](https://img.shields.io/docsrs/rustledger-core)](https://docs.rs/rustledger-core)\n\n[![CI](https://github.com/rustledger/rustledger/actions/workflows/ci.yml/badge.svg)](https://github.com/rustledger/rustledger/actions/workflows/ci.yml)\n[![Compatibility](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/rustledger/rustledger/compatibility/.github/badges/compat-badge.json)](https://github.com/rustledger/rustledger/actions/workflows/compat.yml)\n\n[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE)\n[![Liberapay](https://img.shields.io/liberapay/receives/rustledger.svg?logo=liberapay)](https://liberapay.com/rustledger)\n\n\u003c/div\u003e\n\n______________________________________________________________________\n\n## Why rustledger?\n\n| | |\n|---|---|\n| **10-30x faster** | Parse and validate large ledgers in milliseconds ([see benchmarks](#performance)) |\n| **No dependencies** | No Python runtime, no libraries to install |\n| **Drop-in replacement** | Compatible `bean-*` CLI commands for easy migration |\n| **Full compatibility** | Parses any valid beancount file |\n| **Editor support** | LSP server for VS Code, Neovim, Helix, and more |\n| **AI-ready** | MCP server for Claude, Cursor, and other AI assistants |\n| **Runs anywhere** | WebAssembly support for browser and Node.js |\n| **Better errors** | Detailed error messages with source locations |\n| **30 built-in plugins** | Plus Python plugin compatibility via WASI sandbox |\n| **Bank import** | CSV/OFX import with auto-detection, dedup, and categorization |\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eComparison with other tools\u003c/strong\u003e\u003c/summary\u003e\n\n| Feature | rustledger | Python beancount | hledger | ledger-cli |\n|---------|------------|------------------|---------|------------|\n| **Language** | Rust | Python | Haskell | C++ |\n| **Speed** | Very fast | Slow | Fast | Fast |\n| **Beancount syntax** | Native | Native | Via conversion | No |\n| **Query language** | BQL (100% compat) | BQL | Custom | Custom |\n| **LSP server** | Built-in | No | Via plugin | No |\n| **WASM support** | Yes | No | Partial | No |\n| **Plugin system** | Native + Python | Python | Haskell | Custom |\n| **Active development** | Yes | Maintenance | Yes | Limited |\n\n**When to use rustledger:**\n\n- You use Beancount syntax and want speed\n- You want a single binary with no runtime dependencies\n- You need LSP editor integration\n- You want to use existing Python plugins\n\n**When to use Python beancount:**\n\n- You need Fava web interface (until rustledger integration)\n- You have complex Python plugins with C extensions\n\n**When to use hledger:**\n\n- You prefer hledger's syntax and reports\n- You need time-tracking features\n\n\u003c/details\u003e\n\n## Install\n\n| Platform | Command |\n|----------|---------|\n| **macOS** | `brew install rustledger` |\n| **Linux** | `brew install rustledger` |\n| **Arch Linux** | `yay -S rustledger-bin` |\n| **Fedora/RHEL** | `sudo dnf copr enable robcohen/rustledger \u0026\u0026 sudo dnf install rustledger` |\n| **Windows** | `scoop bucket add rustledger https://github.com/rustledger/scoop-rustledger \u0026\u0026 scoop install rustledger` |\n| **Cargo** | `cargo binstall rustledger` or `cargo install rustledger` |\n| **Nix** | `nix run github:rustledger/rustledger` |\n| **Docker** | `docker run --rm -v \"$PWD:/data\" ghcr.io/rustledger/rustledger /data/ledger.beancount` |\n| **Binaries** | [GitHub Releases](https://github.com/rustledger/rustledger/releases) |\n| **npm (WASM)** | `npm install @rustledger/wasm` |\n| **npm (MCP)** | `npx @rustledger/mcp-server` ([Model Context Protocol](https://modelcontextprotocol.io) server) |\n\n\u003csub\u003eMissing your platform? [Open an issue](https://github.com/rustledger/rustledger/issues/new) to request it.\u003c/sub\u003e\n\n**Coming from Python beancount?** See the [Migration Guide](docs/MIGRATION.md) for command equivalents and plugin mapping.\n\n## Quick Start\n\n```bash\nrledger check ledger.beancount\nrledger query ledger.beancount \"SELECT account, SUM(position) GROUP BY account\"\n```\n\n## CLI Commands\n\n| Command | Description |\n|---------|-------------|\n| `rledger check` | Validate ledger files with detailed error messages |\n| `rledger query` | Run BQL queries (interactive shell or one-shot) |\n| `rledger format` | Auto-format beancount files |\n| `rledger report` | Generate balance, account, and statistics reports |\n| `rledger add` | Add transactions interactively or via quick mode |\n| `rledger doctor` | Debugging tools for ledger issues |\n| `rledger extract` | Import transactions from CSV/OFX bank statements with auto-detection, dedup, and categorization |\n| `rledger price` | Fetch commodity prices from online sources |\n| `rledger-lsp` | Language Server Protocol for editor integration |\n\nPython beancount users can install `bean-check`, `bean-query`, etc. wrapper scripts via `rledger compat install`.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eReport subcommands\u003c/strong\u003e\u003c/summary\u003e\n\n| Subcommand | Alias | Description |\n|------------|-------|-------------|\n| `balances` | | All account balances |\n| `balsheet` | `bal` | Balance sheet report |\n| `income` | `is` | Income statement |\n| `journal` | `register` | Transaction register |\n| `holdings` | | Investment holdings |\n| `networth` | | Net worth over time |\n| `accounts` | | List all accounts |\n| `commodities` | | List all commodities |\n| `prices` | | Price entries |\n| `stats` | | Ledger statistics |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eDoctor subcommands\u003c/strong\u003e\u003c/summary\u003e\n\nDebugging and diagnostic tools:\n\n| Subcommand | Description |\n|------------|-------------|\n| `lex` | Dump lexer tokens (alias: `dump-lexer`) |\n| `parse` | Parse and show directives |\n| `context` | Show transaction context at a line number |\n| `linked` | Find transactions by link (`^link`) or tag (`#tag`) |\n| `missing-open` | Generate missing Open directives |\n| `list-options` | List all available beancount options |\n| `print-options` | Print options parsed from a file |\n| `stats` | Display ledger statistics |\n| `display-context` | Show inferred decimal precision context |\n| `roundtrip` | Round-trip parse/format test |\n| `directories` | Validate directory hierarchy against accounts |\n| `region` | Print transactions in a line range with balances |\n| `generate-synthetic` | Generate synthetic test files |\n\n```bash\n# Debug a parsing issue at line 42\nrledger doctor context ledger.beancount 42\n\n# Find all transactions with a link\nrledger doctor linked ledger.beancount ^trip-2024\n\n# Generate Open directives for accounts missing them\nrledger doctor missing-open ledger.beancount \u003e\u003e ledger.beancount\n```\n\n\u003c/details\u003e\n\n\u003csub\u003eRun `rledger \u003ccommand\u003e --help` for all options.\u003c/sub\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eCLI examples\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\n# Validate with plugins\nrledger check --native-plugin auto_accounts ledger.beancount\n\n# Interactive query shell\nrledger query ledger.beancount\n\n# One-shot query\nrledger query ledger.beancount \"SELECT date, narration WHERE account ~ 'Expenses:Food'\"\n\n# Reports\nrledger report ledger.beancount balances\nrledger report ledger.beancount stats\n\n# Format in place\nrledger format --in-place ledger.beancount\n```\n\n\u003c/details\u003e\n\n## Import \u0026 Categorization\n\nrustledger includes a complete bank import pipeline (`rledger extract`) with automatic CSV/OFX parsing, duplicate detection, transaction categorization, and balance reconciliation.\n\n### CSV Import with Auto-Detection\n\n```bash\n# Auto-detect delimiter, date format, and column roles\nrledger extract bank-statement.csv --auto -a Assets:Bank:Checking\n\n# Check against existing ledger to avoid duplicates\nrledger extract statement.csv --auto -a Assets:Bank --existing ledger.beancount\n\n# Append balance assertion from bank statement\nrledger extract statement.csv --auto -a Assets:Bank --balance 5000.00\n\n# List available importers from config\nrledger extract --list-importers --config importers.toml\n```\n\n### Importers Configuration\n\nCreate `importers.toml` for reusable import profiles:\n\n```toml\n[[importers]]\nname = \"chase\"\naccount = \"Assets:Bank:Chase\"\ndate_column = \"Transaction Date\"\namount_column = \"Amount\"\ndate_format = \"%m/%d/%Y\"\n\n[importers.mappings]\n\"AMAZON\" = \"Expenses:Shopping\"\n\"WHOLE FOODS\" = \"Expenses:Groceries\"\n```\n\n```bash\nrledger extract --importer chase chase-statement.csv\n```\n\nConfig is searched in: current directory, `~/.config/rledger/importers.toml`, or via `--config`.\n\n### Transaction Categorization\n\nA 3-tier pipeline automatically categorizes transactions:\n\n1. **Rules engine** — substring, regex, and exact match patterns from `importers.toml`\n2. **Merchant dictionary** — ~80 built-in patterns across 10 categories (grocery, dining, transport, subscriptions, etc.)\n3. **ML categorization** — TF-IDF + Naive Bayes classification via `linfa`\n\n### Transfer Detection\n\nAutomatically identifies inter-account transfers by matching opposite-sign amounts within date windows, with keyword boosting for common transfer indicators.\n\n### Duplicate Detection\n\nFuzzy matching on date + amount + payee/narration prevents importing the same transaction twice. Structural fingerprinting (BLAKE3) provides stable hashes for comparison.\n\n### Balance Reconciliation\n\nThe `--balance` flag appends a balance assertion directive matching your bank statement's ending balance, helping verify import accuracy.\n\n## Crates\n\n| Crate | Description |\n|-------|-------------|\n| `rustledger` | CLI tool (`rledger check`, `rledger query`, etc.) |\n| `rustledger-core` | Core types: Amount, Position, Inventory |\n| `rustledger-parser` | Lexer and parser with error recovery |\n| `rustledger-loader` | File loading and includes |\n| `rustledger-booking` | Interpolation and 7 booking methods |\n| `rustledger-validate` | 28 validation error codes |\n| `rustledger-query` | BQL query engine |\n| `rustledger-plugin` | 30 built-in plugins + Python plugin support |\n| `rustledger-plugin-types` | Shared plugin type definitions |\n| `rustledger-importer` | CSV/OFX import framework with auto-detection, enrichment, and configurable importers |\n| `rustledger-ops` | Pure operations — ML categorization, LLM prompts, dedup, transfer detection, balance reconciliation, merchant dictionary |\n| `rustledger-lsp` | Language Server Protocol for editor integration |\n| `rustledger-wasm` | WebAssembly bindings for JavaScript/TypeScript |\n| `rustledger-ffi-wasi` | FFI via WASI for embedding in any language |\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eBooking methods (7)\u003c/strong\u003e\u003c/summary\u003e\n\n| Method | Description |\n|--------|-------------|\n| `STRICT` | Lots must match exactly (default) |\n| `STRICT_WITH_SIZE` | Exact-size matches accept oldest lot |\n| `FIFO` | First in, first out |\n| `LIFO` | Last in, first out |\n| `HIFO` | Highest cost first |\n| `AVERAGE` | Average cost basis |\n| `NONE` | No cost tracking |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eBuilt-in plugins (30)\u003c/strong\u003e\u003c/summary\u003e\n\n| Plugin | Description |\n|--------|-------------|\n| `auto_accounts` | Auto-generate Open directives |\n| `auto_tag` | Automatically tag transactions |\n| `box_accrual` | Accrual accounting for boxed periods |\n| `capital_gains_gain_loss` | Split capital gains into gain/loss accounts |\n| `capital_gains_long_short` | Split capital gains by holding period |\n| `check_average_cost` | Validate average cost bookings |\n| `check_closing` | Zero balance assertion on account close |\n| `check_commodity` | Validate commodity declarations |\n| `check_drained` | Ensure accounts are drained before close |\n| `close_tree` | Close descendant accounts |\n| `coherent_cost` | Enforce cost OR price (not both) |\n| `commodity_attr` | Validate commodity attributes |\n| `currency_accounts` | Auto-generate currency trading postings |\n| `effective_date` | Override posting date via metadata |\n| `forecast` | Generate recurring transactions |\n| `generate_base_ccy_prices` | Create base currency price entries |\n| `implicit_prices` | Generate price entries from transaction costs |\n| `leafonly` | Error on postings to non-leaf accounts |\n| `noduplicates` | Hash-based duplicate transaction detection |\n| `nounused` | Warn on unused accounts |\n| `onecommodity` | Single commodity per account |\n| `pedantic` | Enable all strict validations |\n| `rename_accounts` | Rename accounts via metadata |\n| `rxtxn` | Link related transactions |\n| `sellgains` | Cross-check capital gains against sales |\n| `split_expenses` | Split expenses across accounts |\n| `unique_prices` | One price per day per commodity pair |\n| `unrealized` | Calculate unrealized gains |\n| `valuation` | Mark-to-market valuation |\n| `zerosum` | Group transactions that sum to zero |\n\nAdditionally, `document_discovery` auto-discovers documents from `option \"documents\"` directories.\n\n**Python plugins**: Run existing Python beancount plugins via CPython-WASI sandbox.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003ePlugin support\u003c/strong\u003e\u003c/summary\u003e\n\nrustledger supports three types of plugins:\n\n**Native plugins** (built-in, fastest):\n\n```bash\n# Run a native plugin from CLI\nrledger check --native-plugin implicit_prices ledger.beancount\n\n# Or declare in your beancount file (auto-detected as native):\n# plugin \"beancount.plugins.auto_accounts\"\n```\n\n**Python file plugins** (via WASM sandbox):\n\n```bash\n# Declare in your beancount file:\n# plugin \"/path/to/my_plugin.py\"\n```\n\n**WASM plugins** (sandboxed WebAssembly):\n\n```bash\n# Load a WASM plugin\nrledger check --plugin /path/to/plugin.wasm ledger.beancount\n```\n\n**How Python plugins work:**\n\n- File-based plugins (`.py` files) run in a sandboxed CPython compiled to WebAssembly\n- No system Python installation required\n- Plugins cannot access the filesystem or network (sandbox isolation)\n- Compatible with most pure-Python beancount plugins\n\n**Limitations:**\n\n- Module-based plugins (`beancount.plugins.xyz`) only work if rustledger has a native implementation\n- Plugins with C extensions won't work (numpy, pandas, etc.)\n- No network access (price fetching plugins need alternatives)\n\n\u003c/details\u003e\n\n## Editor Integration\n\nrustledger includes a full-featured Language Server (`rledger-lsp`) for IDE support:\n\n- Real-time diagnostics\n- Autocompletion (accounts, currencies, payees)\n- Go to definition / find references\n- Hover information with account balances\n- Rename refactoring\n- Document formatting\n\nSee [LSP setup guide](crates/rustledger-lsp/README.md) for VS Code, Neovim, Helix, Zed, and Emacs.\n\n## Performance\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/rustledger/rustledger/benchmarks/.github/badges/validation-chart.svg\"\u003e\n  \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/rustledger/rustledger/benchmarks/.github/badges/validation-chart.svg\"\u003e\n  \u003cimg alt=\"Validation Benchmark\" src=\"https://raw.githubusercontent.com/rustledger/rustledger/benchmarks/.github/badges/validation-chart.png\" width=\"100%\"\u003e\n\u003c/picture\u003e\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/rustledger/rustledger/benchmarks/.github/badges/balance-chart.svg\"\u003e\n  \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/rustledger/rustledger/benchmarks/.github/badges/balance-chart.svg\"\u003e\n  \u003cimg alt=\"Balance Report Benchmark\" src=\"https://raw.githubusercontent.com/rustledger/rustledger/benchmarks/.github/badges/balance-chart.png\" width=\"100%\"\u003e\n\u003c/picture\u003e\n\n\u003csub\u003eBenchmarks run nightly on 10K transaction ledgers. [View workflow →](https://github.com/rustledger/rustledger/actions/workflows/bench.yml)\u003c/sub\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eBenchmark details\u003c/strong\u003e\u003c/summary\u003e\n\n**What's measured:**\n\n- **Validation**: Parse ledger + validate (balance assertions, account opens, etc.)\n- **Balance Report**: Parse + compute all account balances\n\n**Memory efficiency:**\nrustledger typically uses 3-5x less memory than Python beancount thanks to Rust's zero-cost abstractions and efficient data structures.\n\n**Run locally:**\n\n```bash\n# Quick comparison (requires nix)\nnix develop .#bench\n./scripts/bench.sh\n\n# Criterion micro-benchmarks\ncargo bench -p rustledger-core\ncargo bench -p rustledger-parser\n```\n\nSee [BENCHMARKING.md](docs/BENCHMARKING.md) for detailed benchmark documentation.\n\n\u003c/details\u003e\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.\n\n**Documentation:**\n\n- [Architecture](docs/reference/architecture.md) - Crate structure and data flow\n- [BQL Reference](docs/reference/bql.md) - Query language guide\n- [Importing](docs/guides/importing.md) - CSV/OFX bank import tutorial\n- [Validation errors](docs/reference/errors.md) - Error code reference\n- [API docs](https://docs.rs/rustledger-core) - Rust API documentation\n\nBy submitting a pull request, you agree to the [Contributor License Agreement](CLA.md).\n\n## License\n\n[GPL-3.0](LICENSE)\n\n**Commercial licensing available** - [contact us](https://rustledger.github.io/#contact) for proprietary license options.\n\n## Funding\n\nrustledger is free and open source. If you find it useful, consider supporting development:\n\n[![Support on Liberapay](https://img.shields.io/badge/Support%20on-Liberapay-F6C915?logo=liberapay)](https://liberapay.com/rustledger)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustledger%2Frustledger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frustledger%2Frustledger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustledger%2Frustledger/lists"}