Ledgerbil
A rodent-like program for working with ledger-cli journals.
Install / Use
/learn @scarpent/LedgerbilREADME
ledgerbil
A rodent-like program for working with ledger-cli journals.
Some of ledgerbil's features:
- Automate the entry of recurring transactions via a scheduler.
- Interactively reconcile accounts.
- Sort a file by transaction date.
- Display balances or net worth by year or month in a grid format.
- Display investments with dollar and share amounts side by side.
Hi! I'm a personal finance enthusiast. Keeping my records organized and analyzable is a reassuring activity for me. I've used Ledger since 2013:
http://www.ledger-cli.org/
It's strictly a reporting tool. From the web site: "Ledger never creates or modifies your data. Your entries are kept in a text file that you maintain, and you can rest assured, no automated tool will ever change that data."
That is, no automated tool within the ledger program itself. But you can create or find tools to help with various data entry and reconciliation chores, or to report on your data in ways not supported by ledger.
There's a whole galaxy of tools for working with ledger or ledger-like programs and their data, which you can learn about at:
https://plaintextaccounting.org/
Ledger Data Entry
At a minimum, all you really need is a text editor for data entry. I'm using VSCode for my journal, and with the syntax highlighting files included in this repo, I find it pleasant to work with and look upon:

Once you have data created, you can do about one million things with ledger all by itself.
Why yet another tool? Why ledgerbil?
I had my own ideas for features, and it's fun to have a project to work on. Let's look at a few examples of reporting options before moving on to a deeper dive...
A grid report:

2017 2018 Total
$ 34.63 $ 57.40 $ 92.03 expenses: food: groceries
$ 0.00 $ 42.17 $ 42.17 expenses: food: dining out
$ 17.73 $ 12.00 $ 29.73 expenses: food: take home
------------ ------------ ------------
$ 52.36 $ 111.57 $ 163.93
A grid report with rows and columns transposed:

expenses: expenses: expenses:
food: food: food: take
groceries dining out home Total
$ 34.63 $ 0.00 $ 17.73 $ 52.36 2017
$ 57.40 $ 42.17 $ 12.00 $ 111.57 2018
------------ ------------ ------------ ------------
$ 92.03 $ 42.17 $ 29.73 $ 163.93
An investment report:

$ 1,933.02 assets
$ 1,583.02 401k
11.643 abcdx $ 945.76 big co 500 idx
22.357 lmnop $ 448.26 bonds idx
$ 189.00 cash
15.0 qwrty $ 150.00 ira: glass idx
5.0 yyzxx $ 200.00 mutual: total idx
I don't use many of ledger's features and options, so your mileage may vary for your own data. Please back up before trying, or make sure your changes are committed to the source control system you certainly should be using.
One of my goals with ledgerbil is that it shouldn't modify or reformat your journal entries except in limited and expected ways which are called out below.
Ledgerbil will assume a properly formatted ledger file, although it won't necessarily enforce rules or report problems with an input file. It will be best to feed it files that run cleanly through ledger-cli.
Please see CONTRIBUTING.md for a note to prospective users and contributors.
Building/Running/Testing
You can set up a virtual environment using python3 and the included requirements.txt, or use the included docker files:
just docker
docker build -t ledgerbil . # build it from repo root
docker run --rm ledgerbil pytest # run the test suite
docker run -it ledgerbil /bin/bash # launch and join the container
You can do stuff in the container's bash shell using python main.py
or aliases ledgerbil or lbil, for example:
# lbil --help
<...the help...>
# lbil grid expenses --depth 2
<...grid view of expenses...>
# lbil inv
<...list investments...>
There is a settings.py file that is set up during the build to use sample data in the repo. It's also needed for tests to pass.
docker compose
// settings.py file from build is overwritten by local files, so
// we need to make that settings file available:
$ cp ledgerbil/settings.py.example ledgerbil/settings.py
$ docker-compose build
$ docker-compose run --rm tests
// run commands
$ docker-compose run --rm lbil --help
$ docker-compose run --rm lbil grid income
Ledgerbil Features
And now! Here is the current state of --help, which reflects the current state of exciting features:
$ ./main.py --help
usage: ledgerbil/main.py [-h] [-f FILE] [-S] [-r ACCT] [-R] [-s FILE]
[-n]
{helpful text omitted}
optional arguments:
-h, --help show this help message and exit
-f FILE, --file FILE ledger file(s) to be processed
-S, --sort sort the file(s) by transaction date
-r ACCT, --reconcile ACCT interactively reconcile ledger file(s)
with this account regex; scheduler/sort
have no effect if also specified
-R, --reconciled-status show accounts where reconciler previous
balance differs from cleared balance in
ledger
-s FILE, --schedule FILE scheduled transactions file, with new
entries to be added to -f ledger file; if
given multiple ledger files, will use the
first; if --sort also specified, sorts the
ledger file after entries have been added
-n, --next-scheduled-date show the date of the next scheduled
transaction
other commands (run with -h to see command help):
ledgerbil/main.py
grid ledger reports in year/month tables
investments (or inv) nicer view of shares and dollars
pass passthrough to ledger
portfolio (or port) standalone investment tracker
--sort
Sort files by transaction date. Ledgerbil understands a transaction as something that starts with a date in the first position, like so:
2013/05/11 abc store
expenses: leisure: games
liabilities: credit card $-12.34
If there are comment lines or things it doesn't currently understand
(e.g. lines starting with payee or account), it will glom these
together with the nearest transaction that comes before, so that the
ordering of things will be maintained accordingly. If these items occur
before any dated transactions, they will be given a date in 1899 to
(most likely) keep them before your other transactions. (With that date
being used only for sorting purposes and not written to file.)
Sorting should only change the order of items and not otherwise modify transactions, but note that it will "normalize" spacing so that there is only one space between entries.
Sorting is useful with the scheduler, which will simply add entries to the end of the specified journal file. (The schedule file itself is always sorted after each run so that things will mostly be in order.)
--schedule
The schedule file handles recurring transactions and has two levels of configuration.
At the top of the file, for example:
;; scheduler ; enter 40 days
This determines how many days ahead transactions should be entered into the specified ledger file. Perhaps you'll run:
python main.py --file journal.ledger --schedule schedule.ldg
This will read the schedule.ldg file and create new entries in
journal.ledger up to 40 days into THE FUTURE. schedule.ldg will
also be updated to reflect next dates.
Individual entries use this format on the line below the top line:
;; schedule ; interval uom ; days ; interval ; notes
For example, the monthly interval uom (unit of measure):
2018/01/22 lightning electricity ; todo
;; schedule ; monthly
e: bills: electricity
a: checking $75
Will cause entries to be created on the 22nd of every month, starting in
January 2018. The ;; schedule line will be removed for the journal
entry. For recurring items with varying amounts, I usually include a ; todo comment on the top line as a reminder to go back and set the
actual amount later, but that's just a convention. You can include
whatever you want on the non-schedule lines. The only thing modified is
the date.
Supported units are monthly, weekly, and daily. Weekly
transactions will recur on the same day of the week as the date in the
entry.
Other supported UOMs: bimonthly (every 2 months), quarterly,
biannual, yearly
The days spot can be used to specify more than one day in a month, e.g.:
2018/01/12 johnny paycheck
;; schedule ; monthly ; 15, 30
i: wages: gross pay $500
[...]
Will cause entries to be created on the 15th and 30th of every month. If you start with an entry as above with 2018/01/12, it will first create an entry on that date, and then rotate between the other two. The schedule file entry will always show the date of the next entry to be added.
What will this scheduled transaction do for the 30th, when confronted with February? It will use the 28th or the 29th. You can
