A feature-and-fix release: hooks can now target staged files without touching your worktree, hk install cooperates with global installs, and three separate stash/merge bugs that could clobber fixer output or staged deletions are fixed.
Added
-
--stagedflag forhk run,check,fix, and hook subcommands (@jdx) #950. Runs hooks against the staged file set while leaving unstaged and untracked changes alone — no stash, no worktree mutation. It conflicts with--alland--stash, and forcesStashMethod::Noneeven when the hook config opts into stashing. Fixes #940.hk run pre-commit --staged hk fix --staged
-
hk installskips when hk is configured globally (@jdx) #934. If anyhook.hk-*entry exists in~/.gitconfig,hk installis a no-op and additionally cleans up stale per-repo hooks left behind from a prior install, so the global install is the single source of truth and hk doesn't fire twice per event. Pass--force-localto install per-repo hooks anyway. This means postinstall workarounds likegit config --get-regexp hook\.hk- || hk installcan now be replaced with a plainhk install. Closes #933. -
Named template variables for
post-checkouthooks (@jdx) #951. Steps can now referenceprev_head,new_head, andis_branch_checkout(a real boolean, mapped from git's1/0flag) instead of having to parse the combinedhook_argsstring.docs/hooks.mddocuments the per-hook variables forprepare-commit-msg,commit-msg, andpost-checkout. -
oxfmtbuiltin (@hituzi-no-sippo) #914. Adds oxfmt as a builtin formatter for JS/TS, JSON, YAML, and TOML. -
Vite+ builtin (@hituzi-no-sippo) #913. Adds Vite+ as a builtin formatter/linter for JavaScript/TypeScript.
-
oxlintbuiltin upgrades (@hituzi-no-sippo) #911. Adds--deny-warningsso violations exit non-zero, extends the file glob to.vue,.svelte,.astro,.mjs,.cjs,.mts, and.cts, and registers oxlint config files as project indicators so the builtin is auto-suggested.
Fixed
-
pre-pushref filter was inverted (@jdx) #932. The filter was checking the local sha for all-zeros (a deletion) when the intent was to check the remote sha (a new branch). Two visible consequences:- First push of a new branch was dropped and fell through to resolving
refs/remotes/origin/HEAD, which often failed withFailed to parse reference: refs/remotes/origin/HEAD(likely the root cause of #172). - Branch deletions were kept and triggered linting against the deleted ref.
The filter now drops only deletions, falls back to the real remote-tracking branch (or
Git::resolve_default_branch()) for new-branch pushes, and uses a newgit::is_zero_sha()helper that works for both SHA-1 and SHA-256 repos. - First push of a new branch was dropped and fell through to resolving
-
hk install --globalnow uses absolute paths (@jdx) #939. Global hook commands previously assumedhk/misewere onPATHwhen git invoked the hook, which broke in environments with a sanitizedPATH. The installer now resolveshk(ormise) to an absolute path at install time (using~/when home-relative and quoting otherwise), and--miseglobal installs usemise x hk -- hkso thehktool is requested explicitly. Global installs also pick hook events from the project'shk.pklwhen present. Fixes #937. -
fail_on_fixno longer loses fixer output throughstash = "git"(@jdx) #909.git stash show --name-onlycan list staged files stored in the stash commit that were not part of the unstaged set being restored, so the manual unstash could rewrite a staged-only file and discard the fixer's output that should remain visible as an unstaged diff. hk now tracks the exact path set selected for stashing and filters restore to that set. Follow-up to thefail_on_fixfix in v1.44.3. -
Staged deletions survive
pop_stash(@jdx) #927.pop_stash()walked every path returned bygit stash show --name-onlyand wrote a merged blob to disk, even for paths the user had staged for deletion withgit rm. After the commit, the deleted file reappeared on disk as untracked. hk now queriesgit diff --cached --diff-filter=Dbefore unstashing and skips those paths. Fixes #926. -
Fixer tail-line deletions are preserved across three-way merge (@jdx) #931. In
merge.rs::diff_hunks, when the LCS walk consumedotherentirely after a matching line, a pure tail deletion ofbase[i..n]was dropped, sothree_way_merge_hunkssilently copied the removed lines back in. The classic symptom: a fixer that strips trailing blank lines, applied to a file where you have an unrelated unstaged change in the middle, would have its trailing-line cleanup silently undone. Fixes #929. -
check_difffailures get accurate fix suggestions (@jdx) #949. When a step defined bothcheck_diffandcheck_list_files, the "To fix, run" hint always parsed output with the list-files parser regardless of which check actually ran. hk now passes the executed command intocollect_fix_suggestionand dispatches to the diff parser forcheck_diffoutput, so the suggested files match the real failure. Fixes #942.
Full Changelog: v1.45.0...v1.46.0
💚 Sponsor hk
hk is developed by @jdx at en.dev — a small independent studio behind developer tools like mise, aube, hk, 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 en.dev. Sponsorships are what keep hk moving and the project independent.