Skip to content

feat: add {{ hook_args }} template to pass to downstream commands#807

Merged
jdx merged 8 commits intojdx:mainfrom
JohanLorenzo:feature/hook-args
Apr 11, 2026
Merged

feat: add {{ hook_args }} template to pass to downstream commands#807
jdx merged 8 commits intojdx:mainfrom
JohanLorenzo:feature/hook-args

Conversation

@JohanLorenzo
Copy link
Copy Markdown
Contributor

Hi there! 👋

Thank you so much for quickly accepting and releasing jdx/mise#8961. I truly appreciate it and I got to use it already 🙂

I'm converting a personal project from pre-commit to hk and I stumbled upon an issue with git lfs. git-lfs hooks (post-checkout, post-merge, pre-push) need the arguments that git passes to the hook script. Without this PR, git lfs post-checkout fails with "This should be run through Git's post-checkout hook."

Summary

  • Adds a {{ hook_args }} template variable that forwards git hook arguments to step commands
  • The generated hook scripts now pass $* via HK_HOOK_ARGS env var instead of positional args
  • All hook handlers (generic, pre-commit, pre-push, commit-msg, prepare-commit-msg) read HK_HOOK_ARGS and insert it into the template context

With this change, users can configure git-lfs integration in hk.pkl:

hooks {
    ["post-checkout"] {
        steps {
            ["git-lfs"] { check = "git lfs post-checkout {{ hook_args }}" }
        }
    }
    ["post-merge"] {
        steps {
            ["git-lfs"] { check = "git lfs post-merge {{ hook_args }}" }
        }
    }
    ["pre-push"] {
        steps {
            ["git-lfs"] { check = "git lfs pre-push {{ hook_args }}" }
        }
    }
}

Let me know what you think!

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the ability to pass hook arguments to various git hooks by capturing the HK_HOOK_ARGS environment variable and inserting it into the hook execution context. The changes are applied across multiple command files, and a new test suite has been added to verify the functionality. I agree with the reviewer's feedback that the logic for retrieving and inserting hook_args is currently duplicated across several files and should be refactored into a shared helper method or integrated into the HookOptions struct to improve maintainability.

Comment thread src/cli/run/mod.rs Outdated
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 9, 2026

Greptile Summary

This PR adds a {{ hook_args }} Tera template variable that lets users forward git hook positional arguments (like <remote> <url> for pre-push, or <prev-head> <new-head> <branch-flag> for post-checkout) directly to step commands, enabling git lfs integration. Each dedicated hook handler parses its clap positional args and reconstructs the hook_args string manually; the generated install script continues to use "$@", so the existing clap-parsed fields for commit-msg, prepare-commit-msg, and pre-push still receive their required positional arguments correctly.

Confidence Score: 5/5

Safe to merge — the previous P1 concerns (broken commit-msg/pre-push positional args, $* vs $@) are all resolved; only a minor trailing-space P2 remains.

All dedicated hook handlers correctly parse positional args via clap and reconstruct hook_args manually. The install script retains "$@" so commit-msg, prepare-commit-msg, and pre-push continue to receive their required positional arguments. The single remaining finding is a cosmetic trailing-space edge case in pre_push.rs that only affects manual invocations, not real git-driven hook executions.

src/cli/run/pre_push.rs — minor trailing-space formatting in hook_args when url is absent

Important Files Changed

Filename Overview
src/cli/run/pre_push.rs Builds hook_args from clap-parsed remote/url fields; minor formatting issue when either is None, producing a trailing/leading space.
src/cli/run/commit_msg.rs Sets hook_args to the resolved commit message file path; correct and consistent with git's commit-msg contract.
src/cli/run/prepare_commit_msg.rs Reconstructs hook_args from individual clap fields for all three git-passed argument combinations; logic is correct.
src/cli/run/post_checkout.rs Correctly assembles hook_args from the three SHA/flag fields that git passes to post-checkout.
src/cli/run/mod.rs Generic hook path sets hook_args to empty string with an explanatory comment; intentional design limitation for hooks without a dedicated handler.
test/hook_args.bats Comprehensive bats tests covering all hook types including git-lfs smoke tests; good coverage.

Sequence Diagram

sequenceDiagram
    participant Git
    participant HookScript as "Hook Script"
    participant HK as "hk run hook"
    participant Handler as "Dedicated Handler"
    participant Tera as "Tera Template"
    participant Step as "Step Command"

    Git->>HookScript: "invoke with positional args"
    HookScript->>HK: "exec hk run hook $@"
    HK->>Handler: "clap parses positional args"
    Handler->>Handler: "construct hook_args from parsed fields"
    Handler->>Tera: "tctx.insert(hook_args)"
    Handler->>Step: "run step with rendered template"
    Tera->>Step: "replace {{ hook_args }} in command"
    Step->>Git: "e.g. git lfs post-checkout prev new flag"
