Introduction

Ledger CLI is an open source command line accounting tool used for calculating reports from a ledger (a file containing a list of transactions for different accounts). With Ledger CLI you are able to view a register (a list of transactions), balance of accounts, budget report, etc. In this post, I'll be going over defining a basic ledger and calculating balance and register reports.

Prerequisites

Essential

Optional

  • VS Code
    • I know: a text editor for a command line tool? For me this significantly improved the editing experience.
  • ledger - VS Code Extension
    • For adding syntax highlighting of ledger files.

Getting Started

Let's start by defining a ledger file. For example, we can save an empty text file as sample.ledger. Once we have the file saved, we can now gain the benefit of syntax highlighting if we're using a tool that supports ledger syntax highlighting.

A valid transaction consists of 7 elements:

  1. Date (with a YYYY/mm/dd format)
  2. Vendor name on the same line as the date separated by a space
  3. From Account name on a new line, indented with 4 spaces
  4. From Account amount on the same line as the From Account name, separated by at least 2 spaces
  5. To Account name on a new line, indented with 4 spaces
  6. To Account amount on the same line as the To Account name, separated by at least 2 spaces
  7. From Account and To Account amounts must add to 0.

Here is an example of a valid transaction meeting these requirements:

2019/12/14 Acme, Inc
    My Bank Account  -12.34
    My Expense Account  12.34

I'm particular about having the amounts aligned, which can be achieved by adding extra spaces:

2019/12/14 Acme, Inc
    My Bank Account    -12.34
    My Expense Account  12.34

Ledger's system relies on double entry accounting, meaning transactions always occur between two accounts. For the sake of a concrete example, let's add a few more transactions:

2019/12/01 Opening Balance
    Equity                   -3300.00
    My Bank Account           3300.00
2019/12/05 Mars Expeditions
    My Bank Account          -1024.42
    My Expense Account        1024.42
2019/12/14 Acme, Inc
    My Bank Account            -12.34
    My Expense Account          12.34
2019/12/16 Doe & Doe LLP
    My Bank Account           -900.00
    My Expense Account         900.00
2019/12/17 Fresh Foods Galore
    My Bank Account            -58.65
    My Expense Account          58.65
2019/12/24 Santa Claus
    My Bank Account           -102.34
    My Expense Account         102.34

Notice that we're dealing with three accounts: Equity, My Bank Account and My Expense Account. I hope that the My Bank Account account is self-explanatory, in essence symbolizing a bank account. My Expense Account is an expense account where all spenditures are tracked. Finally, because all transactions must occur between two accounts, we create an equity account to track any balance that was already in the bank account in this case.

One more thing: To run the ledger CLI tool, we'll be specifying the file we are working on with the -f flag (ledger -f sample.ledger ...).

Register Reports

Viewing a register, or a listing of transactions, can be as simple as running ledger -f sample.ledger register or ledger -f sample.ledger reg:

$ ledger -f sample.ledger reg
19-Dec-01 Opening Balance    Equity                     -3300       -3300
                             My Bank Account             3300           0
19-Dec-05 Mars Expeditions   My Bank Account         -1024.42    -1024.42
                             My Expense Account       1024.42           0
19-Dec-14 Acme, Inc          My Bank Account           -12.34      -12.34
                             My Expense Account         12.34           0
19-Dec-16 Doe & Doe LLP      My Bank Account             -900        -900
                             My Expense Account           900           0
19-Dec-17 Fresh Foods Galore My Bank Account           -58.65      -58.65
                             My Expense Account         58.65           0
19-Dec-24 Santa Claus        My Bank Account          -102.34     -102.34
                             My Expense Account        102.34           0

We can also view a register for a specific account by specifying the account name after the register command:

$ ledger -f sample.ledger reg "My Bank Account"
19-Dec-01 Opening Balance    My Bank Account             3300        3300
19-Dec-05 Mars Expeditions   My Bank Account         -1024.42     2275.58
19-Dec-14 Acme, Inc          My Bank Account           -12.34     2263.24
19-Dec-16 Doe & Doe LLP      My Bank Account             -900     1363.24
19-Dec-17 Fresh Foods Galore My Bank Account           -58.65     1304.59
19-Dec-24 Santa Claus        My Bank Account          -102.34     1202.25

