Damien Gonot
Home Blog Notes About


Homepage / Notes / Computer Science / Tools / Beancount

Double-Entry Accounting from Text Files.



directives == entries

A beancount file is a plain text file full of entries. Basic syntax: YYYY-MM-DD <type> ... Order of entries is not important.

Date format

Either YYYY-MM-DD (2022-02-14) or YYYY/MM/DD (2022/02/14).


2014-02-03 open Assets:US:BofA:Checking

2014-04-10 note Assets:US:BofA:Checking "Called to confirm wire transfer."

2014-05-02 balance Assets:US:BofA:Checking   154.20 USD


Commodities are being accumulated in accounts. An account name is a colon-separated list of capitalized words which begin with a letter, and whose first word must be one of five account types:

Example of account names:


Currencies / Commodities

The syntax for a currency is a word all in capital letters, like these:


Currency signs like € or $ should never be used, only the currency code (like USD or CAD or EUR).


Whenever we need to insert some free text as part of an entry, it should be surrounded by double-quotes. This applies to the payee and narration fields, mainly; basically anything that’s not a date, a number, a currency, an account name.


Comments can be insert with a ; before it:

; I paid and left the taxi, forgot to take change, it was cold.
2015-01-01 * "Taxi home from concert in Brooklyn"
  Assets:Cash      -20 USD  ; inline comment

Any line that does not begin as a valid Beancount syntax directive (e.g. with a date) is silently ignored. This way you can insert markup to organize your file for various outline modes, such as org-mode in Emacs.




All accounts need to be declared “open” in order to accept amounts posted to them. You do this by writing a directive that looks like this:

2014-05-01 open Liabilities:CreditCard:CapitalOne     USD

The general format of the Open directive is: YYYY-MM-DD open Account [ConstraintCurrency,...] ["BookingMethod"]



; Closing credit card after fraud was detected.
2016-11-28 close Liabilities:CreditCard:CapitalOne

General format: YYYY-MM-DD close Account



1867-07-01 commodity CAD

General format: YYYY-MM-DD commodity Currency

Not mandatory to disclose a commodity before using it (unlike accounts). It's useful to add metadata about a commodity:

1867-07-01 commodity CAD
  name: "Canadian Dollar"
  asset-class: "cash"

2012-01-01 commodity HOOL
  name: "Hooli Corporation Class C Shares"
  asset-class: "stock"

And get stats by asset-class for example.



2014-05-05 txn "Cafe Mogador" "Lamb tagine with wine"
  Liabilities:CreditCard:CapitalOne         -37.45 USD

txn can be replaced by a flag. By convention, those flags are commonly used:

General format: YYYY-MM-DD [txn|Flag] [[Payee] Narration] [Flag] Account Amount [{Cost}] [@ Price] [Flag] Account Amount [{Cost}] [@ Price] ...


The lines that follow the first line are postings. There can be as many postings as we want.

Example of a salary entry:

2014-03-19 * "Acme Corp" "Bi-monthly salary payment"
  Assets:MyBank:Checking             3062.68 USD     ; Direct deposit
  Income:AcmeCorp:Salary            -4615.38 USD     ; Gross salary
  Expenses:Taxes:TY2014:Federal       920.53 USD     ; Federal taxes
  Expenses:Taxes:TY2014:SocSec        286.15 USD     ; Social security
  Expenses:Taxes:TY2014:Medicare       66.92 USD     ; Medicare
  Expenses:Taxes:TY2014:StateNY       277.90 USD     ; New York taxes
  Expenses:Taxes:TY2014:SDI             1.20 USD     ; Disability insurance

Arithmetic expressions can be used (( ) * / - +):

2014-10-05 * "Costco" "Shopping for birthday"
  Liabilities:CreditCard:CapitalOne         -45.00          USD
  Assets:AccountsReceivable:John            ((40.00/3) + 5) USD
  Assets:AccountsReceivable:Michael         40.00/3         USD

The sum of postings' balance amounts must be zero.

Payee and Narration

A transaction may have an optional “payee” and/or a “narration.” In the first example above, the payee is “Cafe Mogador” and the narration is “Lamb tagine with wine”.

If you place a single string on a transaction line, it becomes its narration: 2014-05-05 * "Lamb tagine with wine"

If you want to set just a payee, put an empty narration string: 2014-05-05 * "Cafe Mogador" ""

