Journal format
A journal is a UTF-8 text file. Everything that starts in column 1 is a directive, a transaction header or a comment; everything indented belongs to the transaction above it.
; comment (also: a line starting with #)
include 2026/*.journal
option strict
commodity INR format "₹1,00,000.00"
account Assets:Bank:HDFC ; declared account
P 2026-01-05 USD 83.12 INR
2026-01-03 ! (REF-42) Grocery store | weekly shop ; tag:food, trip:goa
; a note attached to the transaction
Expenses:Food:Groceries 1,240.50 INR
Assets:Bank:HDFC ; amount left out: auto-balances
Directives
| Directive | Meaning |
|---|---|
include PATH |
Read another file. Relative to the including file; *, ? and [...] globs are expanded in sorted order. An include cycle is an error. |
commodity NAME format "NUMBER" |
Declares how a commodity is displayed (see below). |
account NAME |
Declares an account. Trailing ; comment allowed. |
P DATE COMMODITY AMOUNT |
Market price: one unit of COMMODITY was worth AMOUNT on DATE. |
option strict |
Same as passing --strict: every account used in a posting must be declared. |
~ PERIOD DESCRIPTION |
Periodic transaction, see below. |
Unknown directives are errors (not silently ignored) so typos surface immediately.
Commodity formats
commodity INR format "₹1,00,000.00" teaches ledgerline three things by example:
- symbol and position: everything before the number is a prefix (
₹), everything after is a suffix (" INR"). If the symbol differs from the commodity name (₹vsINR),₹500is accepted in postings as 500 INR. - precision: digits after the point (2). Reports round to this precision (half-up); values are never rounded internally.
- grouping:
1,00,000is Indian lakh/crore grouping (groups of 2 above the first 3 digits),1,000,000is western grouping,1000000is none. Input accepts either style regardless of the declared one; misplaced separators (1,00.50) are an error.
Commodities without a commodity directive are inferred from use: position and spacing of the first occurrence,
the highest precision seen, and grouping if any amount used commas.
Commodity names are letters/symbols, optionally with digits after the first character when written after the number
(10 NIFTY50). Anything else (spaces, a leading digit) must be quoted: 3 "ABC 1".
Accounts and strict mode
Account names are :-separated components (Assets:Bank:HDFC); empty components are an error. A name can contain
single spaces (Assets:Cash In Hand); the account is separated from the amount by two or more spaces or a tab.
If you forget, ledgerline tells you (account name 'Expenses:Food 80 INR' contains an amount-like part).
With option strict / --strict, an undeclared account is an error with a did-you-mean suggestion. Declaring
Expenses:Food:Dining implicitly declares Expenses:Food and Expenses.
Reports classify accounts by their top-level name (case-insensitive): Assets, Liabilities, Equity,
Income/Revenue, Expenses. Other top-level names show up in bal/reg but not in is/bs.
Transactions
DATE [STATUS] [(CODE)] [DESCRIPTION] [; COMMENT]
[; note]
ACCOUNT [AMOUNT] [@ UNITCOST | @@ TOTALCOST] [= ASSERTION] [; comment]
- Date:
YYYY-MM-DDorYYYY/MM/DD, validated against the calendar (2026-02-30is rejected with "2026-02 has only 28 days"). - Status:
*cleared,!pending, or nothing. - Code: free text in parentheses, e.g. a cheque or reference number.
- Description / payee: everything up to
;. If it contains|, the part before it is the payee and the part after is a note:Landlord | Rent. Without|the whole description is the payee. - Comments and tags: a comment is split on commas; every segment of the form
name: valueis a tag. The shorthandtag:fooddeclares a valueless tag calledfood;trip:goadeclares tagtripwith valuegoa. Tags written on the header apply to all postings for queries. - Posting date: the tag
date:2026-01-05on a posting overrides the transaction date for that posting in reports, queries and balance assertions.
Amounts
1,240.50 INR -1800.00 USD ₹1,00,000.00 -$5 10 AAPL 3 "ABC 1" 0
A sign may come before the commodity or the number. An amount with no commodity is allowed (it is the empty
commodity). Numbers are Decimal; there are no floats anywhere.
Costs
10 AAPL @ 180.00 USD states a per-unit price, 10 AAPL @@ 1800.00 USD a total price. For balancing, the
posting is worth the cost, not the quantity. The cost must be positive and in a different commodity.
Costs also feed the price database (see design.md).
Balancing
- Each commodity must sum to exactly zero (Decimal equality; there is no tolerance - use
@@when a unit price would not multiply out exactly). - At most one posting may omit its amount. It receives whatever makes the transaction balance - one posting per commodity if several are out of balance.
- Virtual postings:
(Account)is unbalanced - it needs an amount and is ignored for balancing (budget envelopes, memo accounts).[Account]is balanced virtual - those postings must balance among themselves, separately from the real ones, and one of them may elide its amount. - A transaction with a single zero-amount posting is valid (used for balance assertions).
Balance assertions
Assets:Bank 0 INR = 48,759.50 INR asserts that after this posting the account holds exactly that amount of
that commodity. The amount before = may be anything (zero is typical for a pure check). Only the account itself is
checked, not its sub-accounts. Assertions are evaluated in date order (posting date, then file order), not in
file order, so you can keep them anywhere. A failure shows expected, actual and the difference.
Periodic transactions
~ monthly from 2026-01-01 to 2026-12-31 Rent
Expenses:Rent 25,000 INR
Assets:Bank:HDFC
Period expression: daily, weekly, monthly, quarterly, yearly, or every N days|weeks|months|quarters|years,
then optional from DATE and to DATE (exclusive). Periodic transactions do not affect balances; ledgerline budget
uses their explicitly-amounted postings as budgets (the elided balancing posting is not a budget line).
Formatting
ledgerline fmt rewrites transactions canonically: 4-space posting indent, two spaces between account and amount,
amounts right-aligned within a transaction, one blank line between transactions, amounts rendered with the
commodity's declared format (never losing precision). Comments, directives and elided amounts are kept. The output
is a fixed point: formatting twice changes nothing.