If you are used to paying everything by card you will surely have less difficulty in finding the answer to the title question. By now almost all banks allow you to automatically categorize your expenses and have a monthly statement. But do they allow you to customize the process? Can you change the category of an expense? Can you add new categories? Can you have categories and subcategories? If you use multiple banks how do you merge the data that comes from the various apps? The goal of this post is to answer all of these questions through the use of Ledger.

What is Ledger

Ledger is a double-entry accounting tool designed to be used through the command line. Lots of big words, but I assure you it’s all simpler than it sounds.

Accounting tool

Surely you already understand what accounting is, but why keep it, you’re not a business. True, you’re not a company, but managing your money is getting more complicated every day. The main reason for this increase in complexity is the number of accounts we use; we have the current account where we receive our salary, then there is a deposit account, we have an account we use for travel, Satispay to exchange money with friends. And that’s not all, many also have an investment account, others have wallets for cryptocurrencies, some have money on their PayPal account, some on Amazon and so on. We use more services than before and every service has its reason, but keeping track of our financial situation is more complicated, so we have to approach the problem with the right tools.

Double-entry bookkeeping

Double-entry bookkeeping is an accounting method first used by Florentine merchants in the 14th century. The idea behind the method is to always record a transaction on at least two accounts. This means that if an account increases by 10€, another account must necessarily decrease by 10€, because it is not possible to create money from nothing. At first it may seem a bit counter intuitive, but if it has been used for six hundred years there will be a reason.

used through the command line

I’m not going to lie to you, this post makes extensive use of the terminal and you probably don’t like the terminal. Before you close the page let me just tell you that Ledger started a movement called Plain Text Accounting and there are many software that follow to this movement. Some of these also come with a GUI so you can apply many of the concepts discussed in this post to other tools as well.

Plain Text Accounting

The idea behind plain text accounting is to keep track of accounting through the use of plain text files. What is a plain text file? Simple it is a text file, nothing more, nothing less. No, not like Word, where there are fonts, sizes, bold, color, etc. A plain text file contains only text, nothing else.

Does that sound too limited? I assure you it is not. With plain text files you can do so much with them, like in this case keeping track of accounting. They also have two great advantages:

  • A plain text file can be opened even in a hundred years.
  • A plain text file can also be understood by humans.

Within a Ledger file, often called a journal, there are mostly transactions that alter the balance of various accounts. A transaction consists of a header line, which contains the date and payee/cause of payment, and n lines each representing a change in an account. Here is an example of a transaction in Ledger.

2021-01-17 Airbnb
    expenses:travel:accommodation         550 EUR
    assets:current:revolut               -550 EUR

How does it read? On January 17th, I made a payment to Airbnb. The rental cost was categorized as a travel expense, specifically falling under the accommodation subcategory. The 550€ payment was made through my Revolut account.

Simple no? Maybe too simple, let’s try something more complex. To prepare for the trip, the next day, I bought on Amazon a travel pillow that cost 10€. Also I saw that there is a new kindle model on offer (100€), so I bought that too. Again I want to pay with my Revolut card, but I still have 25€ on my Amazon account, so the transaction on ledger will look like:

2021-01-18 Amazon
    expenses:travel:accessories            10 EUR  ; cuscino da viaggio
    expenses:entertainment:books          100 EUR  ; kindle
    assets:current:amazon                 -25 EUR
    assets:current:revolut

Ok here there seems to be something strange. First of all, you didn’t specify how much money was withdrawn from the Revolut account, but don’t worry this is not an error. Since Ledger uses double-entry bookkeeping, the sum of all changes in the various accounts must always be zero. In our case we have 10 + 100 - 25 so to bring it to zero we need -85. So Ledger is smart enough to understand that 85€ has been taken from Revolut1.

The other peculiarity of the previous transaction is the presence of the symbol ;. A semicolon, in Ledger, is used for notes. If the note is put on a line with a movement (as in the example) then the note refers to the single movement. Whereas when the note is on a line of its own then this refers to the entire transaction.

Account Structure

