Skip to content

Beancount Syntax Overview

This document provides an overview of Beancount syntax. Individual directives are documented in the directives/ directory.

Core Concepts

Beancount is a declarative text-based double-entry bookkeeping system. Input files contain directives (entries) with dates and types, plus optional global options.

File Structure

A Beancount file consists of:

  1. Options - Global configuration (undated)
  2. Directives - Dated accounting entries
  3. Comments - Documentation (ignored by parser)
beancount
; Options at top
option "title" "My Ledger"
option "operating_currency" "USD"

; Directives follow
2024-01-01 open Assets:Checking USD

2024-01-15 * "Payee" "Description"
  Assets:Checking   100.00 USD
  Income:Salary

Date Format

All directives begin with dates in ISO 8601 format:

YYYY-MM-DD

Both dash and slash variants are accepted:

  • 2024-02-03 (preferred)
  • 2024/02/03

Comments

Lines starting with semicolon are comments:

beancount
; This is a comment
2024-01-01 * "Transaction"
  Assets:Cash  -20 USD  ; inline comment
  Expenses:Food

Non-directive lines are silently ignored, enabling org-mode formatting.

Transaction Flags

Flags indicate transaction status:

FlagMeaning
*Complete - "this looks correct"
!Incomplete - needs review, "this looks incorrect"
txnEquivalent to * (keyword form)
PPadding - typically auto-inserted by pad directive (can also be used manually)

The txn keyword is optional; a flag alone suffices:

beancount
2024-01-15 * "Using star flag"
2024-01-15 txn "Using txn keyword"
2024-01-15 ! "Pending transaction"

Accounts

Account names consist of colon-separated components:

RootType:Component:Component:...

Root Types

Every account MUST start with one of five root types:

Root TypePurpose
AssetsThings you own
LiabilitiesThings you owe
EquityNet worth / opening balances
IncomeMoney received
ExpensesMoney spent

Component Rules

  • First component MUST be one of the five root types
  • Each subsequent component MUST begin with an uppercase ASCII letter (A-Z) or digit (0-9)
  • Subsequent characters MAY be letters (including UTF-8), numbers, or dashes
  • UTF-8 characters are supported AFTER the first ASCII character
  • MUST NOT contain spaces or special characters other than dash

Examples:

Assets:US:BofA:Checking
Assets:US:BofA:Savings
Expenses:Food:Groceries
Liabilities:CreditCard:Chase
Income:Salary:2024

Commodities/Currencies

Currency names are recognized by syntax:

  • MUST start with an uppercase letter (A-Z)
  • MUST end with an uppercase letter or digit (A-Z, 0-9)
  • Middle characters MAY include: uppercase letters, digits, apostrophes ('), periods (.), underscores (_), dashes (-)
  • No enforced maximum length (docs mention 24 chars but not enforced)
  • Single-letter currencies are valid (e.g., V)

Examples:

USD       ; US Dollar
EUR       ; Euro
MSFT      ; Stock
V         ; Single letter (valid)
NT.TO     ; Toronto stock exchange
BRK.B     ; Class B shares
VACHR     ; Custom (vacation hours)

Invalid examples:

usd       ; Lowercase not allowed
1USD      ; Cannot start with digit
USD-      ; Cannot end with special character

No pre-declaration required (though commodity directive is available).

Amounts

An amount is a number followed by a currency:

100.00 USD
-50 EUR
1,234.56 CAD

Number Format

  • Decimal point: .
  • Grouping separator: , (optional)
  • Negative: - prefix

Arithmetic Expressions

Amounts support expressions:

beancount
2024-01-01 * "Split"
  Expenses:Food  (100 / 3) USD
  Assets:Cash

Operators: +, -, *, /, (, )

Strings

Text enclosed in double quotes:

beancount
"Simple string"
"Multi-line
string allowed"

Strings MAY span multiple lines.

Tags

Hash-prefixed identifiers for categorizing. Tags may contain letters, numbers, dashes, underscores, slashes, and periods.

beancount
2024-01-15 * "Flight" #berlin-trip #travel #project/2024
  Expenses:Flights  -1230.27 USD
  Liabilities:CreditCard

Tag Stack

Apply tags to multiple directives:

beancount
pushtag #berlin-trip
2024-04-23 * "Hotel"
  ...
2024-04-24 * "Restaurant"
  ...
poptag #berlin-trip

Metadata Stack

Apply metadata to multiple directives:

beancount
pushmeta location: "Berlin"
2024-04-23 * "Hotel"
  ...
2024-04-24 * "Restaurant"
  ...
popmeta location:

Caret-prefixed identifiers connecting related transactions. Links may contain letters, numbers, dashes, underscores, slashes, and periods.

beancount
2024-02-05 * "Invoice" ^invoice/2024/001
  Income:Clients  -8450.00 USD
  Assets:Receivable

2024-02-20 * "Payment" ^invoice/2024/001
  Assets:Checking  8450.00 USD
  Assets:Receivable

Metadata

Key-value pairs attached to directives or postings:

beancount
2024-01-15 * "Purchase"
  receipt: "photo.jpg"
  Assets:Cash  -50 USD
    category: "groceries"
  Expenses:Food

Key Format

  • MUST start with lowercase letter
  • MAY contain letters, numbers, dashes, underscores

Value Types

  • Strings: "text"
  • Numbers: 123.45
  • Dates: 2024-01-15
  • Accounts: Assets:Cash
  • Currencies: USD
  • Tags: #tag
  • Amounts: 100 USD
  • Booleans: TRUE, FALSE

Automatic Metadata

All directives automatically include:

KeyTypeDescription
filenameStringSource file path
linenoIntegerLine number in source file

Directive Types

DirectivePurpose
openDeclare account existence
closeMark account as inactive
commodityDeclare currency with metadata
transactionFinancial exchange
balanceAssert account balance
padAuto-generate balancing entry
noteAttach comment to account
documentLink external file
priceRecord exchange rate
eventTrack variable over time
queryEmbed SQL query
customUser-defined directive

See directives/ for detailed documentation of each.

Entry Ordering

Directives are automatically sorted chronologically after parsing. Within the same date:

  1. Balance assertions and other non-transaction directives first
  2. Transactions after

File order is preserved for directives with identical date and type.

Includes

Split files across documents:

beancount
include "accounts.beancount"
include "2024/january.beancount"

Path Resolution

  • Relative paths resolve to the including file's directory
  • Absolute paths are used as-is
  • Glob patterns are NOT supported

Option Scoping

  • Options are parsed per-file during include processing
  • Only the top-level file's options apply to the final ledger
  • Options in included files are parsed but do not override

Circular Includes

Circular include dependencies MUST be detected and reported as errors.

Plugins

Load transformation modules:

beancount
plugin "beancount.plugins.implicit_prices"
plugin "my_plugin" "config_string"