Skip to the cargo

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 ​

pkl
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:

pkl
["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:

pkl
["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:

pkl
["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: **/*.json

  • Check (diff):

    sh
    failed=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 $failed
  • Fix:

    sh
    failed=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, **/*.yml

  • Check (diff):

    sh
    failed=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 $failed
  • Fix:

    sh
    failed=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: **/*.go

  • Check (diff):

    sh
    DIFF=$(gofmt -s -d {{files}})
    if [ -n "$DIFF" ]; then
    echo "$DIFF"
    exit 1
    fi
  • Check (list files):

    sh
    FILES=$(gofmt -s -l {{files}})
    if [ -n "$FILES" ]; then
    echo "$FILES"
    exit 1
    fi
  • Fix: gofmt -s -w {{files}}

go-fumpt ​

Pkl: Builtins.go_fumpt

Strict Go formatter

  • Glob: **/*.go

  • Check (diff): gofumpt -d {{files}}

  • Check (list files):

    sh
    FILES=$(gofumpt -l {{files}})
    if [ -n "$FILES" ]; then
    echo "$FILES"
    exit 1
    fi
  • Fix: gofumpt -w {{files}}

go-imports ​

Pkl: Builtins.go_imports

Go import management

  • Glob: **/*.go

  • Check (diff):

    sh
    DIFF=$(goimports -d {{files}})
    if [ -n "$DIFF" ]; then
    echo "$DIFF"
    exit 1
    fi
  • Check (list files):

    sh
    FILES=$(goimports -l {{files}})
    if [ -n "$FILES" ]; then
    echo "$FILES"
    exit 1
    fi
  • Fix: 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.hcl

  • Check:

    sh
    for 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:

    sh
    for 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.hcl

  • Check:

    sh
    for 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: **/*.hcl

  • Check:

    sh
    set --
    for f in {{ files }}; do set -- "$@" "--filter=./$f"; done
    if [ "$#" -eq 0 ]; then exit 0; fi
    terragrunt hcl fmt --check --diff "$@"
  • Fix:

    sh
    set --
    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: **/*.hcl

  • Check:

    sh
    set --
    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, **/*.tofu

  • Check:

    sh
    for 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:

    sh
    for 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:

    sh
    pkl 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):

    sh
    files=$(shfmt -l --apply-ignore {{ files }})
    if [ -n "$files" ]; then
    echo "$files"
    exit 1
    fi
  • Fix: 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}}

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}}

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, **/*.just

  • Fix:

    sh
    xargs -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):

    sh
    status=0
    output=$(typos --force-exclude --diff {{files}}) || status=$?
    [ -z "$output" ] && exit "$status"
    printf "%s" "$output"
    exit 1
  • Fix: 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.

MIT LicenseCopyright © 2026jdx.dev