cc-safe-setup 29.8.0 → 30.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +72 -19
- package/.claude-plugin/plugin.json +1 -1
- package/CONTRIBUTING.md +7 -2
- package/COOKBOOK.md +50 -46
- package/LICENSE +21 -0
- package/MIGRATION.md +8 -8
- package/README.md +419 -512
- package/SAFETY_CHECKLIST.md +15 -7
- package/SERVICES.md +194 -0
- package/SETTINGS_REFERENCE.md +236 -17
- package/SKILL.md +5 -5
- package/TROUBLESHOOTING.md +35 -14
- package/action.yml +12 -4
- package/audit/README.md +84 -0
- package/audit/audit-checklist.md +152 -0
- package/audit/boundary-selftest.sh +85 -0
- package/audit/boundary.sh +123 -0
- package/audit/count-hooks.py +42 -0
- package/audit/find-dead-hooks.sh +82 -0
- package/audit/find-unfirable-rules.sh +142 -0
- package/audit/fire.sh +97 -0
- package/audit/selftest.sh +42 -0
- package/audit/unfirable-selftest.sh +81 -0
- package/audit-web/index.html +9 -9
- package/examples/README.md +54 -17
- package/examples/account-billing-log.sh +98 -0
- package/examples/account-routing-preflight.sh +123 -0
- package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
- package/examples/agent-view-quota-decrement.sh +32 -0
- package/examples/agent-view-quota-warn.sh +94 -0
- package/examples/agents-md-edit-drift-warner.sh +223 -0
- package/examples/agents-md-loader.sh +160 -0
- package/examples/agents-md-sync-checker.sh +102 -0
- package/examples/ai-slop-punctuation-arrest.sh +210 -0
- package/examples/allowlist.sh +70 -10
- package/examples/always-allow-pattern-suggester.sh +125 -0
- package/examples/ansible-vault-guard.sh +2 -1
- package/examples/anthropic-base-url-guard.sh +76 -0
- package/examples/api-busyloop-guard.sh +123 -0
- package/examples/api-endpoint-guard.sh +12 -0
- package/examples/api-key-in-url-guard.sh +17 -1
- package/examples/api-rate-limit-guard.sh +36 -1
- package/examples/api-rate-limit-tracker.sh +12 -0
- package/examples/articulated-scope-capture.sh +101 -0
- package/examples/askuserquestion-autonomy-gate.sh +102 -0
- package/examples/attachment-traversal-guard.sh +118 -0
- package/examples/aup-block-pattern-logger.sh +161 -0
- package/examples/aup-false-positive-helper.sh +124 -0
- package/examples/aup-large-tool-output-warner.sh +282 -0
- package/examples/aup-retry-loop-guard.sh +229 -0
- package/examples/auth-expiry-reminder.sh +157 -0
- package/examples/auth-macos-sleep-detector.sh +185 -0
- package/examples/auth-path-detector.sh +171 -0
- package/examples/auth-status-checker.sh +157 -0
- package/examples/authorized-reconfirmation-detector.sh +195 -0
- package/examples/auto-approve-build.sh +39 -0
- package/examples/auto-approve-cargo.sh +31 -1
- package/examples/auto-approve-docker.sh +35 -0
- package/examples/auto-approve-git-read.sh +37 -14
- package/examples/auto-approve-go.sh +30 -1
- package/examples/auto-approve-gradle.sh +29 -1
- package/examples/auto-approve-make.sh +29 -1
- package/examples/auto-approve-maven.sh +29 -1
- package/examples/auto-approve-python.sh +41 -1
- package/examples/auto-approve-readonly-tools.sh +1 -0
- package/examples/auto-approve-readonly.sh +110 -33
- package/examples/auto-approve-ssh.sh +30 -1
- package/examples/auto-approve-test.sh +44 -0
- package/examples/auto-checkpoint.sh +1 -1
- package/examples/auto-compact-prep.sh +0 -0
- package/examples/auto-git-checkpoint.sh +0 -0
- package/examples/auto-mode-safe-commands.sh +53 -1
- package/examples/auto-mode-safety-enforcer.sh +151 -4
- package/examples/auto-push-session-branch.sh +22 -0
- package/examples/aws-production-guard.sh +13 -1
- package/examples/aws-region-guard.sh +1 -1
- package/examples/background-cost-launch-guard.sh +82 -0
- package/examples/background-task-guard.sh +12 -0
- package/examples/backup-before-refactor.sh +0 -0
- package/examples/banned-command-guard.sh +12 -0
- package/examples/bash-allowlist-secondary-check.sh +157 -0
- package/examples/bash-domain-allowlist.sh +12 -0
- package/examples/bash-fanout-bounded-rewriter.sh +191 -0
- package/examples/bash-heuristic-approver.sh +112 -10
- package/examples/bash-project-fence.sh +194 -0
- package/examples/bash-safety-auto-deny.sh +12 -0
- package/examples/bash-secret-output-detector.sh +44 -3
- package/examples/bash-trace-guard.sh +12 -0
- package/examples/bashrc-safety-check.sh +0 -0
- package/examples/bg-permission-prompt-warner.sh +182 -0
- package/examples/bg-task-cooldown-guard.sh +12 -0
- package/examples/binary-read-detector.sh +135 -0
- package/examples/binary-upload-guard.sh +12 -0
- package/examples/block-database-wipe.sh +35 -10
- package/examples/branch-name-check.sh +8 -3
- package/examples/branch-naming-convention.sh +0 -0
- package/examples/broad-find-guard.sh +12 -0
- package/examples/broad-prefix-session-trap-warner.sh +106 -0
- package/examples/bulk-file-delete-guard.sh +45 -0
- package/examples/bypass-mode-effective-verifier.sh +203 -0
- package/examples/cache-creation-drift-detector.sh +120 -0
- package/examples/cache-residue-detector.sh +195 -0
- package/examples/cache-tier-logger.sh +70 -0
- package/examples/cache-ttl-eviction-detector.sh +149 -0
- package/examples/cargo-publish-guard.sh +14 -1
- package/examples/case-insensitive-path-guard.sh +21 -2
- package/examples/case-sensitive-guard.sh +23 -2
- package/examples/cch-cache-guard.sh +0 -0
- package/examples/cch-sentinel-precommit-guard.sh +47 -0
- package/examples/check-abort-controller.sh +1 -1
- package/examples/check-accessibility.sh +0 -0
- package/examples/check-aria-labels.sh +0 -0
- package/examples/check-before-act-enforcer.sh +12 -0
- package/examples/check-charset-meta.sh +0 -0
- package/examples/check-cookie-flags.sh +0 -0
- package/examples/check-cors-config.sh +0 -0
- package/examples/check-csp-headers.sh +0 -0
- package/examples/check-csrf-protection.sh +0 -0
- package/examples/check-debounce.sh +1 -1
- package/examples/check-dependency-age.sh +0 -0
- package/examples/check-dependency-license.sh +0 -0
- package/examples/check-dockerfile-best-practice.sh +0 -0
- package/examples/check-error-boundaries.sh +0 -0
- package/examples/check-error-class.sh +1 -1
- package/examples/check-error-handling.sh +0 -0
- package/examples/check-error-logging.sh +1 -1
- package/examples/check-error-message.sh +0 -0
- package/examples/check-error-stack.sh +0 -0
- package/examples/check-favicon.sh +0 -0
- package/examples/check-git-hooks-compat.sh +0 -0
- package/examples/check-gitattributes.sh +0 -0
- package/examples/check-https-redirect.sh +0 -0
- package/examples/check-input-validation.sh +0 -0
- package/examples/check-lang-attribute.sh +0 -0
- package/examples/check-npm-scripts-exist.sh +0 -0
- package/examples/check-package-size.sh +0 -0
- package/examples/check-port-availability.sh +0 -0
- package/examples/check-promise-all.sh +1 -1
- package/examples/check-rate-limiting.sh +0 -0
- package/examples/check-return-types.sh +0 -0
- package/examples/check-semantic-versioning.sh +0 -0
- package/examples/check-suspense-fallback.sh +1 -1
- package/examples/check-test-exists.sh +0 -0
- package/examples/check-test-naming.sh +0 -0
- package/examples/check-timeout-cleanup.sh +1 -1
- package/examples/check-tls-version.sh +0 -0
- package/examples/check-unsubscribe.sh +1 -1
- package/examples/check-viewport-meta.sh +0 -0
- package/examples/check-worker-terminate.sh +1 -1
- package/examples/checkpoint-tamper-guard.sh +12 -0
- package/examples/chmod-guard.sh +12 -0
- package/examples/chown-guard.sh +24 -0
- package/examples/ci-workflow-guard.sh +6 -1
- package/examples/claim-verify-detector.sh +109 -0
- package/examples/claim-vs-caveat-checker.sh +77 -0
- package/examples/classifier-fallback-allow.sh +114 -40
- package/examples/claude-cache-gc.sh +1 -0
- package/examples/claude-code-version-pin-advisor.sh +183 -0
- package/examples/claude-md-reinjector.sh +129 -0
- package/examples/claude-md-size-monitor.sh +66 -0
- package/examples/claude-update-budget-guard.sh +123 -0
- package/examples/claude-update-smart.sh +113 -0
- package/examples/claudeignore-enforce-guard.sh +12 -0
- package/examples/claudemd-enforcer.sh +0 -0
- package/examples/claudemd-tool-prohibition.sh +128 -0
- package/examples/clear-command-confirm-guard.sh +32 -15
- package/examples/cli-config-pinning-detector.sh +162 -0
- package/examples/cliff-countdown-advisor.sh +96 -0
- package/examples/clipboard-secret-guard.sh +12 -0
- package/examples/closure-word-verify-gate.sh +150 -0
- package/examples/cloud-cli-guard.sh +39 -2
- package/examples/commit-all-scope-guard.sh +44 -0
- package/examples/commit-message-check.sh +1 -1
- package/examples/commit-message-quality.sh +6 -1
- package/examples/commitment-carry-forward-arrest.sh +361 -0
- package/examples/compact-alert-notification.sh +0 -0
- package/examples/compact-dispatch-watchdog.sh +149 -0
- package/examples/completion-claim-without-verification-detector.sh +207 -0
- package/examples/composer-guard.sh +12 -0
- package/examples/compound-bash-permission-resolver.sh +156 -0
- package/examples/compound-command-allow.sh +1 -1
- package/examples/compound-command-deny-enforcer.sh +183 -0
- package/examples/compound-inject-guard.sh +12 -0
- package/examples/concurrent-edit-lock.sh +12 -0
- package/examples/conflict-marker-guard.sh +12 -0
- package/examples/consecutive-error-breaker.sh +0 -0
- package/examples/console-log-count.sh +1 -0
- package/examples/context-compact-advisor.sh +29 -2
- package/examples/context-length-budget.sh +69 -0
- package/examples/context-threshold-alert.sh +12 -0
- package/examples/context-usage-drift-alert.sh +41 -13
- package/examples/conversation-history-guard.sh +12 -0
- package/examples/core-file-protect-guard.sh +12 -0
- package/examples/cors-star-warn.sh +0 -0
- package/examples/cost-incident-self-audit.sh +162 -0
- package/examples/cowork-claude-md-load-checker.sh +100 -0
- package/examples/cowork-fuse-staleness-watcher.sh +140 -0
- package/examples/cowork-hook-absence-warner.sh +167 -0
- package/examples/cowork-model-picker-advisor.sh +115 -0
- package/examples/credential-exfil-guard.sh +65 -4
- package/examples/credential-file-cat-guard.sh +17 -1
- package/examples/cron-create-receipt.sh +112 -0
- package/examples/cron-modification-guard.sh +12 -0
- package/examples/cross-product-mcp-spawn-detector.sh +178 -0
- package/examples/cwd-project-boundary-guard.sh +0 -0
- package/examples/daemon-zombie-worker-surfacer.sh +118 -0
- package/examples/daily-cost-guard.sh +164 -0
- package/examples/daily-usage-tracker.sh +0 -0
- package/examples/dangerous-pip-flag-guard.sh +12 -0
- package/examples/db-connect-guard.sh +13 -1
- package/examples/denied-action-retry-guard.sh +12 -0
- package/examples/deny-bypass-detector.sh +12 -0
- package/examples/deny-rule-integrity-verifier.sh +181 -0
- package/examples/dependency-install-guard.sh +12 -0
- package/examples/deploy-guard.sh +14 -2
- package/examples/deploy-path-verify-guard.sh +12 -0
- package/examples/deployment-readback-gate.sh +135 -0
- package/examples/deployment-readback-gh-adapter.sh +247 -0
- package/examples/deployment-verify-guard.sh +25 -2
- package/examples/destructive-db-script-write-guard.sh +166 -0
- package/examples/destructive-migration-write-guard.sh +163 -0
- package/examples/diff-size-guard.sh +12 -0
- package/examples/disabled-feature-toggle-advisor.sh +88 -0
- package/examples/disk-partition-guard.sh +12 -0
- package/examples/dispatch-allowlist-preflight.sh +301 -0
- package/examples/dispatch-liveness-watchdog.sh +216 -0
- package/examples/dispatch-receipt.sh +174 -0
- package/examples/django-migrate-guard.sh +12 -0
- package/examples/dns-config-guard.sh +12 -0
- package/examples/docker-dangerous-guard.sh +12 -0
- package/examples/docker-volume-guard.sh +0 -0
- package/examples/dockerfile-latest-guard.sh +1 -0
- package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
- package/examples/dotenv-commit-guard.sh +12 -0
- package/examples/dotenv-read-guard.sh +12 -0
- package/examples/dotfile-protection-guard.sh +12 -0
- package/examples/dotnet-build-on-edit.sh +1 -1
- package/examples/drizzle-migrate-guard.sh +27 -2
- package/examples/echo-probe-spam-detector.sh +176 -0
- package/examples/edit-counter-test-gate.sh +12 -0
- package/examples/edit-error-counter.sh +1 -1
- package/examples/edit-guard.sh +12 -0
- package/examples/edit-old-string-validator.sh +12 -0
- package/examples/edit-quote-ambiguity-guard.sh +97 -0
- package/examples/edit-retry-loop-guard.sh +0 -0
- package/examples/edit-verify.sh +0 -0
- package/examples/env-inline-secret-guard.sh +14 -2
- package/examples/env-naming-convention.sh +0 -0
- package/examples/env-prod-guard.sh +0 -0
- package/examples/env-required-check.sh +0 -0
- package/examples/env-source-guard.sh +12 -0
- package/examples/env-var-check.sh +24 -1
- package/examples/ephemeral-container-detector.sh +147 -0
- package/examples/error-memory-guard.sh +12 -0
- package/examples/evidence-claim-gate.sh +187 -0
- package/examples/exploration-budget-guard.sh +12 -0
- package/examples/expo-eject-guard.sh +13 -0
- package/examples/extended-thinking-loop-guard.sh +139 -0
- package/examples/extended-thinking-resume-warning.sh +119 -0
- package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
- package/examples/fabricated-command-detector.sh +145 -0
- package/examples/false-disk-full-guard.sh +63 -0
- package/examples/feature-deprecation-detector.sh +109 -0
- package/examples/file-change-tracker.sh +1 -1
- package/examples/file-change-undo-tracker.sh +0 -0
- package/examples/file-edit-backup.sh +63 -14
- package/examples/file-reference-check.sh +0 -0
- package/examples/file-size-limit.sh +12 -0
- package/examples/financial-operation-guard.sh +12 -0
- package/examples/firewall-guard.sh +12 -0
- package/examples/fish-shell-wrapper.sh +125 -7
- package/examples/five-hundred-milestone.sh +1 -0
- package/examples/flask-static-route-guard.sh +89 -0
- package/examples/forbidden-response-phrase-detector.sh +161 -0
- package/examples/gem-push-guard.sh +13 -0
- package/examples/gh-cli-destructive-guard.sh +13 -1
- package/examples/git-checkout-safety-guard.sh +12 -0
- package/examples/git-checkout-uncommitted-guard.sh +12 -0
- package/examples/git-config-guard.sh +12 -0
- package/examples/git-crypt-worktree-guard.sh +12 -0
- package/examples/git-filter-repo-guard.sh +56 -0
- package/examples/git-history-rewrite-guard.sh +12 -0
- package/examples/git-hook-bypass-guard.sh +0 -0
- package/examples/git-maintenance-guard.sh +83 -0
- package/examples/git-merge-conflict-prevent.sh +0 -0
- package/examples/git-message-length-check.sh +0 -0
- package/examples/git-message-length.sh +0 -0
- package/examples/git-operations-require-approval.sh +68 -14
- package/examples/git-pack-temp-cleanup-guard.sh +102 -0
- package/examples/git-push-blast-radius-guard.sh +218 -0
- package/examples/git-remote-guard.sh +24 -3
- package/examples/git-rm-orphan-wipe-guard.sh +85 -0
- package/examples/git-stash-before-checkout.sh +12 -0
- package/examples/git-stash-before-danger.sh +0 -0
- package/examples/git-submodule-guard.sh +69 -2
- package/examples/git-tag-guard.sh +12 -0
- package/examples/github-actions-secret-guard.sh +0 -0
- package/examples/gitignore-check.sh +0 -0
- package/examples/gitops-drift-guard.sh +12 -0
- package/examples/go-mod-tidy-warn.sh +1 -0
- package/examples/go-vet-after-edit.sh +12 -0
- package/examples/goal-iteration-limit-warner.sh +152 -0
- package/examples/grep-nul-false-negative-guard.sh +30 -0
- package/examples/growthbook-flag-monitor.sh +257 -0
- package/examples/hallucination-url-check.sh +1 -1
- package/examples/halt-signal-detector.sh +135 -0
- package/examples/handoff-on-clear.sh +65 -0
- package/examples/hardcoded-ip-guard.sh +1 -0
- package/examples/headless-empty-result-guard.sh +0 -0
- package/examples/headless-stop-guard.sh +0 -0
- package/examples/helm-install-guard.sh +2 -1
- package/examples/home-critical-bash-guard.sh +17 -1
- package/examples/hook-debug-wrapper.sh +6 -2
- package/examples/hook-permission-fixer.sh +0 -0
- package/examples/hook-self-disable-detector.sh +99 -0
- package/examples/hook-stdout-sanitizer.sh +6 -2
- package/examples/hook-tamper-guard.sh +12 -0
- package/examples/idle-session-cost-alert.sh +0 -0
- package/examples/image-dimension-guard.sh +109 -0
- package/examples/image-file-validator.sh +0 -0
- package/examples/iteration-quality-degradation-detector.sh +170 -0
- package/examples/java-compile-on-edit.sh +1 -1
- package/examples/json-syntax-check.sh +0 -0
- package/examples/k8s-production-guard.sh +13 -1
- package/examples/kill-process-guard.sh +12 -0
- package/examples/kubernetes-guard.sh +13 -1
- package/examples/laravel-artisan-guard.sh +13 -0
- package/examples/large-file-guard.sh +1 -1
- package/examples/log-level-guard.sh +0 -0
- package/examples/log-truncation-guard.sh +12 -0
- package/examples/long-session-malformed-tool-call-detector.sh +183 -0
- package/examples/loop-detector.sh +12 -0
- package/examples/magic-number-warn.sh +1 -0
- package/examples/main-branch-warn.sh +12 -0
- package/examples/markdown-link-check.sh +0 -0
- package/examples/max-concurrent-agents.sh +12 -0
- package/examples/max-edit-size-guard.sh +13 -0
- package/examples/max-file-count-guard.sh +0 -0
- package/examples/max-file-delete-count.sh +0 -0
- package/examples/max-function-length.sh +1 -0
- package/examples/max-import-count.sh +0 -0
- package/examples/max-subagent-count.sh +0 -0
- package/examples/mcp-config-freeze.sh +12 -0
- package/examples/mcp-config-poisoning-audit.sh +150 -0
- package/examples/mcp-data-boundary.sh +1 -1
- package/examples/mcp-misdiagnosis-arrest.sh +209 -0
- package/examples/mcp-orphan-leak-warner.sh +49 -0
- package/examples/mcp-permissions-ask-warner.sh +151 -0
- package/examples/mcp-routine-approval-detector.sh +154 -0
- package/examples/mcp-server-allowlist.sh +12 -0
- package/examples/mcp-server-guard.sh +12 -0
- package/examples/mcp-startup-bloat-detector.sh +87 -0
- package/examples/mcp-stdio-compatibility-test.sh +153 -0
- package/examples/mcp-tool-audit-log.sh +0 -0
- package/examples/mcp-tool-guard.sh +101 -1
- package/examples/mcp-warmup-wait.sh +0 -0
- package/examples/memory-chain-audit.sh +56 -0
- package/examples/memory-orphan-detector.sh +188 -0
- package/examples/memory-write-guard.sh +99 -17
- package/examples/migration-verify-guard.sh +12 -0
- package/examples/model-swap-suggester.sh +177 -0
- package/examples/model-version-alert.sh +5 -1
- package/examples/model-version-lock.sh +63 -0
- package/examples/move-delete-sequence-guard.sh +33 -2
- package/examples/multi-file-plan-routing-gate.sh +192 -0
- package/examples/multi-vendor-concurrent-warner.sh +108 -0
- package/examples/multi-window-auth-drift-detector.sh +183 -0
- package/examples/multiline-command-approver.sh +161 -23
- package/examples/nested-background-agent-guard.sh +109 -0
- package/examples/nested-spawn-inflight-guard.sh +178 -0
- package/examples/network-exfil-guard.sh +12 -0
- package/examples/network-guard.sh +12 -0
- package/examples/network-interface-guard.sh +12 -0
- package/examples/nextjs-env-guard.sh +1 -1
- package/examples/no-absolute-import.sh +0 -0
- package/examples/no-alert-confirm-prompt.sh +0 -0
- package/examples/no-anonymous-default-export.sh +0 -0
- package/examples/no-any-type.sh +0 -0
- package/examples/no-any-typescript.sh +1 -0
- package/examples/no-ask-human.sh +12 -0
- package/examples/no-assignment-in-condition.sh +0 -0
- package/examples/no-base64-exfil.sh +12 -0
- package/examples/no-callback-hell.sh +0 -0
- package/examples/no-circular-dependency.sh +0 -0
- package/examples/no-cleartext-storage.sh +0 -0
- package/examples/no-commented-code.sh +0 -0
- package/examples/no-commit-fixup.sh +0 -0
- package/examples/no-console-assert.sh +0 -0
- package/examples/no-console-error-swallow.sh +0 -0
- package/examples/no-console-in-prod.sh +0 -0
- package/examples/no-console-log-commit.sh +12 -0
- package/examples/no-console-log.sh +0 -0
- package/examples/no-console-time.sh +0 -0
- package/examples/no-cors-wildcard.sh +4 -1
- package/examples/no-curl-upload.sh +0 -0
- package/examples/no-dangerouslySetInnerHTML.sh +0 -0
- package/examples/no-dangling-await.sh +1 -0
- package/examples/no-debug-commit.sh +12 -0
- package/examples/no-debug-in-commit.sh +0 -0
- package/examples/no-deep-nesting.sh +0 -0
- package/examples/no-deep-relative-import.sh +1 -0
- package/examples/no-default-credentials.sh +0 -0
- package/examples/no-deploy-friday.sh +13 -1
- package/examples/no-disabled-test.sh +0 -0
- package/examples/no-document-write.sh +0 -0
- package/examples/no-empty-function.sh +0 -0
- package/examples/no-eval-in-template.sh +0 -0
- package/examples/no-eval-template.sh +3 -1
- package/examples/no-eval.sh +0 -0
- package/examples/no-exec-user-input.sh +0 -0
- package/examples/no-fixme-ship.sh +12 -0
- package/examples/no-floating-promises.sh +0 -0
- package/examples/no-force-flag.sh +22 -5
- package/examples/no-force-install.sh +0 -0
- package/examples/no-git-amend.sh +12 -0
- package/examples/no-git-rebase-public.sh +0 -0
- package/examples/no-global-install.sh +12 -0
- package/examples/no-global-state.sh +0 -0
- package/examples/no-hardcoded-port.sh +1 -0
- package/examples/no-hardcoded-url.sh +0 -0
- package/examples/no-helmet-missing.sh +0 -0
- package/examples/no-http-url.sh +1 -0
- package/examples/no-http-without-https.sh +0 -0
- package/examples/no-inline-style.sh +0 -0
- package/examples/no-inline-styles.sh +1 -0
- package/examples/no-innerhtml.sh +0 -0
- package/examples/no-install-global.sh +12 -0
- package/examples/no-jwt-in-url.sh +0 -0
- package/examples/no-large-commit.sh +0 -0
- package/examples/no-localhost-expose.sh +0 -0
- package/examples/no-magic-number.sh +0 -0
- package/examples/no-md5-sha1.sh +0 -0
- package/examples/no-mixed-line-endings.sh +8 -1
- package/examples/no-mutation-in-reducer.sh +0 -0
- package/examples/no-nested-ternary.sh +0 -0
- package/examples/no-network-exfil.sh +0 -0
- package/examples/no-open-redirect.sh +0 -0
- package/examples/no-output-truncation.sh +12 -0
- package/examples/no-package-downgrade.sh +0 -0
- package/examples/no-package-lock-edit.sh +12 -0
- package/examples/no-path-join-user-input.sh +0 -0
- package/examples/no-port-bind.sh +0 -0
- package/examples/no-process-exit.sh +0 -0
- package/examples/no-prototype-pollution.sh +0 -0
- package/examples/no-push-without-ci.sh +0 -0
- package/examples/no-push-without-tests.sh +12 -0
- package/examples/no-raw-password-in-url.sh +0 -0
- package/examples/no-root-user-docker.sh +1 -0
- package/examples/no-root-write.sh +12 -0
- package/examples/no-secrets-in-args.sh +4 -1
- package/examples/no-secrets-in-logs.sh +0 -0
- package/examples/no-sensitive-log.sh +0 -0
- package/examples/no-sleep-in-hooks.sh +0 -0
- package/examples/no-star-import-python.sh +1 -0
- package/examples/no-string-concat-sql.sh +0 -0
- package/examples/no-sudo-guard.sh +12 -0
- package/examples/no-sync-fs.sh +0 -0
- package/examples/no-todo-in-merge.sh +0 -0
- package/examples/no-todo-in-production.sh +1 -0
- package/examples/no-todo-without-issue.sh +0 -0
- package/examples/no-unused-import.sh +0 -0
- package/examples/no-var-keyword.sh +0 -0
- package/examples/no-verify-blocker.sh +12 -0
- package/examples/no-wget-piped-bash.sh +12 -0
- package/examples/no-wildcard-cors.sh +0 -0
- package/examples/no-wildcard-delete.sh +0 -0
- package/examples/no-wildcard-import.sh +0 -0
- package/examples/no-with-statement.sh +0 -0
- package/examples/no-write-outside-src.sh +0 -0
- package/examples/no-xml-external-entity.sh +0 -0
- package/examples/non-english-quality-warner.sh +156 -0
- package/examples/notify-waiting.sh +1 -1
- package/examples/npm-audit-warn.sh +0 -0
- package/examples/npm-global-install-guard.sh +12 -0
- package/examples/npm-publish-guard.sh +12 -0
- package/examples/npm-script-injection.sh +0 -0
- package/examples/npm-supply-chain-guard.sh +0 -0
- package/examples/nuxt-config-guard.sh +1 -0
- package/examples/oauth-refresh-monitor.sh +210 -0
- package/examples/opus-degradation-tracker.sh +187 -0
- package/examples/opus48-routine-task-warning.sh +196 -0
- package/examples/opus48-thinking-wedge-advisor.sh +143 -0
- package/examples/output-credential-scan.sh +1 -1
- package/examples/output-secret-mask.sh +31 -9
- package/examples/output-token-spike-detector.sh +145 -0
- package/examples/package-json-guard.sh +12 -0
- package/examples/package-lock-frozen.sh +12 -0
- package/examples/parallel-batch-size-limiter.sh +121 -0
- package/examples/parallel-cascade-detector.sh +116 -0
- package/examples/partial-view-claim-arrest.sh +174 -0
- package/examples/path-deny-bash-guard.sh +12 -0
- package/examples/path-traversal-guard.sh +12 -0
- package/examples/per-prompt-token-cap.sh +124 -0
- package/examples/permission-audit-log.sh +1 -1
- package/examples/permission-denial-enforcer.sh +12 -0
- package/examples/permission-entry-validator.sh +0 -0
- package/examples/persisted-1m-model-advisor.sh +88 -0
- package/examples/php-lint-on-edit.sh +1 -1
- package/examples/pii-upload-guard.sh +12 -0
- package/examples/pip-publish-guard.sh +13 -0
- package/examples/pip-requirements-guard.sh +12 -0
- package/examples/pip-venv-required.sh +12 -0
- package/examples/plan-mode-edit-guard.sh +12 -0
- package/examples/plan-mode-enforcer.sh +12 -0
- package/examples/plan-mode-strict-guard.sh +12 -0
- package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
- package/examples/plugin-process-cleanup.sh +0 -0
- package/examples/polyglot-rm-guard.sh +12 -0
- package/examples/post-compact-safety.sh +12 -0
- package/examples/post-edit-disk-verify.sh +152 -0
- package/examples/powershell-remove-item-guard.sh +85 -0
- package/examples/pr-description-check.sh +0 -0
- package/examples/pr-duplicate-guard.sh +13 -0
- package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
- package/examples/pre-compact-knowledge-save.sh +0 -0
- package/examples/pre-compact-transcript-backup.sh +0 -0
- package/examples/pre-execution-claim-detector.sh +179 -0
- package/examples/prefer-builtin-tools.sh +10 -1
- package/examples/prefer-const.sh +0 -0
- package/examples/prefer-dedicated-tools.sh +12 -0
- package/examples/prefer-optional-chaining.sh +0 -0
- package/examples/prisma-migrate-guard.sh +24 -7
- package/examples/production-port-kill-guard.sh +12 -0
- package/examples/prompt-injection-guard.sh +2 -1
- package/examples/prompt-usage-logger.sh +0 -0
- package/examples/protect-claudemd.sh +12 -0
- package/examples/protect-dotfiles.sh +12 -0
- package/examples/proxy-capture-suggester.sh +159 -0
- package/examples/public-artefact-socratic-narrowing.sh +232 -0
- package/examples/public-repo-push-guard.sh +12 -0
- package/examples/push-requires-test-pass-record.sh +0 -0
- package/examples/push-requires-test-pass.sh +12 -0
- package/examples/quota-anomaly-detector.sh +173 -0
- package/examples/quota-reset-audit.sh +58 -0
- package/examples/quoted-flag-approver.sh +99 -10
- package/examples/rails-migration-guard.sh +12 -0
- package/examples/rate-limit-guard.sh +0 -0
- package/examples/read-all-files-enforcer.sh +0 -0
- package/examples/read-budget-guard.sh +12 -0
- package/examples/read-loop-detector.sh +59 -0
- package/examples/read-once-guard.sh +96 -0
- package/examples/read-only-mode.sh +12 -0
- package/examples/readme-exists-check.sh +0 -0
- package/examples/record-read-coverage.sh +73 -0
- package/examples/redirect-fragment-warner.sh +149 -0
- package/examples/redis-flushall-guard.sh +13 -0
- package/examples/redundant-read-blocker.sh +132 -0
- package/examples/refusal-arrest-gate.sh +248 -0
- package/examples/registry-publish-guard.sh +13 -1
- package/examples/remote-control-billing-classifier.sh +135 -0
- package/examples/replace-all-guard.sh +12 -0
- package/examples/repo-visibility-guard.sh +12 -0
- package/examples/reroute-after-block-guard.sh +150 -0
- package/examples/response-budget-guard.sh +0 -0
- package/examples/resume-drift-watcher.sh +57 -0
- package/examples/rg-replace-flag-detector.sh +125 -0
- package/examples/rhetorical-verification-prompt-detector.sh +102 -0
- package/examples/ripgrep-permission-fix.sh +0 -0
- package/examples/rm-safety-net.sh +151 -8
- package/examples/role-tool-guard.sh +12 -0
- package/examples/route-handler-emptiness-gate.sh +324 -0
- package/examples/ruby-lint-on-edit.sh +1 -1
- package/examples/runtime-binary-change-detector.sh +102 -0
- package/examples/same-command-repeat-detector.sh +196 -0
- package/examples/same-correction-arrest.sh +169 -0
- package/examples/sandbox-denywrite-enforcer.sh +78 -0
- package/examples/sandbox-relative-path-audit.sh +83 -25
- package/examples/sandbox-write-verify.sh +12 -0
- package/examples/schema-migration-guard.sh +0 -0
- package/examples/scope-expansion-receipt.sh +178 -0
- package/examples/scope-guard.sh +88 -9
- package/examples/secret-file-read-guard.sh +12 -0
- package/examples/secret-file-write-guard.sh +150 -0
- package/examples/self-modify-bypass-guard.sh +0 -0
- package/examples/sensitive-file-read-guard.sh +23 -3
- package/examples/sensitive-log-guard.sh +1 -0
- package/examples/server-side-prompt-injection-detector.sh +69 -0
- package/examples/session-agent-cost-limiter.sh +12 -0
- package/examples/session-backup-on-start.sh +1 -1
- package/examples/session-cost-alert.sh +12 -0
- package/examples/session-drift-guard.sh +12 -0
- package/examples/session-duration-guard.sh +25 -2
- package/examples/session-end-logger.sh +0 -0
- package/examples/session-health-monitor.sh +0 -0
- package/examples/session-index-repair.sh +1 -1
- package/examples/session-memory-watchdog.sh +1 -0
- package/examples/session-permission-reset-guard.sh +12 -0
- package/examples/session-persistence-verifier.sh +93 -0
- package/examples/session-plugin-pin-watch.sh +68 -0
- package/examples/session-rate-monitor.sh +176 -0
- package/examples/session-resume-env-fix.sh +0 -0
- package/examples/session-start-quota-status.sh +193 -0
- package/examples/session-start-safety-check.sh +55 -3
- package/examples/session-state-saver.sh +0 -0
- package/examples/session-summary-stop.sh +1 -1
- package/examples/session-summary.sh +0 -0
- package/examples/session-token-counter.sh +1 -1
- package/examples/settings-hooks-key-restorer.sh +99 -0
- package/examples/settings-json-health-check.sh +57 -0
- package/examples/settings-json-model-guard.sh +0 -0
- package/examples/settings-regression-tester.sh +188 -0
- package/examples/shell-config-truncation-guard.sh +12 -0
- package/examples/shell-wrapper-guard.sh +12 -0
- package/examples/skill-cumulative-size-detector.sh +104 -0
- package/examples/skill-description-drop-detector.sh +148 -0
- package/examples/skill-gate.sh +0 -0
- package/examples/skill-truncation-detector.sh +154 -0
- package/examples/skills-context-recorder.sh +167 -0
- package/examples/skills-load-verifier.sh +96 -0
- package/examples/skills-settings-validator.sh +139 -0
- package/examples/sonnet-45-deprecation-helper.sh +85 -0
- package/examples/spec-file-scope-guard.sh +12 -0
- package/examples/spring-profile-guard.sh +1 -0
- package/examples/spurious-malformed-notice-detector.sh +247 -0
- package/examples/sql-bulk-delete-warn.sh +88 -0
- package/examples/sql-injection-detect.sh +0 -0
- package/examples/ssh-key-protect.sh +12 -0
- package/examples/staged-secret-scan.sh +22 -1
- package/examples/stale-temp-settings-detector.sh +86 -0
- package/examples/standing-rule-session-surfacer.sh +137 -0
- package/examples/stop-hook-sigterm-wrapper.sh +182 -0
- package/examples/stop-transcript-write-health.sh +64 -0
- package/examples/strict-allowlist.sh +57 -15
- package/examples/strip-coauthored-by.sh +50 -10
- package/examples/subagent-blast-radius-guard.sh +184 -0
- package/examples/subagent-boundary-precheck.sh +126 -0
- package/examples/subagent-budget-guard.sh +12 -0
- package/examples/subagent-claudemd-inject.sh +0 -0
- package/examples/subagent-closure-verify-gate.sh +164 -0
- package/examples/subagent-destructive-git-guard.sh +120 -0
- package/examples/subagent-error-detector.sh +0 -0
- package/examples/subagent-forged-system-reminder-guard.sh +156 -0
- package/examples/subagent-identity-leak-guard.sh +102 -0
- package/examples/subagent-identity-reassertion.sh +51 -0
- package/examples/subagent-inheritance-tester.sh +179 -0
- package/examples/subagent-permission-mode-guard.sh +110 -0
- package/examples/subagent-scope-guard.sh +12 -0
- package/examples/subagent-spawn-verification-enforcer.sh +102 -0
- package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
- package/examples/subagent-tool-call-limiter.sh +87 -15
- package/examples/subcommand-chain-guard.sh +12 -0
- package/examples/subscription-api-billing-warner.sh +160 -0
- package/examples/subscription-bypass-detector.sh +152 -0
- package/examples/svelte-lint-on-edit.sh +1 -0
- package/examples/swift-build-on-edit.sh +1 -1
- package/examples/symlink-guard.sh +27 -2
- package/examples/symlink-protect.sh +1 -0
- package/examples/system-dir-protection-guard.sh +73 -8
- package/examples/system-message-workaround.sh +38 -13
- package/examples/system-package-guard.sh +12 -0
- package/examples/systemd-service-guard.sh +12 -0
- package/examples/task-integrity-guard.sh +12 -0
- package/examples/temp-file-cleanup.sh +1 -1
- package/examples/temporal-suggestion-detector.sh +135 -0
- package/examples/terraform-guard.sh +27 -6
- package/examples/test-after-edit.sh +1 -1
- package/examples/test-before-push.sh +12 -0
- package/examples/test-coverage-reminder.sh +24 -1
- package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
- package/examples/timezone-guard.sh +0 -0
- package/examples/tmp-output-size-guard.sh +0 -0
- package/examples/todo-check.sh +1 -1
- package/examples/token-budget-guard.sh +12 -0
- package/examples/token-budget-per-task.sh +12 -0
- package/examples/token-usage-tracker.sh +7 -1
- package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
- package/examples/tokenizer-ratio-alert.sh +104 -0
- package/examples/tool-call-rate-limiter.sh +0 -0
- package/examples/tool-result-correlation-checker.sh +167 -0
- package/examples/tool-result-size-guard.sh +132 -0
- package/examples/tool-retry-budget-guard.sh +12 -0
- package/examples/transcript-contamination-detector.sh +138 -0
- package/examples/trustfall-mcp-injection-guard.sh +103 -0
- package/examples/ultrareview-large-diff-advisor.sh +184 -0
- package/examples/unbounded-output-guard.sh +94 -0
- package/examples/uncommitted-changes-stop.sh +1 -0
- package/examples/uncommitted-discard-guard.sh +23 -5
- package/examples/uncommitted-work-guard.sh +12 -0
- package/examples/usage-warn.sh +0 -0
- package/examples/user-account-guard.sh +12 -0
- package/examples/userprompt-submit-receipt.sh +123 -0
- package/examples/variable-expansion-guard.sh +12 -0
- package/examples/verify-after-publish-reminder.sh +93 -0
- package/examples/verify-before-commit.sh +12 -0
- package/examples/version-bump-detector.sh +156 -0
- package/examples/version-regression-warner.sh +144 -0
- package/examples/vue-lint-on-edit.sh +1 -0
- package/examples/warn-cron-cost-trap.sh +173 -0
- package/examples/webfetch-runaway-guard.sh +89 -0
- package/examples/wellness-break-reminder.sh +118 -0
- package/examples/windows-destructive-command-guard.sh +177 -0
- package/examples/windows-path-guard.sh +12 -0
- package/examples/windows-python-stub-detector.sh +63 -0
- package/examples/work-hours-guard.sh +12 -0
- package/examples/working-directory-fence.sh +12 -0
- package/examples/workspace-lease-guard.sh +205 -0
- package/examples/worktree-create-log.sh +1 -0
- package/examples/worktree-delete-guard.sh +12 -0
- package/examples/worktree-edit-boundary-guard.sh +127 -0
- package/examples/worktree-escape-write-guard.sh +114 -0
- package/examples/worktree-hook-linker.sh +0 -0
- package/examples/worktree-hooks-path-fix.sh +111 -0
- package/examples/worktree-parent-write-guard.sh +43 -0
- package/examples/worktree-project-unify.sh +2 -1
- package/examples/worktree-remove-uncommitted-guard.sh +13 -0
- package/examples/worktree-unmerged-guard.sh +7 -1
- package/examples/write-byte-integrity-verifier.sh +190 -0
- package/examples/write-empty-content-guard.sh +67 -0
- package/examples/write-nul-corruption-detector.sh +61 -0
- package/examples/write-overwrite-confirm.sh +160 -14
- package/examples/write-secret-guard.sh +27 -5
- package/examples/write-shrink-guard.sh +12 -0
- package/examples/write-test-ratio.sh +0 -0
- package/examples/wsl-host-disk-space-guard.sh +97 -0
- package/examples/xml-format-leak-detector.sh +266 -0
- package/examples/yaml-syntax-check.sh +12 -0
- package/hooks/hooks.json +6 -6
- package/index.mjs +1699 -183
- package/mission.md +2 -0
- package/package.json +4 -4
- package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
- package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
- package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
- package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
- package/scripts/agents-md-sync-setup.sh +156 -0
- package/scripts/autonomy-blocked-summary.sh +148 -0
- package/scripts/build-search-index.py +43 -0
- package/scripts/build-sitemap.py +119 -0
- package/scripts/cc-doctor.sh +192 -0
- package/scripts/check-hook-event-names.py +127 -0
- package/scripts/check-misfire-instrument.sh +64 -0
- package/scripts/claim-verify-audit.sh +467 -0
- package/scripts/cowork-claudemd-helper.sh +136 -0
- package/scripts/june-15-deprecated-model-scan.sh +111 -0
- package/scripts/measure-heredoc-shapes.sh +67 -0
- package/scripts/measure-literal-match-misfire.sh +110 -0
- package/scripts/probe-scope-guard-branches.sh +48 -0
- package/scripts/probe-skip-line-both-ways.sh +65 -0
- package/scripts/receipts-aggregate.py +199 -0
- package/scripts/session-forensic-audit.py +360 -0
- package/scripts.json +9 -9
- package/scripts.json.bak-2026-07-27-find +13 -0
- package/skills/safety-setup/SKILL.md +5 -5
- package/tests/approve-side-remaining-two.test.sh +129 -0
- package/tests/approver-list-granularity.test.sh +145 -0
- package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
- package/tests/audit-ci-gate.test.sh +87 -0
- package/tests/audit-cross-layer-claudemd.test.sh +170 -0
- package/tests/audit-fail-open-parse.test.sh +100 -0
- package/tests/auto-approve-compound-tail.test.sh +194 -0
- package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
- package/tests/auto-mode-quoted-targets.test.sh +127 -0
- package/tests/auto-mode-unquoted-targets.test.sh +112 -0
- package/tests/bash-secret-output-detector-detects.test.sh +102 -0
- package/tests/blindspots-cross-layer.test.sh +177 -0
- package/tests/block-database-wipe.test.sh +64 -0
- package/tests/bundled-short-flags-bypass.test.sh +85 -0
- package/tests/cd-git-allow-compound-tail.test.sh +67 -0
- package/tests/chown-guard-filesystem-root.test.sh +64 -0
- package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
- package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
- package/tests/core-scripts-parser-fallback.test.sh +140 -0
- package/tests/destructive-guard-bare-glob.test.sh +74 -0
- package/tests/destructive-guard-every-operand.test.sh +100 -0
- package/tests/destructive-guard-find-deletion.test.sh +114 -0
- package/tests/destructive-guard-flag-order.test.sh +106 -0
- package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
- package/tests/destructive-guard-quoted-target.test.sh +89 -0
- package/tests/destructive-guard-separators.test.sh +105 -0
- package/tests/destructive-guard-variable-target.test.sh +98 -0
- package/tests/destructive-guard-wrapped-command.test.sh +91 -0
- package/tests/doctor-hook-disabling-env.test.sh +92 -0
- package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
- package/tests/example-guards-wrapped-command.test.sh +169 -0
- package/tests/file-edit-backup.test.sh +93 -0
- package/tests/git-filter-repo-guard.test.sh +60 -0
- package/tests/git-global-options-bypass.test.sh +141 -0
- package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
- package/tests/git-maintenance-guard.test.sh +83 -0
- package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
- package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
- package/tests/git-submodule-guard.test.sh +50 -0
- package/tests/grep-pcre-portability.test.sh +155 -0
- package/tests/hook-registration-matches-input.test.sh +73 -0
- package/tests/hook-trigger-matches-envelope.test.sh +178 -0
- package/tests/install-does-not-claim-protection.test.sh +110 -0
- package/tests/install-example-standalone-tools.test.sh +139 -0
- package/tests/line-continuation-bypass.test.sh +114 -0
- package/tests/mcp-config-poisoning-audit.test.sh +106 -0
- package/tests/nested-background-agent-guard.test.sh +58 -0
- package/tests/no-unqualified-safety-claims.test.sh +114 -0
- package/tests/option-eating-grep-patterns.test.sh +130 -0
- package/tests/outdated-core-guards.test.sh +134 -0
- package/tests/outdated-report.test.sh +155 -0
- package/tests/output-secret-mask-warns.test.sh +73 -0
- package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
- package/tests/plugins-word-order.test.sh +126 -0
- package/tests/powershell-remove-item-guard.test.sh +85 -0
- package/tests/project-dir-naming.test.sh +103 -0
- package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
- package/tests/reroute-after-block-guard.test.sh +104 -0
- package/tests/secret-guard-documented-promises.test.sh +97 -0
- package/tests/session-plugin-pin-watch.test.sh +45 -0
- package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
- package/tests/shield-no-silent-adoption.test.py +110 -0
- package/tests/shield-no-silent-adoption.test.sh +46 -0
- package/tests/stop-transcript-write-health.test.sh +46 -0
- package/tests/system-dir-guard-root-erased.test.sh +66 -0
- package/tests/test-account-billing-log.sh +100 -0
- package/tests/test-account-routing-preflight.sh +77 -0
- package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
- package/tests/test-agent-view-quota-warn.sh +184 -0
- package/tests/test-agents-md-edit-drift-warner.sh +176 -0
- package/tests/test-agents-md-loader.sh +204 -0
- package/tests/test-agents-md-sync-checker.sh +125 -0
- package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
- package/tests/test-allowlist.sh +60 -0
- package/tests/test-always-allow-pattern-suggester.sh +147 -0
- package/tests/test-anthropic-base-url-guard.sh +88 -0
- package/tests/test-articulated-scope-capture.sh +139 -0
- package/tests/test-attachment-traversal-guard.sh +168 -0
- package/tests/test-aup-block-pattern-logger.sh +315 -0
- package/tests/test-aup-false-positive-helper.sh +188 -0
- package/tests/test-aup-large-tool-output-warner.sh +370 -0
- package/tests/test-aup-retry-loop-guard.sh +341 -0
- package/tests/test-auth-expiry-reminder.sh +303 -0
- package/tests/test-auth-macos-sleep-detector.sh +254 -0
- package/tests/test-auth-path-detector.sh +232 -0
- package/tests/test-auth-status-checker.sh +233 -0
- package/tests/test-authorized-reconfirmation-detector.sh +280 -0
- package/tests/test-background-cost-launch-guard.sh +62 -0
- package/tests/test-bash-allowlist-secondary-check.sh +143 -0
- package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
- package/tests/test-bash-project-fence.sh +127 -0
- package/tests/test-bg-permission-prompt-warner.sh +221 -0
- package/tests/test-binary-read-detector.sh +173 -0
- package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
- package/tests/test-bulk-delete-target-resolution.sh +49 -0
- package/tests/test-bypass-mode-effective-verifier.sh +179 -0
- package/tests/test-cache-creation-drift-detector.sh +244 -0
- package/tests/test-cache-residue-detector.sh +429 -0
- package/tests/test-cache-tier-logger.sh +59 -0
- package/tests/test-cache-ttl-eviction-detector.sh +282 -0
- package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
- package/tests/test-claim-verify-detector.sh +222 -0
- package/tests/test-claim-vs-caveat-checker.sh +134 -0
- package/tests/test-claude-code-version-pin-advisor.sh +353 -0
- package/tests/test-claude-md-reinjector.sh +173 -0
- package/tests/test-claude-md-size-monitor.sh +107 -0
- package/tests/test-claude-update-budget-guard.sh +132 -0
- package/tests/test-claude-update-smart.sh +91 -0
- package/tests/test-claudemd-tool-prohibition.sh +239 -0
- package/tests/test-cli-config-pinning-detector.sh +233 -0
- package/tests/test-cliff-countdown-advisor.sh +138 -0
- package/tests/test-closure-word-verify-gate.sh +158 -0
- package/tests/test-commit-all-scope-guard.sh +73 -0
- package/tests/test-commitment-carry-forward-arrest.sh +250 -0
- package/tests/test-compact-dispatch-watchdog.sh +147 -0
- package/tests/test-completion-claim-without-verification-detector.sh +326 -0
- package/tests/test-compound-bash-permission-resolver.sh +264 -0
- package/tests/test-compound-command-deny-enforcer.sh +67 -0
- package/tests/test-context-length-budget.sh +68 -0
- package/tests/test-context-usage-drift-alert.sh +52 -22
- package/tests/test-cost-incident-self-audit.sh +94 -0
- package/tests/test-cowork-claude-md-load-checker.sh +257 -0
- package/tests/test-cowork-claudemd-helper.sh +141 -0
- package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
- package/tests/test-cowork-hook-absence-warner.sh +230 -0
- package/tests/test-cowork-model-picker-advisor.sh +317 -0
- package/tests/test-credential-exfil-guard.sh +62 -0
- package/tests/test-cron-create-receipt.sh +165 -0
- package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
- package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
- package/tests/test-daily-cost-guard.sh +131 -0
- package/tests/test-deny-rule-integrity-verifier.sh +288 -0
- package/tests/test-deployment-readback-gate.sh +92 -0
- package/tests/test-deployment-readback-gh-adapter.sh +163 -0
- package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
- package/tests/test-dispatch-allowlist-preflight.sh +385 -0
- package/tests/test-dispatch-liveness-watchdog.sh +319 -0
- package/tests/test-dispatch-receipt.sh +314 -0
- package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
- package/tests/test-echo-probe-spam-detector.sh +143 -0
- package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
- package/tests/test-ephemeral-container-detector.sh +251 -0
- package/tests/test-evidence-claim-gate.sh +291 -0
- package/tests/test-extended-thinking-loop-guard.sh +289 -0
- package/tests/test-extended-thinking-resume-warning.sh +240 -0
- package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
- package/tests/test-fabricated-command-detector.sh +296 -0
- package/tests/test-false-disk-full-guard.sh +36 -0
- package/tests/test-feature-deprecation-detector.sh +117 -0
- package/tests/test-forbidden-response-phrase-detector.sh +246 -0
- package/tests/test-git-operations-require-approval.sh +53 -0
- package/tests/test-git-push-blast-radius-guard.sh +115 -0
- package/tests/test-goal-iteration-limit-warner.sh +128 -0
- package/tests/test-growthbook-flag-monitor.sh +428 -0
- package/tests/test-halt-signal-detector.sh +120 -0
- package/tests/test-hook-self-disable-detector.sh +232 -0
- package/tests/test-iteration-quality-degradation-detector.sh +244 -0
- package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
- package/tests/test-marketplace-plugins.sh +193 -0
- package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
- package/tests/test-mcp-orphan-leak-warner.sh +71 -0
- package/tests/test-mcp-permissions-ask-warner.sh +207 -0
- package/tests/test-mcp-routine-approval-detector.sh +229 -0
- package/tests/test-mcp-startup-bloat-detector.sh +141 -0
- package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
- package/tests/test-memory-chain-audit.sh +59 -0
- package/tests/test-memory-orphan-detector.sh +227 -0
- package/tests/test-model-swap-suggester.sh +368 -0
- package/tests/test-model-version-lock.sh +83 -0
- package/tests/test-multi-file-plan-routing-gate.sh +277 -0
- package/tests/test-multi-window-auth-drift-detector.sh +262 -0
- package/tests/test-nested-spawn-inflight-guard.sh +281 -0
- package/tests/test-no-force-flag.sh +49 -0
- package/tests/test-non-english-quality-warner.sh +229 -0
- package/tests/test-oauth-refresh-monitor.sh +311 -0
- package/tests/test-opus-degradation-tracker.sh +274 -0
- package/tests/test-opus48-routine-task-warning.sh +201 -0
- package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
- package/tests/test-output-token-spike-detector.sh +315 -0
- package/tests/test-parallel-batch-size-limiter.sh +228 -0
- package/tests/test-parallel-cascade-detector.sh +191 -0
- package/tests/test-partial-view-claim-arrest.sh +272 -0
- package/tests/test-per-prompt-token-cap.sh +136 -0
- package/tests/test-persisted-1m-model-advisor.sh +71 -0
- package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
- package/tests/test-post-edit-disk-verify.sh +294 -0
- package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
- package/tests/test-pre-execution-claim-detector.sh +366 -0
- package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
- package/tests/test-proxy-capture-suggester.sh +214 -0
- package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
- package/tests/test-quota-anomaly-detector.sh +321 -0
- package/tests/test-quota-reset-audit.sh +81 -0
- package/tests/test-read-loop-detector.sh +137 -0
- package/tests/test-read-once-guard.sh +85 -0
- package/tests/test-receipts-aggregate.sh +143 -0
- package/tests/test-redirect-fragment-warner.sh +130 -0
- package/tests/test-redundant-read-blocker.sh +155 -0
- package/tests/test-refusal-arrest-gate.sh +303 -0
- package/tests/test-remote-control-billing-classifier.sh +125 -0
- package/tests/test-resume-drift-watcher.sh +65 -0
- package/tests/test-rg-replace-flag-detector.sh +175 -0
- package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
- package/tests/test-rm-safety-net.sh +115 -0
- package/tests/test-route-handler-emptiness-gate.sh +300 -0
- package/tests/test-runtime-binary-change-detector.sh +196 -0
- package/tests/test-same-command-repeat-detector.sh +165 -0
- package/tests/test-same-correction-arrest.sh +165 -0
- package/tests/test-scope-expansion-receipt.sh +207 -0
- package/tests/test-server-side-prompt-injection-detector.sh +181 -0
- package/tests/test-session-persistence-verifier.sh +128 -0
- package/tests/test-session-rate-monitor.sh +284 -0
- package/tests/test-session-start-quota-status.sh +210 -0
- package/tests/test-session-start-safety-check.sh +138 -0
- package/tests/test-settings-hooks-key-restorer.sh +257 -0
- package/tests/test-settings-json-health-check.sh +70 -0
- package/tests/test-settings-regression-tester.sh +197 -0
- package/tests/test-skill-cumulative-size-detector.sh +198 -0
- package/tests/test-skill-description-drop-detector.sh +236 -0
- package/tests/test-skill-truncation-detector.sh +263 -0
- package/tests/test-skills-context-recorder.sh +329 -0
- package/tests/test-skills-load-verifier.sh +184 -0
- package/tests/test-skills-settings-validator.sh +242 -0
- package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
- package/tests/test-spurious-malformed-notice-detector.sh +290 -0
- package/tests/test-sql-bulk-delete-warn.sh +123 -0
- package/tests/test-ssh-key-protect.sh +81 -0
- package/tests/test-stale-temp-settings-detector.sh +161 -0
- package/tests/test-standing-rule-session-surfacer.sh +215 -0
- package/tests/test-starter-hooks-manifest.sh +96 -0
- package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
- package/tests/test-strict-allowlist.sh +72 -0
- package/tests/test-subagent-boundary-precheck.sh +137 -0
- package/tests/test-subagent-closure-verify-gate.sh +193 -0
- package/tests/test-subagent-destructive-git-guard.sh +86 -0
- package/tests/test-subagent-identity-leak-guard.sh +62 -0
- package/tests/test-subagent-identity-reassertion.sh +61 -0
- package/tests/test-subagent-inheritance-tester.sh +319 -0
- package/tests/test-subagent-permission-mode-guard.sh +61 -0
- package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
- package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
- package/tests/test-subagent-tool-call-limiter.sh +97 -0
- package/tests/test-subscription-api-billing-warner.sh +138 -0
- package/tests/test-subscription-bypass-detector.sh +255 -0
- package/tests/test-temporal-suggestion-detector.sh +183 -0
- package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
- package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
- package/tests/test-tokenizer-ratio-alert.sh +93 -0
- package/tests/test-tool-result-correlation-checker.sh +264 -0
- package/tests/test-tool-result-size-guard.sh +121 -0
- package/tests/test-transcript-contamination-detector.sh +264 -0
- package/tests/test-trigger-header-parsing.sh +151 -0
- package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
- package/tests/test-userprompt-submit-receipt.sh +181 -0
- package/tests/test-verify-after-publish-reminder.sh +184 -0
- package/tests/test-version-bump-detector.sh +212 -0
- package/tests/test-version-regression-warner.sh +165 -0
- package/tests/test-warn-cron-cost-trap.sh +82 -0
- package/tests/test-webfetch-runaway-guard.sh +77 -0
- package/tests/test-wellness-break-reminder.sh +138 -0
- package/tests/test-windows-destructive-command-guard.sh +169 -0
- package/tests/test-windows-python-stub-detector.sh +146 -0
- package/tests/test-worktree-edit-boundary-guard.sh +219 -0
- package/tests/test-write-byte-integrity-verifier.sh +192 -0
- package/tests/test-xml-format-leak-detector.sh +299 -0
- package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
- package/tests/workspace-lease-guard.test.sh +144 -0
- package/tests/worktree-escape-write-guard.test.sh +68 -0
- package/tests/worktree-hooks-path-fix.test.sh +181 -0
- package/tests/worktree-parent-write-guard.test.sh +51 -0
- package/tests/write-empty-content-guard.test.sh +39 -0
- package/tests/write-nul-corruption-detector.test.sh +29 -0
- package/tests/write-overwrite-unread-content.test.sh +178 -0
- package/tests/wsl-host-disk-space-guard.test.sh +55 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# find-dead-hooks.sh — list hook registrations whose script is not on disk.
|
|
3
|
+
#
|
|
4
|
+
# Why this exists: Claude Code treats a hook that fails to launch as a
|
|
5
|
+
# non-blocking error and lets the tool call proceed. A registration pointing at
|
|
6
|
+
# a path that does not exist therefore produces no symptom at all — the guard
|
|
7
|
+
# is simply absent, and everything looks normal.
|
|
8
|
+
#
|
|
9
|
+
# It reads all three settings files, because a registration can rot in any of
|
|
10
|
+
# them and each is merged into the others.
|
|
11
|
+
#
|
|
12
|
+
# Usage: ./find-dead-hooks.sh # run from your project directory
|
|
13
|
+
#
|
|
14
|
+
# Output: one line per registration whose script is missing. No output is good.
|
|
15
|
+
set -u
|
|
16
|
+
|
|
17
|
+
# The same file can appear twice — when HOME is the project directory, or when
|
|
18
|
+
# one path is a symlink to the other. Reporting a registration twice makes it
|
|
19
|
+
# look like two separate problems, so collapse the list by resolved path first.
|
|
20
|
+
raw=(
|
|
21
|
+
"$HOME/.claude/settings.json"
|
|
22
|
+
"$PWD/.claude/settings.json"
|
|
23
|
+
"$PWD/.claude/settings.local.json"
|
|
24
|
+
)
|
|
25
|
+
files=()
|
|
26
|
+
seen=""
|
|
27
|
+
for f in "${raw[@]}"; do
|
|
28
|
+
[ -f "$f" ] || continue
|
|
29
|
+
real=$(readlink -f "$f" 2>/dev/null || printf '%s' "$f")
|
|
30
|
+
case ":$seen:" in *":$real:"*) continue ;; esac
|
|
31
|
+
seen="$seen:$real"
|
|
32
|
+
files+=("$f")
|
|
33
|
+
done
|
|
34
|
+
|
|
35
|
+
reader=""
|
|
36
|
+
for r in jq python3 python node; do command -v "$r" >/dev/null 2>&1 && { reader="$r"; break; }; done
|
|
37
|
+
if [ -z "$reader" ]; then
|
|
38
|
+
echo "find-dead-hooks: needs jq, python3 or node to read settings.json" >&2
|
|
39
|
+
exit 70
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
extract() { # print every command string registered under any hook event
|
|
43
|
+
case "$reader" in
|
|
44
|
+
jq) jq -r '.hooks // {} | .[]?[]?.hooks[]?.command // empty' "$1" 2>/dev/null ;;
|
|
45
|
+
*) "$reader" - "$1" <<'PY' 2>/dev/null
|
|
46
|
+
import json, sys
|
|
47
|
+
try:
|
|
48
|
+
data = json.load(open(sys.argv[1], encoding="utf-8"))
|
|
49
|
+
except Exception:
|
|
50
|
+
sys.exit(0)
|
|
51
|
+
for groups in (data.get("hooks") or {}).values():
|
|
52
|
+
for group in groups or []:
|
|
53
|
+
for hook in (group or {}).get("hooks") or []:
|
|
54
|
+
cmd = hook.get("command")
|
|
55
|
+
if cmd:
|
|
56
|
+
print(cmd)
|
|
57
|
+
PY
|
|
58
|
+
;;
|
|
59
|
+
esac
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
found=0
|
|
63
|
+
for f in "${files[@]}"; do
|
|
64
|
+
[ -f "$f" ] || continue
|
|
65
|
+
extract "$f" | grep -oE '(~|/|\$\{?[A-Za-z_]+\}?/)[^ ";|&)]*\.(sh|py|js|mjs)' | sort -u |
|
|
66
|
+
while read -r script; do
|
|
67
|
+
p="${script/#\~/$HOME}"
|
|
68
|
+
p="${p//\$\{CLAUDE_PROJECT_DIR\}/${CLAUDE_PROJECT_DIR:-$PWD}}"
|
|
69
|
+
p="${p//\$CLAUDE_PROJECT_DIR/${CLAUDE_PROJECT_DIR:-$PWD}}"
|
|
70
|
+
p="${p//\$\{HOME\}/$HOME}"
|
|
71
|
+
if [ ! -e "$p" ]; then
|
|
72
|
+
echo "MISSING $p"
|
|
73
|
+
echo " registered in $f"
|
|
74
|
+
found=1
|
|
75
|
+
fi
|
|
76
|
+
done
|
|
77
|
+
done
|
|
78
|
+
|
|
79
|
+
# The subshell above cannot set `found` in the parent, so report on emptiness instead.
|
|
80
|
+
echo "---"
|
|
81
|
+
echo "Nothing listed above means every registered hook script exists."
|
|
82
|
+
echo "It does NOT mean any of them fires. Use fire.sh for that."
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# find-unfirable-rules.sh — list guard rules whose pattern cannot match anything.
|
|
3
|
+
#
|
|
4
|
+
# Why this exists: find-dead-hooks.sh covers the case where the script is not
|
|
5
|
+
# there. This covers the case where the script is there, is registered, runs on
|
|
6
|
+
# every call, and its rule still cannot return true. The operator-visible
|
|
7
|
+
# symptom is identical to a guard that has simply never seen a dangerous
|
|
8
|
+
# command: an `exit 2` rule, an `exit 0` outcome, and no diagnostic anywhere.
|
|
9
|
+
#
|
|
10
|
+
# Two mechanisms, both measured on shipped guards of mine:
|
|
11
|
+
#
|
|
12
|
+
# 1. The pattern is eaten as options. grep reads an argument that starts with
|
|
13
|
+
# a dash as flags, so
|
|
14
|
+
# grep -qE '--no-verify|SKIP_CI'
|
|
15
|
+
# dies with "unrecognized option" and matches nothing, for every input,
|
|
16
|
+
# forever. Two of my own guards carried this from 2026-03-29 to
|
|
17
|
+
# 2026-09-20 with their tests passing the whole time. Fix: `--` before the
|
|
18
|
+
# pattern, or `-e`.
|
|
19
|
+
#
|
|
20
|
+
# 2. Lookaround in an engine that has none. ERE has no (?! (?= (?<, so
|
|
21
|
+
# grep -qE '(?!origin\b)'
|
|
22
|
+
# is either a warning and exit 1 (GNU grep) or a syntax error and exit 2
|
|
23
|
+
# (ugrep) — and both look the same to the `if` around it. Fix: grep -P
|
|
24
|
+
# where it is available, or restructure the rule.
|
|
25
|
+
#
|
|
26
|
+
# It looks at the scripts your settings actually register, and at inline
|
|
27
|
+
# command strings, because a rule written directly into settings.json has the
|
|
28
|
+
# same failure and no file to inspect.
|
|
29
|
+
#
|
|
30
|
+
# Usage: ./find-unfirable-rules.sh # run from your project directory
|
|
31
|
+
#
|
|
32
|
+
# Output: one block per suspect rule. No output is good.
|
|
33
|
+
#
|
|
34
|
+
# What it does NOT tell you: whether a rule that CAN match ever DOES. A pattern
|
|
35
|
+
# can be well-formed and still name the wrong thing. Use fire.sh and
|
|
36
|
+
# boundary.sh for that. This only rules out the rules that could never have
|
|
37
|
+
# worked.
|
|
38
|
+
set -u
|
|
39
|
+
|
|
40
|
+
raw=(
|
|
41
|
+
"$HOME/.claude/settings.json"
|
|
42
|
+
"$PWD/.claude/settings.json"
|
|
43
|
+
"$PWD/.claude/settings.local.json"
|
|
44
|
+
)
|
|
45
|
+
files=()
|
|
46
|
+
seen=""
|
|
47
|
+
for f in "${raw[@]}"; do
|
|
48
|
+
[ -f "$f" ] || continue
|
|
49
|
+
real=$(readlink -f "$f" 2>/dev/null || printf '%s' "$f")
|
|
50
|
+
case ":$seen:" in *":$real:"*) continue ;; esac
|
|
51
|
+
seen="$seen:$real"
|
|
52
|
+
files+=("$f")
|
|
53
|
+
done
|
|
54
|
+
|
|
55
|
+
reader=""
|
|
56
|
+
for r in jq python3 python node; do command -v "$r" >/dev/null 2>&1 && { reader="$r"; break; }; done
|
|
57
|
+
if [ -z "$reader" ]; then
|
|
58
|
+
echo "find-unfirable-rules: needs jq, python3 or node to read settings.json" >&2
|
|
59
|
+
exit 70
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
extract() { # print every command string registered under any hook event
|
|
63
|
+
case "$reader" in
|
|
64
|
+
jq) jq -r '.hooks // {} | .[]?[]?.hooks[]?.command // empty' "$1" 2>/dev/null ;;
|
|
65
|
+
*) "$reader" - "$1" <<'PY' 2>/dev/null
|
|
66
|
+
import json, sys
|
|
67
|
+
try:
|
|
68
|
+
data = json.load(open(sys.argv[1], encoding="utf-8"))
|
|
69
|
+
except Exception:
|
|
70
|
+
sys.exit(0)
|
|
71
|
+
for groups in (data.get("hooks") or {}).values():
|
|
72
|
+
for group in groups or []:
|
|
73
|
+
for hook in (group or {}).get("hooks") or []:
|
|
74
|
+
cmd = hook.get("command")
|
|
75
|
+
if cmd:
|
|
76
|
+
print(cmd)
|
|
77
|
+
PY
|
|
78
|
+
;;
|
|
79
|
+
esac
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# A quoted grep pattern whose first character is a dash. The quote may be
|
|
83
|
+
# backslash-escaped, because the same commands appear inline inside JSON.
|
|
84
|
+
EATEN='grep[[:space:]]+(-[A-Za-z]+[[:space:]]+)*\\?['"'"'"]-'
|
|
85
|
+
# ... unless -- or -e comes first, which is the correct spelling.
|
|
86
|
+
SPELLED_OK='grep[[:space:]]+(-[A-Za-z]+[[:space:]]+)*(--|-e)[[:space:]]'
|
|
87
|
+
# Lookaround, only a problem when the engine is ERE or BRE (no -P).
|
|
88
|
+
LOOKAROUND='grep[[:space:]]+(-[A-Za-z]+[[:space:]]+)*\\?['"'"'"][^'"'"'"]*\(\?[!=<]'
|
|
89
|
+
|
|
90
|
+
report() { # report <where> <line-no-or-dash> <text> <why> <fix>
|
|
91
|
+
echo "UNFIRABLE $1${2:+:$2}"
|
|
92
|
+
echo " $3"
|
|
93
|
+
echo " why: $4"
|
|
94
|
+
echo " fix: $5"
|
|
95
|
+
echo
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
scan_text() { # scan_text <where> <text-on-stdin>
|
|
99
|
+
local where="$1" n=0
|
|
100
|
+
while IFS= read -r line; do
|
|
101
|
+
n=$((n + 1))
|
|
102
|
+
case "$line" in \#*) continue ;; esac
|
|
103
|
+
if printf '%s' "$line" | grep -qE -- "$EATEN" \
|
|
104
|
+
&& ! printf '%s' "$line" | grep -qE -- "$SPELLED_OK"; then
|
|
105
|
+
report "$where" "$n" "$(printf '%s' "$line" | cut -c1-140)" \
|
|
106
|
+
"the pattern starts with a dash, so grep reads it as options and matches nothing" \
|
|
107
|
+
"put -- before the pattern, or use -e"
|
|
108
|
+
fi
|
|
109
|
+
if printf '%s' "$line" | grep -qE -- "$LOOKAROUND" \
|
|
110
|
+
&& ! printf '%s' "$line" | grep -qE -- 'grep[[:space:]]+(-[A-Za-z]*P[A-Za-z]*[[:space:]])'; then
|
|
111
|
+
report "$where" "$n" "$(printf '%s' "$line" | cut -c1-140)" \
|
|
112
|
+
"lookaround ((?! (?= (?<) does not exist in ERE/BRE; this pattern can never match" \
|
|
113
|
+
"use grep -P if available, or restructure the rule"
|
|
114
|
+
fi
|
|
115
|
+
done
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# 1) the scripts the settings register
|
|
119
|
+
for f in "${files[@]}"; do
|
|
120
|
+
extract "$f" | grep -oE '(~|/|\$\{?[A-Za-z_]+\}?/)[^ ";|&)]*\.sh' | sort -u |
|
|
121
|
+
while read -r script; do
|
|
122
|
+
p="${script/#\~/$HOME}"
|
|
123
|
+
p="${p//\$\{CLAUDE_PROJECT_DIR\}/${CLAUDE_PROJECT_DIR:-$PWD}}"
|
|
124
|
+
p="${p//\$CLAUDE_PROJECT_DIR/${CLAUDE_PROJECT_DIR:-$PWD}}"
|
|
125
|
+
p="${p//\$\{HOME\}/$HOME}"
|
|
126
|
+
[ -f "$p" ] || continue
|
|
127
|
+
scan_text "$p" < "$p"
|
|
128
|
+
done
|
|
129
|
+
done
|
|
130
|
+
|
|
131
|
+
# 2) inline command strings, which have no file to open
|
|
132
|
+
for f in "${files[@]}"; do
|
|
133
|
+
extract "$f" | while IFS= read -r cmd; do
|
|
134
|
+
case "$cmd" in *grep*) ;; *) continue ;; esac
|
|
135
|
+
printf '%s\n' "$cmd" | scan_text "$f (inline)"
|
|
136
|
+
done
|
|
137
|
+
done
|
|
138
|
+
|
|
139
|
+
echo "---"
|
|
140
|
+
echo "Nothing listed above means no rule was found that is structurally unable"
|
|
141
|
+
echo "to match. It does NOT mean any rule fires on the thing you care about."
|
|
142
|
+
echo "Use fire.sh for that, and boundary.sh for the neighbours it misses."
|
package/audit/fire.sh
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# fire.sh — fire one Claude Code hook by hand and print what it decided.
|
|
3
|
+
#
|
|
4
|
+
# Why this exists: installing a hook and having a hook are not the same thing.
|
|
5
|
+
# The only evidence that a guard works is that it exits 2 when you hand it the
|
|
6
|
+
# operation it is supposed to refuse. This script hands it that operation.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# ./fire.sh <hook-script> <tool-name> <json-field>=<value> [more=fields...]
|
|
10
|
+
#
|
|
11
|
+
# Examples:
|
|
12
|
+
# ./fire.sh ~/.claude/hooks/rm-safety-net.sh Bash command="rm -rf \$HOME/projects"
|
|
13
|
+
# ./fire.sh ~/.claude/hooks/env-write-guard.sh Write file_path=/home/me/app/.env
|
|
14
|
+
#
|
|
15
|
+
# Exit codes you will see printed:
|
|
16
|
+
# 2 the hook refused the operation <- what a working guard does
|
|
17
|
+
# 0 the hook allowed the operation <- if you expected a refusal, it is not working
|
|
18
|
+
# 1 the hook itself errored <- it is not protecting you either
|
|
19
|
+
#
|
|
20
|
+
# One flag matters for the audit:
|
|
21
|
+
# --bare run with a PATH that has no jq, no python3 and no node.
|
|
22
|
+
# Many hooks parse the tool-call JSON with one of those. On a
|
|
23
|
+
# minimal container or a fresh CI image they are absent, and a hook
|
|
24
|
+
# that cannot parse its input often exits 0 (allow) instead of 2.
|
|
25
|
+
# A throwaway HOME is always used, so a hook that writes state into ~/.claude
|
|
26
|
+
# cannot touch yours while you are testing. There is no flag for that and no
|
|
27
|
+
# way to turn it off.
|
|
28
|
+
#
|
|
29
|
+
set -u
|
|
30
|
+
|
|
31
|
+
BARE=0
|
|
32
|
+
for a in "$@"; do [ "$a" = "--bare" ] && BARE=1; done
|
|
33
|
+
ARGS=(); for a in "$@"; do [ "$a" = "--bare" ] || ARGS+=("$a"); done
|
|
34
|
+
set -- "${ARGS[@]+"${ARGS[@]}"}"
|
|
35
|
+
|
|
36
|
+
if [ $# -lt 2 ]; then
|
|
37
|
+
sed -n '2,30p' "$0" | sed 's/^# \{0,1\}//'
|
|
38
|
+
exit 64
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
HOOK="$1"; TOOL="$2"; shift 2
|
|
42
|
+
|
|
43
|
+
if [ ! -f "$HOOK" ]; then
|
|
44
|
+
echo "fire.sh: no such hook: $HOOK" >&2
|
|
45
|
+
exit 64
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Build the tool-call JSON that Claude Code would send on stdin.
|
|
49
|
+
# Values are passed through a JSON string escaper so quotes and backslashes survive.
|
|
50
|
+
esc() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; }
|
|
51
|
+
fields=""
|
|
52
|
+
for kv in "$@"; do
|
|
53
|
+
k="${kv%%=*}"; v="${kv#*=}"
|
|
54
|
+
[ -n "$fields" ] && fields="$fields,"
|
|
55
|
+
fields="$fields\"$(esc "$k")\":\"$(esc "$v")\""
|
|
56
|
+
done
|
|
57
|
+
PAYLOAD="{\"tool_name\":\"$(esc "$TOOL")\",\"tool_input\":{$fields}}"
|
|
58
|
+
|
|
59
|
+
SANDBOX_HOME=$(mktemp -d)
|
|
60
|
+
cleanup() {
|
|
61
|
+
[ -n "${FAKEBIN:-}" ] && [ -d "$FAKEBIN" ] && { find "$FAKEBIN" -maxdepth 1 -type l -delete 2>/dev/null; rmdir "$FAKEBIN" 2>/dev/null; }
|
|
62
|
+
rmdir "$SANDBOX_HOME" 2>/dev/null || true
|
|
63
|
+
}
|
|
64
|
+
trap cleanup EXIT
|
|
65
|
+
|
|
66
|
+
FAKEBIN=""
|
|
67
|
+
if [ "$BARE" = "1" ]; then
|
|
68
|
+
# A PATH with the shell tools a hook needs to run at all, but without any
|
|
69
|
+
# JSON parser. This is what a slim container looks like.
|
|
70
|
+
FAKEBIN=$(mktemp -d)
|
|
71
|
+
for c in bash sh env printf echo grep sed awk tr cat cut head tail sort uniq wc dirname basename mktemp rmdir find ln test true false date id whoami; do
|
|
72
|
+
p=$(command -v "$c" 2>/dev/null) && ln -sf "$p" "$FAKEBIN/$c" 2>/dev/null
|
|
73
|
+
done
|
|
74
|
+
for j in jq python3 python node; do
|
|
75
|
+
if PATH="$FAKEBIN" command -v "$j" >/dev/null 2>&1; then
|
|
76
|
+
echo "fire.sh: --bare failed: $j is still reachable" >&2; exit 70
|
|
77
|
+
fi
|
|
78
|
+
done
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
OUT=$(mktemp); trap 'rm -f "$OUT" 2>/dev/null; cleanup' EXIT
|
|
82
|
+
if [ "$BARE" = "1" ]; then
|
|
83
|
+
printf '%s' "$PAYLOAD" | HOME="$SANDBOX_HOME" PATH="$FAKEBIN" bash "$HOOK" >"$OUT" 2>&1
|
|
84
|
+
else
|
|
85
|
+
printf '%s' "$PAYLOAD" | HOME="$SANDBOX_HOME" bash "$HOOK" >"$OUT" 2>&1
|
|
86
|
+
fi
|
|
87
|
+
CODE=$?
|
|
88
|
+
|
|
89
|
+
echo "hook : $HOOK"
|
|
90
|
+
echo "input : $PAYLOAD"
|
|
91
|
+
[ "$BARE" = "1" ] && echo "mode : --bare (no jq, no python3, no node)"
|
|
92
|
+
echo "exit : $CODE $( [ "$CODE" = 2 ] && echo '(refused)' || { [ "$CODE" = 0 ] && echo '(allowed)' || echo '(hook error)'; } )"
|
|
93
|
+
if [ -s "$OUT" ]; then
|
|
94
|
+
echo "message:"
|
|
95
|
+
sed 's/^/ /' "$OUT" | head -20
|
|
96
|
+
fi
|
|
97
|
+
exit "$CODE"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# selftest.sh - prove that find-dead-hooks.sh really detects a registration
|
|
3
|
+
# whose script is missing.
|
|
4
|
+
#
|
|
5
|
+
# A detector that finds nothing proves nothing until you have seen it find
|
|
6
|
+
# something. This builds a deliberately broken settings file in a throwaway
|
|
7
|
+
# directory, with one registration pointing at a script that does not exist and
|
|
8
|
+
# one pointing at a script that does, and checks both directions.
|
|
9
|
+
set -u
|
|
10
|
+
HERE=$(cd "$(dirname "$0")" && pwd)
|
|
11
|
+
T=$(mktemp -d)
|
|
12
|
+
mkdir -p "$T/.claude/hooks"
|
|
13
|
+
printf '#!/bin/bash\nexit 0\n' > "$T/.claude/hooks/real.sh"
|
|
14
|
+
chmod +x "$T/.claude/hooks/real.sh"
|
|
15
|
+
|
|
16
|
+
cat > "$T/.claude/settings.json" <<'JSON'
|
|
17
|
+
{"hooks":{"PreToolUse":[{"matcher":"Bash","hooks":[
|
|
18
|
+
{"type":"command","command":"${CLAUDE_PROJECT_DIR}/.claude/hooks/ghost.sh"},
|
|
19
|
+
{"type":"command","command":"${CLAUDE_PROJECT_DIR}/.claude/hooks/real.sh"}
|
|
20
|
+
]}]}}
|
|
21
|
+
JSON
|
|
22
|
+
|
|
23
|
+
echo "=== control: one registration points at a missing script, one at a real one ==="
|
|
24
|
+
out=$(cd "$T" && CLAUDE_PROJECT_DIR="$T" HOME="$T" bash "$HERE/find-dead-hooks.sh" 2>&1)
|
|
25
|
+
printf '%s\n' "$out"
|
|
26
|
+
echo
|
|
27
|
+
|
|
28
|
+
if printf '%s' "$out" | grep -q "ghost.sh"; then
|
|
29
|
+
echo "result: PASS - the missing registration was reported"
|
|
30
|
+
else
|
|
31
|
+
echo "result: FAIL - the missing registration was NOT reported"
|
|
32
|
+
fi
|
|
33
|
+
if printf '%s' "$out" | grep -q "real.sh"; then
|
|
34
|
+
echo "result: FAIL - the real registration was reported too"
|
|
35
|
+
else
|
|
36
|
+
echo "result: PASS - the real registration was not reported"
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# clean up: remove only what we created, one path at a time
|
|
40
|
+
for f in "$T/.claude/settings.json" "$T/.claude/hooks/real.sh"; do [ -f "$f" ] && unlink "$f"; done
|
|
41
|
+
rmdir "$T/.claude/hooks" "$T/.claude" "$T" 2>/dev/null
|
|
42
|
+
echo "(cleaned up the throwaway directory)"
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# unfirable-selftest.sh - prove that find-unfirable-rules.sh really detects a
|
|
3
|
+
# rule that cannot match, and does not report rules that can.
|
|
4
|
+
#
|
|
5
|
+
# A detector that finds nothing proves nothing until you have seen it find
|
|
6
|
+
# something. This builds a throwaway setup with four rules: two that cannot
|
|
7
|
+
# match (one of each mechanism), and two correct spellings of the same
|
|
8
|
+
# patterns. Both directions are checked, because a detector that flags
|
|
9
|
+
# everything is as useless as one that flags nothing.
|
|
10
|
+
set -u
|
|
11
|
+
HERE=$(cd "$(dirname "$0")" && pwd)
|
|
12
|
+
T=$(mktemp -d)
|
|
13
|
+
mkdir -p "$T/.claude/hooks"
|
|
14
|
+
|
|
15
|
+
cat > "$T/.claude/hooks/broken.sh" <<'SH'
|
|
16
|
+
#!/bin/bash
|
|
17
|
+
# eaten as options: the pattern starts with a dash
|
|
18
|
+
if grep -qE '--no-verify|SKIP_CI' "$1"; then echo "skip detected" >&2; fi
|
|
19
|
+
# lookaround in an engine that has none
|
|
20
|
+
if grep -qE '(?!origin\b)' "$1"; then echo "non-origin remote" >&2; fi
|
|
21
|
+
SH
|
|
22
|
+
|
|
23
|
+
cat > "$T/.claude/hooks/correct.sh" <<'SH'
|
|
24
|
+
#!/bin/bash
|
|
25
|
+
# the same two rules, spelled so they can actually match
|
|
26
|
+
if grep -qE -- '--no-verify|SKIP_CI' "$1"; then echo "skip detected" >&2; fi
|
|
27
|
+
if grep -qP '(?!origin\b)' "$1"; then echo "non-origin remote" >&2; fi
|
|
28
|
+
SH
|
|
29
|
+
chmod +x "$T/.claude/hooks/broken.sh" "$T/.claude/hooks/correct.sh"
|
|
30
|
+
|
|
31
|
+
cat > "$T/.claude/settings.json" <<'JSON'
|
|
32
|
+
{"hooks":{"PreToolUse":[{"matcher":"Bash","hooks":[
|
|
33
|
+
{"type":"command","command":"${CLAUDE_PROJECT_DIR}/.claude/hooks/broken.sh"},
|
|
34
|
+
{"type":"command","command":"${CLAUDE_PROJECT_DIR}/.claude/hooks/correct.sh"},
|
|
35
|
+
{"type":"command","command":"if echo \"$X\" | grep -qE \"--force-with-lease\"; then exit 2; fi"},
|
|
36
|
+
{"type":"command","command":"if echo \"$X\" | grep -qE -- \"--force-with-lease\"; then exit 2; fi"}
|
|
37
|
+
]}]}}
|
|
38
|
+
JSON
|
|
39
|
+
|
|
40
|
+
echo "=== control: two rules that cannot match, two that can, plus the same pair inline ==="
|
|
41
|
+
out=$(cd "$T" && CLAUDE_PROJECT_DIR="$T" HOME="$T" bash "$HERE/find-unfirable-rules.sh" 2>&1)
|
|
42
|
+
printf '%s\n' "$out"
|
|
43
|
+
echo
|
|
44
|
+
|
|
45
|
+
fails=0
|
|
46
|
+
expect_present() {
|
|
47
|
+
if printf '%s' "$out" | grep -q -- "$1"; then
|
|
48
|
+
echo "result: PASS - $2"
|
|
49
|
+
else
|
|
50
|
+
echo "result: FAIL - $2"; fails=$((fails + 1))
|
|
51
|
+
fi
|
|
52
|
+
}
|
|
53
|
+
expect_absent() {
|
|
54
|
+
if printf '%s' "$out" | grep -q -- "$1"; then
|
|
55
|
+
echo "result: FAIL - $2"; fails=$((fails + 1))
|
|
56
|
+
else
|
|
57
|
+
echo "result: PASS - $2"
|
|
58
|
+
fi
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
expect_present "broken.sh" "the script with two unfirable rules was reported"
|
|
62
|
+
expect_present "reads it as options" "the option-eating mechanism was named"
|
|
63
|
+
expect_present "lookaround" "the lookaround mechanism was named"
|
|
64
|
+
expect_present "(inline)" "the inline rule written into settings.json was reported"
|
|
65
|
+
expect_absent "correct.sh" "the correctly spelled script was not reported"
|
|
66
|
+
|
|
67
|
+
# The correct inline spelling uses -- ; it must not appear as a finding. The
|
|
68
|
+
# broken one does, so count the inline blocks rather than the substring.
|
|
69
|
+
inline_hits=$(printf '%s' "$out" | grep -c -- "(inline)" || true)
|
|
70
|
+
if [ "$inline_hits" -eq 1 ]; then
|
|
71
|
+
echo "result: PASS - exactly one of the two inline rules was reported"
|
|
72
|
+
else
|
|
73
|
+
echo "result: FAIL - expected 1 inline finding, got $inline_hits"; fails=$((fails + 1))
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
for f in "$T/.claude/settings.json" "$T/.claude/hooks/broken.sh" "$T/.claude/hooks/correct.sh"; do
|
|
77
|
+
[ -f "$f" ] && unlink "$f"
|
|
78
|
+
done
|
|
79
|
+
rmdir "$T/.claude/hooks" "$T/.claude" "$T" 2>/dev/null
|
|
80
|
+
echo "(cleaned up the throwaway directory)"
|
|
81
|
+
[ "$fails" -eq 0 ]
|
package/audit-web/index.html
CHANGED
|
@@ -155,7 +155,7 @@ exit 0</pre>
|
|
|
155
155
|
|
|
156
156
|
<h3>Quick Commands</h3>
|
|
157
157
|
<table>
|
|
158
|
-
<tr><td><code>npx cc-safe-setup</code></td><td>Install 8 hooks</td></tr>
|
|
158
|
+
<tr><td><code>npx github:yurukusa/cc-safe-setup</code></td><td>Install 8 hooks</td></tr>
|
|
159
159
|
<tr><td><code>--create "desc"</code></td><td>Generate hook</td></tr>
|
|
160
160
|
<tr><td><code>--audit</code></td><td>Score 0-100</td></tr>
|
|
161
161
|
<tr><td><code>--dashboard</code></td><td>Live status</td></tr>
|
|
@@ -194,16 +194,16 @@ function analyze(s) {
|
|
|
194
194
|
const risks=[], good=[];
|
|
195
195
|
const pre=s.hooks?.PreToolUse||[], post=s.hooks?.PostToolUse||[];
|
|
196
196
|
const all=JSON.stringify(pre).toLowerCase();
|
|
197
|
-
if(!pre.length) risks.push({s:'CRITICAL',i:'No PreToolUse hooks',f:'npx cc-safe-setup'});
|
|
197
|
+
if(!pre.length) risks.push({s:'CRITICAL',i:'No PreToolUse hooks',f:'npx github:yurukusa/cc-safe-setup'});
|
|
198
198
|
else { good.push('PreToolUse ('+pre.length+')');
|
|
199
|
-
if(!all.match(/destructive|guard|rm.*rf/)) risks.push({s:'HIGH',i:'No destructive guard',f:'npx cc-safe-setup'});
|
|
199
|
+
if(!all.match(/destructive|guard|rm.*rf/)) risks.push({s:'HIGH',i:'No destructive guard',f:'npx github:yurukusa/cc-safe-setup'});
|
|
200
200
|
else good.push('Destructive protection');
|
|
201
|
-
if(!all.match(/branch|push|main/)) risks.push({s:'HIGH',i:'No branch guard',f:'npx cc-safe-setup'});
|
|
201
|
+
if(!all.match(/branch|push|main/)) risks.push({s:'HIGH',i:'No branch guard',f:'npx github:yurukusa/cc-safe-setup'});
|
|
202
202
|
else good.push('Branch protection');
|
|
203
|
-
if(!all.match(/secret|env|credential/)) risks.push({s:'HIGH',i:'No secret guard',f:'npx cc-safe-setup'});
|
|
203
|
+
if(!all.match(/secret|env|credential/)) risks.push({s:'HIGH',i:'No secret guard',f:'npx github:yurukusa/cc-safe-setup'});
|
|
204
204
|
else good.push('Secret protection');
|
|
205
205
|
}
|
|
206
|
-
if(!post.length) risks.push({s:'MEDIUM',i:'No PostToolUse hooks',f:'npx cc-safe-setup'});
|
|
206
|
+
if(!post.length) risks.push({s:'MEDIUM',i:'No PostToolUse hooks',f:'npx github:yurukusa/cc-safe-setup'});
|
|
207
207
|
else good.push('PostToolUse ('+post.length+')');
|
|
208
208
|
const score=Math.max(0,100-risks.reduce((n,r)=>n+(r.s==='CRITICAL'?30:r.s==='HIGH'?20:10),0));
|
|
209
209
|
return {risks,good,score};
|
|
@@ -239,10 +239,10 @@ const RECIPES=[
|
|
|
239
239
|
{cat:'block',t:'Block .env staging',d:'Secret leak prevention (#6527)',code:'CMD=$(cat|jq -r \'.tool_input.command // empty\')\n[ -z "$CMD" ] && exit 0\necho "$CMD"|grep -qiE \'git\\s+add.*\\.env\' && echo "BLOCKED" >&2 && exit 2\nexit 0',trigger:'PreToolUse'},
|
|
240
240
|
{cat:'block',t:'Block database wipe',d:'migrate:fresh, DROP DATABASE (#37405)',code:'CMD=$(cat|jq -r \'.tool_input.command // empty\')\n[ -z "$CMD" ] && exit 0\necho "$CMD"|grep -qiE \'migrate:fresh|DROP\\s+DATABASE|prisma\\s+migrate\\s+reset\' && echo "BLOCKED" >&2 && exit 2\nexit 0',trigger:'PreToolUse'},
|
|
241
241
|
{cat:'approve',t:'Auto-approve git read',d:'git status/log/diff with -C flag (#36900)',code:'CMD=$(cat|jq -r \'.tool_input.command // empty\')\n[ -z "$CMD" ] && exit 0\necho "$CMD"|grep -qE \'^\\s*git\\s+(-C\\s+\\S+\\s+)?(status|log|diff|branch|show)\' && jq -n \'{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}\'\nexit 0',trigger:'PreToolUse'},
|
|
242
|
-
{cat:'approve',t:'Compound commands',d:'cd && git log auto-approve (#30519)',code:'# Full: npx cc-safe-setup --install-example compound-command-approver',trigger:'PreToolUse'},
|
|
242
|
+
{cat:'approve',t:'Compound commands',d:'cd && git log auto-approve (#30519)',code:'# Full: npx github:yurukusa/cc-safe-setup --install-example compound-command-approver',trigger:'PreToolUse'},
|
|
243
243
|
{cat:'detect',t:'Loop detector',d:'Break command repetition (5+ times)',code:'CMD=$(cat|jq -r \'.tool_input.command // empty\')\n[ -z "$CMD" ] && exit 0\nSTATE=/tmp/cc-loop\necho "$CMD">>$STATE\ntail -n 10 $STATE>${STATE}.tmp&&mv ${STATE}.tmp $STATE\nCOUNT=$(grep -cF "$CMD" $STATE||echo 0)\n[ "$COUNT" -ge 5 ]&&echo "BLOCKED: repeated $COUNT times" >&2&&exit 2\nexit 0',trigger:'PreToolUse'},
|
|
244
|
-
{cat:'utility',t:'Session handoff',d:'Save state for next session',code:'# npx cc-safe-setup --install-example session-handoff',trigger:'Stop'},
|
|
245
|
-
{cat:'utility',t:'Cost tracker',d:'Estimate session token cost',code:'# npx cc-safe-setup --install-example cost-tracker',trigger:'PostToolUse'},
|
|
244
|
+
{cat:'utility',t:'Session handoff',d:'Save state for next session',code:'# npx github:yurukusa/cc-safe-setup --install-example session-handoff',trigger:'Stop'},
|
|
245
|
+
{cat:'utility',t:'Cost tracker',d:'Estimate session token cost',code:'# npx github:yurukusa/cc-safe-setup --install-example cost-tracker',trigger:'PostToolUse'},
|
|
246
246
|
{cat:'utility',t:'tmp cleanup',d:'/tmp/claude-*-cwd files (#8856)',code:'find /tmp -maxdepth 1 -name \'claude-*-cwd\' -type f -mmin +60 -delete 2>/dev/null\nexit 0',trigger:'Stop'},
|
|
247
247
|
];
|
|
248
248
|
|
package/examples/README.md
CHANGED
|
@@ -1,28 +1,65 @@
|
|
|
1
1
|
# Example Hooks
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
As of 2026-08-31 this directory held 914 installable hooks; it holds 916 today
|
|
4
|
+
(2026-09-20). Each solves a real problem from GitHub Issues or autonomous operation.
|
|
5
|
+
Covered by the 296 test files in [`tests/`](../tests) — 295 shell, one Python
|
|
6
|
+
(counted 2026-09-20).
|
|
7
|
+
The category table below is the 2026-08-31 count and has not been recut since.
|
|
4
8
|
|
|
5
9
|
```bash
|
|
6
|
-
npx cc-safe-setup --install-example <name> # install one
|
|
7
|
-
npx cc-safe-setup --examples # list all
|
|
8
|
-
npx cc-safe-setup --examples safety # filter by category
|
|
9
|
-
npx cc-safe-setup --shield # install recommended set
|
|
10
|
+
npx github:yurukusa/cc-safe-setup --install-example <name> # install one
|
|
11
|
+
npx github:yurukusa/cc-safe-setup --examples # list all
|
|
12
|
+
npx github:yurukusa/cc-safe-setup --examples safety # filter by category
|
|
13
|
+
npx github:yurukusa/cc-safe-setup --shield # install recommended set
|
|
10
14
|
```
|
|
11
15
|
|
|
12
16
|
## Categories
|
|
13
17
|
|
|
14
|
-
| Category |
|
|
15
|
-
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
18
|
+
| Category | Hooks | Of which can refuse a call |
|
|
19
|
+
|----------|------:|---------------------------:|
|
|
20
|
+
| Safety Guards | 318 | 132 |
|
|
21
|
+
| Auto-Approve | 35 | 18 |
|
|
22
|
+
| Quality | 174 | 12 |
|
|
23
|
+
| Agent Controls | 15 | 9 |
|
|
24
|
+
| Monitoring | 28 | 2 |
|
|
25
|
+
| Recovery | 32 | 2 |
|
|
26
|
+
| UX | 51 | 13 |
|
|
27
|
+
| Other | 2 | 0 |
|
|
28
|
+
| (uncategorised) | 259 | 112 |
|
|
29
|
+
| **total** | **914** | **300** |
|
|
30
|
+
|
|
31
|
+
"Can refuse" means the script contains `exit 2`, a permission decision,
|
|
32
|
+
`"decision": "block"` or `"deny"` **outside a comment**. The other 614 warn, count or log —
|
|
33
|
+
useful, but they cannot stop a tool call, whatever the filename suggests. (Of those 614, 609
|
|
34
|
+
have no refusal at all; 5 end with a computed exit code such as `exit "$RC"` and have to be
|
|
35
|
+
opened to tell.)
|
|
36
|
+
|
|
37
|
+
**The word "outside a comment" is doing real work here.** A plain `grep` over the file counts
|
|
38
|
+
matches inside comments, and 19 scripts here match only there — including three whose comment
|
|
39
|
+
says, in so many words, that they are not blockers:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
network-guard.sh:5 # This is a warning hook (exit 0), not a blocker (exit 2),
|
|
43
|
+
plan-mode-edit-guard.sh:74 # Warning only (exit 0). Change to exit 2 to block.
|
|
44
|
+
no-push-without-tests.sh:41 # Warning only. Change exit 0 to exit 2 to enforce.
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
So strip comments before you trust the match. To check the hooks you already rely on:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
for f in "$HOME"/.claude/hooks/*.sh; do
|
|
51
|
+
sed 's/#.*//' "$f" | grep -qE 'exit 2|permissionDecision|"decision": *"block"|"deny"' \
|
|
52
|
+
|| echo "WITNESS $f"
|
|
53
|
+
done
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This is still a floor, not a census. `broad-prefix-session-trap-warner.sh` carries
|
|
57
|
+
`permissionDecision: deny` inside a *message string* and its only exit is `exit 0`. The `sed`
|
|
58
|
+
above does drop that line — but only because an issue number, `(#62437)`, appears earlier on the
|
|
59
|
+
same line and takes the rest of it with it. Right answer, wrong reason: write the same warning
|
|
60
|
+
without an issue number and the file counts as a refuser. Telling code from string needs a shell
|
|
61
|
+
parser, which one line of `sed` is not. Adjust the extension too — a hooks directory can hold
|
|
62
|
+
`.py` and `.js`.
|
|
26
63
|
|
|
27
64
|
## Popular Hooks
|
|
28
65
|
|