<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotfiles/.githooks, branch master</title>
<subtitle>My linux config and rc files</subtitle>
<id>https://git.sommerfeld.dev/dotfiles/atom/.githooks?h=master</id>
<link rel='self' href='https://git.sommerfeld.dev/dotfiles/atom/.githooks?h=master'/>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/'/>
<updated>2026-05-19T15:45:17Z</updated>
<entry>
<title>feat(git): user-level hooks auto-dispatch into &lt;repo&gt;/.githooks/</title>
<updated>2026-05-19T15:45:17Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-05-19T15:45:17Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=67868f51bbab5bc3ef5c8ba15433ba401a297f1a'/>
<id>urn:sha1:67868f51bbab5bc3ef5c8ba15433ba401a297f1a</id>
<content type='text'>
Inverts the hook delegation model. Previously per-repo hooks required
a project to either (a) write the entire hook themselves and lose the
global signed-commit / agent-author gate, or (b) override
core.hooksPath and write passthrough stubs that exec back to
$HOME/.config/git/hooks/*. Both are ergonomically miserable.

Now: the global hooks at ~/.config/git/hooks/ are *always* the entry
point. Each one calls a shared dispatcher (_dispatch.sh) that runs
&lt;repo&gt;/.githooks/&lt;hookname&gt; if it exists, propagating its exit status,
and then continues with whatever the global hook itself wants to do.
Projects just drop an executable file at .githooks/&lt;name&gt; — no
core.hooksPath, no stubs, no boilerplate. Repos that don't have a
.githooks/ dir keep working exactly as before.

GIT_HOOK_DISPATCHED guards against re-entry so legacy repos using the
old stub-and-exec pattern don't loop. pre-push tees stdin so both the
repo hook and the global ref-list loop see the full push payload.

Adds two new always-no-op global hooks (pre-commit, post-commit)
purely so the dispatch happens for those events too — previously only
commit-msg and pre-push existed globally.

Refactors this dotfiles repo to use the new pattern: drops the
self-delegating .githooks/pre-push stub and removes the per-repo
core.hooksPath override from `just init` (now an idempotent unsetter
to clean up the override from past bootstraps). The remote-dev VM's
home-manager profile symlinks all four hooks plus _dispatch.sh.
</content>
</entry>
<entry>
<title>feat(git): global pre-push hook rejecting unsigned commits</title>
<updated>2026-05-13T12:43:34Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-05-13T12:43:34Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=0ee8f260727f3e88d26d06f59e5c2fa71211a06d'/>
<id>urn:sha1:0ee8f260727f3e88d26d06f59e5c2fa71211a06d</id>
<content type='text'>
Activated via core.hooksPath = ~/.config/git/hooks in the global
git config. The hook walks each ref being pushed (range: remote..local
or, for new branches, local --not --remotes) and checks %G? on every
commit. Accepts G/U/X/Y (good signature variants), rejects N/B/E/R
(no signature, bad, missing key, revoked).

Bypass: git push --no-verify

This repo overrides hooksPath to .githooks/ for its just-check
pre-commit gate, so a thin .githooks/pre-push delegates to the global
hook to keep the policy enforced here too.
</content>
</entry>
<entry>
<title>feat(justfile): add check-fmt and check recipes; pre-commit hook</title>
<updated>2026-04-21T00:24:38Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-04-21T00:24:38Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=afbc07bb44170d7b6f060dd0276157c8db3da68c'/>
<id>urn:sha1:afbc07bb44170d7b6f060dd0276157c8db3da68c</id>
<content type='text'>
Split concerns: fmt-check (check-fmt) from lint. check-fmt mirrors fmt
with each tool's --check/-d flag. check runs both as a single quality
gate. A new .githooks/pre-commit runs 'just check' on every commit;
bypass with git commit --no-verify.

Also drop just --fmt --check and prettier --check from the lint recipe
(they're format checks, belong in check-fmt).
</content>
</entry>
<entry>
<title>refactor: revert auto-init, add dedicated 'just init' recipe</title>
<updated>2026-04-21T00:23:26Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-04-21T00:23:26Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=91c77a81a5f3c193eda8515e8ef053e80ea125ad'/>
<id>urn:sha1:91c77a81a5f3c193eda8515e8ef053e80ea125ad</id>
<content type='text'>
chezmoi init is only needed when .chezmoi.toml.tmpl changes, so running
it on every apply is unnecessary overhead. Run 'just init' manually
when the template changes.
</content>
</entry>
<entry>
<title>fix: use 'chezmoi init --apply' to regenerate config on template changes</title>
<updated>2026-04-21T00:23:26Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-04-21T00:23:26Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=c8c6fa4fb6685ab4914ff014165a382e9d2db842'/>
<id>urn:sha1:c8c6fa4fb6685ab4914ff014165a382e9d2db842</id>
<content type='text'>
When .chezmoi.toml.tmpl changes (e.g. adding [status] exclude=scripts),
plain 'chezmoi apply' warns and keeps using the stale config. Using
'init --apply' regenerates the config from the template and applies
in one step. Status does a silent init first for the same reason.
</content>
</entry>
<entry>
<title>fix: pass -S . to chezmoi so apply/status work from any CWD</title>
<updated>2026-04-21T00:23:26Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-04-21T00:23:26Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=0cd53c5bbad1d9d16e3e65929f9d730dd9ca4ca8'/>
<id>urn:sha1:0cd53c5bbad1d9d16e3e65929f9d730dd9ca4ca8</id>
<content type='text'>
Without an explicit source, chezmoi defaults to ~/.local/share/chezmoi
which doesn't exist on this setup. The post-commit hook uses git
rev-parse so it works even if the hook is run from a subdirectory.
</content>
</entry>
<entry>
<title>feat: add tracked git hooks and justfile</title>
<updated>2026-04-21T00:23:19Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-04-21T00:23:19Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=e0a91e00736188540b4db9feff8aa77ba1dc46c9'/>
<id>urn:sha1:e0a91e00736188540b4db9feff8aa77ba1dc46c9</id>
<content type='text'>
- .githooks/post-commit: runs chezmoi apply after every commit
- justfile: 'just install-hooks' sets core.hooksPath
- Added justfile and .githooks/ to .chezmoiignore
</content>
</entry>
</feed>
