title: rledger query description: Run BQL queries on your ledger
rledger query
Run BQL (Beancount Query Language) queries against your ledger.
Usage
rledger query [OPTIONS] [FILE] [QUERY]Arguments
| Argument | Description |
|---|---|
FILE | The beancount file (uses $RLEDGER_FILE or config if not specified) |
QUERY | BQL query string (interactive mode if not specified) |
Options
| Option | Description |
|---|---|
-P, --profile <PROFILE> | Use a profile from config |
-F, --query-file <FILE> | Read query from file |
-o, --output <FILE> | Output file (default: stdout) |
-f, --format <FORMAT> | Output format: text, csv, json, beancount |
-m, --numberify | Remove currencies, output raw numbers |
-q, --no-errors | Suppress ledger validation errors on load |
-v, --verbose | Show verbose output |
Examples
One-shot Query
rledger query ledger.beancount "SELECT account, sum(position) GROUP BY account"Interactive Mode
rledger query ledger.beancountOpens an interactive shell with tab completion:
rledger> SELECT date, narration WHERE account ~ 'Expenses'
rledger> BALANCES
rledger> .exitOutput Formats
# Text (default)
rledger query ledger.beancount "BALANCES"
# CSV (for spreadsheets)
rledger query ledger.beancount "BALANCES" -f csv > balances.csv
# JSON (for scripts)
rledger query ledger.beancount "BALANCES" -f json | jq '.rows[]'Common Queries
# Account balances
rledger query ledger.beancount "BALANCES"
# Expenses by category
rledger query ledger.beancount "
SELECT account, sum(position)
WHERE account ~ 'Expenses'
GROUP BY account
ORDER BY sum(position) DESC
"
# Recent transactions
rledger query ledger.beancount "
SELECT date, payee, narration, account, position
ORDER BY date DESC
LIMIT 20
"
# Transactions matching pattern
rledger query ledger.beancount "
SELECT date, narration, position
WHERE narration ~ 'Coffee'
"
# Monthly expenses
rledger query ledger.beancount "
SELECT month(date) as month, sum(number) as total
WHERE account ~ 'Expenses'
GROUP BY month
ORDER BY month
"Using with Pipes
# Filter output with grep
rledger query ledger.beancount "BALANCES" | grep Expenses
# Process JSON with jq
rledger query ledger.beancount "BALANCES" -f json | jq '.rows[] | select(.balance > 100)'
# Export to file
rledger query ledger.beancount "SELECT *" -f csv > transactions.csvBQL Reference
See BQL Reference for complete query language documentation.
Quick Reference
-- Select columns
SELECT date, narration, account, position
-- Filter rows
WHERE account ~ 'Expenses' AND year(date) = 2024
-- Aggregate
GROUP BY account
HAVING sum(number) > 100
-- Sort and limit
ORDER BY date DESC
LIMIT 10
-- Built-in reports
BALANCES [FROM ...]
JOURNAL 'Account:Name'Output precision
Numbers in query output are rendered using a per-currency precision inferred from the input file. This matches Python bean-query's default behavior, so a column of Position values for USD prints with the same number of decimal places bean-query would use.
How precision is inferred
For each currency, rledger tracks a frequency distribution of decimal-place counts seen across postings, balances, and price annotations during loading. The displayed precision for that currency is the mode of the distribution — i.e. the most common dp count. Outliers (a single 28-decimal computed price annotation, a single integer-valued cost amid mostly 2-decimal postings) don't dominate the inferred precision.
Inspect the inferred precision and the underlying distribution with:
rledger doctor display-context my-ledger.beancountSample output:
Display Context for my-ledger.beancount
============================================================
Inference policy: MostCommon (default; matches Python bean-query)
USD:
effective: 2 dp
distribution: dp=0: 5, dp=2: 141
mode (MostCommon): 2
max (Maximum): 4
VBMPX:
effective: 3 dp
distribution: dp=3: 4mode and max are shown side-by-side when they differ, so you can see why a particular column rendered at the precision it did.
Overriding inference
Inferred precision is a heuristic. There are two ways to pin a currency's display precision explicitly.
option "display_precision" — file-level setting (precision is the scale of the example value):
option "display_precision" "USD:0.01" ; 2dp
option "display_precision" "BTC:0.00000001" ; 8dpprecision: N metadata on a commodity directive (rledger extension, issue #991):
2024-01-01 commodity USD
precision: 2
2024-01-01 commodity BTC
precision: 8
2024-01-01 commodity JPY
precision: 0Both achieve the same outcome — pinning the displayed precision for that currency regardless of what the inferred distribution shows. Use whichever is more ergonomic: option "display_precision" keeps the configuration in one place, while precision: metadata co-locates the precision with the rest of the commodity declaration (asset class, ticker, etc.).
Precedence. When both are set for the same currency, the per-commodity precision: metadata wins:
option "display_precision" "USD:0.01" ; 2dp
2024-01-01 commodity USD
precision: 4 ; this wins — USD renders at 4dpIf the same currency has precision: metadata on multiple commodity directives, the last one in load order wins.
Validation. precision: metadata must be a non-negative integer (0 through 4_294_967_295). Invalid values — strings, negatives, fractions, out-of-range — produce an E5003 warning during validation and the loader ignores that declaration. The currency's effective precision then falls back through the precedence stack: any other valid precision: metadata on the same currency, then option "display_precision" if set, then inference. Loading does not fail.
Reserved key. The precision key on commodity directives is reserved by the loader — pre-existing user-defined uses of this key on commodity directives will be reinterpreted as a precision override. Pick a different key (e.g. display_precision, precision_note) if you need to attach unrelated metadata.
Naked-decimal columns
Columns that produce bare numbers (no associated currency) — cost_number, SUM(number), etc. — are tracked independently per column. Each value renders at its own natural decimal scale (matching bean-query's DecimalRenderer), with one exception: if an aggregate collapses to literal zero, the column's inferred default precision is used to pad it (so SUM(0.00) renders as 0.00, not 0).
See Also
- BQL Reference - Full query language docs
- Common Queries - Useful query examples