Managing my finances with hledger
The problem with personal finance apps
I've been trying to find a reliable app or system to manage my personal finances for quite some time. I've experimented with popular tools like Fold Money, Cred Money, and even attempted to build my own solution. Yet, none of them have truly worked for me.
The core issue isn't a lack of features, it's a fundamental mismatch between what most finance apps optimize for and what I actually need.
The obsession with net worth
Most personal finance apps that I've used are heavily centered around net worth.
They aggregate your bank accounts, credit cards, investments, and assets, then present everything neatly as a number or a chart. While this looks impressive, it's largely unhelpful.
Net worth isn't the problem.
If you ask someone what their net worth is, they'll usually have a rough idea. Precision isn't necessary here. What is necessary and far more difficult is understanding where your money actually goes.
The real problem: expense tracking
What I actually care about is:
- Where am I spending the most money each month?
- What category accounted for the majority of my expenses?
- How much am I really spending on food, travel, or leisure?
- Which expenses are habitual, and which are one-offs?
These are actionable questions. Answers to these can influence behavior.
Categorization cannot be fully automated
Expense categorization is not something you can completely automate no matter how advanced the AI is.
For example:
- A UPI transaction to Rahul could be:
- An Uber ride
- A friend you paid back
- A shopkeeper
- Your house help
There's no reliable way for an AI to infer context from a bare transaction name. Human intent and context matter, and those rarely exist in transaction metadata.
The Splitwise problem (shared expenses)
Things get even more complicated with shared expenses.
Consider this scenario:
- You pay for a dinner for 4–5 people.
- You later add the split to Splitwise.
- Eventually, your friends settle their share.
In most finance apps:
- The entire dinner amount is recorded as your expense.
- When you review your monthly food spending, it appears inflated.
- The refund or settlement is either:
- Categorized incorrectly, or
- Ignored altogether
There's also the inverse problem.
Sometimes:
- Someone else pays for a shared expense.
- They add it to Splitwise.
- You settle it later.
In this case:
- The original expense never appears in your bank or credit card statements.
- If you forget to track it manually, it never gets categorized.
- Your expense data becomes incomplete and misleading.
Why manual tracking doesn't work for me
A common workaround for all of this is manual expense tracking.
Some people swear by logging every transaction as it happens using a Telegram bot, a notes app, or a simple form. Others export their bank statements and reconcile everything in an Excel sheet over the weekend or at the end of the month.
And to be fair, this does work for some people.
But for me, manual tracking introduces a different set of problems.
It's cumbersome.
It demands constant discipline.
And it's surprisingly inaccurate over time.
You forget to log small expenses. You postpone reconciliation. You rely on memory to add context days or weeks later.
What worked for me: hledger and python
I recently discovered hledger through a Reddit discussion, where some individuals shared how they leverage it for personal finance tracking. Intrigued by their approach, I decided to explore it myself.
What is hledger?
hledger is a plain-text accounting tool for tracking personal or business finances. It is based on the widely used double-entry method of bookkeeping.
In simple terms, It's a command-line program that reads your financial transactions from plain text files. You manually record transactions in a simple, human-readable format (like a journal). It then generates reports showing where your money went, account balances, expenses by category, etc.
I needed to learn some basic accounting principles first, so I spent time going through their docs. That's where I first came across this equation, which you might already be familiar with.
Assets = Liabilities + Equity
Setup
At the heart of my system is a simple, version-controlled folder on my machine.
Nothing fancy, just text files, scripts, and exported statements.
The idea is straightforward:
- Source data stays raw
- Transformations are explicit
- The ledger is the single source of truth
This is roughly how things are organised:
hledger/
├── opening.journal # For initial state of my bank accounts, credit cards, etc
├── main.journal # Main file in which each transaction is recorded
├── prices.journal # Holds the current market price of stocks I hold
├── scripts/
│ ├── axis_bank.py
│ ├── federal_bank.py
│ ├── axis_credit_card.py
│ ├── hdfc_credit_card.py
│ ├── zerodha.py
│ └── splitwise.py
└── statements/
├── axis_bank.csv
├── axis_credit_card.csv
├── hdfc_credit_card.csv
├── kite.csv
└── splitwise.csv
The Journal Files
main.journal
main.journal contains all day-to-day financial activity after the initial setup:
- Expenses (UPI, credit cards, cash)
- Credit card payments
- Splitwise settlements
- Investment buys and sells
- Refunds and reversals
Every transaction answers two questions:
- Where did the money go?
- Where did it come from?
opening.journal
opening.journal captures a snapshot of my financial life on day one:
- Bank balances
- Cash on hand
- Credit card dues
- Existing investments and holdings
No income.
No expenses.
Just where I stood when I decided to start tracking.
prices.journal
This file exists for one purpose: valuation.
prices.journal tracks the market price of investments (ETFs, mutual funds, stocks) over time.
It does not record transactions, only prices.
This separation is important because it keeps concepts clean:
main.journalanswers what I ownprices.journalanswers what it's worth
How this setup works?
Once the setup was in place, I usually spend 30 minutes every weekend updating everything.
Step 1: Download statements (the most annoying part)
Every weekend, I start by downloading statements from various sources:
- Bank account (UPI-heavy)
- Credit cards
- Broker (Zerodha)
- Splitwise
This is, by far, the worst part of the process.
Bank CSV exports are… not great, but instead of fighting the format, I treat these files as raw input.
Step 2: Bank transactions
I use a small Python script to read bank CSV exports and turn them into hledger transactions.
The script:
- Parses the messy CSV format
- Normalizes dates and amounts
- Prompts me for categorisation
This keeps automation helpful, but not blind.
I still decide what a transaction actually represents.
For example, a coffee paid via credit card ends up as:
2026-01-03 Coffee
expenses:food INR 250.00
liabilities:credit-card
Step 3: Credit cards
One of the biggest improvements came from modeling credit cards properly.
When I spend using a credit card:
- I record an expense
- I also record a liability
When I pay the bill:
- Money moves from my bank account
- The liability reduces
Step 4: Splitwise (the trickiest part)
Splitwise was one of the trickiest parts to model correctly, and it took me a while (and ChatGPT) to get this right. The key rule I follow is simple:
Only banks and credit cards move money. Splitwise does not.
Splitwise records obligations, not transactions.
So I never let Splitwise create or modify bank-related entries directly. It's an important part in my finance tracking as my category spends will now not be inflated with transactions that I did for a group.
In my setup:
Bank and credit card statements
- Represent real money movement
Splitwise
- Represents how much I owe or am owed
- Adds additional accounting context
I export a CSV from the Splitwise app directly, and with a small Python script:
- Reads the Splitwise CSV
- Identifies balances (owed / owing)
- Generates new hledger transactions
- Posts only to Splitwise receivable or payable accounts
Scenario 1: I Pay for Others
Suppose I pay ₹3,000 for a group dinner via UPI.
This appears in my bank statement and is imported as-is:
2026-01-05 Dinner
expenses:food INR 3,000.00
assets:bank
Now Splitwise (from Splitwise CSV) tells me that ₹1,800 of this should be reimbursed.
I add a new transaction to reflect that obligation:
2026-01-05 Splitwise receivable (Dinner)
assets:splitwise INR 1800.00
expenses:food INR
Result:
- Net personal expense: ₹1200
- Bank transaction remains untouched
- Food category expenses is updated
Scenario 2: Someone Else Pays (I Owe)
If someone else pays and I owe ₹300, Splitwise records the obligation, but no money has moved yet.
So I add a transaction representing the liability:
2026-01-06 Splitwise payable (Cab)
expenses:travel INR 300.00
assets:splitwise
Scenario 3: Settlement Happens
When money actually moves via UPI, cash, or card, it shows up in the bank statement and is imported normally.
For example, settling ₹1800:
2026-01-08 Splitwise settlement
assets:splitwise - INR 1800
assets:bank
While categorising my bank statement transaction, I can categorise it to splitwise account.
Step 5: Investments (it's pretty straightforward, thanks to Zerodha)
Adding investment information is pretty straightforward, as Zerodha exports all the equities, ETFs, and mutual funds I hold in a neat format.
It provides me with the quantity of each entity I own and the LTP (Last Traded Price) for each entity at the end of the day.
I update my main journal if I have bought or sold any entity and update the prices.journal file with the LTP values. Neat.
Step 6: Review & commit
Before calling it done, I:
- Scan new entries for mistakes
- Check balances against official apps/websites
- Make sure things reconcile
Once everything lines up, and account information matches upto 2 decimal points, I commit the changes.
At this point, the ledger feels less like bookkeeping and more like documentation, a precise record of decisions already made.
Getting actionable insights
Now that all the data is recorded, I can answer all those questions I mentioned earlier about where my money actually goes.
Check your current balances
hledger balance
This shows the current state of all my accounts:
INR 45,230.00 assets
INR 32,450.00 bank
INR 8,500.00 splitwise
INR 4,280.00 zerodha
INR 124,500.00 expenses
INR 28,400.00 food
INR 15,200.00 rent
INR 12,300.00 shopping
INR 18,600.00 subscriptions
INR 24,000.00 travel
INR 26,000.00 utilities
INR -25,000.00 liabilities:credit-card
--------------------
INR 144,730.00
See category-wise spending
hledger balance expenses
This breaks down exactly where my money went:
INR 124,500.00 expenses
INR 28,400.00 food
INR 15,200.00 rent
INR 12,300.00 shopping
INR 18,600.00 subscriptions
INR 24,000.00 travel
INR 26,000.00 utilities
--------------------
INR 124,500.00
Analyze spending for a specific category
hledger register expenses:food
This shows every food transaction with running totals:
2026-01-03 Coffee expenses:food INR 250.00 INR 250.00
2026-01-05 Dinner expenses:food INR 1,200.00 INR 1,450.00
2026-01-07 Groceries expenses:food INR 3,200.00 INR 4,650.00
2026-01-10 Lunch expenses:food INR 450.00 INR 5,100.00
2026-01-15 Restaurant expenses:food INR 1,800.00 INR 6,900.00
Monthly breakdown of expenses
hledger balance expenses -M
This shows spending trends over time:
Balance changes in 2025-11-01..2026-01-31:
|| 2025-11 2025-12 2026-01
===============++===================================
expenses:food || INR 8,200 INR 9,100 INR 11,100
expenses:rent || INR 15,000 INR 15,000 INR 15,000
expenses:shop || INR 3,400 INR 4,200 INR 4,700
expenses:subs || INR 1,200 INR 1,200 INR 1,200
expenses:trav || INR 5,600 INR 12,400 INR 6,000
expenses:util || INR 8,200 INR 8,800 INR 9,000
---------------++-----------------------------------
|| INR 41,600 INR 50,700 INR 47,000
Income vs. Expenses report
hledger incomestatement
This sort of gives me how much did I saved this month:
Income Statement 2025-11-01..2026-01-31
|| 2025-11-01..2026-01-31
===================++========================
Revenues ||
-------------------++------------------------
income:salary || INR 180,000
-------------------++------------------------
|| INR 180,000
===================++========================
Expenses ||
-------------------++------------------------
expenses:food || INR 28,400
expenses:rent || INR 45,000
expenses:shopping || INR 12,300
expenses:subs || INR 3,600
expenses:travel || INR 24,000
expenses:utilities|| INR 26,000
-------------------++------------------------
|| INR 139,300
===================++========================
Net: || INR 40,700
Filter by date range
hledger balance expenses:food -b 2026-01-01 -e 2026-01-15
This shows food expenses for a specific period:
INR 5,100.00 expenses:food
These commands give me the insights I actually need: where the money went, which categories are growing, and whether my spending aligns with my intentions. No fancy dashboards needed, just clear, precise answers.
PS: above values are just random values generated by Claude
Ending notes (thanks for reading)
I've spent considerable time refining this approach to personal finance tracking, it follows a semi-automatic approach, in which I do the categorization part through script and hledger helps with the accounting part.
I hope it helps anyone wrestling with similar challenges. Initial setup might be a little headache, but once the setup is done, it's a breeze.
If you have suggestions for improving this setup or spot areas for optimization, I'd love to hear from you. Feel free to reach out via email with your feedback.
Until next time, Cheers 🍻!