Skip to content

Built-in Linters Reference

hk provides 90+ pre-configured linters and formatters through the Builtins module. These are production-ready configurations that work out of the box.

Usage

Import and use builtins in your hk.pkl:

pkl
amends "package://github.com/jdx/hk/releases/download/v1.35.0/hk@1.35.0#/Config.pkl"
import "package://github.com/jdx/hk/releases/download/v1.35.0/hk@1.35.0#/Builtins.pkl"

hooks {
  ["pre-commit"] {
    steps {
      ["prettier"] = Builtins.prettier
      ["eslint"] = Builtins.eslint
    }
  }
}

You can also customize builtins:

pkl
["prettier"] = (Builtins.prettier) {
  batch = false  // Override the default batch setting
  glob = List("*.js", "*.ts")  // Override file patterns
}

Available Builtins

Uncategorized

actionlint

  • Glob: .github/workflows/*.yml, .github/workflows/*.yaml
  • Check: actionlint {{ files }}

alejandra

  • Glob: **/*.nix
  • Check: alejandra --check {{ files }}
  • Fix: alejandra {{ files }}

asciidoctor

  • Check: asciidoctor --failure-level=WARNING --out-file=/dev/null {{ files }}

astro

  • Glob: **/*.astro
  • Check: astro check {{ files }}

biome

  • Glob: **/*.js, **/*.jsx, **/*.ts, **/*.tsx, **/*.json
  • Check: biome check --no-errors-on-unmatched {{ files }}
  • Fix: biome check --write --no-errors-on-unmatched {{ files }}

black

  • Glob: **/*.py
  • Check: black --check {{ files }}
  • Fix: black {{ files }}

brakeman

  • Check: brakeman -q -w2 {{ files }}

buf-format

  • Glob: **/*.proto
  • Check (diff): buf format {{workspace}} --diff --exit-code
  • Fix: buf format {{workspace}} --write

buf-lint

  • Glob: **/*.proto
  • Check: buf lint {{workspace}}

bundle-audit

  • Glob: **/Gemfile.lock
  • Check: bundle-audit check {{ files }}
  • Fix: bundle-audit update

byte-order-marker

  • Glob: **/*
  • Check (diff): hk util check-byte-order-marker --diff {{files}}
  • Fix: hk util fix-byte-order-marker {{files}}

cargo-check

  • Glob: **/*.rs
  • Check: cargo +nightly check -Zwarnings --quiet
  • Fix: cargo fix --allow-dirty --allow-staged --quiet

cargo-clippy

  • Glob: **/*.rs
  • Check: cargo clippy --manifest-path {{workspace_indicator}} --quiet
  • Fix: cargo clippy --manifest-path {{workspace_indicator}} --fix --allow-dirty --allow-staged --quiet

cargo-fmt

  • Glob: **/*.rs
  • Check: cargo fmt --check --manifest-path {{workspace_indicator}}
  • Fix: cargo fmt --manifest-path {{workspace_indicator}}

check-added-large-files

  • Glob: **/*
  • Check: hk util check-added-large-files {{files}}

check-byte-order-marker

  • Glob: **/*
  • Check (diff): hk util check-byte-order-marker --diff {{files}}
  • Fix: hk util fix-byte-order-marker {{files}}

check-case-conflict

  • Glob: **/*
  • Check: hk util check-case-conflict {{files}}

check-conventional-commit

  • Check: hk util check-conventional-commit {{commit_msg_file}}

check-executables-have-shebangs

  • Glob: **/*
  • Check: hk util check-executables-have-shebangs {{files}}

check-merge-conflict

  • Glob: **/*
  • Check: hk util check-merge-conflict --assume-in-merge {{files}}
  • Glob: **/*
  • Check: hk util check-symlinks {{files}}

clang-format

  • Glob: **/*.c, **/*.h, **/*.cpp, **/*.hpp, **/*.cc, **/*.hh, **/*.cxx, **/*.hxx
  • Check: clang-format --dry-run -Werror {{ files }}
  • Fix: clang-format -i {{ files }}

cpp-lint

  • Glob: **/*.c, **/*.h, **/*.cpp, **/*.hpp, **/*.cc, **/*.hh, **/*.cxx, **/*.hxx
  • Check: cpplint {{ files }}

deno

  • Glob: **/*.js, **/*.jsx, **/*.ts, **/*.tsx
  • Check: deno fmt --check {{ files }}
  • Fix: deno fmt {{ files }}

deno-check

  • Glob: **/*.js, **/*.jsx, **/*.ts, **/*.tsx
  • Check: deno check {{ files }}

