How I Use Ledger to Manage Personal Finance

June 30, 2023 (updated July 9, 2023)

Ledger is a double-entry plaintext accounting system. Plaintext means that you do your finance editing a simple text file and process it with a command line utility :) In this post, I share my approach to using Ledger. If you want to know more about plaintext accounting, visit https://plaintextaccounting.org/.

I only use Ledger for two months, so this is probably not final. This is not an introduction to the Ledger. I assume you are familiar with it.

File structure and initial setup

I store all related files in a folder called Bookkeeping. Let’s see what’s inside:

$ cd Bookkeeping
$ ls -1
2023-05.ledger.txt
2023-06.ledger.txt
accounts.ledger.txt
commodities.ledger.txt
journal.ledger.txt
price-history.ledger.txt

accounts.ledger.txt

In this file, I declare all my accounts. More about my approach to defining accounts later. Here is a sneak peek:

; Assets
account Assets:Business
account Assets:Personal
account Assets:Cash

; Equity
account Equity:Conversion
account Equity:Opening Balances

; Expenses
account Expenses:Groceries
account Expenses:Fees
account Expenses:Subscriptions

; Income
account Income:Salary

commodities.ledger.txt

Here I declare commodities. So far I only use currencies.

commodity USD
    format 1.00 USD
commodity EUR
    format 1.00 EUR
commodity RUB
    format 1.00 RUB
commodity GEL
    format 1.00 GEL

price-history.ledger.txt

In this file, I track prices of every other currency in USD. This way I can see my net worth in one single number. From time to time I update the data.

P 2023-05-10 00:00:00 GEL 0.395 USD
P 2023-05-10 00:00:00 EUR 1.1 USD
P 2023-05-10 00:00:00 RUB 0.0131 USD

P 2023-06-01 00:00:00 GEL 0.38 USD
P 2023-06-01 00:00:00 EUR 1.07 USD
P 2023-06-01 00:00:00 RUB 0.012 USD

accounts.ledger.txt

This is my actual journal. This file includes every other file and in this file I write my postings for this month. Every month I copy-paste every posting from accounts.ledger.txt into separate file with month and year in its name and include it in accounts.ledger.txt (notice 2023-05.ledger.txt) file. Here is the beginning of the main journal file:

include accounts.ledger.txt
include commodities.ledger.txt
include price-history.ledger.txt

; Order is important here!
include 2023-05.ledger.txt
include 2023-06.ledger.txt

; Here go postings for this month

VS Code and iCloud setup

Actually, I have one more file inside my Bookkeeping directory. It’s called ledger.code-workspace and here is it’s content:

{
  "folders": [{ "path": "/Users/user/Documents/Bookkeeping" }]
}

This file is VS Code workspace. And when I click it VS Code opens my Bookkeeping directory with all the related ledger files and I can now edit them. And ledger extension gives you syntax highlight.

I use MacBook and store my Bookkeeping directory in /Users/user/Library/Mobile Documents/com~apple~CloudDocs/. That way it syncs via iCloud and I can edit my journal on my iPhone (.ledger.txt extension is exactly for this, either way, iPhone can not open files). Though I do not do it often.

Going to /Users/user/Library/Mobile Documents/com~apple~CloudDocs/ every time I want to edit my journal is not that convenient. So I have a symlink to my ~/Documents folder.

How I do actual journaling

My routine by no means is advanced. I do not use any automated tools to parse bank statements. I also use a very basic set of Ledger features, i.e. just regular expenses, no stock tracking. And I don’t use auto postings, because for me they make things implicit, which I don’t like.

Every morning I open my journal file and write down everything that happened the previous day. I check my expenses on the bank’s mobile apps. When I first tried keeping track of money 10 years ago, I thought it would be tedious to record every expense. But it turned out that in real life you do not make so many purchases. Every day I have no more than 5 minutes to keep a journal.

Accounts structure

The fewer accounts the better. My top-level accounts are typical: Assets, Expenses, Equity, and Income.

The most diverse category is of course Expenses. I’d recommend not overcomplicating it and only extracting to separate account things that are important to you. For example, I have an account such as Expenses:Alcohol 😅. Anyway, It takes several weeks for the structure to take its final shape.

Some other accounts under Expenses: Groceries, Subscriptions, Fees, Transport, Utilities.

Typical postings

Here is my top postings type.

Regular expense

