Skip to content

feat(hook): support per-worktree hooks via extensions.worktreeConfig#789

Merged
jdx merged 3 commits intojdx:mainfrom
nkakouros:worktree-worktree-hooks
Apr 4, 2026
Merged

feat(hook): support per-worktree hooks via extensions.worktreeConfig#789
jdx merged 3 commits intojdx:mainfrom
nkakouros:worktree-worktree-hooks

Conversation

@nkakouros
Copy link
Copy Markdown
Contributor

Summary

When extensions.worktreeConfig is enabled and a per-worktree core.hooksPath is set, hk install and hk uninstall now respect that path instead of always using the shared $GIT_COMMON_DIR/hooks/ directory.

This allows different worktrees to have independent hook configurations without conflicting with each other.

Users set up extensions.worktreeConfig and core.hooksPath themselves. hk just reads and respects what's there.

Setup example

# In the main repo, enable per-worktree config
git config extensions.worktreeConfig true

# In each worktree, point hooks to a worktree-local directory
cd /path/to/worktree
git config --worktree core.hooksPath "$(git rev-parse --git-dir)/hooks"
hk install

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 support for per-worktree git hooks by checking the core.hooksPath configuration via git config --worktree. The install and uninstall commands have been updated to prioritize worktree-local hook directories when configured. Additionally, new integration tests were added to verify this behavior. One review comment suggests improving error handling during path canonicalization in git_util.rs to avoid swallowing potential filesystem errors.

Comment thread src/git_util.rs
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 1, 2026

Greptile Summary

This PR adds per-worktree hook installation support: when extensions.worktreeConfig is enabled and a worktree-local core.hooksPath is configured, hk install/hk uninstall route to that path instead of the shared commondir/hooks directory. The previously flagged --worktree--local fallback issue is correctly addressed by gating on extensions.worktreeConfig=true before reading the worktree-scoped config value.

Confidence Score: 5/5

  • Safe to merge; logic is correct, prior concerns are resolved, and the fallback path is fully preserved.
  • No P0 or P1 issues found. The extensions.worktreeConfig guard properly prevents the --worktree--local fallback regression raised in the previous review round. The None fallback is identical to pre-PR behavior. One P2 style nit about eager find_git_path() evaluation does not affect correctness.
  • No files require special attention.

Important Files Changed

Filename Overview
src/git_util.rs Adds worktree_hooks_path(): checks extensions.worktreeConfig=true before querying --worktree scope, correctly preventing the fallback-to-local issue; logic is sound.
src/cli/install.rs Routes install to per-worktree path (with mkdirp) or falls back to shared hooks dir with existing config warnings; refactored lambda into inline loop, no regressions.
src/cli/uninstall.rs Mirrors install's routing logic; adds a safe early-return guard when the hooks dir doesn't exist yet.
test/install_worktree_hooks.bats New bats test file covering install/uninstall to worktree path, hook execution, fallback to shared hooks, and independent multi-worktree setups; mostly solid but has one variable-scoping risk in the multi-worktree test.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[hk install / hk uninstall] --> B{worktree_hooks_path}
    B --> C{extensions.worktreeConfig == true?}
    C -->|No| F[None]
    C -->|Yes| D{core.hooksPath set\nin --worktree scope?}
    D -->|No| F
    D -->|Yes| E[Some: worktree-local path]
    E -->|install| G[mkdirp + write hooks\nto worktree path]
    E -->|uninstall| H[remove hk hooks\nfrom worktree path]
    F -->|install| I[check_hooks_path_config\nglobal + local warning]
    I --> J[resolve shared hooks dir\nvia commondir]
    J --> K[write hooks to\nshared hooks dir]
    F -->|uninstall| L[resolve shared hooks dir\nvia commondir]
    L --> M[remove hk hooks\nfrom shared hooks dir]
Loading

Reviews (7): Last reviewed commit: "Merge branch 'main' into worktree-worktr..." | Re-trigger Greptile

