Add PreToolUse reminder hooks for artifact skills - #28
Merged
jeffhorn-nava merged 7 commits intoJul 13, 2026
Conversation
A retrospective on PR #25 traced repeated rework to hand-rolling a PR instead of invoking the create-pr skill. Add non-blocking PreToolUse hooks that route gh pr create / gh issue create toward their skills and print the staged-vs-unstaged file lists before git commit, so the conventions stay in front of the agent at the moment it acts. Each check is its own small module over a shared stdin/stdout contract in scripts/hooks/, registered per-check in a committed .claude/settings .json and covered by unit tests. Closes #27
jeffhorn-nava
marked this pull request as ready for review
July 10, 2026 21:31
Point $schema at the Claude Code settings schema so editors validate the file; the previous value was the generic JSON Schema meta-schema. Document the scripts/hooks subsystem and the settings.json / settings.local.json split in rules/architecture.md, with pointers from AGENTS.md and README. Relates to #27
Address review feedback on the PreToolUse hooks: - Thread the tool's reported cwd into git_commit's git calls so the staged lists reflect the repo the commit runs in, not the hook's own process cwd. - Match commands with a word-boundary regex instead of a bare substring test, so hyphenated look-alikes no longer trip a check; the raw command string is the only signal available, documented in the matcher. - Mirror create-pr's "already inside the skill, proceed" caveat in the create-issue reminder. - Replace the three settings.json hook entries with a single dispatcher (scripts/hooks/__main__.py) whose CHECKS tuple registers the active checks in tested Python; settings.json now has one entry. Relates to #27
The per-user local settings were only ignored via a personal global gitignore; add them to the repo so every clone ignores them. Relates to #27
There was a problem hiding this comment.
Pull request overview
This PR introduces non-blocking Claude Code PreToolUse hooks (registered in committed .claude/settings.json) that inject reminder context when an agent runs gh pr create, gh issue create, or git commit, reinforcing the repo’s durable-artifact workflow at the moment of action.
Changes:
- Add a
scripts/hooks/Python package with a single dispatcher entrypoint (python3 -m scripts.hooks) and per-checkreminder(command, cwd)modules. - Add unit tests covering matching behavior, JSON hook I/O contract emission, and dispatcher combination behavior.
- Document the hook convention in
rules/architecture.md,README.md, andAGENTS.md, and gitignore.claude/settings.local.json.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
.claude/settings.json |
Registers a single PreToolUse Bash hook that runs the Python dispatcher. |
scripts/hooks/__main__.py |
Dispatcher that reads the hook payload once and aggregates reminders from all registered checks. |
scripts/hooks/__init__.py |
Shared payload parsing, command matching, and JSON emission contract for hook reminders. |
scripts/hooks/pr_create.py |
Reminder check for gh pr create to route through create-pr. |
scripts/hooks/issue_create.py |
Reminder check for gh issue create to route through create-issue. |
scripts/hooks/git_commit.py |
Reminder check for git commit that prints staged/unstaged/untracked file lists. |
tests/test_hook_reminders.py |
Adds unit tests for matching logic, hook JSON output, and dispatcher behavior. |
rules/architecture.md |
Documents the new local reminder hook architecture and invariants. |
README.md |
Notes that opening the repo in Claude Code loads the reminder hooks and what they do. |
AGENTS.md |
Captures the committed vs local Claude settings convention for hooks. |
.gitignore |
Ignores per-user .claude/settings.local.json overrides. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…-durable-artifact-gates # Conflicts: # README.md
The code-review suggestions rewired run() to read the payload directly via payload_from_stdin/command_of/cwd_of, leaving command_from_stdin used only by its own test and its docstring describing a run() path that no longer exists. Remove it and repoint the bad-input test at payload_from_stdin, the robustness boundary both run() and the dispatcher actually use. Relates to #27
baonguyenNava
approved these changes
Jul 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Add non-blocking PreToolUse hooks that keep the repo's durable-artifact conventions in front of an agent at the moment it acts: a reminder to route
gh pr createandgh issue createthrough the create-pr / create-issue skills, and the staged-versus-unstaged file lists beforegit commit.Closes #27
How
Each check is its own small module in
scripts/hooks/exposing a purereminder(command), over a shared stdin/stdout contract inscripts/hooks/__init__.pythat reads the Bash command from the hook payload and emits the reminder as non-blockingadditionalContext..claude/settings.jsonregisters one hook entry per check under theBashmatcher. The reminders guide and never block, so they do not interfere with create-pr's owngh pr createcall.Test plan
python -m pytestpasses (60 tests, including the 7 intests/test_hook_reminders.py).echo '{"tool_input":{"command":"gh pr create"}}' | python3 -m scripts.hooks.pr_createemits the reminder JSON, and an unrelated command emits nothing.git commitand confirm the three reminders fire and the commit hook lists the staged set (confirmed on this branch during development).Notes for reviewers
Scope is hooks-only. The PR #25 retrospective (recorded in #27) traced the rework to skipping create-pr entirely, which these hooks address; tightening the create-pr skill (item 2 in #27 as first filed) was dropped after review as redundant with review-draft's template-adherence check. A personal-memory note captures the same lesson outside the repo.