After looking at the previous examples, you should already understand the way Ledger manages accounts, that is, in a hierarchical way. Each category (e.g. expenses) can have multiple subcategories (e.g. travel) which in turn can have other subcategories (e.g. accessories) and so on. Each level is separated by the colon (:) and there can be infinite sub-levels.

The name of the accounts is totally free and is decided by the user. Although I haven’t used them, the name of an account can also contain spaces and capital letters.

Ledger is democratic with accounts and treats them all the same. This means that the accounts with our expenses in Ledger’s eyes are totally equal to the ones where our belongings are. In fact, I’ll tell you more, Ledger doesn’t even know that the “expenses” account contains our expenses. We are the ones who give semantics to the various accounts, that is why it is important to use meaningful names.

I repeat, you are totally free to use any name you want for your accounts, but I suggest you introduce some rules to manage everything better. In particular, I suggest you to limit to five the number of main accounts and to use the ones listed below.

  • assets: these are the accounts where you store your money.
  • expenses: accounts where your money goes.
  • income: are the accounts where your money comes from.
  • liabilities: these are the accounts where the money you owe to others resides.
  • equity: this is a bit complicated. From a theoretical point of view, these accounts show the real value of your assets. From a practical point of view, these accounts are used as jolly accounts. However, don’t worry, this account is used very little.

Record your income

Before we can see how Ledger works, I need to explain how to record your income. First we need to take a snapshot of the initial situation. So if we start keeping track of our accounts as of January 1, 2022 we need to tell Ledger what our financial situation is.

Assuming we have the following financial situation on January 1:

  • Revolut account: €243
  • Illimity current account: 729€
  • Amazon account balance: 25€
  • cash: 37€

we will have the following Ledger transaction:

2022-01-01 Opening Balances
    assets:current:revolut          243 EUR
    assets:current:amazon            25 EUR
    assets:current:illimity         729 EUR
    assets:current:cash              37 EUR

To verify that the file is correct and understandable to Ledger we use the command stats that in addition to interpreting the file with the transactions provides us with various statistics. In my case the complete command is ledger --file ledger.journal stats because I have inserted the transaction in the file ledger.journal.

An error occurred? Don’t worry, it’s not your fault. The truth is that I am an asshole and I made you make a mistake on purpose. Looking at the transaction again, you can see that we violated Ledger’s first rule: The sum of all transactions must be zero. Ledger wants to know where this 1034€ comes from. It’s money that is already in our account, so it’s not correct to put it as income, so the best solution is to use the jolly category and then the equity account. Therefore our opening transaction will be:

2022-01-01 Opening Balances
    assets:current:revolut          243 EUR
    assets:current:amazon            25 EUR
    assets:current:illimity         729 EUR
    assets:current:cash              37 EUR
    equity:open                   -1034 EUR

Now if you try to run again the command ledger --file ledger.journal stats you should not see any errors, but some statistics on your journal.

Ok the fifteenth of the month has arrived and we receive our paycheck, how to mark this income? Just enter a new transaction in the journal where we add 1500€ (our salary) to the Illimity account (the account where we get our salary). Where do we get this 1500€ from? Simple from our employer’s account.

2022-01-15 Employer
    assets:current:illimity         1500 EUR
    income:salary                  -1500 EUR

Balance & Register

Now that it should be clear how to register movements between our accounts it’s time to see how Ledger works and in particular the two most used commands; balance and register. I recommend that you run the commands I’ll show you step by step, and to get the same results as me, you need to use this journal.

Balance

The command balance allows you to view the current balance of all accounts. Running from terminal the command ledger --file ledger.journal balance gives the following output:

            1607 EUR  assets:current
              37 EUR    cash
            1509 EUR    illimity
              61 EUR    revolut
           -1034 EUR  equity:open
             927 EUR  expenses
             100 EUR    entertainment:books
              47 EUR    food:restaurants
             220 EUR    groceries
             560 EUR    travel
              10 EUR      accessories
             550 EUR      accommodation
           -1500 EUR  income:salary
--------------------
                   0

From this output you can see the hierarchical organization of accounts in Ledger. If you have problems with this representation, you can use the flag --flat.