detect-private-key

  • Glob: **/*
  • Check: hk util detect-private-key {{files}}

dprint

  • Glob: **/*
  • Check: dprint check --allow-no-files {{ files }}
  • Fix: dprint fmt --allow-no-files {{ files }}

editorconfig-checker

  • Check: ec {{ files }}

erb

  • Glob: **/*.erb
  • Check: erb -P -x -T - {{ files }} | ruby -c

err-check

  • Glob: **/*.go
  • Check: errcheck {{ files }}

eslint

  • Glob: **/*.js, **/*.jsx, **/*.ts, **/*.tsx
  • Check: eslint {{ files }}
  • Fix: eslint --fix {{ files }}

fasterer

  • Check: fasterer {{ files }}

fix-byte-order-marker

  • Glob: **/*
  • Check (diff): hk util check-byte-order-marker --diff {{files}}
  • Fix: hk util fix-byte-order-marker {{files}}

fix-smart-quotes

  • Glob: **/*
  • Check (diff): hk util fix-smart-quotes --diff {{files}}
  • Fix: hk util fix-smart-quotes {{files}}

flake8

  • Glob: **/*.py
  • Check: flake8 {{ files }}

ghalint-action

  • Glob: **/action.*
  • Check: ghalint run-action {{ files }}

ghalint-workflow

  • Glob: .github/workflows/*
  • Check: ghalint run

go-fmt

  • Glob: **/*.go
  • Check (diff): DIFF=$(gofmt -s -d {{files}}) if [ -n "$DIFF" ]; then echo "$DIFF" exit 1 fi
  • Fix: gofmt -s -w {{files}}

go-fumpt

  • Glob: **/*.go
  • Check: gofumpt -l {{ files }}
  • Fix: gofumpt -w {{ files }}

go-imports

  • Glob: **/*.go
  • Check: goimports -l {{ files }}
  • Fix: goimports -w {{ files }}

go-lines

  • Glob: **/*.go
  • Check: golines --dry-run {{ files }}
  • Fix: golines -w {{ files }}

go-sec

  • Glob: **/*.go
  • Check: gosec {{ files }}

go-vet

  • Glob: **/*.go
  • Check: go vet {{ files }}

go-vuln-check

  • Glob: **/*.go
  • Check: govulncheck {{ files }}

golangci-lint

  • Glob: **/*.go
  • Check: golangci-lint run --fix=false {{ files }}
  • Fix: golangci-lint run --fix {{ files }}

gomod-tidy

  • Glob: **/go.mod
  • Check (diff): go mod tidy -diff
  • Fix: go mod tidy

hadolint

  • Glob: **/Dockerfile*
  • Check: hadolint {{ files }}

isort

  • Glob: **/*.py
  • Check: isort --check-only {{ files }}
  • Fix: isort {{ files }}

jq

  • Glob: **/*.json
  • Check (diff): failed=0 for f in {{ files }}; do jq . "$f" | diff -u "$f" - || failed=1 done exit $failed
  • Fix: for f in {{ files }}; do tmp=$(mktemp) && jq -S . "$f" > "$tmp" && mv "$tmp" "$f" done

ktlint

  • Glob: **/*.kt
  • Check: ktlint {{ files }}
  • Fix: ktlint -F {{ files }}

luacheck

  • Check: luacheck {{ files }}

lychee

  • Check: lychee --no-progress {{ files }}

markdown-lint

  • Glob: **/*.md, **/*.markdown
  • Check: markdownlint {{ files }}
  • Fix: markdownlint --fix {{ files }}

mise

  • Glob: mise.toml, mise.*.toml, .mise.toml, .mise.*.toml, mise/config.toml, mise/config.*.toml, .mise/config.toml, .mise/config.*.toml, .config/mise.toml, .config/mise.*.toml, .config/mise/config.toml, .config/mise/config.*.toml, .config/mise/mise.toml, .config/mise/mise.*.toml, .config/mise/conf.d/*.toml
  • Check: mise fmt --check
  • Fix: mise fmt

mix-compile

  • Glob: **/*.ex
  • Check: mix compile --warnings-as-errors --strict-errors {{files}}

mix-fmt

  • Glob: **/*.ex, **/*.exs
  • Check: mix format --check-formatted {{files}}
  • Fix: mix format {{files}}

mix-test

  • Glob: **/*.ex, **/*.exs
  • Check: mix test --warnings-as-errors {{files}}

mixed-line-ending

  • Glob: **/*
  • Check (diff): hk util mixed-line-ending --diff {{files}}
  • Fix: hk util mixed-line-ending --fix {{files}}

mypy

  • Glob: **/*.py, **/*.pyi
  • Check: mypy {{ files }}

newlines

  • Glob: **/*
  • Check (diff): hk util end-of-file-fixer --diff {{files}}
  • Fix: hk util end-of-file-fixer --fix {{files}}

