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,124 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# aup-false-positive-helper.sh — Surface the AUP false-positive cluster awareness when Opus models are pinned
|
|
3
|
+
#
|
|
4
|
+
# Background:
|
|
5
|
+
# Starting mid-May 2026 (acceleration peak 2026-05-21 through 2026-05-27), the Anthropic
|
|
6
|
+
# server-side Usage Policy classifier began over-triggering on benign Claude Code prompts.
|
|
7
|
+
# GitHub issue tracker accumulated 25+ open reports in 10 days from independent users:
|
|
8
|
+
# - #60366 (16r): single-word "hi" greeting blocked
|
|
9
|
+
# - #62190 (10r): non-deterministic blocks on greetings, coding, "ok"/"yes"
|
|
10
|
+
# - #61056 (4r), #61638 (3r), #61185 (2r), and 20+ low-reaction reports
|
|
11
|
+
# github-actions[bot] auto-flagged at least three duplicate chains, confirming the
|
|
12
|
+
# shape of the cluster at Anthropic's own intake.
|
|
13
|
+
#
|
|
14
|
+
# Independent reports converge on a clear signature:
|
|
15
|
+
# - Affected: Opus 4.7, Opus 4.6, Opus 1M context variants
|
|
16
|
+
# - Unaffected: Sonnet 4.6, Sonnet 4.7
|
|
17
|
+
# - Languages: false positives observed on English, Russian, Polish, and Spanish
|
|
18
|
+
# - Domains: kernel security audits, biomedical research, FPGA waveform analysis,
|
|
19
|
+
# compression algorithm work, and plain greetings — context-independent
|
|
20
|
+
# - Behavior: non-deterministic on identical input (same prompt blocks one minute,
|
|
21
|
+
# passes the next), strongly indicating an unstable classifier rather than the
|
|
22
|
+
# prompt being the cause
|
|
23
|
+
#
|
|
24
|
+
# The block surfaces as one of two stock error strings:
|
|
25
|
+
# "API Error: Claude Code is unable to respond to this request, which appears to
|
|
26
|
+
# violate our Usage Policy (...). This request triggered cyber-related safeguards."
|
|
27
|
+
# or:
|
|
28
|
+
# "This request triggered safety guardrails. Rephrase your prompt or rewind to continue."
|
|
29
|
+
#
|
|
30
|
+
# This is a server-side defect; there is no client-side fix. The hook exists to surface
|
|
31
|
+
# the four operator-side workarounds when a user is most likely to hit the block (Opus
|
|
32
|
+
# pinned, false-positive flood window still active).
|
|
33
|
+
#
|
|
34
|
+
# Reference: https://gist.github.com/yurukusa/4fa4751044be45bd83345601ee79c2db (4 operator-side paths through the
|
|
35
|
+
# false-positive flood — model swap, prompt warmup, CVP application, retry harness)
|
|
36
|
+
#
|
|
37
|
+
# What this hook does:
|
|
38
|
+
# On SessionStart, inspect ANTHROPIC_MODEL and emit a one-line advisory matching one
|
|
39
|
+
# of four states:
|
|
40
|
+
# - ANTHROPIC_MODEL unset → silent (default routing)
|
|
41
|
+
# - ANTHROPIC_MODEL pinned to a Sonnet variant → silent (unaffected model)
|
|
42
|
+
# - ANTHROPIC_MODEL pinned to an Opus variant + CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1
|
|
43
|
+
# → emit one-time advisory
|
|
44
|
+
# - ANTHROPIC_MODEL pinned to an Opus variant + REMIND unset
|
|
45
|
+
# → silent (opt-in only)
|
|
46
|
+
#
|
|
47
|
+
# Silent by default. CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 opts in to the awareness
|
|
48
|
+
# note. CC_AUP_FALSE_POSITIVE_HELPER_QUIET=1 suppresses permanently after acknowledgement.
|
|
49
|
+
#
|
|
50
|
+
# When this hook does NOT fire a warning:
|
|
51
|
+
# - CC_AUP_FALSE_POSITIVE_HELPER_QUIET=1
|
|
52
|
+
# - ANTHROPIC_MODEL is unset or pinned to a non-Opus model
|
|
53
|
+
# - CC_AUP_FALSE_POSITIVE_HELPER_REMIND is unset (opt-in only)
|
|
54
|
+
#
|
|
55
|
+
# Hook config (settings.json):
|
|
56
|
+
# {
|
|
57
|
+
# "hooks": {
|
|
58
|
+
# "SessionStart": [{
|
|
59
|
+
# "matcher": "",
|
|
60
|
+
# "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/aup-false-positive-helper.sh" }]
|
|
61
|
+
# }]
|
|
62
|
+
# }
|
|
63
|
+
# }
|
|
64
|
+
#
|
|
65
|
+
# Env vars:
|
|
66
|
+
# CC_AUP_FALSE_POSITIVE_HELPER_QUIET=1 — never emit anything
|
|
67
|
+
# CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 — emit advisory when Opus is pinned (opt-in)
|
|
68
|
+
|
|
69
|
+
# Silence path
|
|
70
|
+
if [ "${CC_AUP_FALSE_POSITIVE_HELPER_QUIET:-0}" = "1" ]; then
|
|
71
|
+
exit 0
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# Model unset → use default routing, no specific advisory needed
|
|
75
|
+
if [ -z "${ANTHROPIC_MODEL:-}" ]; then
|
|
76
|
+
exit 0
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Pinned to a model that is NOT an Opus variant → unaffected by the cluster
|
|
80
|
+
case "$ANTHROPIC_MODEL" in
|
|
81
|
+
*opus*|*Opus*|*OPUS*) : ;; # Opus variant — continue to advisory
|
|
82
|
+
*) exit 0 ;; # Sonnet, Haiku, or other — silent
|
|
83
|
+
esac
|
|
84
|
+
|
|
85
|
+
# Opt-in gate: only emit when the user explicitly requested awareness
|
|
86
|
+
if [ "${CC_AUP_FALSE_POSITIVE_HELPER_REMIND:-0}" != "1" ]; then
|
|
87
|
+
exit 0
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# Opt-in advisory path: ANTHROPIC_MODEL pinned to Opus, user wants the awareness note
|
|
91
|
+
cat >&2 <<EOF
|
|
92
|
+
[aup-false-positive-helper] ANTHROPIC_MODEL is pinned to "$ANTHROPIC_MODEL".
|
|
93
|
+
|
|
94
|
+
Between 2026-05-18 and the current session window, the Anthropic Usage Policy classifier
|
|
95
|
+
has over-triggered on benign prompts when Opus models (4.7, 4.6, 1M variants) are pinned.
|
|
96
|
+
Sonnet variants are reportedly unaffected. The block surfaces as:
|
|
97
|
+
|
|
98
|
+
"API Error: ... This request triggered cyber-related safeguards."
|
|
99
|
+
|
|
100
|
+
Four operator-side mitigations while the server-side classifier remains unstable:
|
|
101
|
+
|
|
102
|
+
1. Swap to Sonnet for sensitive sessions
|
|
103
|
+
export ANTHROPIC_MODEL=claude-sonnet-4-7
|
|
104
|
+
(or any Sonnet variant; the cluster signature points to an Opus-specific path)
|
|
105
|
+
|
|
106
|
+
2. Warm up the session with project context before security/kernel/research prompts
|
|
107
|
+
A short context-establishing turn often passes where a cold sensitive prompt blocks
|
|
108
|
+
|
|
109
|
+
3. Apply for the Cyber Verification Program (CVP) if your work routinely involves
|
|
110
|
+
legitimate cyber/kernel/biomedical/FPGA terminology
|
|
111
|
+
https://www.anthropic.com/legal/cyber-verification-program
|
|
112
|
+
|
|
113
|
+
4. The classifier is non-deterministic — a single retry on identical input frequently
|
|
114
|
+
succeeds. If a benign prompt blocks once, retry before rewording
|
|
115
|
+
|
|
116
|
+
To suppress this advisory:
|
|
117
|
+
export CC_AUP_FALSE_POSITIVE_HELPER_QUIET=1
|
|
118
|
+
|
|
119
|
+
GitHub tracker (25+ independent reports, 2026-05-18 through 2026-05-27):
|
|
120
|
+
https://github.com/anthropics/claude-code/issues/60366
|
|
121
|
+
https://github.com/anthropics/claude-code/issues/62190
|
|
122
|
+
EOF
|
|
123
|
+
|
|
124
|
+
exit 0
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# aup-large-tool-output-warner.sh — Warn before Bash commands that may produce large
|
|
3
|
+
# sensitive-looking outputs that can trigger the Cluster 9 Usage Policy classifier
|
|
4
|
+
#
|
|
5
|
+
# Background:
|
|
6
|
+
# Cluster 9 (Usage Policy classifier over-trigger) has a known trigger surface that
|
|
7
|
+
# the first four defense hooks do not address: a single tool result containing a
|
|
8
|
+
# large volume of security-shaped content (IP blocklists, firewall rules, packet
|
|
9
|
+
# captures, kernel log dumps) can flip the classifier even when the surrounding
|
|
10
|
+
# conversation is unambiguously benign.
|
|
11
|
+
#
|
|
12
|
+
# Direct evidence from issue #61185 (filipghoulin, 2026-05-23):
|
|
13
|
+
# "What triggered it: A lab-review skill dispatched a sub-agent that ran
|
|
14
|
+
# `cat /etc/banip/banip.blocklist` on an OpenWRT router. The blocklist has
|
|
15
|
+
# ~17,000 entries. That volume of content in a single tool result, combined
|
|
16
|
+
# with the security shape of the content, appears to have flipped the
|
|
17
|
+
# classifier into a permanent block state for the whole session."
|
|
18
|
+
#
|
|
19
|
+
# Reference: ~/ops/customer-pain-cluster-9-secondary-pains-2026-05-30.md (axis 4)
|
|
20
|
+
#
|
|
21
|
+
# The first three hooks address awareness, evidence collection, and session-start
|
|
22
|
+
# model swap. The fourth hook (aup-retry-loop-guard.sh) breaks intra-session retry
|
|
23
|
+
# cycles. None of them act *before* the offending tool call: by the time the
|
|
24
|
+
# classifier has fired on the large output, the session is already wedged and
|
|
25
|
+
# compact / clear may themselves block (see #61185 k33bs report). The only place
|
|
26
|
+
# to address this trigger surface is the PreToolUse boundary.
|
|
27
|
+
#
|
|
28
|
+
# What this hook does:
|
|
29
|
+
# On PreToolUse for the Bash tool, parse the proposed command. When the command
|
|
30
|
+
# shape matches one of the five well-known large-output patterns AND the path or
|
|
31
|
+
# command target carries a security-shaped sentinel (blocklist, firewall, iptables,
|
|
32
|
+
# denylist, allowlist, banlist, ipset, etc. — or sits under a known security path
|
|
33
|
+
# like /etc/banip/, /var/log/, /proc/net/), emit a non-blocking stderr advisory
|
|
34
|
+
# recommending a narrower variant.
|
|
35
|
+
#
|
|
36
|
+
# The hook never blocks the command. Exit is always 0. The advisory is informational
|
|
37
|
+
# — the operator can ignore it and continue. The point is to put the recommendation
|
|
38
|
+
# in front of the operator BEFORE the large output exists, not after the session is
|
|
39
|
+
# already wedged.
|
|
40
|
+
#
|
|
41
|
+
# Detection categories (intentionally narrow to keep false-positive rate low):
|
|
42
|
+
# A) `cat <path>` where path is under /etc/banip/, /var/log/, or ends in .blocklist
|
|
43
|
+
# / .denylist / .allowlist / .banlist / .iplist / .firewall / iptables-save
|
|
44
|
+
# B) `find <broad_path>` without `head`, `tail`, `-print -quit`, or `-quit`
|
|
45
|
+
# (broad recursion on security-shaped paths)
|
|
46
|
+
# C) `journalctl` without `-n`, `--lines`, or `--since` (full system log dump)
|
|
47
|
+
# D) `dmesg` without a pipe to head/tail/wc/grep with a follow-up size cap
|
|
48
|
+
# E) `grep -r` / `grep -R` on a security-shaped path without a pipe to head/tail
|
|
49
|
+
#
|
|
50
|
+
# Plus a separate strong-signal path: ANY command (Bash or otherwise) whose
|
|
51
|
+
# argument string contains a sentinel substring from a curated security-content
|
|
52
|
+
# wordlist gets a sentinel-only advisory, on top of the category match.
|
|
53
|
+
#
|
|
54
|
+
# When this hook does NOT emit anything:
|
|
55
|
+
# - CC_AUP_LARGE_OUTPUT_WARNER_DISABLE=1
|
|
56
|
+
# - CC_AUP_LARGE_OUTPUT_WARNER_QUIET=1
|
|
57
|
+
# - tool_name is not "Bash" (other tools are not parsed by this hook)
|
|
58
|
+
# - command is missing, empty, or unreadable
|
|
59
|
+
# - command already includes a size-cap pipe (head, tail, -n NNN, etc.)
|
|
60
|
+
# - the same command pattern already fired an advisory in this session
|
|
61
|
+
#
|
|
62
|
+
# Hook config (settings.json):
|
|
63
|
+
# {
|
|
64
|
+
# "hooks": {
|
|
65
|
+
# "PreToolUse": [{
|
|
66
|
+
# "matcher": "Bash",
|
|
67
|
+
# "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/aup-large-tool-output-warner.sh" }]
|
|
68
|
+
# }]
|
|
69
|
+
# }
|
|
70
|
+
# }
|
|
71
|
+
#
|
|
72
|
+
# Env vars:
|
|
73
|
+
# CC_AUP_LARGE_OUTPUT_WARNER_DISABLE=1 — never emit
|
|
74
|
+
# CC_AUP_LARGE_OUTPUT_WARNER_QUIET=1 — silent
|
|
75
|
+
# CC_AUP_LARGE_OUTPUT_WARNER_STATE_DIR=<p> — one-shot state dir (default $HOME/.claude)
|
|
76
|
+
# CC_AUP_LARGE_OUTPUT_WARNER_SESSION_ID=<id> — session id override (tests / automation)
|
|
77
|
+
#
|
|
78
|
+
# Design notes:
|
|
79
|
+
# - PreToolUse only. The classifier fires on the *output* of the tool call, so by
|
|
80
|
+
# the time PostToolUse runs the damage is done. The advisory has to land before
|
|
81
|
+
# the command executes.
|
|
82
|
+
# - Never blocks. The hook recommends a narrower variant but the operator may have
|
|
83
|
+
# a legitimate reason for the full output (audit, evidence collection, etc.).
|
|
84
|
+
# - One-shot per (session, pattern_hash). If the operator runs `cat
|
|
85
|
+
# /etc/banip/banip.blocklist` three times in a session, only the first call
|
|
86
|
+
# triggers the advisory. This prevents the hook from becoming its own noise loop.
|
|
87
|
+
# - Conservative category set. Five patterns rather than fifteen. A false positive
|
|
88
|
+
# here doesn't break anything (the command still runs), but it does add cognitive
|
|
89
|
+
# load. The set covers #61185's pattern plus the four closest neighbors from
|
|
90
|
+
# #60366's comment chain.
|
|
91
|
+
# - Sentinel wordlist is the high-confidence path. When the command target itself
|
|
92
|
+
# contains "blocklist" / "iptables-save" / etc., the advisory fires even if the
|
|
93
|
+
# command shape isn't on the five-category list — because the sentinel itself
|
|
94
|
+
# carries the cluster-9 trigger signature regardless of how the file is read.
|
|
95
|
+
|
|
96
|
+
set -u
|
|
97
|
+
|
|
98
|
+
# Disable path
|
|
99
|
+
if [ "${CC_AUP_LARGE_OUTPUT_WARNER_DISABLE:-0}" = "1" ]; then
|
|
100
|
+
exit 0
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# Quiet path
|
|
104
|
+
if [ "${CC_AUP_LARGE_OUTPUT_WARNER_QUIET:-0}" = "1" ]; then
|
|
105
|
+
exit 0
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# Read PreToolUse JSON payload from stdin
|
|
109
|
+
INPUT=$(cat 2>/dev/null) || exit 0
|
|
110
|
+
[ -n "$INPUT" ] || exit 0
|
|
111
|
+
|
|
112
|
+
# Parse tool_name and command via jq when available; fall back to grep heuristics.
|
|
113
|
+
TOOL_NAME=""
|
|
114
|
+
COMMAND=""
|
|
115
|
+
if command -v jq >/dev/null 2>&1; then
|
|
116
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
117
|
+
COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
118
|
+
else
|
|
119
|
+
# Best-effort fallback when jq is unavailable. Match "tool_name": "Bash" and
|
|
120
|
+
# "command": "..." in the JSON payload. This is intentionally lenient — the
|
|
121
|
+
# detection categories below double-check the command shape.
|
|
122
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | grep -oE '"tool_name"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed -E 's/.*"tool_name"[[:space:]]*:[[:space:]]*"([^"]*)".*/\1/')
|
|
123
|
+
COMMAND=$(printf '%s' "$INPUT" | grep -oE '"command"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed -E 's/.*"command"[[:space:]]*:[[:space:]]*"([^"]*)".*/\1/')
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# Only act on Bash
|
|
127
|
+
[ "$TOOL_NAME" = "Bash" ] || exit 0
|
|
128
|
+
[ -n "$COMMAND" ] || exit 0
|
|
129
|
+
|
|
130
|
+
# Skip if the command already has a size-cap somewhere in the pipeline.
|
|
131
|
+
# Common cap shapes: `| head -N`, `| tail -N`, `head -N <file>`, `tail -N <file>`,
|
|
132
|
+
# `find ... -print -quit`, `find ... -quit`, `journalctl -n N`, `journalctl --lines N`,
|
|
133
|
+
# `journalctl --since ...`, `grep ... | head`, `dmesg | head`, `wc -l`.
|
|
134
|
+
if printf '%s' "$COMMAND" | grep -qE '(\|[[:space:]]*head\b|\|[[:space:]]*tail\b|head[[:space:]]+-n[[:space:]]+[0-9]+|tail[[:space:]]+-n[[:space:]]+[0-9]+|head[[:space:]]+-[0-9]+|tail[[:space:]]+-[0-9]+|-print[[:space:]]+-quit\b|[[:space:]]-quit\b|--lines[[:space:]]+[0-9]+|[[:space:]]-n[[:space:]]+[0-9]+|--since\b|\|[[:space:]]*wc\b|^[[:space:]]*wc\b|^[[:space:]]*grep[[:space:]]+-c\b)'; then
|
|
135
|
+
exit 0
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
# Sentinel wordlist for security-shaped content. Case-insensitive substring match
|
|
139
|
+
# against the full command string. These are the substrings that, by themselves,
|
|
140
|
+
# strongly indicate the classifier will see the output as "security-shaped."
|
|
141
|
+
SENTINEL=""
|
|
142
|
+
case " $(printf '%s' "$COMMAND" | tr '[:upper:]' '[:lower:]') " in
|
|
143
|
+
*blocklist*) SENTINEL="blocklist" ;;
|
|
144
|
+
*denylist*) SENTINEL="denylist" ;;
|
|
145
|
+
*banlist*) SENTINEL="banlist" ;;
|
|
146
|
+
*iplist*) SENTINEL="iplist" ;;
|
|
147
|
+
*iptables-save*) SENTINEL="iptables-save" ;;
|
|
148
|
+
*ipset[[:space:]]save*) SENTINEL="ipset save" ;;
|
|
149
|
+
*/etc/banip/*) SENTINEL="/etc/banip/" ;;
|
|
150
|
+
*/etc/fail2ban/*) SENTINEL="/etc/fail2ban/" ;;
|
|
151
|
+
*/var/log/auth*) SENTINEL="/var/log/auth*" ;;
|
|
152
|
+
*/var/log/secure*) SENTINEL="/var/log/secure*" ;;
|
|
153
|
+
*firewall.conf*) SENTINEL="firewall.conf" ;;
|
|
154
|
+
esac
|
|
155
|
+
|
|
156
|
+
# Category match. Even without a sentinel, the following shapes are likely to
|
|
157
|
+
# produce large outputs that look security-shaped to the classifier.
|
|
158
|
+
CATEGORY=""
|
|
159
|
+
CATEGORY_DESC=""
|
|
160
|
+
if printf '%s' "$COMMAND" | grep -qE '^[[:space:]]*cat[[:space:]]+(/etc/banip/|/var/log/|/proc/net/)'; then
|
|
161
|
+
CATEGORY="A"
|
|
162
|
+
CATEGORY_DESC="cat on a security-shaped system path"
|
|
163
|
+
elif printf '%s' "$COMMAND" | grep -qE '^[[:space:]]*cat[[:space:]]+[^|]*\.(blocklist|denylist|allowlist|banlist|iplist|firewall)([[:space:]]|$)'; then
|
|
164
|
+
CATEGORY="A"
|
|
165
|
+
CATEGORY_DESC="cat on a security-shaped file extension"
|
|
166
|
+
elif printf '%s' "$COMMAND" | grep -qE '(^|[[:space:];&|])find[[:space:]]+(/etc/banip/|/var/log/|/proc/net/|/etc/fail2ban/)'; then
|
|
167
|
+
CATEGORY="B"
|
|
168
|
+
CATEGORY_DESC="find recursing under a security-shaped path"
|
|
169
|
+
elif printf '%s' "$COMMAND" | grep -qE '(^|[[:space:];&|])journalctl([[:space:]]|$)'; then
|
|
170
|
+
CATEGORY="C"
|
|
171
|
+
CATEGORY_DESC="journalctl without a line/since cap"
|
|
172
|
+
elif printf '%s' "$COMMAND" | grep -qE '(^|[[:space:];&|])dmesg([[:space:]]|$)'; then
|
|
173
|
+
CATEGORY="D"
|
|
174
|
+
CATEGORY_DESC="dmesg without a size cap"
|
|
175
|
+
elif printf '%s' "$COMMAND" | grep -qE '(^|[[:space:];&|])grep[[:space:]]+(-r|-R|--recursive)[[:space:]]+(.*)(/etc/banip/|/var/log/|/proc/net/|/etc/fail2ban/)'; then
|
|
176
|
+
CATEGORY="E"
|
|
177
|
+
CATEGORY_DESC="grep -r/-R on a security-shaped path"
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
# If neither a sentinel nor a category match, the command is out of scope.
|
|
181
|
+
if [ -z "$SENTINEL" ] && [ -z "$CATEGORY" ]; then
|
|
182
|
+
exit 0
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
# One-shot per (session, pattern_hash). Pattern hash = first 40 chars of command
|
|
186
|
+
# stripped of timestamps and whitespace runs. This keeps the same pattern from
|
|
187
|
+
# firing twice in a row (e.g. operator runs the same cat three times) while still
|
|
188
|
+
# allowing a different pattern (cat foo.blocklist vs cat bar.denylist) to fire.
|
|
189
|
+
STATE_DIR="${CC_AUP_LARGE_OUTPUT_WARNER_STATE_DIR:-$HOME/.claude}"
|
|
190
|
+
mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
|
|
191
|
+
STATE_FILE="$STATE_DIR/aup-large-tool-output-warner.fired"
|
|
192
|
+
|
|
193
|
+
SESSION_ID="${CC_AUP_LARGE_OUTPUT_WARNER_SESSION_ID:-}"
|
|
194
|
+
if [ -z "$SESSION_ID" ]; then
|
|
195
|
+
SESSION_ID="${CLAUDECODE_SESSION_ID:-}"
|
|
196
|
+
fi
|
|
197
|
+
if [ -z "$SESSION_ID" ] && command -v tty >/dev/null 2>&1; then
|
|
198
|
+
TTY_PATH=$(tty 2>/dev/null)
|
|
199
|
+
if [ -n "$TTY_PATH" ] && [ "$TTY_PATH" != "not a tty" ]; then
|
|
200
|
+
SESSION_ID=$(printf '%s' "$TTY_PATH" | tr '/' '_')
|
|
201
|
+
fi
|
|
202
|
+
fi
|
|
203
|
+
[ -n "$SESSION_ID" ] || SESSION_ID="ppid-${PPID:-0}"
|
|
204
|
+
|
|
205
|
+
# Pattern hash: collapse whitespace, take first 60 chars.
|
|
206
|
+
PATTERN_HASH=$(printf '%s' "$COMMAND" | tr -s '[:space:]' ' ' | cut -c1-60 | tr ' /' '__')
|
|
207
|
+
FIRED_KEY="${SESSION_ID}::${PATTERN_HASH}"
|
|
208
|
+
|
|
209
|
+
if [ -f "$STATE_FILE" ] && grep -Fq -- "$FIRED_KEY" "$STATE_FILE" 2>/dev/null; then
|
|
210
|
+
exit 0
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
# Bound the state file to ~100 lines to avoid unbounded growth.
|
|
214
|
+
if [ -f "$STATE_FILE" ]; then
|
|
215
|
+
tail -n 100 "$STATE_FILE" > "${STATE_FILE}.tmp" 2>/dev/null \
|
|
216
|
+
&& mv "${STATE_FILE}.tmp" "$STATE_FILE" 2>/dev/null || true
|
|
217
|
+
fi
|
|
218
|
+
printf '%s\n' "$FIRED_KEY" >> "$STATE_FILE" 2>/dev/null || true
|
|
219
|
+
|
|
220
|
+
# Compose the advisory.
|
|
221
|
+
ADVISORY_REASON=""
|
|
222
|
+
if [ -n "$SENTINEL" ] && [ -n "$CATEGORY" ]; then
|
|
223
|
+
ADVISORY_REASON="security-content sentinel \"$SENTINEL\" + $CATEGORY_DESC"
|
|
224
|
+
elif [ -n "$SENTINEL" ]; then
|
|
225
|
+
ADVISORY_REASON="security-content sentinel \"$SENTINEL\" in the command"
|
|
226
|
+
else
|
|
227
|
+
ADVISORY_REASON="$CATEGORY_DESC"
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
# Trim command excerpt for the advisory (avoid dumping a 500-char one-liner).
|
|
231
|
+
CMD_EXCERPT=$(printf '%s' "$COMMAND" | cut -c1-120)
|
|
232
|
+
if [ "${#COMMAND}" -gt 120 ]; then
|
|
233
|
+
CMD_EXCERPT="${CMD_EXCERPT}..."
|
|
234
|
+
fi
|
|
235
|
+
|
|
236
|
+
cat >&2 <<EOF
|
|
237
|
+
[aup-large-tool-output-warner] About to run a Bash command that may produce a
|
|
238
|
+
large security-shaped output. Trigger: $ADVISORY_REASON.
|
|
239
|
+
|
|
240
|
+
Command excerpt:
|
|
241
|
+
$CMD_EXCERPT
|
|
242
|
+
|
|
243
|
+
Why this matters:
|
|
244
|
+
Cluster 9 (Usage Policy classifier over-trigger) has fired on tool results
|
|
245
|
+
carrying high-volume security-shaped content even when the surrounding
|
|
246
|
+
conversation is benign. Issue #61185 documents a session-wedging block
|
|
247
|
+
triggered by a single \`cat /etc/banip/banip.blocklist\` returning ~17,000
|
|
248
|
+
IP entries — after which /compact and /clear also blocked, leaving no
|
|
249
|
+
recovery path within the session.
|
|
250
|
+
|
|
251
|
+
The command is NOT being blocked. This is an advisory only — the operator may
|
|
252
|
+
have a legitimate reason for the full output (audit trail, evidence package,
|
|
253
|
+
forensics). If a summary is sufficient, narrower variants reduce the trigger
|
|
254
|
+
surface without losing the answer:
|
|
255
|
+
|
|
256
|
+
Line count only: wc -l <path>
|
|
257
|
+
First N lines: head -200 <path>
|
|
258
|
+
Last N lines: tail -200 <path>
|
|
259
|
+
Matching subset: grep -c <pattern> <path> (count only)
|
|
260
|
+
grep -E <pattern> <path> | head -200
|
|
261
|
+
journalctl: journalctl --since "1 hour ago" -n 200
|
|
262
|
+
find: find <path> -type f | head -200
|
|
263
|
+
dmesg: dmesg | tail -200
|
|
264
|
+
|
|
265
|
+
For multi-thousand-entry blocklists, prefer the count + a sampled head/tail
|
|
266
|
+
over the full dump.
|
|
267
|
+
|
|
268
|
+
To silence this advisory for the current session only:
|
|
269
|
+
export CC_AUP_LARGE_OUTPUT_WARNER_QUIET=1
|
|
270
|
+
|
|
271
|
+
Related hooks (already active in this defense suite):
|
|
272
|
+
aup-false-positive-helper.sh — SessionStart awareness, 4 operator-side options
|
|
273
|
+
aup-block-pattern-logger.sh — PostToolUse evidence collection
|
|
274
|
+
aup-retry-loop-guard.sh — PostToolUse intra-session retry breaker
|
|
275
|
+
model-swap-suggester.sh — SessionStart cross-session swap recommendation
|
|
276
|
+
|
|
277
|
+
GitHub references:
|
|
278
|
+
https://github.com/anthropics/claude-code/issues/60366 (cluster anchor)
|
|
279
|
+
https://github.com/anthropics/claude-code/issues/61185 (large-output trigger)
|
|
280
|
+
EOF
|
|
281
|
+
|
|
282
|
+
exit 0
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# aup-retry-loop-guard.sh — Detect retry-loop pattern during Cluster 9 blocks and recommend exit
|
|
3
|
+
#
|
|
4
|
+
# Background:
|
|
5
|
+
# Cluster 9 (Usage Policy classifier over-trigger) has a secondary failure mode that the
|
|
6
|
+
# first three defense hooks do not address: even when an operator has been blocked and is
|
|
7
|
+
# actively retrying the same input (the non-deterministic classifier sometimes passes on
|
|
8
|
+
# retry — see #60366, #62190), each retry burns transcript context. For paying users on
|
|
9
|
+
# Pro / Max quota, the retry loop drains the daily quota faster than the productive work
|
|
10
|
+
# would have, leading to the "session quota MAX reached early" symptom.
|
|
11
|
+
#
|
|
12
|
+
# Direct evidence from issue #61664 (Japanese paid user, 2026-05-23):
|
|
13
|
+
# "ブロック発生時も context/credit は消費される"
|
|
14
|
+
# "ブロック→巻き戻し→同じ処理の再実行 で context を浪費"
|
|
15
|
+
# "昨日まで丸 1 日使っても使用量上限に達しなかったが、本日は早々に MAX に到達"
|
|
16
|
+
#
|
|
17
|
+
# The first three hooks address awareness (helper), evidence collection (logger), and
|
|
18
|
+
# session-start swap recommendations (suggester). None of them break a retry loop that
|
|
19
|
+
# is already in progress within a single session.
|
|
20
|
+
#
|
|
21
|
+
# Reference: ~/ops/customer-pain-cluster-9-secondary-pains-2026-05-30.md (axis 1)
|
|
22
|
+
#
|
|
23
|
+
# What this hook does:
|
|
24
|
+
# On PostToolUse, read the aup-block-history.log (written by aup-block-pattern-logger.sh)
|
|
25
|
+
# and check whether the last N blocks within a short window (default 5 minutes) all
|
|
26
|
+
# targeted the same tool. When that pattern is detected, emit a non-blocking stderr
|
|
27
|
+
# advisory recommending one of two cycle-breaking actions:
|
|
28
|
+
# - `/exit` to end the session before more context is burned, then restart with Sonnet
|
|
29
|
+
# - immediate `export ANTHROPIC_MODEL=claude-sonnet-4-7` for the current session
|
|
30
|
+
#
|
|
31
|
+
# Distinct from model-swap-suggester (SessionStart, 60-min window): retry-loop-guard
|
|
32
|
+
# runs PostToolUse, looks at a 5-min window, and addresses the intra-session retry
|
|
33
|
+
# cycle that burns context — not the cross-session model selection decision.
|
|
34
|
+
#
|
|
35
|
+
# When this hook does NOT emit anything:
|
|
36
|
+
# - CC_AUP_RETRY_LOOP_GUARD_DISABLE=1
|
|
37
|
+
# - CC_AUP_RETRY_LOOP_GUARD_QUIET=1
|
|
38
|
+
# - aup-block log missing, empty, or unreadable
|
|
39
|
+
# - Fewer than threshold blocks in the configured window
|
|
40
|
+
# - Blocks in window span multiple tools (single-tool retry loop is the diagnostic signal)
|
|
41
|
+
# - The current advisory has already fired within the same session (one-shot per session)
|
|
42
|
+
#
|
|
43
|
+
# Hook config (settings.json):
|
|
44
|
+
# {
|
|
45
|
+
# "hooks": {
|
|
46
|
+
# "PostToolUse": [{
|
|
47
|
+
# "matcher": "",
|
|
48
|
+
# "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/aup-retry-loop-guard.sh" }]
|
|
49
|
+
# }]
|
|
50
|
+
# }
|
|
51
|
+
# }
|
|
52
|
+
#
|
|
53
|
+
# Env vars:
|
|
54
|
+
# CC_AUP_RETRY_LOOP_GUARD_DISABLE=1 — never emit
|
|
55
|
+
# CC_AUP_RETRY_LOOP_GUARD_QUIET=1 — silent
|
|
56
|
+
# CC_AUP_RETRY_LOOP_GUARD_THRESHOLD=<n> — block count threshold (default 3)
|
|
57
|
+
# CC_AUP_RETRY_LOOP_GUARD_WINDOW_MIN=<n> — lookback window in minutes (default 5)
|
|
58
|
+
# CC_AUP_RETRY_LOOP_GUARD_TARGET=<model> — target Sonnet model (default claude-sonnet-4-7)
|
|
59
|
+
# CC_AUP_RETRY_LOOP_GUARD_STATE_DIR=<path> — one-shot state directory (default $HOME/.claude)
|
|
60
|
+
# CC_AUP_RETRY_LOOP_GUARD_SESSION_ID=<id> — session identifier override for one-shot logic
|
|
61
|
+
# CC_AUP_BLOCK_LOG_PATH=<path> — log path (shared with logger; default $HOME/.claude/aup-block-history.log)
|
|
62
|
+
#
|
|
63
|
+
# Design notes:
|
|
64
|
+
# - Single-tool restriction: the diagnostic for a retry loop is "same tool, same kind, in
|
|
65
|
+
# a short window." A burst of blocks across different tools is more consistent with a
|
|
66
|
+
# general session sensitivity than a retry cycle, and breaking the session for the
|
|
67
|
+
# latter is more disruptive than helpful.
|
|
68
|
+
# - One-shot per session: the advisory fires at most once per session. The state file
|
|
69
|
+
# lives in $CC_AUP_RETRY_LOOP_GUARD_STATE_DIR/aup-retry-loop-guard.lock with the
|
|
70
|
+
# session PID. Subsequent invocations from the same session see the lock and stay
|
|
71
|
+
# silent so the advisory doesn't become its own noise loop.
|
|
72
|
+
# - Never blocks. All failure paths exit 0 — a corrupt log or missing date utility
|
|
73
|
+
# cannot break the tool call cycle.
|
|
74
|
+
|
|
75
|
+
set -u
|
|
76
|
+
|
|
77
|
+
# Disable path
|
|
78
|
+
if [ "${CC_AUP_RETRY_LOOP_GUARD_DISABLE:-0}" = "1" ]; then
|
|
79
|
+
exit 0
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# Quiet path
|
|
83
|
+
if [ "${CC_AUP_RETRY_LOOP_GUARD_QUIET:-0}" = "1" ]; then
|
|
84
|
+
exit 0
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
LOG_PATH="${CC_AUP_BLOCK_LOG_PATH:-$HOME/.claude/aup-block-history.log}"
|
|
88
|
+
[ -f "$LOG_PATH" ] || exit 0
|
|
89
|
+
[ -r "$LOG_PATH" ] || exit 0
|
|
90
|
+
[ -s "$LOG_PATH" ] || exit 0
|
|
91
|
+
|
|
92
|
+
THRESHOLD="${CC_AUP_RETRY_LOOP_GUARD_THRESHOLD:-3}"
|
|
93
|
+
WINDOW_MIN="${CC_AUP_RETRY_LOOP_GUARD_WINDOW_MIN:-5}"
|
|
94
|
+
TARGET="${CC_AUP_RETRY_LOOP_GUARD_TARGET:-claude-sonnet-4-7}"
|
|
95
|
+
STATE_DIR="${CC_AUP_RETRY_LOOP_GUARD_STATE_DIR:-$HOME/.claude}"
|
|
96
|
+
|
|
97
|
+
case "$THRESHOLD" in
|
|
98
|
+
''|*[!0-9]*) THRESHOLD=3 ;;
|
|
99
|
+
esac
|
|
100
|
+
case "$WINDOW_MIN" in
|
|
101
|
+
''|*[!0-9]*) WINDOW_MIN=5 ;;
|
|
102
|
+
esac
|
|
103
|
+
|
|
104
|
+
NOW=$(date -u '+%s' 2>/dev/null) || exit 0
|
|
105
|
+
CUTOFF=$((NOW - WINDOW_MIN * 60))
|
|
106
|
+
|
|
107
|
+
ts_to_epoch() {
|
|
108
|
+
local ts="$1"
|
|
109
|
+
date -u -d "$ts" '+%s' 2>/dev/null \
|
|
110
|
+
|| date -j -u -f '%Y-%m-%dT%H:%M:%SZ' "$ts" '+%s' 2>/dev/null
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# Collect blocks in window. The log schema is:
|
|
114
|
+
# ISO8601_UTC | MODEL | TOOL | PATTERN_KIND | EXCERPT
|
|
115
|
+
# We track the tools that fired in the window. If all in-window blocks targeted the same
|
|
116
|
+
# tool and there are at least THRESHOLD of them, the pattern is a retry loop.
|
|
117
|
+
COUNT=0
|
|
118
|
+
UNIQUE_TOOLS=""
|
|
119
|
+
LAST_TOOL=""
|
|
120
|
+
LAST_KIND=""
|
|
121
|
+
while IFS='|' read -r LOG_TS _LOG_MODEL LOG_TOOL LOG_KIND _LOG_EXCERPT; do
|
|
122
|
+
[ -z "$LOG_TS" ] && continue
|
|
123
|
+
[ -z "$LOG_TOOL" ] && continue
|
|
124
|
+
LOG_EPOCH=$(ts_to_epoch "$LOG_TS")
|
|
125
|
+
[ -z "$LOG_EPOCH" ] && continue
|
|
126
|
+
case "$LOG_EPOCH" in
|
|
127
|
+
*[!0-9]*) continue ;;
|
|
128
|
+
esac
|
|
129
|
+
if [ "$LOG_EPOCH" -ge "$CUTOFF" ] 2>/dev/null; then
|
|
130
|
+
COUNT=$((COUNT + 1))
|
|
131
|
+
LAST_TOOL="$LOG_TOOL"
|
|
132
|
+
LAST_KIND="$LOG_KIND"
|
|
133
|
+
case "$UNIQUE_TOOLS" in
|
|
134
|
+
*"|$LOG_TOOL|"*) : ;;
|
|
135
|
+
*) UNIQUE_TOOLS="${UNIQUE_TOOLS}|${LOG_TOOL}|" ;;
|
|
136
|
+
esac
|
|
137
|
+
fi
|
|
138
|
+
done < "$LOG_PATH"
|
|
139
|
+
|
|
140
|
+
if [ "$COUNT" -lt "$THRESHOLD" ] 2>/dev/null; then
|
|
141
|
+
exit 0
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
# Count unique tools. Multi-tool bursts are not retry loops.
|
|
145
|
+
TOOL_COUNT=$(printf '%s' "$UNIQUE_TOOLS" | tr -cd '|' | wc -c)
|
|
146
|
+
TOOL_COUNT=$((TOOL_COUNT / 2))
|
|
147
|
+
if [ "$TOOL_COUNT" -ne 1 ] 2>/dev/null; then
|
|
148
|
+
exit 0
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# One-shot per session. Session identifier resolution, in order of preference:
|
|
152
|
+
# 1. CC_AUP_RETRY_LOOP_GUARD_SESSION_ID env var (explicit override; tests, automation)
|
|
153
|
+
# 2. CLAUDECODE_SESSION_ID env var (Claude Code may export this in the future)
|
|
154
|
+
# 3. Controlling tty path (stable across child shells in an interactive session)
|
|
155
|
+
# 4. PPID fallback (last resort; less stable across subshell hops)
|
|
156
|
+
SESSION_ID="${CC_AUP_RETRY_LOOP_GUARD_SESSION_ID:-}"
|
|
157
|
+
if [ -z "$SESSION_ID" ]; then
|
|
158
|
+
SESSION_ID="${CLAUDECODE_SESSION_ID:-}"
|
|
159
|
+
fi
|
|
160
|
+
if [ -z "$SESSION_ID" ] && command -v tty >/dev/null 2>&1; then
|
|
161
|
+
TTY_PATH=$(tty 2>/dev/null)
|
|
162
|
+
if [ -n "$TTY_PATH" ] && [ "$TTY_PATH" != "not a tty" ]; then
|
|
163
|
+
SESSION_ID=$(printf '%s' "$TTY_PATH" | tr '/' '_')
|
|
164
|
+
fi
|
|
165
|
+
fi
|
|
166
|
+
if [ -z "$SESSION_ID" ]; then
|
|
167
|
+
SESSION_ID="ppid-${PPID:-0}"
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
|
|
171
|
+
STATE_FILE="$STATE_DIR/aup-retry-loop-guard.lock"
|
|
172
|
+
|
|
173
|
+
if [ -f "$STATE_FILE" ]; then
|
|
174
|
+
PRIOR=$(cat "$STATE_FILE" 2>/dev/null | head -1)
|
|
175
|
+
if [ "$PRIOR" = "$SESSION_ID" ]; then
|
|
176
|
+
exit 0
|
|
177
|
+
fi
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
# Trim stale entries: keep only the most recent 10 session IDs to bound the file.
|
|
181
|
+
if [ -f "$STATE_FILE" ]; then
|
|
182
|
+
tail -n 10 "$STATE_FILE" > "${STATE_FILE}.tmp" 2>/dev/null \
|
|
183
|
+
&& mv "${STATE_FILE}.tmp" "$STATE_FILE" 2>/dev/null || true
|
|
184
|
+
fi
|
|
185
|
+
printf '%s\n' "$SESSION_ID" >> "$STATE_FILE" 2>/dev/null || true
|
|
186
|
+
|
|
187
|
+
# Emit the advisory. The recommendation tier is:
|
|
188
|
+
# 1. `/exit` immediately to stop burning context, then restart fresh with Sonnet pinned.
|
|
189
|
+
# 2. If you must continue this session, swap the model in-place; the same prompt may
|
|
190
|
+
# pass on Sonnet without retry.
|
|
191
|
+
cat >&2 <<EOF
|
|
192
|
+
[aup-retry-loop-guard] Retry-loop pattern detected: $COUNT Usage Policy block(s) on
|
|
193
|
+
tool "$LAST_TOOL" within the last $WINDOW_MIN minute(s). Pattern kind: $LAST_KIND.
|
|
194
|
+
|
|
195
|
+
This shape — same tool, same block, repeated within a short window — is the retry-loop
|
|
196
|
+
signature reported in issue #61664: each retry consumes session context, even when the
|
|
197
|
+
attempt itself blocks. Pro / Max quota holders report hitting their daily quota MAX in
|
|
198
|
+
hours instead of a full day during this loop.
|
|
199
|
+
|
|
200
|
+
Recommended cycle-breaker (pick one):
|
|
201
|
+
|
|
202
|
+
Option A — exit and restart fresh (safest for quota)
|
|
203
|
+
1. /exit
|
|
204
|
+
2. export ANTHROPIC_MODEL=$TARGET
|
|
205
|
+
3. claude # new session, no inherited context, Sonnet path
|
|
206
|
+
|
|
207
|
+
Option B — swap in-place (continues current session)
|
|
208
|
+
export ANTHROPIC_MODEL=$TARGET
|
|
209
|
+
# the next prompt may pass; Sonnet is unaffected by the Cluster 9 signature
|
|
210
|
+
|
|
211
|
+
The Cluster 9 classifier is non-deterministic, so retrying identical input on the same
|
|
212
|
+
Opus pin sometimes works — but the context cost per retry typically exceeds the value
|
|
213
|
+
of the eventual successful turn. Breaking the cycle now preserves more daily quota for
|
|
214
|
+
productive work.
|
|
215
|
+
|
|
216
|
+
Related hooks (already active in this defense suite):
|
|
217
|
+
aup-false-positive-helper.sh — generic awareness at session start
|
|
218
|
+
aup-block-pattern-logger.sh — evidence shape recorded at $LOG_PATH
|
|
219
|
+
model-swap-suggester.sh — session-start swap recommendation (60-min window)
|
|
220
|
+
|
|
221
|
+
To silence this advisory for the current session only:
|
|
222
|
+
export CC_AUP_RETRY_LOOP_GUARD_QUIET=1
|
|
223
|
+
|
|
224
|
+
GitHub references:
|
|
225
|
+
https://github.com/anthropics/claude-code/issues/60366 (cluster anchor)
|
|
226
|
+
https://github.com/anthropics/claude-code/issues/61664 (retry-loop quota burn)
|
|
227
|
+
EOF
|
|
228
|
+
|
|
229
|
+
exit 0
|