Loading

Reviews (7): Last reviewed commit: "feat: {{ hook_args }} for prepare-commit..." | Re-trigger Greptile

Comment thread src/cli/install.rs Outdated
Comment thread src/cli/run/pre_push.rs Outdated
Comment thread src/cli/install.rs Outdated
@JohanLorenzo JohanLorenzo marked this pull request as draft April 9, 2026 21:16
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 9, 2026

Tip:

Greploop — Automatically fix all review issues by running /greploops in Claude Code. It iterates: fix, push, re-review, repeat until 5/5 confidence.

Use the Greptile plugin for Claude Code to query reviews, search comments, and manage custom context directly from your terminal.

@JohanLorenzo JohanLorenzo force-pushed the feature/hook-args branch 2 times, most recently from 9684900 to 31f846e Compare April 10, 2026 08:04
Comment thread test/hook_args.bats
Comment on lines +176 to +178
if [ "$HK_LIBGIT2" = "0" ]; then
skip "libgit2 is not installed"
fi
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ This follows the same pattern as:

hk/test/pre_push.bats

Lines 20 to 22 in 54d2112

if [ "$HK_LIBGIT2" = "0" ]; then
skip "libgit2 is not installed"
fi

@JohanLorenzo JohanLorenzo marked this pull request as ready for review April 10, 2026 08:17
Comment thread src/cli/install.rs Outdated
format!(
r#"#!/bin/sh
test "${{HK:-1}}" = "0" || exec {hk} run {hook} "$@"
test "${{HK:-1}}" = "0" || HK_HOOK_ARGS="$*" exec {hk} run {hook} "$@"
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't going to deal with spaces in args properly

Copy link
Copy Markdown
Contributor Author

@JohanLorenzo JohanLorenzo Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review! Understood. I reworked the PR to use dedicated clap handlers per hook instead of the HK_HOOK_ARGS env var, in order to match the existing PrepareCommitMsg pattern. What do you think?

@jdx jdx merged commit 64f8b54 into jdx:main Apr 11, 2026
18 checks passed
@jdx jdx mentioned this pull request Apr 11, 2026
jdx added a commit that referenced this pull request Apr 12, 2026
### 🚀 Features

- add {{ hook_args }} template to pass to downstream commands by
[@JohanLorenzo](https://github.com/JohanLorenzo) in
[#807](#807)

### 🐛 Bug Fixes

- **(step)** preserve cmd.exe quoting for {{files}} on Windows by
[@jdx](https://github.com/jdx) in
[#824](#824)

### 🛡️ Security

- **(deps)** update dependency eslint to v10 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#813](#813)

### 📦️ Dependency Updates

- update taiki-e/upload-rust-binary-action digest to 10c1cf6 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#810](#810)
- update nick-fields/retry action to v4 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#812](#812)
- update anthropics/claude-code-action digest to 657fb7c by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#809](#809)
- update dependency typescript to v6 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#814](#814)
- update rust crate demand to v2 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#815](#815)
- update rust crate expr-lang to v1 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#816](#816)
- update rust crate similar to v3 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#817](#817)
- update rust crate toml to v1 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#820](#820)
- update actions/upload-artifact digest to 043fb46 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#821](#821)
- update anthropics/claude-code-action digest to b47fd72 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#822](#822)

### New Contributors

- @JohanLorenzo made their first contribution in
[#807](#807)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk release bookkeeping: version bumps, regenerated CLI/docs, and
routine dependency lockfile updates with no functional code changes in
this PR.
> 
> **Overview**
> Bumps `hk` to **v1.42.0** and adds the corresponding `CHANGELOG.md`
release notes.
> 
> Regenerates versioned docs/CLI artifacts (`docs/cli/*`,
`hk.usage.kdl`) and updates all documentation/examples to reference the
`v1.42.0` Pkl package URLs. Updates `Cargo.lock` for minor dependency
revisions.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
4b9834f. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: mise-en-dev <123107610+mise-en-dev@users.noreply.github.com>
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Apr 15, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [hk](https://github.com/jdx/hk) | minor | `1.41.1` → `1.42.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jdx/hk (hk)</summary>

### [`v1.42.0`](https://github.com/jdx/hk/blob/HEAD/CHANGELOG.md#1420---2026-04-12)

[Compare Source](jdx/hk@v1.41.1...v1.42.0)

##### 🚀 Features

- add {{ hook\_args }} template to pass to downstream commands by [@&#8203;JohanLorenzo](https://github.com/JohanLorenzo) in [#&#8203;807](jdx/hk#807)

##### 🐛 Bug Fixes

- **(step)** preserve cmd.exe quoting for {{files}} on Windows by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;824](jdx/hk#824)

##### 🛡️ Security

- **(deps)** update dependency eslint to v10 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;813](jdx/hk#813)

##### 📦️ Dependency Updates

- update taiki-e/upload-rust-binary-action digest to [`10c1cf6`](jdx/hk@10c1cf6) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;810](jdx/hk#810)
- update nick-fields/retry action to v4 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;812](jdx/hk#812)
- update anthropics/claude-code-action digest to [`657fb7c`](jdx/hk@657fb7c) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;809](jdx/hk#809)
- update dependency typescript to v6 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;814](jdx/hk#814)
- update rust crate demand to v2 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;815](jdx/hk#815)
- update rust crate expr-lang to v1 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;816](jdx/hk#816)
- update rust crate similar to v3 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;817](jdx/hk#817)
- update rust crate toml to v1 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;820](jdx/hk#820)
- update actions/upload-artifact digest to [`043fb46`](jdx/hk@043fb46) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;821](jdx/hk#821)
- update anthropics/claude-code-action digest to [`b47fd72`](jdx/hk@b47fd72) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;822](jdx/hk#822)

##### New Contributors

- [@&#8203;JohanLorenzo](https://github.com/JohanLorenzo) made their first contribution in [#&#8203;807](jdx/hk#807)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMTAuMTMiLCJ1cGRhdGVkSW5WZXIiOiI0My4xMTAuMTMiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbIlJlbm92YXRlIEJvdCIsImF1dG9tYXRpb246Ym90LWF1dGhvcmVkIiwiZGVwZW5kZW5jeS10eXBlOjptaW5vciJdfQ==-->
jdx pushed a commit that referenced this pull request Apr 16, 2026
Hey again! Thank you very much for merging and releasing #807! It's been
working great with almost all `git lfs` hooks. There's one I missed in
my original PR: `pre-push`. While `{{ hook_args }}` solved positional
argument forwarding, `git lfs pre-push` also needs **stdin**. `git`
pipes ref data through it so LFS knows which objects to upload.

Currently, hk's `PrePush` handler consumes stdin for its own ref
resolution, leaving nothing for step commands. This PR preserves the raw
stdin as `{{ hook_stdin }}` so steps can pipe it via the existing
`stdin` field.

  ## The problem

  `git lfs pre-push` receives ref data via stdin:
  refs/heads/main  refs/heads/main

Without it, `git lfs pre-push` exits 0 silently and uploads nothing. The
remote then rejects the push:

```
  $ git push origin main
    files - Fetching git status
  ✔ files - Fetching files between refs/remotes/origin/main and HEAD (1 file)
  ❯ git-lfs
    git-lfs – 0 files –  – git lfs pre-push origin URL
  ✔ git-lfs
  remote: LFS objects are missing. Ensure LFS is properly set up or try a manual "git lfs push --all".
   ! [remote rejected]   main -> main (pre-receive hook declined)
```

  ## After the fix

```
  $ git push origin main
    files - Fetching git status
  ✔ files - Fetching files between refs/remotes/origin/main and HEAD (1 file)
  ❯ git-lfs
    git-lfs – 0 files –  – git lfs pre-push origin URL
    git-lfs – Uploading LFS objects: 100% (1/1), 0 B | 0 B/s, done.
  ✔ git-lfs
  To URL
     cdd0595..21798fe  main -> main
```

  ## Steps to reproduce locally

```
  mkdir /tmp/hk-lfs-test && cd /tmp/hk-lfs-test
  git init && git lfs install
  echo "*.bin filter=lfs diff=lfs merge=lfs -text" > .gitattributes

  cat > hk.pkl << 'EOF'
  amends "package://github.com/jdx/hk/releases/download/v1.42.0/hk@1.42.0#/Config.pkl"
  hooks {
      ["pre-push"] {
          steps {
              ["git-lfs"] {
                  check = "git lfs pre-push {{ hook_args }}"
                  stdin = "{{ hook_stdin }}"
              }
          }
      }
  }
  EOF

  dd if=/dev/urandom bs=1024 count=5 of=big.bin 2>/dev/null
  git add .gitattributes hk.pkl big.bin && git commit -m "init"
  git init --bare ../hk-lfs-remote.git
  git remote add origin ../hk-lfs-remote.git
  HK=0 git push -u origin main          # initial push without hk
  git remote set-head origin main

  hk install
  dd if=/dev/urandom bs=1024 count=5 of=big2.bin 2>/dev/null
  git add big2.bin && git commit -m "second"
  git push origin main                   # should show "Uploading LFS objects"
```

  ## Usage

  ```pkl
  hooks {
      ["pre-push"] {
          steps {
              ["git-lfs"] {
                  check = "git lfs pre-push {{ hook_args }}"
                  stdin = "{{ hook_stdin }}"
              }
          }
      }
  }
```
@JohanLorenzo JohanLorenzo deleted the feature/hook-args branch April 16, 2026 19:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants