What happened?
In a repo that also uses lefthook to manage git hooks, entire and lefthook fight over .git/hooks/pre-push. After any change to lefthook.yml, lefthook silently reclaims the hook and entire's session-log-on-push stops working β with no error β until someone manually re-wraps it.
How the conflict arises
- lefthook installs and manages
pre-push. Its installed hooks self-sync on every run, gated by a checksum of lefthook.yml stored in .git/info/lefthook.checksum.
entire enable / entire configure --force wraps the existing hook: it renames the current pre-push to pre-push.pre-entire and installs its own wrapper that runs the entire handler then chains down:
# Entire CLI hooks
if command -v entire >/dev/null 2>&1; then entire hooks git pre-push "$1" || true; else :; fi
# Chain: run pre-existing hook
"$(dirname "$0")/pre-push.pre-entire" "$@"
At this point both run on push β entire pushes session logs, then chains to lefthook. π
- But whenever
lefthook.yml changes, lefthook's checksum goes stale. Its next self-sync (at the top of any lefthook-managed hook, e.g. the next commit's pre-commit) sees that pre-push is no longer its hook, backs entire's wrapper up to pre-push.old, and reinstalls its own bare hook. entire's session push is now silently gone.
- On the next
lefthook.yml change after that, lefthook also emits a recurring warning, because its earlier backup collides:
sync hooks: β
could not replace the hook: can't rename pre-push to pre-push.old - file already exists
Why there is no clean user-side fix (verified on 0.7.3)
The natural fix β make lefthook the sole owner of pre-push and run entire's push as a lefthook job/script β is blocked:
entire configure --force re-installs entire's pre-push wrapper even with push_sessions: false β you cannot stop entire owning the hook.
entire hooks git pre-push <remote> is itself gated by push_sessions (no-ops when off) β you cannot disable the wrapper and still call the handler from a lefthook script.
entire configure --force re-wraps whatever is at pre-push with no detection β if lefthook reclaimed it, entire silently wraps lefthook's bare hook again, with no idempotency check or "another manager owns this" warning.
The only local mitigation is a self-heal step that re-wraps after each re-sync, which still can't cover a push that happens with no intervening commit.
Proposed fixes (any one resolves it)
- Idempotent / manager-aware install β if
pre-push already chains to pre-push.pre-entire (or contains entire's wrapper), don't blindly re-wrap; detect known managers (lefthook, husky, pre-commit, core.hooksPath).
- Decouple handler from install β an option to install the handler behavior without owning the
pre-push file, so managers like lefthook can invoke entire hooks git pre-push as a job/script. (Today --skip-push-sessions disables the handler too, defeating this.)
- Register via the host manager β when lefthook is detected, register entire's push as a lefthook script (lefthook scripts receive the hook's
$@, including the remote) instead of taking the file.
- Self-repair marker β let entire re-assert/repair its wrapper automatically so a reclaim heals without manual
entire configure --force.
Steps to reproduce
- A repo using lefthook with a
pre-push: section; run lefthook install.
entire enable (wraps pre-push, chaining to lefthook).
- Edit
lefthook.yml (any change) and make a commit or push.
- lefthook's self-sync reclaims
pre-push; entire's session push silently stops (no error). Confirm with head .git/hooks/pre-push β the entire wrapper is gone.
Entire CLI version
Entire CLI 0.7.3
OS and architecture
macOS 26.5, arm64 (Darwin 25.5.0)
Agent
claude code
Terminal
ghostty
Logs / debug output
Additional context
- lefthook 2.0.12;
.entire/settings.json committed (team-wide setup), so this affects every macOS dev on the team using entire.
- The 0.7.3 pre-push wrapper added a
command -v entire guard (no-ops cleanly when entire is off-PATH) β good, but it does not address this ownership conflict.
- Also reproduces across git worktrees, which share a single
.git/hooks dir.
- No log output to attach: the failure is silent (entire's hook is simply removed; nothing is logged).
What happened?
In a repo that also uses lefthook to manage git hooks, entire and lefthook fight over
.git/hooks/pre-push. After any change tolefthook.yml, lefthook silently reclaims the hook and entire's session-log-on-push stops working β with no error β until someone manually re-wraps it.How the conflict arises
pre-push. Its installed hooks self-sync on every run, gated by a checksum oflefthook.ymlstored in.git/info/lefthook.checksum.entire enable/entire configure --forcewraps the existing hook: it renames the currentpre-pushtopre-push.pre-entireand installs its own wrapper that runs the entire handler then chains down:lefthook.ymlchanges, lefthook's checksum goes stale. Its next self-sync (at the top of any lefthook-managed hook, e.g. the next commit'spre-commit) sees thatpre-pushis no longer its hook, backs entire's wrapper up topre-push.old, and reinstalls its own bare hook. entire's session push is now silently gone.lefthook.ymlchange after that, lefthook also emits a recurring warning, because its earlier backup collides:Why there is no clean user-side fix (verified on 0.7.3)
The natural fix β make lefthook the sole owner of
pre-pushand run entire's push as a lefthook job/script β is blocked:entire configure --forcere-installs entire's pre-push wrapper even withpush_sessions: falseβ you cannot stop entire owning the hook.entire hooks git pre-push <remote>is itself gated bypush_sessions(no-ops when off) β you cannot disable the wrapper and still call the handler from a lefthook script.entire configure --forcere-wraps whatever is atpre-pushwith no detection β if lefthook reclaimed it, entire silently wraps lefthook's bare hook again, with no idempotency check or "another manager owns this" warning.The only local mitigation is a self-heal step that re-wraps after each re-sync, which still can't cover a push that happens with no intervening commit.
Proposed fixes (any one resolves it)
pre-pushalready chains topre-push.pre-entire(or contains entire's wrapper), don't blindly re-wrap; detect known managers (lefthook, husky, pre-commit,core.hooksPath).pre-pushfile, so managers like lefthook can invokeentire hooks git pre-pushas a job/script. (Today--skip-push-sessionsdisables the handler too, defeating this.)$@, including the remote) instead of taking the file.entire configure --force.Steps to reproduce
pre-push:section; runlefthook install.entire enable(wrapspre-push, chaining to lefthook).lefthook.yml(any change) and make a commit or push.pre-push; entire's session push silently stops (no error). Confirm withhead .git/hooks/pre-pushβ the entire wrapper is gone.Entire CLI version
Entire CLI 0.7.3
OS and architecture
macOS 26.5, arm64 (Darwin 25.5.0)
Agent
claude code
Terminal
ghostty
Logs / debug output
Additional context
.entire/settings.jsoncommitted (team-wide setup), so this affects every macOS dev on the team using entire.command -v entireguard (no-ops cleanly when entire is off-PATH) β good, but it does not address this ownership conflict..git/hooksdir.