nix-fmt

  • Glob: **/*.nix
  • Check: nixfmt --check {{ files }}
  • Fix: nixfmt {{ files }}

nixpkgs-format

  • Glob: **/*.nix
  • Check: nixpkgs-fmt --check {{ files }}
  • Fix: nixpkgs-fmt {{ files }}

no-commit-to-branch

  • Check: hk util no-commit-to-branch

ox-lint

  • Glob: **/*.js, **/*.jsx, **/*.ts, **/*.tsx
  • Check: oxlint {{ files }}
  • Fix: oxlint --fix {{ files }}

php-cs

  • Glob: **/*.php
  • Check: phpcs {{ files }}
  • Fix: phpcbf {{ files }}

pinact

  • Glob: .github/workflows/*, */action.*
  • Check (diff): pinact run --verify --check {{ files }}
  • Fix: pinact run --verify {{ files }}

pinact-update

  • Glob: .github/workflows/*, */action.*
  • Check (diff): pinact run --update --verify --check {{ files }}
  • Fix: pinact run --update --verify {{ files }}

pkl

  • Check: pkl eval {{files}} >/dev/null

pkl-format

  • Check (list-files): pkl format --diff-name-only {{ files }}
  • Fix: pkl format --write {{ files }} code=$? if [ $code -eq 11 ]; then exit 0 else exit $code fi

prettier

  • Glob: **/*.js, **/*.jsx, **/*.mjs, **/*.cjs, **/*.ts, **/*.tsx, **/*.mts, **/*.cts, **/*.css, **/*.scss, **/*.less, **/*.html, **/*.json, **/*.json5, **/*.jsonc, **/*.yaml, **/*.yml, **/*.markdown, **/*.markdown.mdx, **/*.md, **/*.graphql, **/*.handlebars, **/*.svelte, **/*.astro, **/*.htmlangular, **/*.vue
  • Check: prettier --check {{ files }}
  • Fix: prettier --write {{ files }}

pylint

  • Glob: **/*.py
  • Check: pylint {{ files }}

python-check-ast

  • Glob: **/*.py
  • Check: hk util python-check-ast {{files}}

python-debug-statements

  • Glob: **/*.py
  • Check: hk util python-debug-statements {{files}}

reek

  • Check: reek {{ files }}

revive

  • Glob: **/*.go
  • Check: revive {{ files }}

rubocop

  • Check: rubocop --force-exclusion {{ files }}
  • Fix: rubocop --force-exclusion --autocorrect {{ files }}

ruff

  • Glob: **/*.py, **/*.pyi
  • Check: ruff check --force-exclude {{ files }}
  • Fix: ruff check --force-exclude --fix {{ files }}

ruff-format

  • Glob: **/*.py, **/*.pyi
  • Check: ruff format --force-exclude --check {{ files }}
  • Fix: ruff format --force-exclude {{ files }}

rumdl

  • Glob: **/*.md, **/*.markdown
  • Check (diff): rumdl check --diff {{ files }}
  • Fix: rumdl check --fix {{ files }}

rustfmt

  • Glob: **/*.rs
  • Check: rustfmt --check --edition 2024 {{ files }}
  • Fix: rustfmt --edition 2024 {{ files }}

ryl

  • Check: ryl {{ files }}

selene

  • Check (diff): selene {{ files }}

shellcheck

  • Glob: **/*.sh, **/*.bash
  • Check: shellcheck {{ files }}

shfmt

  • Glob: **/*.sh, **/*.bash, **/*.mksh, **/*.bats, **/*.zsh
  • Check (diff): shfmt -d --apply-ignore {{ files }}
  • Fix: shfmt -w --apply-ignore {{ files }}

sorbet

  • Check: srb tc {{ files }}

sort-package-json

  • Glob: **/package.json
  • Check: sort-package-json --check {{ files }}
  • Fix: sort-package-json {{ files }}

sql-fluff

  • Glob: **/*.sql
  • Check: sqlfluff lint {{ files }}
  • Fix: sqlfluff fix {{ files }}

standard-js

  • Glob: **/*.js, **/*.jsx, **/*.ts, **/*.tsx
  • Check: standard {{ files }}
  • Fix: standard --fix {{ files }}

standard-rb

  • Check: standardrb {{ files }}
  • Fix: standardrb --fix {{ files }}

staticcheck

  • Glob: **/*.go
  • Check: staticcheck {{ files }}

stylelint

  • Glob: **/*.css, **/*.scss, **/*.sass, **/*.less
  • Check: stylelint {{ files }}
  • Fix: stylelint --fix {{ files }}

