Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Code

Last updated: 2026

hledger is a suite of applications, tools and libraries. The main hledger code repository is github.com/hledgerorg/hledger (shortcut url code.hledger.org). There are also various hledger scripts and add-ons maintained as separate projects with their own repos.

hledger packages

Within the main repo, there are a number of separate cabal packages, making it easier to pick and choose parts of hledger to install or to package. They are:

hledger-lib

package, code

Core data models, parsing, standard reports, and utilities. Most data types are defined in Hledger.Data.Types, while functions that operate on them are defined in Hledger.Data.TYPENAME. Under Hledger.Read are parsers for the supported input formats. Data files are parsed into a Journal, which contains a list of Transactions, each containing multiple Postings of some MixedAmount (multiple single-CommoditySymbol Amounts) to some AccountName. When needed, the Journal is further processed to derive a Ledger, which contains summed Accounts. In Hledger.Reports there are standard reports, which extract useful data from the Journal or Ledger.

Here’s a diagram of the main data model:

diagram

The main modules:

  • Hledger.Data: Types, Amount, Posting, Transaction, Journal, Account, Balancing, Lots, Valuation, Dates, Period, Errors..
  • Hledger.Read: JournalReader, CsvReader (with RulesReader), TimeclockReader, TimedotReader
  • Hledger.Query: the query language, used for filtering in reports and UIs
  • Hledger.Reports: ReportOptions, BalanceReport, MultiBalanceReport, PostingsReport, BudgetReport, EntriesReport..
  • Hledger.Write: output formats: Csv, Html, Ods/Spreadsheet, Beancount, Ledger
  • Hledger.Utils: Debug, Parse, Regex, String, Text, IO, Test helpers
  • Hledger re-exports all of the above, so most modules just import Hledger.

hledger

package, code, manual

hledger’s command line interface, and command line options and utilities for other hledger tools.

The main modules:

Each command is a module Somecommand.hs and a doc Somecommand.md in Commands/. The doc is converted to Somecommand.txt, which is embedded in the module to provide hledger somecommand --help, and also included in the hledger manual. See Commands/README.md.

Try tracing the execution of a hledger command:

  1. Hledger.Cli:main parses the command line to select a command, then
  2. gives it to Hledger.Cli.Utils:withJournal, which runs it after doing all the initial parsing.
  3. Parsing code is under hledger-lib:Hledger.Read, eg Hledger.Read.JournalReader.
  4. Commands extract useful information from the parsed data model using hledger-lib:Hledger.Reports, and
  5. render in plain text for console output (or another output format, like CSV).
  6. Everything uses the data types and utilities from hledger-lib:Hledger.Data and hledger-lib:Hledger.Utils.

A suggested reading order for newcomers: Hledger.Data.Types for the data model, Hledger.Read.JournalReader for how journals are parsed, a simple command like Commands/Accounts.hs or Commands/Balance.hs, and then the report it calls in Hledger.Reports.

hledger-ui

package, code, manual

A terminal interface, built with brick and vty. It reads the journal file(s) at startup and, with --watch, again whenever they change. Screens are kept on a stack, so that going into an account register or a transaction and back out restores the previous view.

The main modules, all under Hledger/UI:

  • Main: startup, the brick app definition, file watching and date change detection
  • UIOptions: command line options
  • UITypes: the app state (UIState), the Screen type and each screen’s state type, widget names
  • UIState: app state updates: toggling filters, depth, tree mode, lot detail, etc.
  • UIScreens: constructors and updaters for all screens, gathered here so any screen can (re)generate the others
  • MenuScreen, AccountsScreen, RegisterScreen, TransactionScreen, ErrorScreen: each screen’s drawing and event handling. AccountsScreen serves the all accounts, cash, balance sheet and income statement screens.
  • UIUtils: shared drawing and key handling helpers, the help dialog, suspend/resume, warning collection
  • Editor: launching an external editor at a file position
  • Theme: the colour themes

Manual test procedures are in test/uitest.md.

hledger-web

package, code, manual

A web interface. hledger-web starts a web server built with the yesod framework, and (by default) opens a web browser view on it. It reads the journal file(s) at startup and again whenever they change. It can also write (append) new transactions to the journal file. The views, sidebar, add form and keyboard shortcuts are described in the manual’s WEB UI section.

Most of the action is in

Handler module and function names end with R, like the yesod-generated route type they deal with.

Dynamically generated page content is mostly inline hamlet. Lucius/Julius files and widgets generally are not used, except for the default layout.

For ways to run it during development, see Run hledger-web in development.

Conventions

  • Functions for a type in Hledger.Data.Types live in Hledger.Data.TYPENAME (Amount, Posting, Journal, ..).
  • Module name suffixes: *Reader parses an input format, *Report computes a report, *Options declares command line options; in hledger-web, *R is a route handler.
  • Most modules import Hledger, which re-exports the hledger-lib API.
  • Tags whose names begin with _ are hidden tags for internal use; print shows them only with --verbose-tags.
  • Code style: post-qualified imports (import Data.Map qualified as M), and the -Wall variant shown in DEVWORKFLOWS.
  • Keep imports compatible with the oldest supported GHC (see tested-with: in hledger-lib/package.yaml).

Debug output

The main hledger programs accept --debug[=N] (N from 1 to 9), which prints debug output on stderr (hledger-ui logs it to hledger-ui.log instead, since it is redrawing the screen). In code, use the dbg0..dbg9 helpers from Hledger.Utils.Debug, eg dbg4 "report" x prints a label and the pretty-printed value when the debug level is 4 or more. Levels are used roughly as: 0 for unconditional logging during development, 1 warnings and common troubleshooting, 3-5 report options and generation, 6-7 input file reading, 8 command line parsing, 9 anything else; see the module’s haddock.

Tests

hledger has unit tests, functional tests, doctests, performance tests, installation tests, and browser tests for hledger-web (README). See TESTS for the kinds of tests and their coverage, and DEVWORKFLOWS for how to run them.

Haddock comments

hledger is a documentation-driven project, and this is one reason it has held together and kept improving for so long. (More discussion in #2222.)

Haddock comments are used pervasively in the hledger codebase, and they are considered when reviewing code. There is no hard requirement, but most definitions should have at least a line of english description. The bar can be lower in single-purpose, rarely-changed modules like FODS.hs, and obviously redundant haddocks that add no value should be avoided.

Why: haddocks anchor the developer while writing or changing code; they are the cheapest kind of doc, spec and test suite, and a place to add doctests later; they help contributors who are not expert haskellers, and experienced developers returning to code months or years later. They also help AI tools work effectively on the hledger codebase.