Skip to main content

The Complete Guide to Managing Accounts in Beancount and Fava

· 12 min read
Mike Thrift
Mike Thrift
Marketing Manager

Your chart of accounts is the backbone of your Beancount ledger. A well-designed account hierarchy makes every report clearer, every query faster, and every tax season less painful. In this guide, we will walk through everything you need to know about creating, reading, updating, and closing accounts in Beancount and Fava -- from beginner basics to advanced patterns.

The Five Account Types

Beancount uses the standard double-entry bookkeeping model with exactly five root account types:

TypePurposeNormal SignReport
AssetsResources you own (cash, investments, property)Positive (debit)Balance Sheet
LiabilitiesDebts you owe (credit cards, loans, mortgages)Negative (credit)Balance Sheet
EquityOwner's stake, retained earnings, opening balancesNegative (credit)Balance Sheet
IncomeRevenue sources (salary, interest, dividends)Negative (credit)Income Statement
ExpensesCost categories (food, rent, utilities)Positive (debit)Income Statement

The fundamental accounting equation always holds:

Assets + Expenses + Equity + Income + Liabilities = 0

A helpful heuristic: if the amounts are only relevant for a period of time (e.g., "How much did I spend on food this month?"), use Income or Expenses. If they represent an ongoing balance (e.g., "How much is in my checking account?"), use Assets or Liabilities.

Account Naming Conventions

Account names in Beancount are colon-separated hierarchical identifiers. The rules are:

  • Must begin with one of the five root types: Assets, Liabilities, Equity, Income, Expenses
  • Each component starts with a capital letter or number
  • Components may contain letters, numbers, and dashes (no spaces or underscores)
  • At least two components are required (e.g., Expenses:Food, not just Expenses)
  • Colons (:) separate hierarchy levels
; Valid account names
Assets:US:BofA:Checking
Liabilities:CA:RBC:CreditCard
Equity:Retained-Earnings
Income:US:Acme:Salary
Expenses:Food:Groceries
Assets:Crypto:BTC-Holdings

; Invalid account names
assets:checking ; lowercase root type
Assets:my checking ; spaces not allowed
Expenses ; only one component

The recommended naming pattern for balance sheet accounts is:

Type : Country : Institution : Account : SubAccount

For example: Assets:US:Vanguard:401k:VTSAX or Liabilities:US:Chase:Sapphire.

For expense and income accounts, use category-based naming instead:

Expenses:Food:Groceries
Expenses:Housing:Utilities:Electric
Income:US:Employer:Salary

Customizing Root Names

You can rename the five root types for localization or personal preference:

option "name_assets"       "Actifs"
option "name_liabilities" "Passifs"
option "name_equity" "Capital"
option "name_income" "Revenus"
option "name_expenses" "Depenses"

Creating Accounts (Open Directive)

Every account must be declared with an open directive before you can post transactions to it. The full syntax is:

YYYY-MM-DD open Account [ConstraintCurrency,...] ["BookingMethod"]

Basic Open

2014-05-01 open Assets:US:BofA:Checking

With Currency Constraints

Restricting currencies prevents accidentally posting the wrong currency:

2014-05-01 open Assets:US:BofA:Checking       USD
2014-05-01 open Assets:Cash USD,CAD,EUR
2012-03-01 open Assets:US:ETrade:Main:ITOT ITOT

With Booking Methods

For investment accounts, specify how lots are matched when you sell:

2014-02-11 open Assets:US:ETrade:IVV   IVV   "FIFO"
2014-02-11 open Assets:US:Schwab:AAPL AAPL "LIFO"
2014-02-11 open Assets:US:Fidelity GOOG "STRICT"

Available booking methods:

MethodBehavior
"STRICT"Default. Requires exact lot specification; errors on ambiguity
"FIFO"First-In-First-Out -- reduces oldest lots first
"LIFO"Last-In-First-Out -- reduces newest lots first
"AVERAGE"Merges all lots and recalculates average cost
"NONE"No lot matching; any price accepted

