#journal #formatter #accounting #hledger

no-std bin+lib hledger-fmt

An opinionated hledger's journal files formatter

23 releases

new 0.3.7 Nov 11, 2025
0.3.0 Sep 16, 2025
0.2.11 Jun 22, 2025
0.2.5 Feb 9, 2025
0.2.1 Nov 13, 2024

#14 in Finance

Download history 138/week @ 2025-09-16 6/week @ 2025-09-23 16/week @ 2025-09-30 171/week @ 2025-10-07 16/week @ 2025-10-14 281/week @ 2025-10-21 105/week @ 2025-10-28

575 downloads per month

MIT license

190KB
4.5K SLoC

hledger-fmt

Crates.io docs.rs Tests License

An opinionated hledger's journal files formatter.

Installation

Crates.io downloads GitHub downloads

Standalone pre-built binaries

Download standalone pre-built binaries from releases page.

Cargo binaries

Install from pre-built binaries using cargo-binstall:

cargo binstall hledger-fmt

Build from source

Build from source using cargo:

cargo install hledger-fmt

pre-commit

Use it with pre-commit by adding the hook to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/mondeja/hledger-fmt
    rev: v0.3.7
    hooks:
      # id: hledger-fmt       # Use this id to format files in place
      - id: hledger-fmt-check # Use this id to check files without formatting

VS Code

With hledger-fmt in your PATH, use the Custom Local Formatters extension. Just install it and add the next configuration to your settings.json:

{
  "customLocalFormatters.formatters": [
    {
      "command": "hledger-fmt - --no-diff --exit-zero-on-changes",
      "languages": ["hledger"]
    }
  ]
}

To format on save:

{
  "editor.formatOnSave": true
}

Zed

With hledger-fmt in your PATH, add the next configuration to your settings.json:

{
  "languages": {
    "Ledger": {
      "formatter": {
        "external": {
          "command": "hledger-fmt",
          "arguments": ["--no-diff", "--exit-zero-on-changes"]
        }
      }
    }
  }
}

To format on save:

{
  "format_on_save": "on"
}

Library

You can use hledger-fmt as a standalone library in your Rust projects. Add the following to your Cargo.toml:

[dependencies]
hledger-fmt = { version = "0.3", default-features = false, features = ["std"] }

Usage

CLI

When you don't pass files to format, it reads all the files with the extensions .journal, .hledger and .j in the current directory and its subdirectories.

hledger-fmt [OPTIONS] [FILES]...

To fix them in place, use the --fix option:

Warning: This is a potentially destructive operation. Make sure to make a backup of your files before running this command for the first time.

hledger-fmt --fix [FILES]...

See hledger-fmt --help for more information.

Library

use hledger_fmt::{format_journal, format_journal_bytes};

fn main() {
    let journal = r#"
2024-01-01 * "Sample transaction"
    Assets:Cash  $100
    Expenses:Food  $100
"#;
    match format_journal(journal) {
        Ok(formatted) => println!("{formatted}"),
        Err(e) => eprintln!("Error formatting journal: {e}"),
    }

    match format_journal_bytes(journal.as_bytes()) {
        Ok(formatted_bytes) => println!("{}", String::from_utf8_lossy(&formatted_bytes)),
        Err(e) => eprintln!("Error formatting journal: {e}"),
    }
}

Features

  • color (enabled): Build with terminal color support.
  • auto-color (enabled): Detects if your terminal supports colors.
  • diff (enabled): Show a diff of the changes made to the files. Adds the --no-diff option to disable it.
  • cli (enabled): Build the CLI binary tool.
  • std: (enabled) Build with the standard library. Disable it to build with no_std + alloc support.
  • env: Read configuration from environment variables at run time.
  • tracing: Build with tracing support. Adds the CLI argument --trace-file to write tracing logs to a file.

Configuration

By default, hledger-fmt comes with sensible opinionated defaults. You can customize them at compile or run time by using the next environment variables:

Variable name Default value Description
HLEDGER_FMT_ENTRY_SPACING 2 Minimum number of spaces between entry columns.

By default, environment variables are read at compile time only. Enabling the env feature adds support for reading these variables at runtime.

Dependencies

~0.1–13MB
~77K SLoC