This release adds a cargo-deny builtin, meaningfully speeds up config resolution and hook runs in large repos, and fixes two correctness bugs around dependency graphs and stashing. It also hardens hk's Git invocations against argument injection.
Added
-
cargo_denybuiltin (@risu729) #1081. Runs cargo-deny for Rust dependency policy checks (advisories, bans, licenses, sources). It triggers onCargo.toml,Cargo.lock, anddeny.toml/.deny.toml(including.cargo/and exceptions variants), groups executions by Cargo workspace and runs from the workspace directory, and uses--lockedso checks never create or updateCargo.lock.["cargo_deny"] = Builtins.cargo_deny
Fixed
-
Dependents no longer hang after a failed dependency (@jdx) #1099. With
fail_fast = false, a failed step returned without marking its dependency watch channel as done, so any step withdependson it waited forever and the run hung. The failed step now signals its dependents so they can proceed.fail_fast = truebehavior is unchanged. Fixes discussion #1098. -
No stashing when a hook has no steps to run (@jdx) #1106. When a hook resolved to zero steps but the worktree had unstaged or untracked changes, hk stashed them and returned early — before the restore ran — leaving a dangling stash and a stripped working tree (each retry piling on another stash). The "no steps to run" guard now runs before any side effects, so there is nothing to stash. Stash-restore failures also now report the
~/.local/state/hk/patches/*.patchbackup path for manual recovery. Fixes #1105.
Changed
- Hardened Git invocations against argument injection (@sshine) #1101. hk now passes
--end-of-optionsbefore untrusted revisions inmerge-base,rev-parse,ls-tree, and diff ranges, and replacesls-remoteshell interpolation with an argv invocation. This prevents repo-config-controlled refs (hk.pkldefault_branch,--from-ref/--to-ref) and hyphen-prefixed branch names from being misread as options. Note:rev-parse --end-of-optionsrequires Git 2.30+.
Performance
-
Resolved config cached in-process (@mharris-figma) #1104. Each
Config::get()previously re-applied subprojects and user config, re-validated, and cloned on every call. Since hk runs one command against one project, the resolved config is now built once per process (callers still get clones). A warm-cachehk validatebenchmark against a large config improved 46% (102.60 ms to 55.21 ms). -
Final status snapshot skipped outside debug logging (@mharris-figma) #1102. The final Git status scan is only used for debug diagnostics, but hk was running a full repository scan at every log level and discarding it. It's now gated behind debug logging. A no-op benchmark over a 6,156-file repo with 4,000 modified files improved ~40% on both backends (libgit2: 221 ms to 131 ms; shell Git: 223 ms to 136 ms). Status reads used for file selection, stashing, and hook behavior are unchanged.
New Contributors
- @mharris-figma made their first contribution in #1104
Full Changelog: v1.52.0...v1.53.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.