With Metadata

2013-03-14 open Assets:US:BTrade:HOOLI
category: "taxable"
institution: "BTrade Corp"
account-number: "XX-1234-5678"

Choosing Open Dates Strategically

  • Use your birth date for universal accounts like Expenses:Groceries (this gives you lifetime sums)
  • Use employment start date for job-related income accounts
  • Use the actual account creation date for institution-specific accounts (bank accounts, credit cards)

Auto-Opening with a Plugin

If you want to skip manual open directives during prototyping:

plugin "beancount.plugins.auto_accounts"

This auto-generates open directives for any account referenced in transactions. However, this reduces typo detection, so it is not recommended for production use.

Listing and Querying Accounts

Using bean-query (BQL)

# List all accounts with balances
bean-query ledger.beancount "SELECT account, units(sum(position)) GROUP BY 1"

# List only expense accounts
bean-query ledger.beancount "SELECT account WHERE account ~ 'Expenses'"

# Account statement with running balance
bean-query ledger.beancount \
"SELECT date, account, position, balance WHERE account ~ 'BofA:Checking'"

# Journal view for a specific account
bean-query ledger.beancount "JOURNAL 'Assets:US:BofA:Checking'"

Using bean-report

# Trial balance (all accounts with final balances)
bean-report ledger.beancount balances

# Balance sheet
bean-report ledger.beancount balsheet

# Income statement
bean-report ledger.beancount income

# Journal for a specific account
bean-report ledger.beancount journal -a Assets:US:BofA:Checking

Using Fava

Fava provides a rich visual interface for exploring accounts:

  • Balance Sheet page: interactive tree of all Assets, Liabilities, and Equity
  • Income Statement page: interactive tree of all Income and Expenses
  • Account page: click any account name to see its Journal, Changes, and Balances tabs
  • Filter bar: use regex patterns to show only matching accounts (e.g., Assets:US)

Updating Accounts (Renaming and Reorganizing)

Beancount has no built-in rename directive, but several approaches exist.

1. Find-and-Replace

Simple search-and-replace works, but be careful -- Assets:Bank would also match Assets:Bank:Cash. Use word-boundary-aware patterns:

sed -i 's/Assets:US:OldBank:Checking/Assets:US:NewBank:Checking/g' *.beancount

2. The rename_accounts Plugin

The beancount_reds_plugins package provides a powerful rename plugin:

plugin "beancount_reds_plugins.rename_accounts.rename_accounts" "{
'Expenses:Taxes' : 'Income:Taxes',
'Assets:House:Capital-Improvements' : 'Expenses:House:Appliances',
}"

This plugin:

  • Uses substring matching (Expenses:Taxes:Federal automatically becomes Income:Taxes:Federal)
  • Supports regex with backreferences
  • Automatically generates Open directives for renamed accounts
  • Does not modify your source files -- only changes the in-memory representation
  • Can be toggled on/off by commenting out the plugin line

3. Close and Reopen Pattern

For real account migrations (e.g., switching banks):

; Old account
2010-01-01 open Assets:US:OldBank:Checking USD

; Close old, open new
2024-06-15 close Assets:US:OldBank:Checking
2024-06-15 open Assets:US:NewBank:Checking USD

; Transfer the remaining balance
2024-06-15 * "Transfer to new bank"
Assets:US:OldBank:Checking -5000.00 USD
Assets:US:NewBank:Checking 5000.00 USD

Closing Accounts

The close directive marks an account as no longer active:

2016-11-28 close Liabilities:CreditCard:CapitalOne

What Closing Does

  • Raises an error if any postings occur after the close date
  • Filters the account from reports outside its active period
  • Tells Fava to hide the account from tree views (configurable)

When to Close Accounts

  • When you close a real-world bank account or credit card
  • When you switch employers
  • When you consolidate or reorganize your chart of accounts
  • When you sell a property or close an investment position

