This release seeds hk with an embedded Pkl package so matching-version configs validate offline on a cold cache, adds templated dir support for workspace-aware steps, and lands a new check_after_diff mechanism that lets partial fixers (like ShellCheck) apply what they can while still reporting what they cannot. It also brings several new Go and lint builtins plus a batch of correctness fixes for Go linters, gitleaks, workspace paths, Windows shims, and stashing.
Added
-
Embedded matching-version Pkl package (@sahidvelji) #1218. hk now ships the Pkl package built for its own version and seeds
HK_PKL_CACHE_DIRwith it before evaluatinghk.pkl, so a config pinned to that version validates with no network round trip on a cold cache — a fresh clone, CI runner, new container, or upgrade. Cached content always wins over the embedded copy, and other versions are fetched as before. SetHK_PKL_EMBEDDED=0to disable seeding. Addresses discussion #1216. -
Templated
dirthrough Tera (@sahidvelji) #1219. A step'sdiris now rendered through Tera, so a workspace-aware step can point its working directory at the workspace it was matched for instead of prefixing every command withcd {{workspace}} && .... The eight workspace-aware builtins (the Go ones pluscargo_deny) drop theircdprefix as a result. Literaldirvalues are unaffected.["go-vet"] { glob = "**/*.go" workspace_indicator = "go.mod" dir = "{{workspace}}" check = "go vet ./..." }
-
check_after_difffor partial fixers (@jdx) #1243. New opt-in step setting that rerunscheckon the original file batch after acheck_diffpatch applies, so non-fixable findings stay visible instead of being masked by a clean apply. Requires bothcheckandcheck_diffto be defined. This underpins ShellCheck's new fixer and other partial fixers. -
ShellCheck autofix via
check_diff(@sahidvelji) #1237.shellchecknow applies the fixes it can via--format=diff, and thanks tocheck_after_diffa file with both fixable and non-fixable findings is fixed and still fails on what remains. Implements proposal 2 of #1234. -
go_fixbuiltin (@sahidvelji) #1224. Wraps Go'sgo fix(the Go 1.26+ analyzer-driven modernizer) —interface{}→any,sort.Slice→slices.Sort,wg.Add/go/wg.Done→wg.Go, and more.check_diffrunsgo fix -diff ./...and hk applies the patch directly. Requires Go 1.26+. -
golangci_lint_fmtformatter builtin (@sahidvelji) #1244. Wrapsgolangci-lint fmt, the formatter half of golangci-lint, formatting only the changed files viacheck_diff(usingfmt --diff) — separate from the existinggolangci_lintbuiltin that runs the full linter. -
ls_lintbuiltin (@sahidvelji) #1238. Adds a builtin for ls-lint, which enforces directory and filename naming conventions against.ls-lint.yml. Runs once per invocation. Implements proposal 3 of #1234. -
gitleaks_stagedbuiltin (@jdx) #1248. A new builtin that runsgitleaks git --pre-commit --stagedto scan only the staged index, suited to pre-commit hooks. -
Per-step
allow_failure(@jdx) #1291. Steps can report a non-zero command exit without failing the overall hook, including conditional policies via expressions such asenv('KNOWN_BROKEN') == 'true'. hk's own execution and configuration errors remain blocking, and allowed failures are surfaced in structured output.
Fixed
- Go linters that reported success on bad code (@sahidvelji) #1225.
go_imports,go_lines,revive, andgo_fumptsilently passed in check mode even with real findings; they now take their exit code correctly.gomod_tidycould not run outside the repo root and is now scoped like the other Go builtins. - gitleaks scan modes (@jdx) #1248.
Builtins.gitleaksnow explicitly scans the repository working tree rather than silently changing behavior when{{files}}expanded to multiple paths. gomod_tidynow runs on.gochanges (@sahidvelji) #1236. Broadened the glob to**/*.go,**/go.mod, and**/go.sumso the common drift (editing an import) is caught at commit time, and itsgo.mod/go.sumupdates are now staged when triggered by a Go change (@jdx) #1240.- Partial diff fixes no longer pass silently (@jdx) #1245. Enabled
check_after_diffforrumdl,ryl,ryl_markdown,zizmor, andpinact_v3, so remaining violations surface after hk applies each partial patch. - Workspace paths in literal
dirsteps (@jdx) #1242.{{workspace}}and{{workspace_indicator}}are now rendered relative to a literal step directory, preventing duplicated paths likeui/ui/tsconfig.jsonin subprojects. Addresses discussion #1233. - Windows command shims (@jdx) #1221. Structured
argvsteps now resolve.cmd/.battargets (including npmnode_modules/.binshims) via the effectivePATH/PATHEXTand run them throughcmd.exewith argument-boundary-preserving escaping. Fixes discussion #1220. - Empty pathspec stashes (@jdx) #1283. Pre-commit runs no longer reset the index and leave an orphaned stash when a path-limited stash has no HEAD-to-worktree diff (e.g. mode-only staged changes). Addresses discussion #1281.
New Contributors
- @sahidvelji made their first contribution in #1218
Full Changelog: v1.56.1...v1.57.0
💚 Sponsor hk
hk is maintained by @jdx, an open source developer for entire.io, the title sponsor of the jdx.dev open source tools including mise, aube, and more. Work on hk is funded by sponsorships.
If hk has sped up your pre-commit loop or made linting feel less painful, please consider sponsoring at jdx.dev. Sponsorships are what keep hk moving and the project independent.
AI-assisted — Tool: Codex; model: openai/gpt-5; version: unavailable.