Skip to content

Pre-commit Integration

Use the rumdl pre-commit hook for a read-only lint check and add rumdl-fmt only when you want files formatted automatically. Both hooks use the same rumdl configuration as the CLI and CI, so repositories can enforce one Markdown rule set throughout the authoring loop.

Last verified: September 2026. Hook names and exit behavior match the current rumdl pre-commit integration.

Setup

Add to your .pre-commit-config.yaml:

.pre-commit-config.yaml
repos:
  - repo: https://github.com/rvben/rumdl-pre-commit
    rev: v0.3.0  # Use latest version
    hooks:
      - id: rumdl      # Lint only; add args [--fix] to auto-fix
      - id: rumdl-fmt  # Pure format, exits 0 on violations

Then install the hooks:

pre-commit install

Available Hooks

rumdl

Lints files and exits 1 if violations are found. Non-destructive by default. Use this as your primary hook.

- id: rumdl

To auto-fix violations in place, opt in with args (the same model as ruff's linter hook):

- id: rumdl
  args: [--fix]

rumdl-fmt

Formats files in place and exits 0 whether or not violations remain. Relies on pre-commit's file-change detection to signal failures. Use alongside rumdl when you want to separate formatting from linting.

The one thing it does fail on is a run it could not complete: a file it could not read, or a code-block tool that could not run under a fail setting. Those exit 2, because the alternative is reporting a file as formatted when it was not.

- id: rumdl-fmt

Recommended setup

Use rumdl first for lint coverage, then rumdl-fmt for formatting - the same pattern as ruff + ruff-format.

Configuration

Custom Arguments

hooks:
  - id: rumdl
    args: [--config, .rumdl.toml, --verbose]

Code-block tools

Both hooks accept the code-block tool mode flags through args. To check the outer Markdown and skip the configured tools:

hooks:
  - id: rumdl
    args: [--no-code-block-tools]
  - id: rumdl-fmt
    args: [--no-code-block-tools]

To run only the configured tools and leave the outer Markdown alone:

hooks:
  - id: rumdl
    args: [--only-code-block-tools, --deny-config-warnings]
  - id: rumdl-fmt
    args: [--only-code-block-tools, --deny-config-warnings]

Only mode has two ways to pass while checking nothing, and --deny-config-warnings is what catches both.

With no tools configured it exits 0 with a config warning.

The second is easy to miss under pre-commit specifically. The hook environment installs rumdl and nothing else, so the tools it drives (ruff, shellcheck, shfmt, prettier) have to come from the machine running the hook, and on a CI runner they are often absent. Every block is then skipped, and a run that checked none of your code blocks looks exactly like a clean one. rumdl says so once for the run:

[config warning] code-block tools not installed: ruff. Those code blocks were
not checked. Install them, or set `code-block-tools.on-missing-tool-binary` to
"fail" to stop the run or "ignore" to accept the gap

That is the on-missing-tool-binary = "warn" default, and it is a warning rather than a failure, so --deny-config-warnings is what turns it into a failing hook.

To fail on a missing tool without --deny-config-warnings, and to have it reported against the block rather than against the run, set the config to fail:

.rumdl.toml
[code-block-tools]
enabled = true
on-missing-tool-binary = "fail"

The rumdl hook then reports the missing binary as a violation (Tool binary 'ruff' not found in PATH) and exits 1. rumdl-fmt names it too and exits 2 rather than 1: a formatter that could not run leaves the document partly formatted, which is an incomplete run rather than a document with something wrong in it.

To keep the guard on the hook rather than on the whole project, pass the same setting inline instead (rumdl 0.2.66 and later):

hooks:
  - id: rumdl
    args:
      - --only-code-block-tools
      - --config
      - 'code-block-tools.on-missing-tool-binary = "fail"'

To accept the gap deliberately, on a machine where the tools are known to be absent and that is fine, set it to "ignore". That is silent even under --deny-config-warnings.

Supplying the tools

The guard above tells you a tool is missing. To make it present, use pre-commit's additional_dependencies, which installs into the hook's own virtualenv and puts that virtualenv's bin on the PATH rumdl scans:

hooks:
  - id: rumdl
    additional_dependencies: [ruff==0.16.6]

Pin the versions. An unpinned tool changes its output when it releases, and the hook starts failing on files nobody touched.

These packages install the binary rumdl looks for:

Tool Package to add Binary
ruff:check, ruff:format ruff ruff
black black black
sqlfluff:lint, sqlfluff:fix sqlfluff sqlfluff
djlint, djlint:* djlint djlint
beautysh beautysh beautysh
shellcheck shellcheck-py shellcheck
shfmt shfmt-py shfmt
clang-format clang-format clang-format
taplo taplo taplo
tombi, tombi:* tombi tombi
oxfmt, oxfmt:* oxfmt oxfmt
deno-fmt, deno-fmt:* deno deno

The rest have no Python package, so they have to be installed on the machine running the hook: prettier (npm), jq, gofmt, goimports, rustfmt, stylua, nixfmt, ormolu, elm-format, swift-format, ktfmt, terraform, shuck. On CI that means an install step before pre-commit run. This is the case the on-missing-tool-binary = "fail" guard exists for.

Two package names collide with something else

yamlfmt on PyPI is an unrelated ruamel-based formatter, not the yamlfmt rumdl drives. It installs a binary of the right name, passes the PATH check, and then fails when rumdl pipes a code block to it. prettier on PyPI is an unrelated pretty-printing library and installs no binary at all. Do not add either to additional_dependencies.

To run both modes as separate hooks, give each entry its own alias and name. pre-commit uses the alias for pre-commit run <alias> and the name in its output, and each entry can carry its own files, exclude or stages:

hooks:
  - id: rumdl
    alias: rumdl-no-code-block-tools
    name: rumdl check (no code-block tools)
    args: [--no-code-block-tools]
  - id: rumdl
    alias: rumdl-only-code-block-tools
    name: rumdl check (only code-block tools)
    args: [--only-code-block-tools, --deny-config-warnings]

File Filtering

hooks:
  - id: rumdl
    files: ^docs/.*\.md$  # Only lint docs/
    exclude: ^docs/drafts/

No Exclude

Exclude patterns from your config are always respected by default (as of v0.0.156).

To disable all configured exclusions, use --no-exclude flag.

hooks:
  - id: rumdl
    args: [--no-exclude]  # Disable exclude patterns defined in config

Stages

Run hooks at different stages:

hooks:
  - id: rumdl
    stages: [commit]  # Default

  - id: rumdl
    stages: [push]    # Run on push instead

Running Manually

# Run on all files
pre-commit run rumdl --all-files

# Run on staged files only
pre-commit run rumdl

Updating

# Update to latest version
pre-commit autoupdate --repo https://github.com/rvben/rumdl-pre-commit

Troubleshooting

Slow First Run

The first run downloads and installs rumdl. Subsequent runs use the cached version.

Files Not Being Checked

Check your files pattern matches your Markdown files:

hooks:
  - id: rumdl
    types: [markdown]  # Use file type instead of pattern

Conflicts with Other Formatters

Run rumdl last to ensure consistent formatting:

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    hooks:
      - id: trailing-whitespace

  - repo: https://github.com/rvben/rumdl-pre-commit
    hooks:
      - id: rumdl      # Run after other hooks
      - id: rumdl-fmt