Always Assert Zero Balance Before Closing

Beancount does not automatically verify a zero balance on close. Add a manual assertion:

2023-12-31 balance Assets:US:OldBank:Savings  0.00 USD
2023-12-31 close Assets:US:OldBank:Savings

Organizing Your Chart of Accounts

Start Simple, Refine Over Time

You don't need the perfect chart of accounts on day one. Start with broad categories and split them as your reporting needs grow. The Beancount author reports having 250+ expense accounts, all created organically over time.

Common Organization Patterns

Pattern 1: By Institution (for balance sheet accounts)

Assets:US:BofA:Checking
Assets:US:BofA:Savings
Assets:US:Vanguard:401k:VTSAX
Assets:US:Vanguard:401k:VBTLX
Liabilities:US:Amex:Platinum
Liabilities:US:Chase:Sapphire

Pattern 2: By Category (for income and expense accounts)

Expenses:Food:Groceries
Expenses:Food:Restaurant
Expenses:Food:Coffee
Expenses:Housing:Rent
Expenses:Housing:Insurance
Expenses:Housing:Utilities:Electric
Expenses:Housing:Utilities:Water
Expenses:Transport:Subway
Expenses:Transport:Gas
Expenses:Health:Medical
Expenses:Health:Dental

Pattern 3: By Geography (for multi-country finances)

Assets:US:BofA:Checking
Assets:CA:RBC:Checking
Assets:UK:HSBC:Current
Income:US:Acme:Salary
Income:CA:Freelance:Consulting

Pattern 4: By Property or Project (for real estate or business)

Assets:US:Loft4530:Property
Income:US:Loft4530:Rental
Expenses:Loft4530:Electricity
Expenses:Loft4530:Insurance
Expenses:Loft4530:Maintenance

Pattern 5: Related Account Mirroring (same institution component)

Assets:US:ETrade:Cash
Assets:US:ETrade:AAPL
Income:US:ETrade:Dividends
Income:US:ETrade:PnL
Expenses:US:ETrade:Commissions

How Deep Should Hierarchies Go?

  • 2-3 levels is common for expense categories (Expenses:Food:Restaurant)
  • 3-4 levels for structured balance sheet items (Assets:US:Vanguard:401k:VTSAX)
  • Avoid going deeper than 5 levels unless you have a strong reporting reason
  • Deep hierarchies work well when Fava collapses them in tree views

A Real-World Example

Here is a practical chart of accounts for personal finance:

; ── Assets ──
Assets:US:BofA:Checking USD
Assets:US:BofA:Savings USD
Assets:US:Vanguard:401k:VTSAX VTSAX
Assets:US:Vanguard:Roth:VTSAX VTSAX
Assets:US:ETrade:Cash USD
Assets:US:ETrade:AAPL AAPL
Assets:Cash:Wallet USD

; ── Liabilities ──
Liabilities:US:Amex:Platinum USD
Liabilities:US:Chase:Freedom USD
Liabilities:US:BofA:Mortgage USD

; ── Income ──
Income:US:Employer:Salary
Income:US:Employer:Bonus
Income:US:Employer:Match401k
Income:US:ETrade:Dividends
Income:US:BofA:Interest

; ── Expenses ──
Expenses:Food:Groceries
Expenses:Food:Restaurant
Expenses:Food:Coffee
Expenses:Housing:Rent
Expenses:Housing:Insurance
Expenses:Housing:Utilities:Electric
Expenses:Housing:Utilities:Water
Expenses:Transport:Subway
Expenses:Transport:Taxi
Expenses:Transport:Gas
Expenses:Health:Medical
Expenses:Health:Dental
Expenses:Health:Pharmacy
Expenses:Shopping:Clothing
Expenses:Shopping:Electronics
Expenses:Entertainment:Streaming
Expenses:Entertainment:Books
Expenses:Travel:Flights
Expenses:Travel:Hotels
Expenses:Taxes:Federal
Expenses:Taxes:State
Expenses:Taxes:SocialSecurity
Expenses:Taxes:Medicare

