Author: Simon Michael
Last updated: 201903
Tested on: mac mojave
Tested with: hledger 1.14
Tools used: hledger, hledger-ui, GNU make, ...
LEDGER_FILE environment variable is currently set to
This is done in some super secret way that I'll have to track down, or more likely several ways,
to ensure that it is consistent for:
- programs started from command line in iTerm/Terminal windows
- programs started from emacs shell buffers
- emacs modes such as ledger-mode
- for both text-mode and graphical emacs, whether started from command line or mac GUI (Dock/Finder/Spotlight)
$ tree ~/notes /Users/simon/notes ├── 2019.journal ├── 2019.prices ├── all.journal ├── current.journal -> 2019.journal ├── forecast.journal ...
Files are in
There's one YEAR.journal file per year containing all transactions in date order.
- YEAR.prices containing P records for the year
- forecast.journal containing periodic transaction rules
all.journal includes all the year journals. It provides all historical data, but is slow, and my old journals are inconsistent/broken, so it's currently rarely used.
current.journal is a symlink for scripts which don't know the year. Symbolic links are a mixed blessing, causing file path confusion in emacs, eg.
Most journal entries are generated from downloaded CSV:
Transactions from three banks are aggregated and cleaned in a Google sheet by Tiller ($5/mo). A command line tool downloads this sheet as CSV (via cron ? currently disabled).
Paypal CSV is downloaded manually, then moved into place by a make rule. I use Paypal's CSV because Tiller doesn't handle multiple currencies and Paypal's extra metadata fields.
For troubleshooting: when downloading a CSV the previous copy is saved as FILE.csv.old.
$ make csv
Cash transactions are entered in emacs, using ledger-mode. Mostly by copying and pasting similar past transactions.
When rewriting account names, I use either
ledger-mode completion (
TAB) or dabbrev-expand completion (
which have different strengths.
I fetch currency prices with barrucadu's market-prices.py script (details).
Journal file, included files, makefile and scripts in git. A mixture of manual and cron-based automatic committing.
; Recurring (daily, weekly, monthly, yearly..) workflows
- In an iterm3 tab titled FINANCE, I have a TUI emacs with two side-by-side windows.
- In the first window is 2021.journal, with ledger-mode and auto-revert-mode enabled.
- In the second window I switch to a shell and run make Import to download and import latest transactions.
- These show up in the journal right away. I switch focus there, select all the new entries and hit M-q to realign them with ledger-mode (which is better at that).
- I process them one at a time from the top, marking each one cleared (C-c C-e) when it looks good.
- When there's an unknown posting, I:
- replace the unknown account with the appropriate account (assuming I know it)
- switch to common.rules in the second window, and search for that account or its parent (assuming it's in the rules somewhere)
- add some portion of the new entry's description as a new pattern for this account. Or tweak the existing patterns so it will be matched next time (or to avoid over-matching by the wrong rule).
- when all new entries are marked cleared, I git commit the journal and any updated rules file(s). Or if I don't, it will be auto-committed by a nightly cron job, in theory.
- I do this daily-ish, so it's a small number of new txns each time.
For transactions which don't appear in downloaded data (cash transactions, loans, etc.):
- Note it somewhere, anywhere, as quickly possible, or it will be forgotten (and I'll have to add an unexplained cash adjustment transaction later).
- If the laptop is out of reach, that will usually be a brief note on today's page in a phone notes app (Obsidian, currently) or a paper notebook. Later that gets copied to the laptop.
- On the laptop, my usual routine is:
- get to the place of data entry
- iterm3 app (or start it if not running),
- FINANCE tab where a TUI emacs (client) is running (or create that tab/start that emacs client),
- emacs window showing the journal (or
C-j lif not showing),
- end of buffer (
- add the journal entry: either
- if short of time: just a commented line, or date and description (and expand it later)
- if a familiar transaction: search back for a similar one, copy, jump to the end again, paste, adjust as needed (especially the date)
- otherwise type it in, starting with the date, using ledger-mode's completion (
TAB), or hippie-expand's completion (
M-/) if they help. (ledger-mode required careful configuration for best behaviour with account names, the main thing I recall is turn on
- when the journal entry is finalised, mark it cleared (
- get to the place of data entry
; Account hierarchy used, any organisational principles, how I maintain it..
I have convenience aliases for hledger commands and reports in
which is automatically sourced by my bash profile.
More reports and file-generating scripts are defined in
Increasingly, I am moving reports and scripts in a (more powerful and robust) Shake file,