I have electronic records for personal finances dating back to 1997. Much like this blog, it’s had several homes. It used to be in Quicken. Then I moved it to Gnucash. Now it’s in a plaintext format readable by ledger.

Why Ledger

What was wrong with Gnucash? Nothing. It did everything Quicken did but was free. Were it not for wanting several specific optimizations, I’d still be using Gnucash.

First off, the Gnucash XML data file format is fairly large so it needs to be compressed when stored on disk. This means it is sloooooow to open, especially a large file such as mine. Not very conducive to adding quick transactions throughout the day. It’s also not very human readable. And while there are recurring transactions, there are no automated or virtual transactions, something that has come in handy due to my style of virtual envelope budgeting.

Enter plaintext accounting.

The data format is simple, readable, and surprisingly metadata-rich (if you want it to be). You could print it out as-is and hand it over to an accountant (please don’t physically print it), or you could use ledger to parse through all the data very quickly to generate reports.

I’ve taught myself Emacs because there’s a feature-filled plugin for it that helps me manipulate my ledger text files. I also use ledgerbil to help me enter recurring transactions and ledger-autosync to keep up-to-date with the banks. But at its core it’s just a plain ol’ text file.

Now I can enter transactions much more quickly, maintain git version control on my finances, and automate certain tasks. I can also script my finances and there is a shared spreadsheet that updates every night with monthly budget expenses, retirement assets, and a projected retirement date.

Admittedly it’s not for everyone but if you are comfortable with a command line, or are willing to learn and have a proclivity toward geekiness, seek out the ledger likes.

An example

Earlier I noted that ledger supports automated and virtual transactions. Here’s an example that uses both to simplify the accounting process.

Automated transactions

I like to set aside money for a credit card transaction when it happens. Therefore, every credit card transaction has four postings instead of the typical two. When paying with the checking debit card, a transaction might look like this:

1
2
3
2019-03-08 McDonald's
    Expenses:Food:Dining            $5.00
    Assets:Checking                -$5.00

But paying for the same meal with a credit card would look like this:

1
2
3
4
5
2019-03-08 McDonald's
    Expenses:Food:Dining            $5.00
    Liabilities:CreditCard         -$5.00
    Checking:Funds:CreditCard       $5.00
    Checking                       -$5.00

That way at the end of the month, the Checking:Funds:CreditCard account balances with the Liabilities:CreditCard account. And in the meantime I’ve subtracted money from my checking account into a sub-account for paying the credit card bill, even though I didn’t have to do any actual moving around of “real” money.

The problem is that this is a lot of extra typing. But it was necessary before ledger. After ledger, I can add an automatic rule at the top of the file that looks like this:

1
2
3
= /Liabilities:CreditCard/
    Checking:Funds:CreditCard      (amount)
    Checking                       (-amount)

The (amount) is not a placeholder, that’s the actual syntax. It creates an automated transaction that uses the amount from the matching posting. In this case, it’s anything that matches the pattern /Liabilities:CreditCard/.

So now I can enter a credit card transaction like this:

1
2
3
2019-03-08 McDonald's
    Expenses:Food:Dining            $5.00
    Liabilities:CreditCard         -$5.00

And I automataically get another transaction that takes that same amount from Checking and moves it to Checking:Funds:CreditCard. Cool.

Virtual transactions

But that’s not all.

If I put the account names in square brackets, the transactions become virtual, so I can create a rule like the above:

1
2
3
= /Liabilities:CreditCard/
    [Checking:Funds:CreditCard]    (amount)
    [Checking]                     (-amount)

What does that get me? I can now generate reports with the --real option flag and any virtual transactions won’t show up. That way when I want to reconcile my Checking account register with the bank’s statement, I don’t see a lot of extra stuff that was only there to help me manage money and didn’t represent any “real” transaction.

Combine these two capabilities and endless possibilities arise. Let your imagination run.

And it only scratches the surface of ledger’s capabilities.