cc-safe-setup 29.7.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-circuit-breaker.sh +72 -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 +89 -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/thinking-stall-detector.sh +61 -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-circuit-breaker.sh +134 -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-exploration-budget-guard.sh +164 -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-thinking-stall-detector.sh +151 -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,174 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# dispatch-receipt.sh — Receipt-and-refuse layer for agent
|
|
4
|
+
# dispatch operations
|
|
5
|
+
# ================================================================
|
|
6
|
+
# PURPOSE:
|
|
7
|
+
# PreToolUse on Task / Agent. Writes a structured JSONL receipt
|
|
8
|
+
# before each dispatch, and (optionally) refuses dispatches to
|
|
9
|
+
# agent names that fall outside a declared allowlist.
|
|
10
|
+
#
|
|
11
|
+
# Sibling of scope-expansion-receipt.sh. Where the destructive
|
|
12
|
+
# sibling records and gates *file system* operations, this hook
|
|
13
|
+
# records and gates *agent dispatch* operations. Both implement
|
|
14
|
+
# the receipt-persistence-layer architecture:
|
|
15
|
+
# https://gist.github.com/yurukusa/8c0d19d59730868672270e7312492d1d
|
|
16
|
+
#
|
|
17
|
+
# TRIGGER: PreToolUse
|
|
18
|
+
# MATCHER: "Task|Agent"
|
|
19
|
+
#
|
|
20
|
+
# WHY THIS MATTERS:
|
|
21
|
+
# anthropics/claude-code#61167 reported a production audit at a
|
|
22
|
+
# healthcare startup: 39 specialized agents deployed (OpenClaw,
|
|
23
|
+
# AWS Lightsail, Bedrock Sonnet 4.6), 5 ever used, ~20 total
|
|
24
|
+
# sessions across all of them. Opus 4.7 reported dispatching
|
|
25
|
+
# the unused agents — ZELDA, LYRA, MIRA, TESTER, CLINIC, OPS,
|
|
26
|
+
# CFO, LEX, SABRINA, UXI — with correct names, correct
|
|
27
|
+
# terminology, plausible outputs. None of those dispatches
|
|
28
|
+
# ever happened.
|
|
29
|
+
#
|
|
30
|
+
# The cluster name is "phantom agent dispatch", a specialization
|
|
31
|
+
# of the broader recognition-without-arrest pattern (#60226).
|
|
32
|
+
# In the healthcare case, the fabricated dispatches included
|
|
33
|
+
# verification agents (CLINIC, GUARD, SAFE, LEX, TESTER). When
|
|
34
|
+
# a model fabricates the output of *the agents whose job is to
|
|
35
|
+
# detect fabrication*, the safety architecture inverts.
|
|
36
|
+
#
|
|
37
|
+
# This hook moves the receipt to the tool boundary: every
|
|
38
|
+
# Task / Agent invocation lands a record before execution. The
|
|
39
|
+
# audit query becomes "show me receipts for CLINIC dispatches in
|
|
40
|
+
# the last N days." If the count is zero while CLINIC's review
|
|
41
|
+
# output appears in session transcripts, the fabrication is
|
|
42
|
+
# recoverable with one grep.
|
|
43
|
+
#
|
|
44
|
+
# RECEIPT FORMAT (one JSONL per dispatch):
|
|
45
|
+
# {"ts":"2026-05-22T05:00:00Z",
|
|
46
|
+
# "subagent_type":"general-purpose",
|
|
47
|
+
# "description":"<short task description>",
|
|
48
|
+
# "prompt_hash":"<sha256 of prompt>",
|
|
49
|
+
# "prompt_length":1234,
|
|
50
|
+
# "allowlist_match":"general-purpose" | null,
|
|
51
|
+
# "decision":"execute" | "refuse" | "execute-bypassed"}
|
|
52
|
+
#
|
|
53
|
+
# Note: the full prompt is NOT stored. Healthcare and other
|
|
54
|
+
# sensitive deployments may include PHI / PII in dispatch
|
|
55
|
+
# prompts; storing only a sha256 hash lets the audit verify
|
|
56
|
+
# "this exact prompt was dispatched" without persisting the
|
|
57
|
+
# content. Use prompt_length + prompt_hash + ts as the
|
|
58
|
+
# correlation key against session transcripts.
|
|
59
|
+
#
|
|
60
|
+
# RECEIPT LOCATION:
|
|
61
|
+
# ${HOME}/.claude/receipts/dispatch-YYYY-MM-DD.jsonl
|
|
62
|
+
#
|
|
63
|
+
# CONFIGURATION:
|
|
64
|
+
# CC_DISPATCH_ALLOWLIST — JSON array of allowed subagent types,
|
|
65
|
+
# e.g. '["general-purpose","Explore","code-reviewer"]'
|
|
66
|
+
# If unset, the hook only writes receipts (never refuses).
|
|
67
|
+
#
|
|
68
|
+
# CC_DISPATCH_BYPASS=1 — single-call escape hatch. The receipt
|
|
69
|
+
# is still written (with decision="execute-bypassed"); refuse
|
|
70
|
+
# logic is skipped. Use only when you have read the receipt
|
|
71
|
+
# and verified the intent.
|
|
72
|
+
#
|
|
73
|
+
# CC_DISPATCH_RECEIPT_DIR — override the receipt directory
|
|
74
|
+
# (default: ${HOME}/.claude/receipts)
|
|
75
|
+
#
|
|
76
|
+
# RELATED:
|
|
77
|
+
# https://github.com/anthropics/claude-code/issues/61167
|
|
78
|
+
# https://github.com/anthropics/claude-code/issues/61107
|
|
79
|
+
# https://github.com/anthropics/claude-code/issues/61102
|
|
80
|
+
# https://github.com/anthropics/claude-code/issues/60226
|
|
81
|
+
# https://gist.github.com/yurukusa/69f3ba47ed94afabc20424b4c82d46f2
|
|
82
|
+
# (Phantom Agent Cluster — A Pre-Launch Forensic Survey)
|
|
83
|
+
# ================================================================
|
|
84
|
+
|
|
85
|
+
set -u
|
|
86
|
+
|
|
87
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
88
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
89
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
90
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
91
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
92
|
+
_nojq_warned="/tmp/cc-nojq-warned-dispatch-receipt-$PPID"
|
|
93
|
+
[ -f "$_nojq_warned" ] || {
|
|
94
|
+
echo "WARNING [dispatch-receipt]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
95
|
+
: > "$_nojq_warned"
|
|
96
|
+
}
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
INPUT=$(cat)
|
|
100
|
+
|
|
101
|
+
SUBAGENT_TYPE=$(printf '%s' "$INPUT" | jq -r '.tool_input.subagent_type // empty' 2>/dev/null)
|
|
102
|
+
DESCRIPTION=$(printf '%s' "$INPUT" | jq -r '.tool_input.description // empty' 2>/dev/null)
|
|
103
|
+
PROMPT=$(printf '%s' "$INPUT" | jq -r '.tool_input.prompt // empty' 2>/dev/null)
|
|
104
|
+
|
|
105
|
+
# If we cannot identify a dispatch payload at all, exit silently.
|
|
106
|
+
# A Task call with no subagent_type and no prompt is malformed upstream;
|
|
107
|
+
# refusing here would create false-positive friction without audit value.
|
|
108
|
+
if [ -z "$SUBAGENT_TYPE" ] && [ -z "$PROMPT" ]; then
|
|
109
|
+
exit 0
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# Default subagent_type when omitted (Claude Code uses general-purpose).
|
|
113
|
+
[ -z "$SUBAGENT_TYPE" ] && SUBAGENT_TYPE="general-purpose"
|
|
114
|
+
|
|
115
|
+
# Compute prompt hash and length without storing the prompt itself.
|
|
116
|
+
PROMPT_LEN=$(printf '%s' "$PROMPT" | wc -c | tr -d ' ')
|
|
117
|
+
PROMPT_HASH=$(printf '%s' "$PROMPT" | sha256sum 2>/dev/null | awk '{print $1}')
|
|
118
|
+
[ -z "$PROMPT_HASH" ] && PROMPT_HASH="$(printf '%s' "$PROMPT" | shasum -a 256 2>/dev/null | awk '{print $1}')"
|
|
119
|
+
|
|
120
|
+
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
121
|
+
TYPE_JSON=$(printf '%s' "$SUBAGENT_TYPE" | jq -Rs -c .)
|
|
122
|
+
DESC_JSON=$(printf '%s' "$DESCRIPTION" | jq -Rs -c .)
|
|
123
|
+
|
|
124
|
+
# Allowlist decision
|
|
125
|
+
ALLOWLIST_JSON="${CC_DISPATCH_ALLOWLIST:-}"
|
|
126
|
+
BYPASS="${CC_DISPATCH_BYPASS:-0}"
|
|
127
|
+
DECISION="execute"
|
|
128
|
+
ALLOWLIST_MATCH_JSON="null"
|
|
129
|
+
|
|
130
|
+
if [ -n "$ALLOWLIST_JSON" ]; then
|
|
131
|
+
# Validate allowlist is a JSON array; if not, fail open (receipt-only).
|
|
132
|
+
if printf '%s' "$ALLOWLIST_JSON" | jq -e 'type == "array"' >/dev/null 2>&1; then
|
|
133
|
+
MATCH=$(printf '%s' "$ALLOWLIST_JSON" | jq -r --arg t "$SUBAGENT_TYPE" '
|
|
134
|
+
.[] | select(. == $t)
|
|
135
|
+
' 2>/dev/null | head -1)
|
|
136
|
+
if [ -n "$MATCH" ]; then
|
|
137
|
+
ALLOWLIST_MATCH_JSON=$(printf '%s' "$MATCH" | jq -Rs -c .)
|
|
138
|
+
else
|
|
139
|
+
DECISION="refuse"
|
|
140
|
+
fi
|
|
141
|
+
fi
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
if [ "$BYPASS" = "1" ] && [ "$DECISION" = "refuse" ]; then
|
|
145
|
+
DECISION="execute-bypassed"
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
# Write receipt
|
|
149
|
+
RECEIPT_DIR="${CC_DISPATCH_RECEIPT_DIR:-${HOME}/.claude/receipts}"
|
|
150
|
+
mkdir -p "$RECEIPT_DIR" 2>/dev/null
|
|
151
|
+
RECEIPT_FILE="${RECEIPT_DIR}/dispatch-$(date +%Y-%m-%d).jsonl"
|
|
152
|
+
|
|
153
|
+
printf '{"ts":"%s","subagent_type":%s,"description":%s,"prompt_hash":"%s","prompt_length":%s,"allowlist_match":%s,"decision":"%s"}\n' \
|
|
154
|
+
"$TS" "$TYPE_JSON" "$DESC_JSON" "$PROMPT_HASH" "$PROMPT_LEN" "$ALLOWLIST_MATCH_JSON" "$DECISION" \
|
|
155
|
+
>> "$RECEIPT_FILE" 2>/dev/null
|
|
156
|
+
|
|
157
|
+
if [ "$DECISION" = "refuse" ]; then
|
|
158
|
+
ALLOWED=$(printf '%s' "$ALLOWLIST_JSON" | jq -r 'join(", ")' 2>/dev/null)
|
|
159
|
+
echo "BLOCKED: dispatch-receipt — agent type \"$SUBAGENT_TYPE\" is not in the declared allowlist." >&2
|
|
160
|
+
echo "" >&2
|
|
161
|
+
echo "Allowed agent types: $ALLOWED" >&2
|
|
162
|
+
echo "Receipt: $RECEIPT_FILE" >&2
|
|
163
|
+
echo "" >&2
|
|
164
|
+
echo "Principle: subagent dispatch is an action that must produce a verifiable record." >&2
|
|
165
|
+
echo " (https://github.com/anthropics/claude-code/issues/61167)" >&2
|
|
166
|
+
echo "" >&2
|
|
167
|
+
echo "To proceed:" >&2
|
|
168
|
+
echo " 1. Verify the agent type matches a deployed agent (avoid phantom dispatches)." >&2
|
|
169
|
+
echo " 2. Either add the agent type to CC_DISPATCH_ALLOWLIST, or" >&2
|
|
170
|
+
echo " 3. Re-issue with CC_DISPATCH_BYPASS=1 (recorded in the receipt)." >&2
|
|
171
|
+
exit 2
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
exit 0
|
|
@@ -20,6 +20,18 @@
|
|
|
20
20
|
#
|
|
21
21
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
22
22
|
|
|
23
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
24
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
25
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
26
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
27
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
28
|
+
_nojq_warned="/tmp/cc-nojq-warned-django-migrate-guard-$PPID"
|
|
29
|
+
[ -f "$_nojq_warned" ] || {
|
|
30
|
+
echo "WARNING [django-migrate-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
31
|
+
: > "$_nojq_warned"
|
|
32
|
+
}
|
|
33
|
+
fi
|
|
34
|
+
|
|
23
35
|
INPUT=$(cat)
|
|
24
36
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
25
37
|
|
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
#
|
|
8
8
|
# TRIGGER: PreToolUse MATCHER: "Bash|Edit|Write"
|
|
9
9
|
|
|
10
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
11
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
12
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
13
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
14
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
15
|
+
_nojq_warned="/tmp/cc-nojq-warned-dns-config-guard-$PPID"
|
|
16
|
+
[ -f "$_nojq_warned" ] || {
|
|
17
|
+
echo "WARNING [dns-config-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
18
|
+
: > "$_nojq_warned"
|
|
19
|
+
}
|
|
20
|
+
fi
|
|
21
|
+
|
|
10
22
|
INPUT=$(cat)
|
|
11
23
|
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
12
24
|
|
|
@@ -17,6 +17,18 @@
|
|
|
17
17
|
# }
|
|
18
18
|
# }
|
|
19
19
|
|
|
20
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
21
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
22
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
23
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
24
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
25
|
+
_nojq_warned="/tmp/cc-nojq-warned-docker-dangerous-guard-$PPID"
|
|
26
|
+
[ -f "$_nojq_warned" ] || {
|
|
27
|
+
echo "WARNING [docker-dangerous-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
28
|
+
: > "$_nojq_warned"
|
|
29
|
+
}
|
|
30
|
+
fi
|
|
31
|
+
|
|
20
32
|
INPUT=$(cat)
|
|
21
33
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
22
34
|
[ -z "$COMMAND" ] && exit 0
|
|
File without changes
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# dotenv-anthropic-key-billing-guard.sh — Warn when project .env contains ANTHROPIC_API_KEY
|
|
3
|
+
#
|
|
4
|
+
# Solves: Reddit r/ClaudeAI 1tbaq2d (314 points, 86 comments as of 2026-05-13)
|
|
5
|
+
# "If your project has an ANTHROPIC_API_KEY in any .env file,
|
|
6
|
+
# Claude Code will silently bill your API account instead of your Max plan."
|
|
7
|
+
# User reported 9 auto-recharge events totaling ~$187 USD loss.
|
|
8
|
+
# Anthropic support confirmed: "this is intentional functionality."
|
|
9
|
+
#
|
|
10
|
+
# WHY THIS MATTERS:
|
|
11
|
+
# When .env contains ANTHROPIC_API_KEY=sk-ant-..., Claude Code shells inherit
|
|
12
|
+
# the variable and the model client prefers the env var over the Max plan
|
|
13
|
+
# subscription credentials. The user sees no warning, no UI indicator;
|
|
14
|
+
# billing silently routes to the API account and prepaid funds get
|
|
15
|
+
# consumed (and are non-refundable per Anthropic policy).
|
|
16
|
+
#
|
|
17
|
+
# This is the exact "claim-verify gap" pattern: the user's mental model
|
|
18
|
+
# ("I'm on Max plan, billing is fixed") diverges from system reality
|
|
19
|
+
# (env var overrides Max plan, billing is per-token).
|
|
20
|
+
#
|
|
21
|
+
# TRIGGER: SessionStart MATCHER: ""
|
|
22
|
+
#
|
|
23
|
+
# CONFIGURATION:
|
|
24
|
+
# CC_DOTENV_AK_FILES — comma-separated filenames to check
|
|
25
|
+
# (default: .env,.env.local,.env.development,.env.production,.env.dev)
|
|
26
|
+
# CC_DOTENV_AK_ACTION — "warn" or "block" (default: warn)
|
|
27
|
+
# CC_DOTENV_AK_LOG — log file path (default: /tmp/cc-dotenv-ak-warnings.log)
|
|
28
|
+
#
|
|
29
|
+
# Usage:
|
|
30
|
+
# {
|
|
31
|
+
# "hooks": {
|
|
32
|
+
# "SessionStart": [{
|
|
33
|
+
# "hooks": [{ "type": "command", "command": "~/.claude/hooks/dotenv-anthropic-key-billing-guard.sh" }]
|
|
34
|
+
# }]
|
|
35
|
+
# }
|
|
36
|
+
# }
|
|
37
|
+
|
|
38
|
+
FILES="${CC_DOTENV_AK_FILES:-.env,.env.local,.env.development,.env.production,.env.dev}"
|
|
39
|
+
ACTION="${CC_DOTENV_AK_ACTION:-warn}"
|
|
40
|
+
LOG_FILE="${CC_DOTENV_AK_LOG:-/tmp/cc-dotenv-ak-warnings.log}"
|
|
41
|
+
|
|
42
|
+
# Determine project root: prefer CLAUDE_PROJECT_DIR, fall back to PWD
|
|
43
|
+
PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$PWD}"
|
|
44
|
+
[ -d "$PROJECT_ROOT" ] || exit 0
|
|
45
|
+
|
|
46
|
+
FOUND_FILES=()
|
|
47
|
+
|
|
48
|
+
IFS=',' read -ra PATTERNS <<< "$FILES"
|
|
49
|
+
for pat in "${PATTERNS[@]}"; do
|
|
50
|
+
pat=$(echo "$pat" | xargs) # trim whitespace
|
|
51
|
+
[ -z "$pat" ] && continue
|
|
52
|
+
candidate="$PROJECT_ROOT/$pat"
|
|
53
|
+
if [ -f "$candidate" ]; then
|
|
54
|
+
# Match a non-empty assignment (allow optional spaces, optional export, optional quotes)
|
|
55
|
+
# Skip lines that are commented out (start with #)
|
|
56
|
+
if grep -qE '^[[:space:]]*(export[[:space:]]+)?ANTHROPIC_API_KEY[[:space:]]*=[[:space:]]*["'"'"']?[^[:space:]"'"'"'#][^"'"'"'#]*' "$candidate" 2>/dev/null; then
|
|
57
|
+
FOUND_FILES+=("$candidate")
|
|
58
|
+
fi
|
|
59
|
+
fi
|
|
60
|
+
done
|
|
61
|
+
|
|
62
|
+
# If no offending files, pass through silently
|
|
63
|
+
if [ ${#FOUND_FILES[@]} -eq 0 ]; then
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Found offending file(s) — log and notify
|
|
68
|
+
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
|
69
|
+
for f in "${FOUND_FILES[@]}"; do
|
|
70
|
+
echo "[$TIMESTAMP] $f contains ANTHROPIC_API_KEY action=$ACTION" >> "$LOG_FILE"
|
|
71
|
+
done
|
|
72
|
+
|
|
73
|
+
# Build human-readable message
|
|
74
|
+
MSG="⚠️ ANTHROPIC_API_KEY detected in project .env file(s):"
|
|
75
|
+
for f in "${FOUND_FILES[@]}"; do
|
|
76
|
+
MSG+=$'\n'" - $f"
|
|
77
|
+
done
|
|
78
|
+
MSG+=$'\n'
|
|
79
|
+
MSG+=$'\n'" Claude Code shell tools inherit env vars from the project, and the"
|
|
80
|
+
MSG+=$'\n'" client prefers ANTHROPIC_API_KEY over the Max plan subscription."
|
|
81
|
+
MSG+=$'\n'" Result: API charges may silently consume prepaid funds while you"
|
|
82
|
+
MSG+=$'\n'" believe you are on the flat-rate Max plan. Refunds are not offered"
|
|
83
|
+
MSG+=$'\n'" for funds already consumed."
|
|
84
|
+
MSG+=$'\n'
|
|
85
|
+
MSG+=$'\n'" Mitigations:"
|
|
86
|
+
MSG+=$'\n'" 1. Remove the ANTHROPIC_API_KEY line from the .env file, OR"
|
|
87
|
+
MSG+=$'\n'" 2. Set ANTHROPIC_API_KEY= (empty) at the start of your shell session, OR"
|
|
88
|
+
MSG+=$'\n'" 3. Move the key to a separate file that is not auto-sourced."
|
|
89
|
+
MSG+=$'\n'
|
|
90
|
+
MSG+=$'\n'" Reference: reddit.com/r/ClaudeAI/comments/1tbaq2d/ ($187 loss reported)"
|
|
91
|
+
|
|
92
|
+
if [ "$ACTION" = "block" ]; then
|
|
93
|
+
# SessionStart cannot truly block, but exit 2 surfaces error to user.
|
|
94
|
+
printf '%s\n' "$MSG" >&2
|
|
95
|
+
exit 2
|
|
96
|
+
else
|
|
97
|
+
printf '%s\n' "$MSG" >&2
|
|
98
|
+
exit 0
|
|
99
|
+
fi
|
|
@@ -12,6 +12,18 @@
|
|
|
12
12
|
|
|
13
13
|
set -euo pipefail
|
|
14
14
|
|
|
15
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
16
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
17
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
18
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
19
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
20
|
+
_nojq_warned="/tmp/cc-nojq-warned-dotenv-commit-guard-$PPID"
|
|
21
|
+
[ -f "$_nojq_warned" ] || {
|
|
22
|
+
echo "WARNING [dotenv-commit-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
23
|
+
: > "$_nojq_warned"
|
|
24
|
+
}
|
|
25
|
+
fi
|
|
26
|
+
|
|
15
27
|
INPUT=$(cat)
|
|
16
28
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
17
29
|
[ -z "$COMMAND" ] && exit 0
|
|
@@ -24,6 +24,18 @@
|
|
|
24
24
|
#
|
|
25
25
|
# TRIGGER: PreToolUse MATCHER: "Read"
|
|
26
26
|
|
|
27
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
28
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
29
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
30
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
31
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
32
|
+
_nojq_warned="/tmp/cc-nojq-warned-dotenv-read-guard-$PPID"
|
|
33
|
+
[ -f "$_nojq_warned" ] || {
|
|
34
|
+
echo "WARNING [dotenv-read-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
35
|
+
: > "$_nojq_warned"
|
|
36
|
+
}
|
|
37
|
+
fi
|
|
38
|
+
|
|
27
39
|
INPUT=$(cat)
|
|
28
40
|
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
29
41
|
|
|
@@ -20,6 +20,18 @@
|
|
|
20
20
|
|
|
21
21
|
set -euo pipefail
|
|
22
22
|
|
|
23
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
24
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
25
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
26
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
27
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
28
|
+
_nojq_warned="/tmp/cc-nojq-warned-dotfile-protection-guard-$PPID"
|
|
29
|
+
[ -f "$_nojq_warned" ] || {
|
|
30
|
+
echo "WARNING [dotfile-protection-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
31
|
+
: > "$_nojq_warned"
|
|
32
|
+
}
|
|
33
|
+
fi
|
|
34
|
+
|
|
23
35
|
INPUT=$(cat)
|
|
24
36
|
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
25
37
|
[ -z "$FILE" ] && exit 0
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
# }
|
|
19
19
|
# ================================================================
|
|
20
20
|
#
|
|
21
|
-
# TRIGGER:
|
|
21
|
+
# TRIGGER: PostToolUse MATCHER: "Edit|Write"
|
|
22
22
|
|
|
23
23
|
INPUT=$(cat)
|
|
24
24
|
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
@@ -10,14 +10,26 @@
|
|
|
10
10
|
# {
|
|
11
11
|
# "hooks": {
|
|
12
12
|
# "PreToolUse": [{
|
|
13
|
-
# "matcher": "Bash",
|
|
13
|
+
# "matcher": "Bash|PowerShell",
|
|
14
14
|
# "hooks": [{ "type": "command", "command": "~/.claude/hooks/drizzle-migrate-guard.sh" }]
|
|
15
15
|
# }]
|
|
16
16
|
# }
|
|
17
17
|
# }
|
|
18
18
|
# ================================================================
|
|
19
19
|
#
|
|
20
|
-
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
20
|
+
# TRIGGER: PreToolUse MATCHER: "Bash|PowerShell"
|
|
21
|
+
|
|
22
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
23
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
24
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
25
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
26
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
27
|
+
_nojq_warned="/tmp/cc-nojq-warned-drizzle-migrate-guard-$PPID"
|
|
28
|
+
[ -f "$_nojq_warned" ] || {
|
|
29
|
+
echo "WARNING [drizzle-migrate-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
30
|
+
: > "$_nojq_warned"
|
|
31
|
+
}
|
|
32
|
+
fi
|
|
21
33
|
|
|
22
34
|
INPUT=$(cat)
|
|
23
35
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
@@ -31,4 +43,17 @@ if echo "$COMMAND" | grep -qE 'drizzle-kit\s+drop'; then
|
|
|
31
43
|
exit 2
|
|
32
44
|
fi
|
|
33
45
|
|
|
46
|
+
# Block 'drizzle-kit push --force'. Plain 'push' prompts before any data-loss
|
|
47
|
+
# change; --force (and the legacy push:pg/push:mysql/push:sqlite variants)
|
|
48
|
+
# skips that prompt and applies the change directly — the exact way autonomous
|
|
49
|
+
# agents have wiped production databases (anthropics/claude-code#27063, and the
|
|
50
|
+
# sibling prisma case #36183). The header has always advertised this block; it
|
|
51
|
+
# was never implemented, so a user relying on this hook was unprotected.
|
|
52
|
+
if echo "$COMMAND" | grep -qE 'drizzle-kit\s+push(:[a-z]+)?\b' && echo "$COMMAND" | grep -qE '\-\-force(-reset)?\b'; then
|
|
53
|
+
echo "BLOCKED: 'drizzle-kit push --force' applies schema changes without the data-loss prompt and can wipe table data." >&2
|
|
54
|
+
echo "Command: $COMMAND" >&2
|
|
55
|
+
echo "Use 'drizzle-kit generate' + 'drizzle-kit migrate' for a reviewable migration, or drop --force to keep the interactive guard." >&2
|
|
56
|
+
exit 2
|
|
57
|
+
fi
|
|
58
|
+
|
|
34
59
|
exit 0
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# echo-probe-spam-detector.sh — Block Opus 4.8 echo-probe spam bursts
|
|
3
|
+
# (Cluster 25 candidate, axis 25B — tool-result delivery compensation)
|
|
4
|
+
#
|
|
5
|
+
# Background:
|
|
6
|
+
# When the Bash tool's result delivery is slow or buffered, Opus 4.8 emits
|
|
7
|
+
# bursts of no-op echo probe commands ("echo s1", "echo s2", ...,
|
|
8
|
+
# sometimes "sleep N; echo x") between real commands, apparently to coax
|
|
9
|
+
# buffered output to flush. Dozens per turn bury the actual work, clutter
|
|
10
|
+
# the screen, and burn tokens. The behaviour started after the Opus 4.8
|
|
11
|
+
# upgrade and was not present on prior model versions.
|
|
12
|
+
#
|
|
13
|
+
# Anchor case:
|
|
14
|
+
# #63887 — Agent spams no-op echo probe commands to flush shell output
|
|
15
|
+
# (14 reactions, Opus 4.8 + v2.1.156+ regression)
|
|
16
|
+
#
|
|
17
|
+
# Cost-side sibling:
|
|
18
|
+
# #64343 — Excessive token consumption from repeated echo tool calls
|
|
19
|
+
# ("burned my tokens on hundreds of echo calls")
|
|
20
|
+
#
|
|
21
|
+
# Cluster 25 axes (4 sub-clusters + 1 overlap):
|
|
22
|
+
# 25A — late/empty tool-result delivery (substrate)
|
|
23
|
+
# 25B — echo-probe spam compensation (this hook)
|
|
24
|
+
# 25C — 2>&1 permission-engine fragmentation hang
|
|
25
|
+
# 25D — compounding cost (downstream of 25B/25C)
|
|
26
|
+
# 25E — empty-result triggered fabrication (Cluster 22 overlap)
|
|
27
|
+
#
|
|
28
|
+
# This hook is a PreToolUse hook on Bash that:
|
|
29
|
+
# - Matches the echo-probe spam shapes (echo s\d+, echo with one-char
|
|
30
|
+
# trivial arg, sleep N; echo *)
|
|
31
|
+
# - Tracks consecutive probe-shaped commands per session
|
|
32
|
+
# - Warns on first probe-shaped command
|
|
33
|
+
# - Blocks (exit 2) on the third consecutive probe-shaped command
|
|
34
|
+
#
|
|
35
|
+
# The threshold-and-escalate shape is what works against compensation-
|
|
36
|
+
# routine bursts that are not stopped by warnings alone — the model needs
|
|
37
|
+
# to be forced to re-evaluate, not just nudged.
|
|
38
|
+
#
|
|
39
|
+
# When this hook does NOT block:
|
|
40
|
+
# - CC_ECHO_PROBE_DISABLE=1 — never warn or block
|
|
41
|
+
# - CC_ECHO_PROBE_QUIET=1 — silent (no stderr output)
|
|
42
|
+
# - CC_ECHO_PROBE_THRESHOLD=N — block after N consecutive (default 3)
|
|
43
|
+
# - the Bash command is not probe-shaped — exit 0
|
|
44
|
+
# - the operator has reset the counter via `# RESET ECHO PROBE` echo comment
|
|
45
|
+
#
|
|
46
|
+
# Hook config (settings.json):
|
|
47
|
+
# {
|
|
48
|
+
# "hooks": {
|
|
49
|
+
# "PreToolUse": [{
|
|
50
|
+
# "matcher": "Bash",
|
|
51
|
+
# "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/echo-probe-spam-detector.sh" }]
|
|
52
|
+
# }]
|
|
53
|
+
# }
|
|
54
|
+
# }
|
|
55
|
+
#
|
|
56
|
+
# Env vars:
|
|
57
|
+
# CC_ECHO_PROBE_DISABLE=1 — never warn or block
|
|
58
|
+
# CC_ECHO_PROBE_QUIET=1 — silent (process but never write to stderr)
|
|
59
|
+
# CC_ECHO_PROBE_THRESHOLD=N — block at N consecutive probes (default 3)
|
|
60
|
+
|
|
61
|
+
set -u
|
|
62
|
+
|
|
63
|
+
if [ "${CC_ECHO_PROBE_DISABLE:-}" = "1" ]; then
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
THRESHOLD="${CC_ECHO_PROBE_THRESHOLD:-3}"
|
|
68
|
+
STATE_DIR="${TMPDIR:-/tmp}/cc-echo-probe-spam-detector"
|
|
69
|
+
mkdir -p "$STATE_DIR"
|
|
70
|
+
SESSION_ID="${CLAUDE_SESSION_ID:-default}"
|
|
71
|
+
COUNTER_FILE="$STATE_DIR/${SESSION_ID}.counter"
|
|
72
|
+
|
|
73
|
+
INPUT=$(cat 2>/dev/null || true)
|
|
74
|
+
CMD=""
|
|
75
|
+
if command -v jq >/dev/null 2>&1 && [ -n "$INPUT" ]; then
|
|
76
|
+
CMD=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null || true)
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
if [ -z "$CMD" ]; then
|
|
80
|
+
exit 0
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Strip leading/trailing whitespace
|
|
84
|
+
CMD_TRIM=$(printf '%s' "$CMD" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
85
|
+
|
|
86
|
+
# Detect probe shapes:
|
|
87
|
+
# 1. "echo s\d+" — the canonical #63887 burst pattern
|
|
88
|
+
# 2. "echo <1-3 chars>" — generic short throwaway
|
|
89
|
+
# 3. "sleep <N>; echo *" — wrapped flush attempt
|
|
90
|
+
is_probe_shape() {
|
|
91
|
+
local c="$1"
|
|
92
|
+
# echo s\d+ pattern (s followed by digits, no other args)
|
|
93
|
+
if printf '%s\n' "$c" | grep -Eq '^echo[[:space:]]+s[0-9]+[[:space:]]*$'; then
|
|
94
|
+
return 0
|
|
95
|
+
fi
|
|
96
|
+
# echo <very short single arg> pattern (1-3 chars, no special meaning)
|
|
97
|
+
if printf '%s\n' "$c" | grep -Eq '^echo[[:space:]]+[a-zA-Z0-9._-]{1,3}[[:space:]]*$'; then
|
|
98
|
+
return 0
|
|
99
|
+
fi
|
|
100
|
+
# sleep N; echo ... pattern
|
|
101
|
+
if printf '%s\n' "$c" | grep -Eq '^sleep[[:space:]]+[0-9.]+[[:space:]]*;[[:space:]]*echo[[:space:]]'; then
|
|
102
|
+
return 0
|
|
103
|
+
fi
|
|
104
|
+
return 1
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# Check for reset signal embedded in the command (operator override)
|
|
108
|
+
if printf '%s\n' "$CMD_TRIM" | grep -Eq '#[[:space:]]*RESET ECHO PROBE'; then
|
|
109
|
+
rm -f "$COUNTER_FILE"
|
|
110
|
+
exit 0
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
if ! is_probe_shape "$CMD_TRIM"; then
|
|
114
|
+
# Non-probe command resets the streak
|
|
115
|
+
rm -f "$COUNTER_FILE"
|
|
116
|
+
exit 0
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
# Probe-shaped: increment counter
|
|
120
|
+
CURRENT=0
|
|
121
|
+
if [ -f "$COUNTER_FILE" ]; then
|
|
122
|
+
CURRENT=$(cat "$COUNTER_FILE" 2>/dev/null || echo 0)
|
|
123
|
+
# Validate it's a number
|
|
124
|
+
case "$CURRENT" in
|
|
125
|
+
''|*[!0-9]*) CURRENT=0 ;;
|
|
126
|
+
esac
|
|
127
|
+
fi
|
|
128
|
+
CURRENT=$((CURRENT + 1))
|
|
129
|
+
printf '%d' "$CURRENT" > "$COUNTER_FILE"
|
|
130
|
+
|
|
131
|
+
if [ "${CC_ECHO_PROBE_QUIET:-}" = "1" ]; then
|
|
132
|
+
if [ "$CURRENT" -ge "$THRESHOLD" ]; then
|
|
133
|
+
exit 2
|
|
134
|
+
fi
|
|
135
|
+
exit 0
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
if [ "$CURRENT" -ge "$THRESHOLD" ]; then
|
|
139
|
+
cat >&2 <<EOF
|
|
140
|
+
|
|
141
|
+
BLOCKED: This is the ${CURRENT}th consecutive echo-probe-shaped Bash command.
|
|
142
|
+
|
|
143
|
+
Pattern detected: Opus 4.8 emits bursts of "echo s1, echo s2, ..." or
|
|
144
|
+
"sleep N; echo x" to flush suspected buffered output. This is Cluster 25
|
|
145
|
+
axis 25B — a compensation routine for tool-result delivery delay that
|
|
146
|
+
burns tokens without doing user-visible work.
|
|
147
|
+
|
|
148
|
+
What to do instead:
|
|
149
|
+
- If you genuinely need to flush output: run the real command once and
|
|
150
|
+
wait for its result; tolerate shell latency.
|
|
151
|
+
- If you are waiting on async work: use a single backgrounded command
|
|
152
|
+
with a real completion signal — never a burst of no-op echoes.
|
|
153
|
+
- If the tool-result really did come back empty: verify via side effect
|
|
154
|
+
(git log, ls, etc.) rather than retrying or probing.
|
|
155
|
+
|
|
156
|
+
Background: gist.github.com/yurukusa/5881286479969d5bac0323511dc33ab2
|
|
157
|
+
Anchor issue: github.com/anthropics/claude-code/issues/63887
|
|
158
|
+
|
|
159
|
+
To override this block once: include "# RESET ECHO PROBE" in the next command.
|
|
160
|
+
To disable: export CC_ECHO_PROBE_DISABLE=1
|
|
161
|
+
To adjust threshold: export CC_ECHO_PROBE_THRESHOLD=N (default 3)
|
|
162
|
+
|
|
163
|
+
EOF
|
|
164
|
+
exit 2
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
cat >&2 <<EOF
|
|
168
|
+
|
|
169
|
+
NOTICE: Detected echo-probe-shaped Bash command (${CURRENT}/${THRESHOLD}).
|
|
170
|
+
This shape (echo s\d+ / short single-arg echo / sleep; echo) is the
|
|
171
|
+
Cluster 25 axis 25B compensation routine. Will block at ${THRESHOLD}
|
|
172
|
+
consecutive occurrences. See gist 5881286479969d5bac0323511dc33ab2.
|
|
173
|
+
|
|
174
|
+
EOF
|
|
175
|
+
|
|
176
|
+
exit 0
|
|
@@ -14,6 +14,18 @@
|
|
|
14
14
|
|
|
15
15
|
set -euo pipefail
|
|
16
16
|
|
|
17
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
18
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
19
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
20
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
21
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
22
|
+
_nojq_warned="/tmp/cc-nojq-warned-edit-counter-test-gate-$PPID"
|
|
23
|
+
[ -f "$_nojq_warned" ] || {
|
|
24
|
+
echo "WARNING [edit-counter-test-gate]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
25
|
+
: > "$_nojq_warned"
|
|
26
|
+
}
|
|
27
|
+
fi
|
|
28
|
+
|
|
17
29
|
INPUT=$(cat)
|
|
18
30
|
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
19
31
|
MAX_EDITS="${CC_MAX_EDITS_BEFORE_TEST:-3}"
|