The standing crew: built-in linters
Builtins be the standing crew who come with the ship: reusable Pkl step definitions for linters, formatters, and hk's own utilities. Between them they bring file patterns, check and fix commands, and optimizations such as diff output.
Bring the tools aboard separately. A builtin calls on executables from yer environment; it does not install them. Provision them with yer project's package manager or with mise, the quartermaster.
Muster a builtin
amends "package://github.com/jdx/hk/releases/download/v2.4.0/hk@2.4.0#/Config.pkl"
import "package://github.com/jdx/hk/releases/download/v2.4.0/hk@2.4.0#/Builtins.pkl"
hooks {
["check"] {
steps {
["prettier"] = Builtins.prettier
["eslint"] = Builtins.eslint
}
}
}Builtins.prettier is the Pkl property name, the name the hand goes by on the roster. The step name, "prettier", is yer own label for that hand, the one ye name in calls such as hk check --step prettier.
Aye, and keep the schema and Builtins imports on the same version. The roster below describes the version of the source this website was built from; an older pinned package may differ.
Refit a builtin
Amend a builtin to keep its defaults while ye change particular properties:
["prettier"] = (Builtins.prettier) {
glob = List("*.js", "*.ts", "*.json")
exclude = List("**/generated/**")
batch = false
}Mind this: a property assignment replaces that property whole. If ye override glob or exclude, include every pattern ye want to keep.
Use dependencies to set the order the hands work in, and profiles (the ship's watches) for optional checks:
["prettier"] = (Builtins.prettier) {
depends = "eslint"
}
["mypy"] = (Builtins.mypy) {
profiles = List("types")
}Run the type checker by calling its watch: hk check --profile types. See the configuration charts for groups, workspaces, and command templates.
Utilities hk carries aboard
Hands such as Builtins.trailing_whitespace, Builtins.newlines, and Builtins.check_merge_conflict call on hk util commands. These sail with hk itself and need no separate linter executable.
Tools on hand
A builtin charts how hk calls a tool; it does not install that tool. The executable the builtin uses must be on PATH, or the step must use a prefix that resolves it.
With the standing order HK_MISE=1, hk resolves the quartermaster's mise environment for the step's own directory, so tools declared in a subproject's mise.toml are on hand without a prefix. For a Node tool installed locally by aube, prefix its builtin with aube exec:
["eslint"] = (Builtins.eslint) {
prefix = List("aube", "exec")
}Mind ye, use an argv list for builtins backed by structured commands. A string prefix such as "aube exec" or "mise x --" cannot be combined with those commands.
The crew roster
The roster below is generated from the builtin definitions themselves, so it stays in plain English. Each entry gives the exact Pkl property to call the hand by. Look to the source definitions for more options and tests.
.NET
dotnet-format
Pkl: Builtins.dotnet_format
Format C# and Visual Basic with the .NET SDK
- Glob:
**/*.cs,**/*.vb - Check:
dotnet format --verify-no-changes --include {{files}} - Fix:
dotnet format --include {{files}}
AsciiDoc
asciidoctor
Pkl: Builtins.asciidoctor
AsciiDoc syntax validator and processor
- Check:
asciidoctor --failure-level=WARNING --out-file=/dev/null {{files}}
Build Systems
buildifier-format
Pkl: Builtins.buildifier_format
Formatter for Bazel BUILD, WORKSPACE, and Starlark files
- Glob:
**/BUILD,**/BUILD.bazel,WORKSPACE,WORKSPACE.bazel,MODULE.bazel,**/*.bzl,**/*.star,**/*.sky - Check:
buildifier -mode=check {{files}} - Check (diff):
hk util format-diff {{files}} -- buildifier '-path={}' - Fix:
buildifier {{files}}
buildifier-lint
Pkl: Builtins.buildifier_lint
Linter for Bazel BUILD, WORKSPACE, and Starlark files
- Glob:
**/BUILD,**/BUILD.bazel,WORKSPACE,WORKSPACE.bazel,MODULE.bazel,**/*.bzl,**/*.star,**/*.sky - Check:
buildifier -mode=check -lint=warn {{files}} - Fix:
buildifier -lint=fix {{files}}
CSS
stylelint
Pkl: Builtins.stylelint
CSS linter
- Glob:
**/*.css,**/*.scss,**/*.sass,**/*.less - Check:
stylelint {{files}} - Fix:
stylelint --fix {{files}}
Configuration
sort-package-json
Pkl: Builtins.sort_package_json
Sort package.json keys
- Glob:
**/package.json - Check:
sort-package-json --check {{files}} - Fix:
sort-package-json {{files}}
Data Formats
buf-format
Pkl: Builtins.buf_format
Protocol Buffers formatter
- Glob:
**/*.proto - Check (diff):
buf format {{workspace}} --diff --exit-code - Fix:
buf format {{workspace}} --write
buf-lint
Pkl: Builtins.buf_lint
Protocol Buffers linter
- Glob:
**/*.proto - Check:
buf lint {{workspace}}
jq
Pkl: Builtins.jq
JSON processor
Glob:
**/*.jsonCheck (diff):
shfailed=0 broken=0 trap 'rm -f "$out" "$patch" "$new"' EXIT trap 'exit 2' HUP INT TERM out=$(mktemp) && patch=$(mktemp) && new=$(mktemp) || exit 2 n=0 set -- for f in {{ files }}; do n=$((n + 1)) set -- "$@" --rawfile "f$n" "$f" done # Each file's output follows \u001e, which formatted JSON never # contains, and is \u001f if jq cannot parse the file. todo=all if [ "$n" -gt 1 ] && jq -n -j -S --argjson n "$n" "$@" ' range(1; $n + 1) as $i | "\u001e", ($ARGS.named["f\($i)"] | try (fromjson | if type == "string" then tojson else . end, "\n") catch "\u001f") ' > "$new" 2>/dev/null; then todo=$(jq -n -r --argjson n "$n" --rawfile new "$new" "$@" ' ($new | split("\u001e")) as $new | [range(1; $n + 1) | select($new[.] != $ARGS.named["f\(.)"] or ($new[.] | contains("\u001f") or contains("\ufffd"))) | tostring] | " " + join(" ") + " " ' 2>/dev/null) || todo=all fi i=0 for f in {{ files }}; do i=$((i + 1)) case $todo in all | *" $i "*) ;; *) continue ;; esac if jq -S . "$f" > "$out"; then # hk runs this with `set -e`, so take diff's status through `||`. status=0 diff -u -L "a/$f" -L "b/$f" "$f" "$out" >> "$patch" || status=$? case $status in 0) ;; 1) failed=1 ;; *) broken=1 ;; esac else broken=1 fi done # When a file failed to parse or diff, print no patch: hk then runs the # fixer on every file, and the fixer reports the error. [ "$broken" = 1 ] && exit 1 cat "$patch" || exit 2 exit $failedFix:
shfailed=0 tmp= trap 'rm -f "$tmp"' EXIT trap 'exit 2' HUP INT TERM for f in {{ files }}; do # Write a copy beside the file, with its permissions, then rename it # over the file, so a failed write never truncates the original. A # file that is already formatted is left alone, links and all. tmp=$(mktemp "$f.XXXXXX") && cp -p "$f" "$tmp" && jq -S . "$f" > "$tmp" && { cmp -s "$f" "$tmp" || mv "$tmp" "$f"; } || failed=1 rm -f "$tmp" tmp= done exit $failed
sql-fluff
Pkl: Builtins.sql_fluff
SQL linter and formatter
- Glob:
**/*.sql - Check:
sqlfluff lint {{files}} - Fix:
sqlfluff fix {{files}}
taplo
Pkl: Builtins.taplo
TOML linter
- Glob:
**/*.toml - Check:
taplo lint {{files}}
taplo-format
Pkl: Builtins.taplo_format
TOML formatter
- Glob:
**/*.toml - Check:
taplo format --check --diff {{files}} - Fix:
taplo format {{files}}
tombi
Pkl: Builtins.tombi
TOML linter
- Glob:
**/*.toml - Check:
tombi lint --quiet {{files}}
tombi-format
Pkl: Builtins.tombi_format
TOML formatter
- Glob:
**/*.toml - Check:
tombi format --quiet --check --diff {{files}} - Check (diff):
hk util format-diff {{files}} -- tombi format --quiet --stdin-filename '{}' - - Fix:
tombi format --quiet {{files}}
xmllint
Pkl: Builtins.xmllint
XML validator
- Glob:
**/*.xml - Check:
xmllint --noout {{files}}
yamlfmt
Pkl: Builtins.yamlfmt
YAML formatter
- Glob:
**/*.yml,**/*.yaml - Check:
yamlfmt -lint {{files}} - Fix:
yamlfmt {{files}}
yamllint
Pkl: Builtins.yamllint
YAML linter
- Glob:
**/*.yml,**/*.yaml - Check:
yamllint --strict {{files}}
yq
Pkl: Builtins.yq
YAML processor
Glob:
**/*.yaml,**/*.ymlCheck (diff):
shfailed=0 broken=0 trap 'rm -rf "$out" "$patch" "$split"' EXIT trap 'exit 2' HUP INT TERM out=$(mktemp) && patch=$(mktemp) && split=$(mktemp -d) || exit 2 set -- for f in {{ files }}; do case $f in *.[yY][aA][mM][lL] | *.[yY][mM][lL]) set -- "$@" "$f" ;; esac done fast=0 if [ $# -gt 1 ] && YQ_SPLIT="$split/" yq -P -N -s 'strenv(YQ_SPLIT) + (file_index | tostring) + "-" + (document_index | tostring)' "$@" > /dev/null 2>&1; then fast=1 fi i=0 for f in {{ files }}; do new= case $f in *.[yY][aA][mM][lL] | *.[yY][mM][lL]) new="$split/$i-0.yml" i=$((i + 1)) ;; esac if [ "$fast" = 1 ] && [ -n "$new" ] && [ -f "$new" ] && [ ! -e "${new%-0.yml}-1.yml" ] && cmp -s "$f" "$new"; then continue fi if yq -P "$f" > "$out"; then # hk runs this with `set -e`, so take diff's status through `||`. status=0 diff -u -L "a/$f" -L "b/$f" "$f" "$out" >> "$patch" || status=$? case $status in 0) ;; 1) failed=1 ;; *) broken=1 ;; esac else broken=1 fi done # When a file failed to parse or diff, print no patch: hk then runs the # fixer on every file, and the fixer reports the error. [ "$broken" = 1 ] && exit 1 cat "$patch" || exit 2 exit $failedFix:
shfailed=0 for f in {{ files }}; do yq -iP "$f" || failed=1 done exit $failed
EditorConfig
editorconfig-checker
Pkl: Builtins.editorconfig_checker
Validate files against EditorConfig rules
- Check:
editorconfig-checker {{files}} - Fix:
editorconfig-checker --fix {{files}}
Elixir
mix-compile
Pkl: Builtins.mix_compile
Compile Elixir with Mix
- Glob:
**/*.ex - Check:
mix compile --warnings-as-errors --strict-errors {{files}}
mix-fmt
Pkl: Builtins.mix_fmt
Format Elixir with Mix
- Glob:
**/*.ex,**/*.exs - Check:
mix format --check-formatted {{files}} - Fix:
mix format {{files}}
mix-test
Pkl: Builtins.mix_test
Test Elixir with Mix
- Glob:
**/*.ex,**/*.exs - Check:
mix test --warnings-as-errors {{files}}
Go
err-check
Pkl: Builtins.err_check
Error handling checker
- Glob:
**/*.go - Check:
errcheck ./...
go-fix
Pkl: Builtins.go_fix
Go modernizer (requires Go 1.26+)
- Glob:
**/*.go - Check (diff):
go fix -diff ./... - Fix:
go fix ./...
go-fmt
Pkl: Builtins.go_fmt
Go formatter
Glob:
**/*.goCheck (diff):
shDIFF=$(gofmt -s -d {{files}}) if [ -n "$DIFF" ]; then echo "$DIFF" exit 1 fiCheck (list files):
shFILES=$(gofmt -s -l {{files}}) if [ -n "$FILES" ]; then echo "$FILES" exit 1 fiFix:
gofmt -s -w {{files}}
go-fumpt
Pkl: Builtins.go_fumpt
Strict Go formatter
Glob:
**/*.goCheck (diff):
gofumpt -d {{files}}Check (list files):
shFILES=$(gofumpt -l {{files}}) if [ -n "$FILES" ]; then echo "$FILES" exit 1 fiFix:
gofumpt -w {{files}}
go-imports
Pkl: Builtins.go_imports
Go import management
Glob:
**/*.goCheck (diff):
shDIFF=$(goimports -d {{files}}) if [ -n "$DIFF" ]; then echo "$DIFF" exit 1 fiCheck (list files):
shFILES=$(goimports -l {{files}}) if [ -n "$FILES" ]; then echo "$FILES" exit 1 fiFix:
goimports -w {{files}}
go-lines
Pkl: Builtins.go_lines
Long line fixer
- Glob:
**/*.go - Check (diff):
hk util format-diff {{files}} -- golines - Fix:
golines -w {{files}}
go-sec
Pkl: Builtins.go_sec
Security scanner
- Glob:
**/*.go - Check:
gosec ./...
go-vet
Pkl: Builtins.go_vet
Go code vetting
- Glob:
**/*.go - Check:
go vet ./...
go-vuln-check
Pkl: Builtins.go_vuln_check
Vulnerability scanner
- Glob:
**/*.go - Check:
govulncheck ./...
golangci-lint
Pkl: Builtins.golangci_lint
Go meta-linter
- Glob:
**/*.go - Check:
golangci-lint run --fix=false ./... - Fix:
golangci-lint run --fix ./...
golangci-lint-fmt
Pkl: Builtins.golangci_lint_fmt
Go formatter (part of golangci-lint)
- Glob:
**/*.go - Check (diff):
golangci-lint fmt --diff {{files}} - Fix:
golangci-lint fmt {{files}}
gomod-tidy
Pkl: Builtins.gomod_tidy
Go module maintenance
- Glob:
**/*.go,**/go.mod,**/go.sum - Check (diff):
go mod tidy -diff - Fix:
go mod tidy
revive
Pkl: Builtins.revive
Fast Go linter
- Glob:
**/*.go - Check:
revive -set_exit_status ./...
staticcheck
Pkl: Builtins.staticcheck
Go static analysis
- Glob:
**/*.go - Check:
staticcheck ./...
Infrastructure
actionlint
Pkl: Builtins.actionlint
GitHub Actions workflow linter
- Glob:
.github/workflows/*.yml,.github/workflows/*.yaml - Check:
actionlint {{files}}
dclint
Pkl: Builtins.dclint
Docker Compose linter
- Glob:
**/compose*.yml,**/compose*.yaml,**/docker-compose*.yml,**/docker-compose*.yaml - Check:
dclint {{files}} - Fix:
dclint --fix {{files}}
droast
Pkl: Builtins.droast
Dockerfile linter for security, layer hygiene, and best-practice violations
- Glob:
**/Dockerfile,**/Dockerfile.*,**/*.Dockerfile,**/*.dockerfile,**/Containerfile,**/Containerfile.* - Check:
droast {{files}} - Fix:
droast --fix {{files}}
ghalint-action
Pkl: Builtins.ghalint_action
GitHub Actions action linter
- Glob:
**/action.* - Check:
ghalint run-action {{files}}
ghalint-workflow
Pkl: Builtins.ghalint_workflow
GitHub Actions workflow linter
- Glob:
.github/workflows/* - Check:
ghalint run
hadolint
Pkl: Builtins.hadolint
Dockerfile linter
- Glob:
**/Dockerfile* - Check:
hadolint {{files}}
hclfmt
Pkl: Builtins.hclfmt
Hashicorp's hclfmt
- Glob:
**/*.hcl - Fix:
hclfmt -w {{files}}
kube-linter
Pkl: Builtins.kube_linter
Check Kubernetes manifests for security and reliability issues
- Glob:
**/k8s/**/*.yaml,**/k8s/**/*.yml,**/kubernetes/**/*.yaml,**/kubernetes/**/*.yml,**/manifests/**/*.yaml,**/manifests/**/*.yml,**/deploy/**/*.yaml,**/deploy/**/*.yml,**/deployments/**/*.yaml,**/deployments/**/*.yml - Check:
kube-linter lint --fail-if-no-objects-found {{files}}
kubeconform
Pkl: Builtins.kubeconform
Kubernetes manifest validator
- Glob:
**/k8s/**/*.yaml,**/k8s/**/*.yml,**/kubernetes/**/*.yaml,**/kubernetes/**/*.yml,**/manifests/**/*.yaml,**/manifests/**/*.yml,**/deploy/**/*.yaml,**/deploy/**/*.yml,**/deployments/**/*.yaml,**/deployments/**/*.yml - Check:
kubeconform -summary -strict -ignore-missing-schemas {{files}}
mise
Pkl: Builtins.mise
mise-en-place's built-in formatter and linter
- 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
pinact
Pkl: Builtins.pinact
Pin GitHub Actions to commit SHA for security
- Glob:
.github/workflows/*,**/action.* - Check:
pinact run --verify-comment --check {{files}} - Check (diff):
hk util sarif-diff -- pinact run --verify-comment --check --format sarif {{files}} - Fix:
pinact run --verify-comment {{files}}
pinact-update
Pkl: Builtins.pinact_update
Pin GitHub Actions to update actions to latest versions
- Glob:
.github/workflows/*,**/action.* - Check:
pinact run --update --verify-comment --check {{files}} - Check (diff):
hk util sarif-diff -- pinact run --update --verify-comment --check --format sarif {{files}} - Fix:
pinact run --update --verify-comment {{files}}
terraform
Pkl: Builtins.terraform
Terraform formatter
- Glob:
**/*.tf,**/*.tfvars,**/*.tftest.hcl - Check:
terraform fmt -check {{files}} - Check (diff):
hk util format-diff {{files}} -- terraform fmt - - Fix:
terraform fmt {{files}}
terraform-docs
Pkl: Builtins.terraform_docs
Terraform module documentation generator
Glob:
**/*.tf,**/*.tofu,**/.terraform.lock.hclCheck:
shfor f in {{ files }}; do dirname "$f"; done | sort -u | { code=0; while IFS= read -r dir; do terraform-docs markdown table --output-check --output-file README.md --output-mode inject "$dir" || code=1 done; exit $code; }Fix:
shfor f in {{ files }}; do dirname "$f"; done | sort -u | { code=0; while IFS= read -r dir; do terraform-docs markdown table --output-file README.md --output-mode inject "$dir" || code=1 done; exit $code; }
terraform-validate
Pkl: Builtins.terraform_validate
Terraform configuration validator
Glob:
**/*.tf,**/*.tfvars,**/*.tf.json,**/*.tofu,**/.terraform.lock.hclCheck:
shfor f in {{ files }}; do dirname "$f"; done | sort -u | { code=0; while IFS= read -r dir; do terraform -chdir="$dir" validate && continue terraform -chdir="$dir" init -backend=false -input=false > /dev/null || { code=1; continue; } terraform -chdir="$dir" validate || code=1 done; exit $code; }
terragrunt-hcl-fmt
Pkl: Builtins.terragrunt_hcl_fmt
Terragrunt HCL formatter
Glob:
**/*.hclCheck:
shset -- for f in {{ files }}; do set -- "$@" "--filter=./$f"; done if [ "$#" -eq 0 ]; then exit 0; fi terragrunt hcl fmt --check --diff "$@"Fix:
shset -- for f in {{ files }}; do set -- "$@" "--filter=./$f"; done if [ "$#" -eq 0 ]; then exit 0; fi terragrunt hcl fmt "$@"
terragrunt-hcl-validate
Pkl: Builtins.terragrunt_hcl_validate
Terragrunt HCL validator
Glob:
**/*.hclCheck:
shset -- for f in {{ files }}; do case "$f" in */*) d="./${f%/*}" ;; *) d="." ;; esac set -- "$@" "--filter=$d" "--filter=reading=./$f" done if [ "$#" -eq 0 ]; then exit 0; fi terragrunt hcl validate --show-config-path --log-level error "$@"
tf-lint
Pkl: Builtins.tf_lint
Terraform linter
Glob:
**/*.tf,**/*.tfvars,**/*.tofuCheck:
shfor f in {{ files }}; do dirname "$f"; done | sort -u | { code=0; while IFS= read -r dir; do tflint --chdir="$dir" || code=1 done; exit $code; }Fix:
shfor f in {{ files }}; do dirname "$f"; done | sort -u | { code=0; while IFS= read -r dir; do tflint --chdir="$dir" --fix || tflint --chdir="$dir" || code=1 done; exit $code; }
tofu
Pkl: Builtins.tofu
OpenTofu formatter
- Glob:
**/*.tf,**/*.tfvars,**/*.tftest.hcl - Check:
tofu fmt -check {{files}} - Check (diff):
hk util format-diff {{files}} -- tofu fmt - - Fix:
tofu fmt {{files}}
zizmor
Pkl: Builtins.zizmor
GitHub Actions security static analysis tool
- Glob:
.github/workflows/*.yml,.github/workflows/*.yaml,.github/dependabot.yml,**/action.yml,**/action.yaml - Check:
zizmor --no-progress {{files}} - Fix:
zizmor --no-progress --fix {{files}}
Java
google-java-format
Pkl: Builtins.google_java_format
Google Java Format
- Glob:
**/*.java - Check:
google-java-format --dry-run --set-exit-if-changed {{files}} - Check (list files):
google-java-format --dry-run {{files}} - Fix:
google-java-format --replace {{files}}
JavaScript/TypeScript
biome
Pkl: Builtins.biome
Fast formatter and linter
- Glob:
**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.json - Check:
biome check --no-errors-on-unmatched {{files}} - Fix:
biome check --write --no-errors-on-unmatched {{files}}
deno
Pkl: Builtins.deno
Deno formatter
- Glob:
**/*.js,**/*.jsx,**/*.ts,**/*.tsx - Check:
deno fmt --check {{files}} - Fix:
deno fmt {{files}}
deno-check
Pkl: Builtins.deno_check
Deno type checker
- Glob:
**/*.js,**/*.jsx,**/*.ts,**/*.tsx - Check:
deno check {{files}}
eslint
Pkl: Builtins.eslint
Pluggable JavaScript linter
- Glob:
**/*.js,**/*.jsx,**/*.ts,**/*.tsx - Check:
eslint {{files}} - Fix:
eslint --fix {{files}}
knip
Pkl: Builtins.knip
Find unused files, dependencies, and exports
- Check:
knip --no-progress --directory {{workspace}} - Fix:
knip --fix --no-progress --directory {{workspace}}
ox-lint
Pkl: Builtins.ox_lint
Oxidation compiler linter
- Glob:
**/*.js,**/*.mjs,**/*.cjs,**/*.ts,**/*.mts,**/*.cts,**/*.jsx,**/*.tsx,**/*.vue,**/*.svelte,**/*.astro - Check:
oxlint --deny-warnings {{files}} - Fix:
oxlint --deny-warnings --fix {{files}}
oxfmt
Pkl: Builtins.oxfmt
Fast Rust-powered code formatter (Prettier compatible)
- Glob:
**/*.js,**/*.mjs,**/*.cjs,**/*.ts,**/*.mts,**/*.cts,**/*.jsx,**/*.tsx,**/*.mdx,**/*.vue,**/*.json,**/*.jsonc,**/*.json5,**/*.yaml,**/*.yml,**/*.toml,**/*.md,**/*.markdown,**/*.html,**/*.htm,**/*.css,**/*.scss,**/*.less,**/*.graphql,**/*.gql,**/*.handlebars,**/*.hbs - Check:
oxfmt --check --no-error-on-unmatched-pattern {{files}} - Check (diff):
hk util format-diff {{files}} -- oxfmt --stdin-filepath '{}' - Fix:
oxfmt --write --no-error-on-unmatched-pattern {{files}}
prettier
Pkl: Builtins.prettier
Opinionated code formatter
- 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}} - Check (list files):
prettier --list-different {{files}} - Fix:
prettier --write {{files}}
sherif
Pkl: Builtins.sherif
Opinionated, zero-config linter for TypeScript & JavaScript monorepos
- Glob:
**/package.json,**/pnpm-workspace.yaml - Check:
sherif - Fix:
sherif --fix --no-install
standard-js
Pkl: Builtins.standard_js
JavaScript Standard Style
- Glob:
**/*.js,**/*.jsx,**/*.ts,**/*.tsx - Check:
standard {{files}} - Fix:
standard --fix {{files}}
tsc
Pkl: Builtins.tsc
TypeScript type checker
- Glob:
**/*.ts,**/*.tsx - Check:
tsc --noEmit -p {{workspace_indicator}}
tsserver
Pkl: Builtins.tsserver
TypeScript language server diagnostics
- Glob:
**/*.ts,**/*.tsx - Check:
tsc-files --noEmit {{files}}
vp-check
Pkl: Builtins.vp_check
Formats, lints, and type checks code together
- Glob:
**/*.js,**/*.mjs,**/*.cjs,**/*.ts,**/*.mts,**/*.cts,**/*.jsx,**/*.tsx,**/*.mdx,**/*.vue,**/*.svelte,**/*.astro,**/*.json,**/*.jsonc,**/*.json5,**/*.yaml,**/*.yml,**/*.md,**/*.markdown,**/*.html,**/*.htm,**/*.css,**/*.scss,**/*.less,**/*.graphql,**/*.gql,**/*.handlebars,**/*.hbs,**/*.toml - Check:
vp check {{files}} - Fix:
vp check --fix {{files}}
vp-fmt
Pkl: Builtins.vp_fmt
Formats code with Oxfmt
- Glob:
**/*.js,**/*.mjs,**/*.cjs,**/*.ts,**/*.mts,**/*.cts,**/*.jsx,**/*.tsx,**/*.mdx,**/*.vue,**/*.json,**/*.jsonc,**/*.json5,**/*.yaml,**/*.yml,**/*.toml,**/*.md,**/*.markdown,**/*.html,**/*.htm,**/*.css,**/*.scss,**/*.less,**/*.graphql,**/*.gql,**/*.handlebars,**/*.hbs - Check:
vp fmt --check {{files}} - Check (list files):
vp fmt --list-different {{files}} - Fix:
vp fmt {{files}}
vp-lint
Pkl: Builtins.vp_lint
Lints code with OxLint
- Glob:
**/*.js,**/*.mjs,**/*.cjs,**/*.ts,**/*.mts,**/*.cts,**/*.jsx,**/*.tsx,**/*.mdx,**/*.vue,**/*.svelte,**/*.astro - Check:
vp lint --deny-warnings {{files}} - Fix:
vp lint --deny-warnings --fix {{files}}
xo
Pkl: Builtins.xo
JavaScript/TypeScript linter with great defaults
- Glob:
**/*.js,**/*.jsx,**/*.ts,**/*.tsx - Check:
xo {{files}} - Fix:
xo --fix {{files}}
Lua
luacheck
Pkl: Builtins.luacheck
Lua linter
- Check:
luacheck {{files}}
selene
Pkl: Builtins.selene
Lua linter
- Check:
selene {{files}}
stylua
Pkl: Builtins.stylua
Lua formatter
- Check:
stylua --check {{files}} - Check (diff):
hk util format-diff {{files}} -- stylua --stdin-filepath '{}' - - Fix:
stylua {{files}}
Markdown
contextlint
Pkl: Builtins.contextlint
Rule-based linter for structured Markdown documents
- Check:
contextlint {{files}}
mado
Pkl: Builtins.mado
Fast Markdown linter (CommonMark/GFM)
- Check:
mado check {{files}}
markdown-lint
Pkl: Builtins.markdown_lint
Markdown linter
- Glob:
**/*.md,**/*.markdown - Check:
markdownlint {{files}} - Fix:
markdownlint --fix {{files}}
mdschema
Pkl: Builtins.mdschema
Schema-based Markdown documentation validator
- Check:
mdschema check {{files}}
rumdl
Pkl: Builtins.rumdl
Markdown linter
- Glob:
**/*.md,**/*.markdown - Check:
rumdl check {{files}} - Check (diff):
rumdl check --diff {{files}} - Fix:
rumdl check --fix {{files}}
rumdl-format
Pkl: Builtins.rumdl_format
Markdown formatter
- Glob:
**/*.md,**/*.markdown - Check (diff):
rumdl fmt --check --diff {{files}} - Fix:
rumdl fmt {{files}}
ryl-markdown
Pkl: Builtins.ryl_markdown
Lint YAML embedded in Markdown (front matter + fenced yaml blocks) with ryl
- Check:
ryl --markdown {{files}} - Check (diff):
ryl --diff --markdown {{files}} - Check (list files):
ryl --list-files --markdown {{files}} - Fix:
ryl --fix --markdown {{files}}
Nix
alejandra
Pkl: Builtins.alejandra
Alternative Nix formatter
- Glob:
**/*.nix - Check:
alejandra --check {{files}} - Fix:
alejandra {{files}}
deadnix
Pkl: Builtins.deadnix
Scan Nix files for dead code
- Glob:
**/*.nix - Check:
deadnix --fail {{files}} - Fix:
deadnix --edit {{files}}
nil
Pkl: Builtins.nil
Nix Language server
- Glob:
**/*.nix - Check:
nil diagnostics --deny-warnings {{files}}
nix-fmt
Pkl: Builtins.nix_fmt
Nix formatter
- Glob:
**/*.nix
nixf-diagnose
Pkl: Builtins.nixf_diagnose
Nix linter based on libnixf
- Glob:
**/*.nix - Check:
nixf-diagnose {{files}}
nixpkgs-format
Pkl: Builtins.nixpkgs_format
Nixpkgs formatter
- Glob:
**/*.nix - Check:
nixpkgs-fmt --check {{files}} - Fix:
nixpkgs-fmt {{files}}
Other Languages
astro
Pkl: Builtins.astro
Astro component checker
- Glob:
**/*.astro - Check:
astro check {{files}}
clang-format
Pkl: Builtins.clang_format
C/C++ formatter
- Glob:
**/*.c,**/*.h,**/*.cpp,**/*.hpp,**/*.cc,**/*.hh,**/*.cxx,**/*.hxx - Check:
clang-format --dry-run -Werror {{files}} - Fix:
clang-format -i {{files}}
cmake-format
Pkl: Builtins.cmake_format
Source code formatter for cmake listfiles
- Glob:
**/CMakeLists.txt,**/*.cmake - Check:
cmake-format --check {{files}} - Fix:
cmake-format --in-place {{files}}
cpp-lint
Pkl: Builtins.cpp_lint
C++ style checker
- Glob:
**/*.c,**/*.h,**/*.cpp,**/*.hpp,**/*.cc,**/*.hh,**/*.cxx,**/*.hxx - Check:
cpplint {{files}}
dprint
Pkl: Builtins.dprint
Pluggable code formatter
- Check:
dprint check --allow-no-files {{files}} - Check (list files):
dprint check --allow-no-files --list-different {{files}} - Fix:
dprint fmt --allow-no-files {{files}}
ktlint
Pkl: Builtins.ktlint
Kotlin linter and formatter
- Glob:
**/*.kt - Check:
ktlint {{files}} - Fix:
ktlint -F {{files}}
swiftlint
Pkl: Builtins.swiftlint
Swift style and conventions
- Glob:
**/*.swift - Check:
swiftlint lint {{files}} - Fix:
swiftlint --fix {{files}}
vacuum
Pkl: Builtins.vacuum
Fast OpenAPI linter
- Glob:
**/*openapi*.yaml,**/*openapi*.yml,**/*openapi*.json,**/*swagger*.yaml,**/*swagger*.yml,**/*swagger*.json - Check:
vacuum lint {{files}} - Fix:
vacuum lint --fix {{files}}
PHP
php-cs
Pkl: Builtins.php_cs
PHP coding standards
- Glob:
**/*.php - Check:
phpcs {{files}} - Fix:
phpcbf {{files}}
Package
aqua-update-checksum
Pkl: Builtins.aqua_update_checksum
create or update aqua checksums
- Glob:
{aqua,.aqua}.{yml,yaml},{aqua,.aqua}/**/*.{yml,yaml},aqua-checksums.json,{aqua,.aqua}/aqua-checksums.json - Fix:
aqua update-checksum --prune
Pkl
pkl
Pkl: Builtins.pkl
Pkl configuration language
- Check:
pkl eval {{files}} >/dev/null
pkl-format
Pkl: Builtins.pkl_format
Pkl formatter
Check (list files):
pkl format --diff-name-only {{ files }}Fix:
shpkl format --write {{ files }} code=$? if [ $code -eq 11 ]; then exit 0 else exit $code fi
Python
black
Pkl: Builtins.black
Opinionated Python formatter
- Glob:
**/*.py - Check:
black --check {{files}} - Fix:
black {{files}}
flake8
Pkl: Builtins.flake8
Python style guide enforcement
- Glob:
**/*.py - Check:
flake8 {{files}}
isort
Pkl: Builtins.isort
Python import sorter
- Glob:
**/*.py - Check:
isort --check-only {{files}} - Check (diff):
isort --check-only --diff {{files}} - Fix:
isort {{files}}
mypy
Pkl: Builtins.mypy
Static type checker for Python
- Glob:
**/*.py,**/*.pyi - Check:
mypy {{files}}
pylint
Pkl: Builtins.pylint
Python code analysis
- Glob:
**/*.py - Check:
pylint {{files}}
python-check-ast
Pkl: Builtins.python_check_ast
Validate Python syntax by parsing the AST
- Glob:
**/*.py - Check:
hk util python-check-ast {{files}}
python-debug-statements
Pkl: Builtins.python_debug_statements
Detect debug statements in Python code
- Glob:
**/*.py - Check:
hk util python-debug-statements {{files}}
ruff
Pkl: Builtins.ruff
Fast Python linter
- Check:
ruff check --force-exclude {{files}} - Check (diff):
ruff check --force-exclude --diff --exit-non-zero-on-fix {{ files }} && ruff check --force-exclude {{ files }} - Fix:
ruff check --force-exclude --fix {{files}}
ruff-format
Pkl: Builtins.ruff_format
Fast Python formatter (part of ruff)
- Check (diff):
ruff format --quiet --force-exclude --diff {{files}} - Fix:
ruff format --quiet --force-exclude {{files}}
ty
Pkl: Builtins.ty
Fast Python type checker
- Glob:
**/*.py,**/*.pyi - Check:
ty check {{files}}
Ruby
brakeman
Pkl: Builtins.brakeman
Security scanner for Rails
- Check:
brakeman -q -w2 {{files}}
bundle-audit
Pkl: Builtins.bundle_audit
Dependency security audit
- Glob:
**/Gemfile.lock - Check:
bundle-audit check {{files}} - Fix:
bundle-audit update
erb
Pkl: Builtins.erb
ERB template linter
- Glob:
**/*.erb - Check:
erb -P -x -T - {{ files }} | ruby -c
fasterer
Pkl: Builtins.fasterer
Performance suggestions
- Check:
fasterer {{files}}
reek
Pkl: Builtins.reek
Code smell detector
- Check:
reek {{files}}
rubocop
Pkl: Builtins.rubocop
Ruby style guide
- Glob:
**/*.rb,**/*.arb,**/*.axlsx,**/*.builder,**/*.gemfile,**/*.gemspec,**/*.jb,**/*.jbuilder,**/*.mspec,**/*.opal,**/*.pluginspec,**/*.podspec,**/*.rabl,**/*.rake,**/*.rbw,**/*.ru,**/*.ruby,**/*.schema,**/*.spec,**/*.thor,**/.irbrc,**/.pryrc,**/.simplecov,**/buildfile,**/Appraisals,**/Berksfile,**/Brewfile,**/Buildfile,**/Capfile,**/Dangerfile,**/Deliverfile,**/Fastfile,**/*Fastfile,**/Gemfile,**/Guardfile,**/Jarfile,**/Mavenfile,**/Podfile,**/Puppetfile,**/Rakefile,**/rakefile,**/Schemafile,**/Snapfile,**/Steepfile,**/Thorfile,**/Vagrantfile - Check:
rubocop --force-exclusion {{files}} - Check (list files):
rubocop --force-exclusion --format files {{files}} - Fix:
rubocop --force-exclusion --autocorrect {{files}}
rubocop-server
Pkl: Builtins.rubocop_server
Ruby style guide (using RuboCop's --server mode)
- Glob:
**/*.rb,**/*.arb,**/*.axlsx,**/*.builder,**/*.gemfile,**/*.gemspec,**/*.jb,**/*.jbuilder,**/*.mspec,**/*.opal,**/*.pluginspec,**/*.podspec,**/*.rabl,**/*.rake,**/*.rbw,**/*.ru,**/*.ruby,**/*.schema,**/*.spec,**/*.thor,**/.irbrc,**/.pryrc,**/.simplecov,**/buildfile,**/Appraisals,**/Berksfile,**/Brewfile,**/Buildfile,**/Capfile,**/Dangerfile,**/Deliverfile,**/Fastfile,**/*Fastfile,**/Gemfile,**/Guardfile,**/Jarfile,**/Mavenfile,**/Podfile,**/Puppetfile,**/Rakefile,**/rakefile,**/Schemafile,**/Snapfile,**/Steepfile,**/Thorfile,**/Vagrantfile - Check:
rubocop --server --force-exclusion {{files}} - Check (list files):
rubocop --server --force-exclusion --format files {{files}} - Fix:
rubocop --server --force-exclusion --autocorrect {{files}}
sorbet
Pkl: Builtins.sorbet
Type checker for Ruby
- Check:
srb tc {{files}}
standard-rb
Pkl: Builtins.standard_rb
Ruby Standard Style
- Check:
standardrb {{files}} - Fix:
standardrb --fix {{files}}
Rust
cargo-check
Pkl: Builtins.cargo_check
Fast Rust type checking
- Glob:
**/*.rs - Check:
cargo check --quiet - Fix:
cargo fix --allow-dirty --allow-staged --quiet
cargo-clippy
Pkl: Builtins.cargo_clippy
Rust linter
- Glob:
**/*.rs - Check:
cargo clippy --manifest-path {{workspace_indicator}} --quiet - Fix:
cargo clippy --manifest-path {{workspace_indicator}} --fix --allow-dirty --allow-staged --quiet
cargo-deny
Pkl: Builtins.cargo_deny
Rust dependency linter
- Glob:
**/Cargo.toml,**/Cargo.lock,**/deny.toml,**/.deny.toml,**/deny.exceptions.toml,**/.deny.exceptions.toml - Check:
cargo-deny --locked --workspace check
cargo-fmt
Pkl: Builtins.cargo_fmt
Rust code formatter
- Glob:
**/*.rs,**/rustfmt.toml,**/.rustfmt.toml - Check:
cargo fmt --check --manifest-path {{workspace_indicator}} - Check (list files):
cargo fmt --check --manifest-path {{workspace_indicator}} -- --files-with-diff - Fix:
cargo fmt --manifest-path {{workspace_indicator}}
rustfmt
Pkl: Builtins.rustfmt
Rust code formatter (standalone)
- Glob:
**/*.rs - Check:
rustfmt --check --edition 2024 {{files}} - Check (list files):
rustfmt --check --edition 2024 --files-with-diff {{files}} - Fix:
rustfmt --edition 2024 {{files}}
Secrets
betterleaks
Pkl: Builtins.betterleaks
A Better Secrets Scanner built for configurability and speed
- Check:
betterleaks dir --redact --verbose --no-banner {{files}}
gitleaks
Pkl: Builtins.gitleaks
Secret scanner for repository working trees
- Check:
gitleaks dir --redact --verbose --no-banner .
kingfisher
Pkl: Builtins.kingfisher
Secret scanner with live validation and 1,000+ rules
- Check:
kingfisher scan {{files}} --no-update-check --no-validate --quiet
Shell
shellcheck
Pkl: Builtins.shellcheck
Shell script analyzer
- Check:
shellcheck {{files}} - Check (diff):
shellcheck --format=diff {{files}}
shellharden
Pkl: Builtins.shellharden
The corrective bash syntax highlighter
- Check:
shellharden --check {{files}} - Check (diff):
hk util format-diff --no-stdin {{files}} -- shellharden --transform '{}' - Fix:
shellharden --replace {{files}}
shfmt
Pkl: Builtins.shfmt
Shell formatter
Check (diff):
shfmt -d --apply-ignore {{ files }}Check (list files):
shfiles=$(shfmt -l --apply-ignore {{ files }}) if [ -n "$files" ]; then echo "$files" exit 1 fiFix:
shfmt -w --apply-ignore {{ files }}
Special Purpose
byte-order-marker
Pkl: Builtins.byte_order_marker
Detect UTF-8 BOM
- Check (diff):
hk util check-byte-order-marker --diff {{files}} - Fix:
hk util fix-byte-order-marker {{files}}
check-added-large-files
Pkl: Builtins.check_added_large_files
Prevent committing large files
- Glob:
**/* - Check:
hk util check-added-large-files {{files}}
check-case-conflict
Pkl: Builtins.check_case_conflict
Detect case-insensitive filename conflicts
- Glob:
**/* - Check:
hk util check-case-conflict {{files}}
check-conventional-commit
Pkl: Builtins.check_conventional_commit
Verify commit message matches conventional commits formatting
- Check:
hk util check-conventional-commit {{commit_msg_file}}
check-executables-have-shebangs
Pkl: Builtins.check_executables_have_shebangs
Verify executable files have shebang lines
- Check:
hk util check-executables-have-shebangs {{files}}
check-merge-conflict
Pkl: Builtins.check_merge_conflict
Detect merge conflict markers
- Check:
hk util check-merge-conflict --assume-in-merge {{files}}
check-shebang-scripts-are-executable
Pkl: Builtins.check_shebang_scripts_are_executable
Verify files with shebang lines are executable
- Check:
hk util check-shebang-scripts-are-executable {{files}}
check-symlinks
Pkl: Builtins.check_symlinks
Detect broken symlinks
- Glob:
**/* - Check:
hk util check-symlinks {{files}}
cocogitto-commit-msg
Pkl: Builtins.cocogitto_commit_msg
Conventional commits linter
- Check:
cog --quiet verify --file {{commit_msg_file}}
destroyed-symlinks
Pkl: Builtins.destroyed_symlinks
Detect symlinks replaced by regular files holding their target path
- Check:
hk util destroyed-symlinks
detect-private-key
Pkl: Builtins.detect_private_key
Detect accidentally committed private keys
- Check:
hk util detect-private-key {{files}}
fix-smart-quotes
Pkl: Builtins.fix_smart_quotes
Replace smart quotes with regular quotes
- Check (diff):
hk util fix-smart-quotes --diff {{files}} - Fix:
hk util fix-smart-quotes {{files}}
forbid-submodules
Pkl: Builtins.forbid_submodules
Forbid git submodules in the repository
- Check:
hk util forbid-submodules
harper
Pkl: Builtins.harper
Grammar checker for prose and documentation
- Check:
harper-cli lint {{files}}
harper-commit-message
Pkl: Builtins.harper_commit_message
Grammar checker for commit message
- Check:
harper-cli lint {{commit_msg_file}}
hk-test
Pkl: Builtins.hk_test
Run step-defined hk's tests
- Glob:
hk.pkl,.config/hk.pkl - Check:
hk test --quiet
just-format
Pkl: Builtins.just_format
Justfile formatter
Glob:
**/justfile,**/*.justFix:
shxargs -d' ' -I {} -- just --fmt --unstable --justfile {}
ls-lint
Pkl: Builtins.ls_lint
Directory and filename naming linter
- Glob:
**/* - Check:
ls-lint
lychee
Pkl: Builtins.lychee
Fast, async, stream-based link checker
- Check:
lychee --no-progress {{files}}
lychee-extended
Pkl: Builtins.lychee_extended
Flint's repository-aware link check (requires flint and lychee). See https://github.com/grafana/flint/blob/main/docs/linters/lychee.md
- Check:
flint checker lychee --files-from -
mixed-line-ending
Pkl: Builtins.mixed_line_ending
Detect and fix mixed line endings
- Check (diff):
hk util mixed-line-ending --diff {{files}} - Fix:
hk util mixed-line-ending --fix {{files}}
newlines
Pkl: Builtins.newlines
Ensure files end with newline
- Check (diff):
hk util end-of-file-fixer --diff {{files}} - Fix:
hk util end-of-file-fixer --fix {{files}}
no-commit-to-branch
Pkl: Builtins.no_commit_to_branch
Prevent direct commits to protected branches
- Check:
hk util no-commit-to-branch
renovate-deps
Pkl: Builtins.renovate_deps
Flint's repository-aware dependency check (requires flint and renovate). See https://github.com/grafana/flint/blob/main/docs/linters/renovate-deps.md
- Glob:
**/* - Check:
flint checker renovate-deps --files-from - - Fix:
flint checker renovate-deps --fix --files-from -
textlint
Pkl: Builtins.textlint
Pluggable natural language linter
- Glob:
**/*.md,**/*.markdown,**/*.txt - Check:
textlint {{files}} - Fix:
textlint --fix {{files}}
trailing-whitespace
Pkl: Builtins.trailing_whitespace
Detect and remove trailing whitespace
- Check (diff):
hk util trailing-whitespace --diff {{files}} - Fix:
hk util trailing-whitespace --fix {{files}}
typos
Pkl: Builtins.typos
Source code spell checker
Check (diff):
shstatus=0 output=$(typos --force-exclude --diff {{files}}) || status=$? [ -z "$output" ] && exit "$status" printf "%s" "$output" exit 1Fix:
typos --force-exclude --write-changes {{ files }}
vale
Pkl: Builtins.vale
Prose linter for markup and code comments
- Check:
vale sync && vale {{ files }}
YAML
ryl
Pkl: Builtins.ryl
Re-implementation of yamllint in Rust
- Check:
ryl {{files}} - Check (diff):
ryl --diff {{files}} - Check (list files):
ryl --list-files {{files}} - Fix:
ryl --fix {{files}}
Bring a tool of yer own aboard
If there's no builtin for yer tool, define a step with glob, check, and an optional fix command. Only enable batching if the tool can process independent subsets of the files correctly.
See custom steps for a complete example. And, as the song goes, all you hands who would sign aboard: see contributing to add a reusable definition to the standing crew.