Costs and Prices

Basic example:

2012-11-03 * "Transfer to pay credit card"
  Assets:MyBank:Checking            -400.00 USD
  Liabilities:CreditCard             400.00 USD

Example with USD.CAD conversion with specific conversion rate:

2012-11-03 * "Transfer to account in Canada"
  Assets:MyBank:Checking            -400.00 USD @ 1.09 CAD
  Assets:FR:SocGen:Checking          436.01 CAD

Example with a total cost specified with @@:

2012-11-03 * "Transfer to account in Canada"
  Assets:MyBank:Checking            -400.00 USD @@ 436.01 CAD
  Assets:FR:SocGen:Checking          436.01 CAD

When something needs to be held at a specific cost (like a stock for investing to calculate cost basis, capital gains and taxes), it can be specified inside curly brackets:

2014-02-11 * "Bought shares of S&P 500"
  Assets:ETrade:IVV                10 IVV {183.07 USD}
  Assets:ETrade:Cash         -1830.70 USD
2014-07-11 * "Sold shares of S&P 500"
  Assets:ETrade:IVV               -10 IVV {183.07 USD} @ 197.90 USD
  Assets:ETrade:Cash          1979.90 USD

Tags can be added to transactions:

2014-04-23 * "Flight to Berlin" #berlin-trip-2014
  Expenses:Flights              -1230.27 USD

Multiple tags work too:

2014-04-23 * "Flight to Berlin" #berlin-trip-2014 #germany
  Expenses:Flights              -1230.27 USD

Using pushtag / poptag:

pushtag #berlin-trip-2014

2014-04-23 * "Flight to Berlin"
  Expenses:Flights              -1230.27 USD

poptag #berlin-trip-2014

This way, you can also push multiple tags onto a long, consecutive set of transactions without having to type them all in.

Transactions can be linked together:

2014-02-05 * "Invoice for January" ^invoice-pepe-studios-jan14
  Income:Clients:PepeStudios           -8450.00 USD

2014-02-20 * "Check deposit - payment from Pepe" ^invoice-pepe-studios-jan14
  Assets:BofA:Checking                  8450.00 USD

Balance Assertions

A balance assertion is a way for you to input your statement balance into the flow of transactions. It tells Beancount to verify that the number of units of a particular commodity in some account should equal some expected value at some point in time. For instance, this:

2014-12-26 balance Liabilities:US:CreditCard   -3492.02 USD

says “Check that the number of USD units in account Liabilities:US:CreditCard on the morning of December 26th, 2014 is -3492.02 USD.”

General format: YYYY-MM-DD balance Account Amount


A padding directive automatically inserts a transaction that will make the subsequent balance assertion succeed, if it is needed. It inserts the difference needed to fulfill that balance assertion.


2014-06-01 pad Assets:BofA:Checking Equity:Opening-Balances

General format: YYYY-MM-DD pad Account AccountPad

Realistic example:

; Account was opened way back in the past.
2002-01-17 open Assets:US:BofA:Checking

2002-01-17 pad Assets:US:BofA:Checking Equity:Opening-Balances

2014-07-09 balance Assets:US:BofA:Checking  987.34 USD


Notes can be used to insert a dated comment to a specific account:

2013-11-03 note Liabilities:CreditCard "Called about fraudulent card."

General format: YYYY-MM-DD note Account Description


A Document directive can be used to attach an external file to the journal of an account:

2013-11-03 document Liabilities:CreditCard "/home/joe/stmts/apr-2014.pdf"

General format: YYYY-MM-DD document Account PathToDocument


Price can be used to indicate the price of a commodity (to calculate unrealized capital gains for example):

2014-07-09 price HOOL  579.18 USD

General format: YYYY-MM-DD price Commodity Price


Events can be used to track the value of something over time, like location:

2014-07-09 event "location" "Paris, France"

General format: YYYY-MM-DD event Name Value

Ideas of what to track:


bean-check {file} to check the validity of a file.

bean-web {file} to view the web interface.

bean-report {file} {report-name} to report on {report-name}, like balances.

bean-query {file} to run a query against file.

bean-format {file} to re-format the file.



Accounting Cookbook


Query Language





BeanHub is a modern accounting book service based on the most popular open source version control system Git and text-based double entry accounting book software Beancount.