In other cases you don’t want to know the balance of all accounts, so Ledger allows you to select only the accounts which match a regular expression. In case you are interested in knowing the position of all the money you have and display the various accounts in a flat way you can use the command ledger --file ledger.journal balance assets --flat which generates the following output:

              37 EUR  assets:current:cash
            1509 EUR  assets:current:illimity
              61 EUR  assets:current:revolut
--------------------
            1607 EUR

Register

Another fundamental command of Ledger is register whose task is to simulate a cash register. This command allows you to see the effect on accounts of every single movement. Again, the report can be reduced to only certain accounts.

To see all transactions in groceries we can use the command ledger --file ledger.journal register groceries which has the following output:

2022-01-10 Esselunga          expenses:groceries          137 EUR       137 EUR
2022-01-23 Esselunga          expenses:groceries           83 EUR       220 EUR

In addition to the date and account of the transaction in the output there are two columns, the first shows the amount of the transaction, while the second keeps track of the sum of all transactions.

How much did I spend this month?

After this long introduction we can finally answer the title question. The best tool, provided by Ledger, to know our expenses is the register command. In particular, if we are interested only in the expenses of the current month, we must also use the flag --period which allows us to select only a specific time interval. So to know all the expenses of this month we use the command: ledger --file ledger.journal register expenses --period 'this month'2.

2022-01-10 Esselunga            expenses:groceries                      137 EUR       137 EUR
2022-01-17 Airbnb               expenses:travel:accommodation           550 EUR       687 EUR
2022-01-18 Amazon               expenses:travel:accessories              10 EUR       697 EUR
2022-01-18 Amazon               expenses:entertainment:books            100 EUR       797 EUR
2022-01-23 Esselunga            expenses:groceries                       83 EUR       880 EUR
2022-01-29 Pub                  expenses:food:restaurants                47 EUR       927 EUR

In the output we have the list of all expenses for the month. In the first column there is the date of the expense and the commercial establishment where it was made. In the second column is reported the category and in the third the amount. The last column shows the current sum, so to know the total expenses for January we must look at the last column of the last row. So in this example in January we have spent 927€.

Not interested in all expenses, but only in travel expenses? Nothing simpler, just use the following command: ledger --file ledger.journal register expenses:travel --period 'this month'

2022-01-17 Airbnb               expenses:travel:accommodation           550 EUR       550 EUR
2022-01-18 Amazon               expenses:travel:accessories              10 EUR       560 EUR

In other cases we are not interested in individual transactions, but in the total for each category. In these cases we can use the flag --subtotal obtaining the following command: ledger --file ledger.journal register expenses --period 'this month' --subtotal.

2022-01-10 - 2022-01-29           expenses:entertainment:books            100 EUR       100 EUR
                                  expenses:food:restaurants                47 EUR       147 EUR
                                  expenses:groceries                      220 EUR       367 EUR
                                  expenses:travel:accessories              10 EUR       377 EUR
                                  expenses:travel:accommodation           550 EUR       927 EUR

In this case the most important column is the third in which it comes brought back the total expense for the category. So in this example we spent 100€ in books, 47€ in restaurants and so on.

We arrived at the end of this first post on Ledger. Probably this tool will seem overkilled to you for the purpose we set at the beginning of the post and in part you are right. Ledger is a very powerful and flexible tool that gives its best only when you get the hang of it. In the next posts of the series there will be a way to cover different topics and expand on those already mentioned. Stay tuned!

This post contains several referral links.


  1. Of course it is possible to leave only one value blank, so by leaving two blank Ledger is no longer able to determine the missing ones. ↩︎

  2. Ledger allows us to express time intervals through various expressions. Relative expressions like ’this month’ are convenient because they allow us to use the same command that automatically fits the current situation, but there are cases where we need to identify the reference period more directly. For example if you are reading this article in February you won’t get any result because for Ledger ’this month’ is equivalent to February. In these cases you can use the name of the month (--period 'jan') or define the interval explicitly (--period 'from 2022-01-01 to 2022-01-31'). ↩︎