diff options
| author | Craig Jennings <c@cjennings.net> | 2026-04-19 17:06:10 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-04-19 17:06:10 -0500 |
| commit | 4957c60c9ee985628ad59344e593d20a18ca8fdb (patch) | |
| tree | e8d6659dd2d7dd24126782fa83ccccffc6c6f836 /Makefile | |
| parent | ab4a07b3c081609a81ee049ec9bbe6ccded09b54 (diff) | |
| download | rulesets-4957c60c9ee985628ad59344e593d20a18ca8fdb.tar.gz rulesets-4957c60c9ee985628ad59344e593d20a18ca8fdb.zip | |
feat(hooks): add global hooks — PreCompact priorities + git/gh confirm modals
Three new machine-wide hooks installed via `make install-hooks`:
- `precompact-priorities.sh` (PreCompact) — injects a priority block into
the compaction prompt so the generated summary retains information most
expensive to reconstruct: unanswered questions, root causes with
file:line, subagent findings as primary evidence, exact numbers/IDs,
A-vs-B decisions, open TODOs, classified-data handling.
- `git-commit-confirm.py` (PreToolUse/Bash) — gates `git commit` behind a
confirmation modal showing parsed message, staged files, diff stats,
author. Parses both HEREDOC and `-m`/`--message` forms.
- `gh-pr-create-confirm.py` (PreToolUse/Bash) — gates `gh pr create`
behind a modal showing title, base ← head, reviewers, labels,
assignees, milestone, draft flag, body (HEREDOC or quoted).
Makefile: adds `install-hooks` / `uninstall-hooks` targets and extends
`list` with a Hooks section. Install prints the settings.json snippet
(in `hooks/settings-snippet.json`) to merge into `~/.claude/settings.json`.
Also: `languages/elisp/claude/hooks/validate-el.sh` now emits JSON with
`hookSpecificOutput.additionalContext` on failure (via new `fail_json()`
helper) so Claude sees a structured error in context, in addition to
the existing stderr output and exit 2.
Patterns synthesized clean-room from fcakyon/claude-codex-settings
(Apache-2.0). Each hook is original content.
Diffstat (limited to 'Makefile')
| -rw-r--r-- | Makefile | 48 |
1 files changed, 47 insertions, 1 deletions
@@ -3,12 +3,14 @@ SHELL := /bin/bash SKILLS_DIR := $(HOME)/.claude/skills RULES_DIR := $(HOME)/.claude/rules +HOOKS_DIR := $(HOME)/.claude/hooks SKILLS := c4-analyze c4-diagram debug add-tests respond-to-review review-code fix-issue security-check \ arch-design arch-decide arch-document arch-evaluate \ brainstorm codify root-cause-trace five-whys prompt-engineering \ playwright-js playwright-py frontend-design pairwise-tests \ finish-branch RULES := $(wildcard claude-rules/*.md) +HOOKS := $(wildcard hooks/*.sh hooks/*.py) LANGUAGES := $(notdir $(wildcard languages/*)) # Pick target project — use PROJECT= or interactive fzf over local .git dirs. @@ -35,7 +37,7 @@ $(if $(shell command -v pacman 2>/dev/null),sudo pacman -S --noconfirm $(1),\ $(error No supported package manager found (brew/apt-get/pacman))))) endef -.PHONY: help install uninstall list \ +.PHONY: help install uninstall list install-hooks uninstall-hooks \ install-lang install-elisp install-python list-languages \ diff lint deps @@ -168,6 +170,50 @@ list: ## Show global install status echo " - $$name"; \ fi \ done + @echo "" + @echo "Hooks:" + @for hook in $(HOOKS); do \ + name=$$(basename $$hook); \ + if [ -L "$(HOOKS_DIR)/$$name" ]; then \ + echo " ✓ $$name (installed)"; \ + else \ + echo " - $$name"; \ + fi \ + done + +install-hooks: ## Symlink global hooks into ~/.claude/hooks/ + print settings.json snippet + @mkdir -p $(HOOKS_DIR) + @echo "Hooks:" + @for hook in $(HOOKS); do \ + name=$$(basename $$hook); \ + if [ -L "$(HOOKS_DIR)/$$name" ]; then \ + echo " skip $$name (already linked)"; \ + elif [ -e "$(HOOKS_DIR)/$$name" ]; then \ + echo " WARN $$name exists and is not a symlink — skipping"; \ + else \ + ln -s "$(CURDIR)/$$hook" "$(HOOKS_DIR)/$$name"; \ + echo " link $$name → $(HOOKS_DIR)/$$name"; \ + fi \ + done + @echo "" + @echo "Merge this into ~/.claude/settings.json (preserve any existing hooks arrays):" + @echo "" + @cat hooks/settings-snippet.json + @echo "" + @echo "After merging, reload Claude Code (open /hooks menu once, or restart the session)." + +uninstall-hooks: ## Remove global hook symlinks from ~/.claude/hooks/ + @for hook in $(HOOKS); do \ + name=$$(basename $$hook); \ + if [ -L "$(HOOKS_DIR)/$$name" ]; then \ + rm "$(HOOKS_DIR)/$$name"; \ + echo " rm $$name"; \ + else \ + echo " skip $$name (not a symlink)"; \ + fi \ + done + @echo "" + @echo "Note: this does NOT edit ~/.claude/settings.json — remove the hook entries manually." ##@ Per-project language bundles |