stylua

  • Check (diff): stylua --check {{ files }}
  • Fix: stylua {{ files }}

swiftlint

  • Glob: **/*.swift
  • Check: swiftlint lint {{ files }}
  • Fix: swiftlint --fix {{ files }}

taplo

  • Glob: **/*.toml
  • Check: taplo lint {{ files }}

taplo-format

  • Glob: **/*.toml
  • Check: taplo format --check {{ files }}
  • Fix: taplo format {{ files }}

terraform

  • Glob: **/*.tf, **/*.tfvars, **/*.tftest.hcl
  • Check (list-files): terraform fmt -check {{ files }}
  • Fix: terraform fmt {{ files }}

tf-lint

  • Glob: **/*.tf
  • Check: tflint
  • Fix: tflint --fix

tofu

  • Glob: **/*.tf, **/*.tfvars, **/*.tftest.hcl
  • Check (list-files): tofu fmt -check {{ files }}
  • Fix: tofu fmt {{ files }}

tombi

  • Glob: **/*.toml
  • Check: tombi lint {{ files }}

tombi-format

  • Glob: **/*.toml
  • Check (diff): tombi format --check --diff {{ files }}
  • Fix: tombi format {{ files }}

trailing-whitespace

  • Glob: **/*
  • Check (diff): hk util trailing-whitespace --diff {{files}}
  • Fix: hk util trailing-whitespace --fix {{files}}

tsc

  • Glob: **/*.ts, **/*.tsx
  • Check: tsc --noEmit -p {{workspace_indicator}}

tsserver

  • Glob: **/*.ts, **/*.tsx
  • Check: tsc-files --noEmit {{ files }}

typos

  • Glob: **/*
  • Check (diff): output=$(typos --diff {{files}}) [ -z "$output" ] && exit 0 printf "%s" "$output" exit 1
  • Fix: typos --write-changes {{ files }}

vacuum

  • Glob: **/*openapi*.yaml, **/*openapi*.yml, **/*openapi*.json, **/*swagger*.yaml, **/*swagger*.yml, **/*swagger*.json
  • Check: vacuum lint {{files}}
  • Fix: vacuum lint --fix {{files}}

vale

  • Check: vale sync && vale {{ files }}

xmllint

  • Glob: **/*.xml
  • Check: xmllint --noout {{ files }}

xo

  • Glob: **/*.js, **/*.jsx, **/*.ts, **/*.tsx
  • Check: xo {{ files }}
  • Fix: xo --fix {{ files }}

yamlfmt

  • Glob: **/*.yml, **/*.yaml
  • Check (diff): yamlfmt -lint {{ files }}
  • Fix: yamlfmt {{ files }}

yamllint

  • Glob: **/*.yml, **/*.yaml
  • Check: yamllint {{ files }}

yq

  • Glob: **/*.yaml, **/*.yml
  • Check (diff): failed=0 for f in {{ files }}; do yq -P "$f" | diff -u "$f" - || failed=1 done exit $failed
  • Fix: yq -iP {{ files }}

zizmor

  • Glob: .github/workflows/*.yml, .github/workflows/*.yaml, .github/dependabot.yml, **/action.yml, **/action.yaml
  • Check (diff): zizmor --no-progress {{ files }}
  • Fix: zizmor --no-progress --fix {{ files }}

Customizing Builtins

Override Properties

pkl
["prettier"] = (Builtins.prettier) {
  // Override glob patterns
  glob = List("src/**/*.js", "src/**/*.ts")

  // Disable batch processing
  batch = false

  // Add environment variables
  env {
    ["PRETTIER_CONFIG"] = ".prettierrc.json"
  }
}

Add Dependencies

pkl
["eslint"] = (Builtins.eslint) {
  // Run after prettier
  depends = "prettier"
}

Workspace-Specific Configuration

pkl
["cargo_clippy"] = (Builtins.cargo_clippy) {
  // Only run in directories with Cargo.toml
  workspace_indicator = "Cargo.toml"

  // Custom command using workspace
  check = "cargo clippy --manifest-path {{workspace}}/Cargo.toml"
}

Profile-Based Configuration

pkl
["mypy"] = (Builtins.mypy) {
  // Only run with "python" profile
  profiles = List("python")
}

Creating Custom Steps

If a builtin doesn't exist for your tool:

pkl
["custom-tool"] {
  glob = List("*.custom")
  check = "custom-tool --check {{files}}"
  fix = "custom-tool --fix {{files}}"
  batch = true  // Enable parallel processing
}

See Also

Licensed under the MIT License. Maintained by @jdx and friends.