Almost all of my postings are cleared (*). I wish this was by default, so I don’t need to specify it every time. I also learned to always specify fractional part for consistency, even if it’s zero. Regarding payee (e.g. Bolt) it’s not very strict, I might omit it completely. I also don’t use currencies symbols, because except $ they are hard to type. VS Code automatically autocompletes my accounts while I type.

2023-07-01 * Bolt
    Expenses:Transport:Taxi  5.10 GEL
    Assets:BOG:Personal

Transfer

I always use Equity:Conversion so that transfers are balanced.

2023-07-04 * Transfer
    Assets:BOG:Personal  257.50 GEL
    Equity:Conversion  -257.50 GEL
    Equity:Conversion  100.00 USD
    Assets:BOG:Personal  -100.00 USD

Lending money

Just move assets to Assets:Reimbursements:<Person> account.

2023-07-04 * John Doe
    Assets:Reimbursements:John  100.00 USD
    Assets:Bank

Reporting

First of all, to not specify a journal file in every command I specify LEDGER_FILE environment variable in my .zshrc:

export LEDGER_FILE="/Users/user/Library/Mobile Documents/com~apple~CloudDocs/Bookkeeping/journal.ledger.txt"

To be honest, my most used command is not ledger’s command, but rather hledger’s command. Yep, hledger is another plaintext accounting program with an almost compatible journal format. I haven’t yet decided which one to use exclusively so I use both.

Here is my top-used reports.

How much money do I have?

I use this command right after I am done with writing postings for the previous day. Then I compare the output with what I see on the bank’s apps and fix errors if any.

$ hledger bs
Balance Sheet 2023-07-05

                         ||                                       2023-07-05 
=========================++==================================================
 Assets                  ||                                                  
-------------------------++--------------------------------------------------
 Assets:Business         ||                            12.92 GEL, 300.00 USD 
 Assets:Cool Bank        ||                                     50000.50 RUB 
 Assets:Personal         ||                           200.00 GEL, 350.00 USD 
 Assets:Personal:Deposit ||                  50.00 EUR, 50.00 GEL, 50.00 USD 
 Assets:Savings:Cash     ||                           200.00 EUR, 100.00 USD 
-------------------------++--------------------------------------------------
                         || 250.00 EUR, 262.92 GEL, 50000.50 RUB, 800.00 USD 
=========================++==================================================
 Liabilities             ||                                                  
-------------------------++--------------------------------------------------
-------------------------++--------------------------------------------------
                         ||                                                  
=========================++==================================================
 Net:                    || 250.00 EUR, 262.92 GEL, 50000.50 RUB, 800.00 USD

If I want to see my net worth in one single number, I convert everything to USD based on price-history.ledger.txt:

$ hledger -f wow.ledger bs -X USD
Balance Sheet 2023-07-05, valued at period ends

                         ||  2023-07-05
=========================++=============
 Assets                  ||
-------------------------++-------------
 Assets:Business         ||  304.91 USD
 Assets:Cool Bank        ||  600.01 USD
 Assets:Personal         ||  426.00 USD
 Assets:Personal:Deposit ||  122.50 USD
 Assets:Savings:Cash     ||  314.00 USD
-------------------------++-------------
                         || 1767.42 USD
=========================++=============
 Liabilities             ||
-------------------------++-------------
-------------------------++-------------
                         ||
=========================++=============
 Net:                    || 1767.42 USD

How much money did I spend the last month?

This command shows only top-level categories under Expenses.

$ ledger -S T --depth 2 --no-pager --period 'last month' --group-by 'commodity' balance Expenses
GEL
         1105.00 GEL  Expenses
            5.00 GEL    Fees
          100.00 GEL    Transport
         1000.00 GEL    Groceries
--------------------
         1105.00 GEL

RUB
         2200.00 RUB  Expenses
         1000.00 RUB    Subscriptions
          200.00 RUB    Entertainment
         1000.00 RUB    Utilities
--------------------
         2200.00 RUB

USDs
          107.94 USD  Expenses
          100.00 USD    Rent
            5.98 USD    Subscriptions
            1.96 USD    Fees
--------------------
          107.94 USD

That’s pretty much all I care about for now – net worth and last month’s expenses.

Checks

From time to time I run checks to be sure everything is correct. E.g. it will throw an error if there are postings with unspecified accounts. For reference see docs.

$ hledger check --strict ordereddates

Conclusion

I am only at the beginning of mastering the program, but already I am benefiting from its use. And I think it will only get better with time. The most important thing is that I have developed discipline and regularly keep my journal and even do it with pleasure, which I cannot say about other means, such as mobile applications.