Conversation
Two ready-to-use Python hooks using cchooks SDK: - block_destructive.py: blocks rm -rf, git reset --hard, force push - block_secrets.py: blocks git add .env and credential files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aae36d432a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if re.search(r'git\s+push\s+.*\b(main|master)\b', command): | ||
| ctx.block("Push to protected branch. Push to a feature branch and create a PR.") | ||
|
|
||
| ctx.allow() |
There was a problem hiding this comment.
Call PreToolUse decisions through ctx.output in example hook
create_context() returns a PreToolUseContext, and in this codebase decision methods live on PreToolUseOutput (ctx.output.allow()/deny() in src/cchooks/contexts/pre_tool_use.py), not on the context itself. Calling ctx.allow() here raises AttributeError for normal PreToolUse executions, so this example hook crashes instead of emitting a valid JSON decision.
Useful? React with 👍 / 👎.
| if re.search(r'git\s+add\s+.*(credentials|\.pem|\.key|\.p12|id_rsa|id_ed25519)', command, re.IGNORECASE): | ||
| ctx.block("Credential/key file should never be committed. Add to .gitignore.") | ||
|
|
||
| ctx.allow() |
There was a problem hiding this comment.
Use ctx.output decision API in block_secrets example
Like the destructive-command example, this script calls ctx.allow()/ctx.block() on PreToolUseContext, but those methods are not defined on the context type in src/cchooks/contexts/pre_tool_use.py; only ctx.output.allow()/deny() are available. As a result, the example fails with AttributeError and never returns the hook response Claude expects.
Useful? React with 👍 / 👎.
| ctx.block("git clean removes untracked files permanently. Use git clean -n to preview.") | ||
|
|
||
| # Block force push | ||
| if re.search(r'git\s+push\s+.*(-f\b|--force\b)', command): |
There was a problem hiding this comment.
Exclude --force-with-lease from the force-push deny regex
This pattern treats --force-with-lease as --force because --force\b matches before the hyphen, so lease-protected pushes are blocked too. git push -h documents --force-with-lease as a separate, safer option, and your deny message explicitly tells users to use it; with the current regex, that recommendation cannot work.
Useful? React with 👍 / 👎.
Adds examples/ directory with two safety hooks using cchooks SDK:
Both demonstrate the cchooks SDK pattern (create_context, isinstance, block/allow).
🤖 Generated with Claude Code