Skip to content

apauley/hledger-flow

Repository files navigation

hledger-flow

Project Status

I haven’t been able to spend much time on this project in the last few years, and looking at my current responsibilities this is likely to remain the case.

I do still try to respond to bug reports as they happen.

What is it?

hledger-flow is a command-line program that gives you a guided Hledger workflow. It is important to note that most of the heavy lifting is done by the upstream hledger project. For example, hledger-flow cares about where you put your files for long-term maintainability, but the actual conversion to classified accounting journals is done by hledger.

hledger-flow focuses on automated processing of electronic statements as much as possible, as opposed to manually adding your own hledger journal entries. Manual entries are still possible, it just saves time in the long run to automatically process a statement whenever one is available.

Within hledger-flow you will keep your original bank statements around permanently as input, and generate (h)ledger journals each time you run the program. The classification is done with hledger’s rules files, and/or your own script hooks.

Keeping the original statements means that you never have to worry too much about “am I doing this accounting thing right?” or “what happens if I make a mistake?”. If you want to change your mind about some classification, or if you made a mistake, you just change your classification rules, and run the program again.

It started when I realized that the scripts I wrote while playing around with adept’s Full-fledged Hledger aren’t really specific to my own finances, and can be shared.

Overview of the Basic Workflow

  1. Save an input transaction file (typically CSV) to a specific directory.
  2. Add an hledger rules file. Include some classification rules if you want.
  3. Run hledger-flow import

Add all your files to your favourite version control system.

The generated journal that you most likely want to use as your LEDGER_FILE is called all-years.journal. This has include directives to all the automatically imported journals, as well as includes for your own manually managed journal entries.

In a typical software project we don’t add generated files to version control, but in this case I think it is a good idea to add all the generated files to version control as well - when you inevitably change something, e.g. how you classify transactions in your rules file, then you can easily see if your change had the desired effect by looking at a diff.

Who should use this?

hledger-flow is intended for you if:

  • You want a way to organise your finances into a structure that will be maintainable over the long term.
  • You like the idea of treating your source transactions (typically CSV files) as input, and having your hledger journals (mostly) being generated as output.
  • You want to automate as much as possible when dealing with your financial life.
  • You don’t mind writing some scripts when needed, as long as it saves you time over the long term.

How do I install it?

If you can compile it yourself, please do so by following the build instructions.

Otherwise download the latest release for your OS (Linux or Mac OS X), and copy the hledger-flow executable to a directory in your PATH.

On Linux you should just be able to run the executable. On Mac you may see a warning.

Windows Support

Currently hledger-flow does not work on Windows.

This list of issues describes some of the details of what doesn’t work.

I believe it wouldn’t take too much effort to fix those issues, but I’m going to leave Windows support for other contributors.

Please send me some pull requests if you would like hledger-flow to work on Windows.

Getting Started

Have a look at the detailed step-by-step instructions and the feature reference.

You can see the example imported financial transactions as it was generated by the step-by-step instructions here:

https://github.com/apauley/hledger-flow-example

Compatibility with hledger

hledger-flow should work with any recent version of hledger.

The most recent version that it was tested with is hledger-1.50 (September 2025).

Note to future readers: if you are using hledger-flow with a more recent version of hledger than mentioned above, please submit a small pull request with the updated version of hledger.

Compatibility with ledger-cli

hledger-flow uses hledger to produce journal’s, so this page about hledger and Ledger should be relevant for all hledger-flow users.

That said, here are some observations that are specifically relevant to hledger-flow:

When writing out the journal include files, hledger-flow sorts the include statements by filename.

Ledger fails any balance assertions when the transactions aren’t included in chronological order.

An easy way around this is to name your input files so that March’s statement is listed before December’s statement.

Another option is to add --permissive to any ledger command.

So you should easily be able to use both ledger and hledger on these journals if you take care to avoid the few incompatibilities which exists (eg in your rules files or manual journals).

Project Goals

My hledger files started to collect a bunch of supporting code that weren’t really specific to my financial situation.

I want to extract and share as much as possible of that supporting code.

Adept’s goals also resonated with me:

  • Tracking expenses should take as little time, effort and manual work as possible
  • Eventual consistency should be achievable: even if I can’t record something precisely right now, maybe I would be able to do it later, so I should be able to leave things half-done and pick them up later
  • Ability to refactor is a must. I want to be able to go back and change the way I am doing things, with as little effort as possible and without fear of irrevocably breaking things.

Contributing to hledger-flow

Have a look at the contribution guidelines.

FAQ

How do you balance transfers between 2 accounts when you have statements for both accounts?

The Problem

In your primary bank account you’ve happily been classifying transfers to a secondary account as just Expenses:OtherAccount.

But you’ve recently started processing the statements from the second account as well so that you can classify those expenses more accurately.

And now the balances of these two accounts are all wrong when the statements of each account deals with money transferred between these two accounts.

In bank1.journal, imported from bank1.csv:

2018/11/09 Transfer from primary account to secondary account
    Assets:Bank1:Primary    $-200
    Assets:Bank2:Secondary

In bank2.journal, imported from bank2.csv:

2018/11/09 Transfer from primary account to secondary account
    Assets:Bank2:Secondary  $200
    Assets:Bank1:Primary

The Solution

As soon as you start importing statements for both accounts you will have to introduce an intermediate account for classification between these two accounts.

I use Assets:Transfers:*.

And we may have reports looking at these transfers accounts at some point, you should consider using the same names.

The above example then becomes as follows.

In bank1.journal, imported from bank1.csv:

2019-05-18 Transfer from primary account to secondary account
    Assets:Bank1:Primary         $-200
    Assets:Transfers:Bank1Bank2

In bank2.journal, imported from bank2.csv:

2019-05-18 Transfer from primary account to secondary account
    Assets:Bank2:Secondary       $200
    Assets:Transfers:Bank1Bank2

Any posting to Assets:Transfers:* indicates an in “in-flight” amount. You would expect the balance of Assets:Transfers to be zero most of the time. Whenever it isn’t zero it means that you either don’t yet have the other side of the transfer, or that something is wrong in your rules.

You could theoretically just use Assets:Transfers without any subaccounts, but I found it useful to use subaccounts. Because then the subaccounts can show me where I should look for any missing transfer transaction.

I typically use sorted names as the subaccount (Python code sample):

"Assets:Transfers:" + "".join(sorted(["Bank2", "Bank1"]))

External references

This approach is based on what is described in Full-fledged hledger: https://github.com/adept/full-fledged-hledger/wiki/Adding-more-accounts#lets-make-sure-that-transfers-are-not-double-counted

The question was first asked in issue #51.

About

An hledger/ledger-cli workflow focusing on automated statement import and classification

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published