This report is similar to a bank statement, where you see the amount of the transaction and remaining balance for the account.

Balance Reports

Similar to the register report, the balance report can be executed with the balance command: ledger -f sample.ledger balance or ledger -f sample.ledger bal.

$ ledger -f sample.ledger bal
               -3300  Equity
             1202.25  My Bank Account
             2097.75  My Expense Account
--------------------
                   0

Notice that 0? That means that the sum of all accounts equal to zero. In other words, the same amount that was taken from one account went into another account (or several in the case of split transactions) evenly, and thus there is balance in the world. If a transaction does not balance, Ledger CLI would not calculate any report; instead, it would specify with an error message the offending transaction and the amount that was not accounted for.

Akin to the register report, you can specify the account name to the balance command to get the balance of a specific account:

$ ledger -f sample.ledger bal "My Bank Account"
             1202.25  My Bank Account

Specifying Time Periods (Months)

So far, the reports we ran are on every transaction in the sample.ledger file. Realistically, we would be interested in a specific period of time. Unfortunately, the Ledger CLI documentation is lacking so I do not know the full extent to how we can specify time periods; however, I will show how you can query a specific month (which is to the extent that I use this feature for).

The period is specified with the -p flag after a report command (i.e. register and balance from what we've discussed) followed by a period query.

For instance, since I am writing this in December and all of the transactions are limited to this month, the following queries will all display the same report:

  • ledger -f sample.ledger reg -p "this month"
  • ledger -f sample.ledger reg -p "dec"
  • ledger -f sample.ledger reg -p "in dec"
  • ledger -f sample.ledger reg -p "2019/12"
  • ledger -f sample.ledger reg -p "in 2019/12"

Other queries include "last month", and "###" (where ### are the first three characters of the month).

The documentation for ledger can be found here (section 14.3.5 discusses pre-commands including period): https://www.ledger-cli.org/3.0/doc/ledger3.html

Simplifying Entries

When entering transactions it can be a bit mundane to have to write the amounts for each transaction twice. Fortuantely, Ledger CLI will assume the equal, and opposite, amount will be applied to the other account listed in the transaction.

This means that our sample.ledger can also be defined as follows:

2019/12/01 Opening Balance
    Equity                   
    My Bank Account           3300.00
2019/12/05 Mars Expeditions
    My Bank Account          
    My Expense Account        1024.42
2019/12/14 Acme, Inc
    My Bank Account            
    My Expense Account          12.34
2019/12/16 Doe & Doe LLP
    My Bank Account           
    My Expense Account         900.00
2019/12/17 Fresh Foods Galore
    My Bank Account            
    My Expense Account          58.65
2019/12/24 Santa Claus
    My Bank Account           
    My Expense Account         102.34

Even better is the ability to add transactions into what Ledger CLI calls "buckets". In our case, all of the transactions pertain to the My Bank Account account. Rather than have to input this account for each transaction, we can specify a bucket as follows:

bucket My Bank Account
2019/12/01 Opening Balance
    Equity                   -3300.00
2019/12/05 Mars Expeditions
    My Expense Account        1024.42
2019/12/14 Acme, Inc
    My Expense Account          12.34
2019/12/16 Doe & Doe LLP
    My Expense Account         900.00
2019/12/17 Fresh Foods Galore
    My Expense Account          58.65
2019/12/24 Santa Claus
    My Expense Account         102.34

Notice that when the amount is negative it means that amount is being taken away from the listed amount and being added to the bucket account. When the account is positive, it is being added to the listed account from the bucket account.

Conclusion

In this post, I went over the very basics of getting started with Ledger CLI. I went over how to create a file, how to write transactions, and how to view register and balance reports. This post is truly a surface introduction to Ledger CLI as it can accomplish a lot more. I personally use it because I needed an accounting solution that supported multiple currencies. Perhaps in a future post I will discuss dealing with multiple currencies, structuring accounts, and budgeting. In the meantime, if you want to learn more about Ledger CLI, I highly recommend checking out these resources:

Many thanks!