Skip to main content

Beancount syntax reference: directives, accounts, amounts

Beancount language syntax reference: directives, transactions, account naming, tags, metadata, and formatting for plain-text ledgers.

This provides a concise yet comprehensive reference for the Beancount language syntax, blending practical structure, rules, and examples. For more details, see the Cheat Sheet.

Overview​

Beancount is a plain-text double-entry accounting system. Its language is structured around three main building blocks:

  • Commodities (currencies, stocks, points, etc.)
  • Accounts (hierarchical, categorized ledgers)
  • Directives (dated entries recording events or configuration)

Commodities​

Commodities are always written in uppercase, e.g., USD, EUR, AAPL, BTC, MILES, HOURS.

Accounts​

Accounts are colon-separated, capitalized hierarchical names. They must begin with one of the five root account types:

NameTypeTypical ContentsExample
Assets+Cash, Bank, InvestmentsAssets:Checking
Liabilities-Credit Cards, LoansLiabilities:CreditCard
Income-Salary, InterestIncome:EmployerA
Expenses+Purchases, BillsExpenses:Food:Dining
Equity-Opening/Closing BalancesEquity:Opening-Balances
  • Components must be capitalized, separated by colons (:), with no spaces.
  • Numbers and dashes are allowed in components.
  • The root account names can be customized via options (see below).

Directives​

Directives are the core statements in a Beancount file. Most start with a date, followed by a directive type and arguments. They are processed in chronological order (by date), not file order.

General format:

YYYY-MM-DD <directive> <arguments...>

Common Directives & Examples​

Opening and Closing Accounts​

2023-01-01 open Assets:Checking USD,EUR  ; Optionally specify allowed currencies
2023-12-31 close Assets:Checking

Declaring Commodities​

2020-07-22 commodity AAPL
  name: "Apple Inc."

Price Declarations​

2022-04-30 price AAPL 150.00 USD

For automatic valuation quotes in a hosted ledger, set up Live Prices. Managed feeds supply ordinary dated price directives. They do not replace transaction prices (@, @@) or lot costs ({}).

Notes & Documents​

2022-03-20 note Assets:Checking "Asked about refund"
2022-03-20 document Assets:Checking "statements/2022-03.pdf"

Transactions​

2024-01-05 * "Coffee Shop" "Morning coffee"
  Expenses:Food         4.50 USD
  Assets:Cash         -4.50 USD
 
2024-01-06 ! "Phone Bill" "Monthly payment" #utilities ^phone
  id: "INV12345"              ; Metadata
  Expenses:Utilities  60.00 USD
  Assets:Checking

Posting Features​

; With cost basis
  Assets:Stocks    1 AAPL {150.00 USD}
; With price annotation
  Assets:Cash   -100 USD @ 1.25 CAD
; With total price
  Assets:Cash   -100 USD @@ 125.00 CAD
; Implicit balance
  Assets:Cash   -100 USD
  Assets:Bank

Balance Assertions & Padding​

The pad must be dated before the balance it feeds, because the assertion is checked at the start of its day:

2024-06-01 pad Assets:Checking Equity:Opening-Balances
2024-06-02 balance Assets:Checking 1000.00 USD

Events​

2024-06-01 event "location" "San Francisco, CA"

Options​

Set file-wide configuration:

option "title" "My Ledger"
option "operating_currency" "USD"
option "documents" "docs/"
option "name_assets" "Vermoegen"

See the Options Reference for more.

Plugins & File Organization​

plugin "beancount.plugins.module_name"
plugin "beancount.plugins.module_name" "config-string"
include "other/file.beancount"
pushtag #project
; ...
poptag #project

Hosted Beancount.io also resolves supported managed price URL includes. This is an extension to upstream Beancount: use the Live Prices setup guide for hosted and local compatibility.

Important Rules​

  • All transactions must balance: the weights of all postings sum to zero. A posting's weight is its amount, or its cost ({}) or price (@) converted to the other currency when one is present.
  • Accounts must be opened before use; closed accounts cannot accept postings.
  • Balance assertions check only the specified currency, can be used on parent accounts, and are evaluated at the start of their date (so they exclude same-day transactions).
  • Price annotations (@ per unit, @@ total) do affect balancing: they set the posting's weight in the other currency. -100 USD @ 1.25 CAD weighs 125 CAD and offsets a 125 CAD posting; remove the price and the transaction no longer balances.

Common Patterns​

Opening Accounts with Initial Balance​

Open both accounts, pad on the start date, and assert the balance the next day (the assertion is checked at the start of its date):

2024-01-01 open Assets:Checking USD
2024-01-01 open Equity:Opening-Balances
2024-01-01 pad Assets:Checking Equity:Opening-Balances
2024-01-02 balance Assets:Checking 1000.00 USD

Investment Transaction​

2024-01-01 * "Buy stock"
  Assets:Broker:Stock   10 AAPL {150.00 USD}
  Assets:Broker:Cash -1500.00 USD

Multi-Currency Transaction​

2024-01-01 * "Currency exchange"
  Assets:USD   -100.00 USD @ 1.25 CAD
  Assets:CAD    125.00 CAD

Comments​

poptag  #trip-to-peru
; inline comments begin with a semi-colon
* any line not starting with a valid directive is also ignored silently

Source: https://beancount.io/docs/Basics/syntax