Comment thread src/git_util.rs
Comment thread src/git_util.rs
@nkakouros nkakouros force-pushed the worktree-worktree-hooks branch from 20fd751 to 82b5279 Compare April 1, 2026 23:05
When hk install runs in a git worktree where extensions.worktreeConfig
is enabled, hooks are now installed to the worktree-local git dir with
core.hooksPath set per-worktree. The full path to hk is embedded in the
hook script to avoid PATH issues in non-interactive shells.

If extensions.worktreeConfig is not enabled, the existing shared-hooks
behavior is preserved.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@nkakouros nkakouros force-pushed the worktree-worktree-hooks branch from 33c61d7 to afcce83 Compare April 2, 2026 13:47
@jdx jdx merged commit cabcea3 into jdx:main Apr 4, 2026
18 checks passed
@jdx jdx mentioned this pull request Apr 4, 2026
jdx added a commit that referenced this pull request Apr 5, 2026
### 🚀 Features

- **(hook)** support per-worktree hooks via extensions.worktreeConfig by
[@nkakouros](https://github.com/nkakouros) in
[#789](#789)

### 🐛 Bug Fixes

- **(config)** use XDG_CONFIG_HOME for config path instead of
dirs::config_dir() by [@fukuchancat](https://github.com/fukuchancat) in
[#801](#801)

### 📦️ Dependency Updates

- update anthropics/claude-code-action digest to 0432df8 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#791](#791)
- update rust crate indexmap to v2.13.1 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#792](#792)
- update actions/configure-pages action to v6 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#795](#795)
- update rust crate strum to 0.28 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#794](#794)
- update actions/deploy-pages action to v5 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#796](#796)
- update dependency globals to v17 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#797](#797)
- update github artifact actions (major) by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#798](#798)
- update jdx/mise-action action to v4 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#799](#799)

### New Contributors

- @fukuchancat made their first contribution in
[#801](#801)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Primarily a version bump and documentation/lockfile updates; no
functional Rust source changes are included in this diff.
> 
> **Overview**
> Publishes the `v1.41.0` release by bumping the crate/CLI version
(`Cargo.toml`, `Cargo.lock`, `hk.usage.kdl`, generated CLI docs) and
adding the `1.41.0` entry to `CHANGELOG.md`.
> 
> Updates documentation and example Pkl snippets to reference the
`v1.41.0` release artifacts, and refreshes `Cargo.lock` with dependency
patch/minor updates (e.g., `tokio`, ICU crates, `signal-hook`,
`semver`).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
0c8dea7. 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 8, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [hk](https://github.com/jdx/hk) | minor | `1.40.0` → `1.41.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.41.0`](https://github.com/jdx/hk/blob/HEAD/CHANGELOG.md#1410---2026-04-05)

[Compare Source](jdx/hk@v1.40.0...v1.41.0)

##### 🚀 Features

- **(hook)** support per-worktree hooks via extensions.worktreeConfig by [@&#8203;nkakouros](https://github.com/nkakouros) in [#&#8203;789](jdx/hk#789)

##### 🐛 Bug Fixes

- **(builtins)** use workspace\_indicator for Go package-level analysis tools by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;803](jdx/hk#803)
- **(config)** use XDG\_CONFIG\_HOME for config path instead of dirs::config\_dir() by [@&#8203;fukuchancat](https://github.com/fukuchancat) in [#&#8203;801](jdx/hk#801)

##### 📦️ Dependency Updates

- update anthropics/claude-code-action digest to [`0432df8`](jdx/hk@0432df8) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;791](jdx/hk#791)
- update rust crate indexmap to v2.13.1 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;792](jdx/hk#792)
- update actions/configure-pages action to v6 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;795](jdx/hk#795)
- update rust crate strum to 0.28 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;794](jdx/hk#794)
- update actions/deploy-pages action to v5 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;796](jdx/hk#796)
- update dependency globals to v17 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;797](jdx/hk#797)
- update github artifact actions (major) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;798](jdx/hk#798)
- update jdx/mise-action action to v4 by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;799](jdx/hk#799)

##### New Contributors

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

</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:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDQuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwNC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6bWlub3IiXX0=-->
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.

3 participants