Skip to content

Python

Use Ruff for linting and formatting, with mypy behind the types profile.

Prerequisites: ruff and mypy on PATH, along with your project’s rules and type-checking configuration. Activate your virtual environment or use mise to provide the tools.

Download python-project.pkl and save it as hk.pkl.

Configuration

pkl
/// Ruff linting and formatting, with optional mypy checks.
amends "package://github.com/jdx/hk/releases/download/v2.0.1/hk@2.0.1#/Config.pkl"

import "package://github.com/jdx/hk/releases/download/v2.0.1/hk@2.0.1#/Builtins.pkl"

steps {
  ["ruff"] = Builtins.ruff
  ["ruff-format"] = (Builtins.ruff_format) {
    depends = "ruff"
  }
  ["mypy"] = (Builtins.mypy) {
    profiles = List("types")
  }
}

Try it

sh
hk validate
hk check --all --plan
hk check --all
hk check --all --profile types
hk fix

Ruff’s formatter waits for Ruff’s lint fixes. mypy runs only when types is enabled. The profile must be enabled for the hk invocation; setting HK_PROFILE in a hook’s child-command environment does not select it.

Adapt it

If you prefer Black, replace the ruff-format entry with Builtins.black. Choose one primary formatter to avoid conflicting formatting passes.

For a push hook that always includes mypy, add a pre-push hook that copies the top-level steps and clears mypy’s profile requirement there:

pkl
hooks {
  ["pre-push"] {
    steps = (module.steps) {
      ["mypy"] = (Builtins.mypy) {
        profiles = List()
      }
    }
  }
}

Add this block after the top-level steps block. module.steps refers to those shared steps. Locally and in CI, hk check --all --profile types includes type checking without a separate hook.

MIT LicenseCopyright © 2026jdx.dev