; ── Equity ──
Equity:Opening-Balances
Equity:Retained-Earnings

Fava-Specific Features

Up-to-Date Indicators

One of Fava's best features for account management. Add this metadata to any account:

2014-05-01 open Assets:US:BofA:Checking  USD
fava-uptodate-indication: TRUE

Fava then shows colored dots next to the account:

  • Green dot: last entry is a passing balance assertion (account is reconciled)
  • Red dot: last entry is a failing balance assertion (needs attention)
  • Yellow dot: last entry exists but is not a balance assertion (not yet reconciled)
  • Grey dot: no activity within the lookback period

Configure the grey threshold:

2016-06-14 custom "fava-option" "uptodate-indicator-grey-lookback-days" "60"

Tree View Controls

Control how Fava displays accounts:

; Show closed accounts in the tree
2016-06-14 custom "fava-option" "show-closed-accounts" "true"

; Show accounts with zero transactions
2016-06-14 custom "fava-option" "show-accounts-with-zero-transactions" "true"

; Show accounts with zero balance
2016-06-14 custom "fava-option" "show-accounts-with-zero-balance" "true"

Collapse Patterns

Collapse deeply nested accounts by default:

; Collapse all accounts 3+ levels deep
2016-06-14 custom "fava-option" "collapse-pattern" ".*:.*:.*"

; Collapse specific subtrees
2016-06-14 custom "fava-option" "collapse-pattern" "Assets:US:Vanguard:.*"

Include Children in Account Journal

When viewing an account's journal in Fava, include postings from child accounts:

2016-06-14 custom "fava-option" "account-journal-include-children" "true"

Invert Signs for Readability

By default, income and liabilities show as negative numbers (their natural sign). To display them as positive:

2016-06-14 custom "fava-option" "invert-income-liabilities-equity" "true"

Document Management

Fava integrates document handling with your account hierarchy. Set a documents root:

option "documents" "/path/to/documents"

Then organize files by account path:

/path/to/documents/
Assets/
US/
BofA/
Checking/
2024-01-15.january-statement.pdf
2024-02-15.february-statement.pdf
Liabilities/
US/
Amex/
Platinum/
2024-03-15.march-bill.pdf

Files starting with YYYY-MM-DD are automatically discovered by Fava and appear in the account's journal view.

Common Mistakes and How to Avoid Them

1. Typos in Account Names

A single typo like Expenses:Grocries creates a completely new, unintended account.

Fix: Do not use auto_accounts plugin in production. Require explicit open directives. Beancount will immediately error on any undeclared account:

ERROR: Invalid reference to unknown account 'Expenses:Grocries'

2. Forgetting Currency Constraints

Without currency constraints, you can accidentally post EUR to a USD-only account.

Fix: Always specify currencies on open directives:

2014-01-01 open Assets:US:BofA:Checking  USD

3. Not Asserting Balances Regularly

Without regular balance assertions, errors can go undetected for months.

Fix: Add monthly balance assertions for every active account:

2024-01-01 balance Assets:US:BofA:Checking   5,432.10 USD
2024-02-01 balance Assets:US:BofA:Checking 4,890.55 USD
2024-03-01 balance Assets:US:BofA:Checking 6,123.00 USD

4. Inconsistent Naming Conventions

Mixing patterns (e.g., Expenses:Food vs Expenses:US:Food) makes queries and reports confusing.

Fix: Pick a convention and stick with it. Use country prefixes for balance sheet accounts, category-based naming for income and expenses.

5. Closing Without Zero Balance Assertion

The close directive does not verify balance. You could close an account that still has money in it.

Fix: Always pair close with a balance assertion:

2023-12-31 balance Assets:US:OldBank:Savings  0.00 USD
2023-12-31 close Assets:US:OldBank:Savings

Advanced Patterns

Multi-Currency Tips

Declare your operating currencies for dedicated report columns:

option "operating_currency" "USD"
option "operating_currency" "EUR"

For multi-currency accounts, list all allowed currencies:

2014-01-01 open Assets:Cash  USD,CAD,EUR

Balance assertions with multiple currencies must be done one currency at a time:

2024-01-01 balance Assets:Cash     562.00 USD
2024-01-01 balance Assets:Cash 210.00 CAD
2024-01-01 balance Assets:Cash 60.00 EUR

Pad and Balance for Initial Setup

Use the pad directive to establish opening balances without manually calculating amounts:

2000-05-28 open Assets:US:BofA:Checking  USD
2000-05-28 pad Assets:US:BofA:Checking Equity:Opening-Balances
2024-07-01 balance Assets:US:BofA:Checking 12,345.67 USD

Beancount automatically synthesizes the adjustment transaction. One important caveat: balance assertions check the balance at the beginning of the specified date. So a pad on January 2 needs a balance assertion on January 3 or later.

Account Metadata for Categorization

Use metadata on open directives for custom reporting:

2014-01-01 open Assets:US:BofA:Checking  USD
category: "liquid"
tax-status: "taxable"

2014-01-01 open Assets:US:Vanguard:401k USD
category: "retirement"
tax-status: "tax-deferred"

Query metadata with BQL:

SELECT account, META("category") WHERE META("tax-status") = "taxable"

Notes for Account History

Attach dated notes to any account's journal:

2024-03-20 note Assets:US:BofA:Checking "Called about disputed charge, ref #12345"
2024-06-01 note Liabilities:US:Chase:Sapphire "Annual fee waived after calling retention"

These notes appear in the account's journal in Fava, providing an audit trail.

Tracking Accounts and Earmarking

Beancount does not have Ledger's virtual postings, but you can use subaccounts for earmarking:

; Track emergency fund within checking
Assets:US:BofA:Checking:EmergencyFund USD
Assets:US:BofA:Checking:Operating USD

; Track reimbursements
Assets:Receivables:Employer:Travel USD
Assets:Receivables:Friend:SharedDinner USD

Tax-Friendly Expense Categories

Structure expense accounts to make tax preparation easier:

Expenses:Health:Medical:Deductible
Expenses:Charity:Deductible
Expenses:Business:Office
Expenses:Business:Equipment
Expenses:Education:Professional

Quick Reference Cheat Sheet

TaskSyntax
Open an account2024-01-01 open Assets:US:BofA:Checking USD
Close an account2024-12-31 close Assets:US:OldBank:Savings
Assert balance2024-01-01 balance Assets:US:BofA:Checking 5,432.10 USD
Pad to balance2024-01-01 pad Assets:Cash Equity:Opening-Balances
Add note2024-01-15 note Assets:US:BofA:Checking "Monthly reconciliation done"
Attach document2024-01-15 document Assets:US:BofA:Checking "/path/to/statement.pdf"
Add metadataIndented key-value on the line after open
Auto-open (dev)plugin "beancount.plugins.auto_accounts"
Restrict currency2024-01-01 open Assets:Cash USD,EUR
Set booking method2024-01-01 open Assets:US:ETrade:AAPL AAPL "FIFO"

Summary

Managing accounts well is the foundation of effective Beancount bookkeeping. Here are the key takeaways:

  1. Always use explicit open directives -- they catch typos and enforce discipline
  2. Add currency constraints to prevent cross-currency errors
  3. Use a consistent naming convention -- by institution for balance sheet, by category for income/expenses
  4. Start simple and refine -- split accounts as your reporting needs grow
  5. Assert balances regularly -- monthly reconciliation catches errors early
  6. Close accounts properly -- with a zero-balance assertion
  7. Leverage Fava's features -- up-to-date indicators, collapse patterns, and document integration
  8. Use metadata for custom categorization and reporting

Happy accounting!

References: