cc-safe-setup 29.8.0 → 30.0.5
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 +421 -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 +1718 -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,93 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# verify-after-publish-reminder.sh — Remind to verify persisted state after publish commands
|
|
3
|
+
#
|
|
4
|
+
# Solves: "Silent failure" where a publish command reports success but the
|
|
5
|
+
# content is not actually visible at the destination. Examples observed:
|
|
6
|
+
# - Zenn GitHub sync rate-limited the article but `git push` reported success
|
|
7
|
+
# - Tweet auto-tool reported failure while the tweet was actually live in broken form
|
|
8
|
+
# - Gumroad CDP form-input updated the DOM value but React state was untouched,
|
|
9
|
+
# so Save click serialized the old state
|
|
10
|
+
#
|
|
11
|
+
# How it works: After the user runs a Bash command that looks like a publish action,
|
|
12
|
+
# the hook reads the candidate URL from stdout (if visible) and reminds the user to
|
|
13
|
+
# verify the persisted state through a second channel (re-fetch the public URL, hit
|
|
14
|
+
# the article API, or inspect the dashboard). The hook does NOT block — it emits a
|
|
15
|
+
# reminder so the user catches silent-success failures before logging completion.
|
|
16
|
+
#
|
|
17
|
+
# Detected publish patterns:
|
|
18
|
+
# - git push (anywhere)
|
|
19
|
+
# - hashnode-publish, qiita-post, zenn-update, hatena-post, tweet-post
|
|
20
|
+
# - npm publish, cargo publish, pip publish, gh release create
|
|
21
|
+
# - cdp-bridge eval ... Save changes
|
|
22
|
+
#
|
|
23
|
+
# TRIGGER: PostToolUse
|
|
24
|
+
# MATCHER: "Bash"
|
|
25
|
+
#
|
|
26
|
+
# CONFIG:
|
|
27
|
+
# CC_PUBLISH_VERIFY_DISABLE=1 # Disable the reminder entirely
|
|
28
|
+
#
|
|
29
|
+
# This is defense-in-depth, not a complete safeguard. The reminder text is logged to
|
|
30
|
+
# the agent's transcript so the agent sees it on the next turn and is prompted to run
|
|
31
|
+
# the verification before claiming success.
|
|
32
|
+
|
|
33
|
+
set -euo pipefail
|
|
34
|
+
|
|
35
|
+
[ "${CC_PUBLISH_VERIFY_DISABLE:-0}" = "1" ] && exit 0
|
|
36
|
+
|
|
37
|
+
INPUT=$(cat)
|
|
38
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
39
|
+
[ -z "$COMMAND" ] && exit 0
|
|
40
|
+
|
|
41
|
+
# Patterns that indicate a publish-like action
|
|
42
|
+
PUBLISH_PATTERNS='git[[:space:]]+push|hashnode-publish|qiita-post|zenn-update|hatena-post|tweet-post|note-publish|note-update|npm[[:space:]]+publish|cargo[[:space:]]+publish|pip[[:space:]]+publish|twine[[:space:]]+upload|gh[[:space:]]+release[[:space:]]+create|cdp-bridge[[:space:]].*[Ss]ave[[:space:]]+changes'
|
|
43
|
+
|
|
44
|
+
if ! printf '%s\n' "$COMMAND" | grep -qE "$PUBLISH_PATTERNS"; then
|
|
45
|
+
exit 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Identify which platform was published to (best effort)
|
|
49
|
+
PLATFORM="unknown"
|
|
50
|
+
case "$COMMAND" in
|
|
51
|
+
*hashnode-publish*) PLATFORM="Hashnode" ;;
|
|
52
|
+
*qiita-post*) PLATFORM="Qiita" ;;
|
|
53
|
+
*zenn-update*|*zenn-cc-book*) PLATFORM="Zenn" ;;
|
|
54
|
+
*hatena-post*) PLATFORM="hatena" ;;
|
|
55
|
+
*tweet-post*) PLATFORM="X (Twitter)" ;;
|
|
56
|
+
*note-publish*|*note-update*) PLATFORM="note" ;;
|
|
57
|
+
*npm*publish*) PLATFORM="npm" ;;
|
|
58
|
+
*cargo*publish*) PLATFORM="crates.io" ;;
|
|
59
|
+
*pip*publish*|*twine*upload*|*twine[[:space:]]upload*) PLATFORM="PyPI" ;;
|
|
60
|
+
*gh*release*create*) PLATFORM="GitHub Release" ;;
|
|
61
|
+
*git*push*) PLATFORM="git remote (may trigger downstream publish via GitHub sync)" ;;
|
|
62
|
+
*Save*changes*) PLATFORM="dashboard (Gumroad / Ko-fi / other SaaS)" ;;
|
|
63
|
+
esac
|
|
64
|
+
|
|
65
|
+
cat >&2 <<EOF
|
|
66
|
+
=== verify-after-publish-reminder ===
|
|
67
|
+
A publish-like action was just executed against: ${PLATFORM}
|
|
68
|
+
|
|
69
|
+
The tool's "success" response is not the same as "the content is live and correct".
|
|
70
|
+
|
|
71
|
+
Before logging this as completed, verify the persisted state through a second channel:
|
|
72
|
+
|
|
73
|
+
1. Re-fetch the public URL or page and confirm HTTP 200 + correct content
|
|
74
|
+
2. Query the platform's API (article API, product API, etc.) for the new state
|
|
75
|
+
3. Inspect the platform dashboard for any rate-limit, deployment-failure, or "blocked"
|
|
76
|
+
notification
|
|
77
|
+
|
|
78
|
+
Common silent-failure modes to check:
|
|
79
|
+
- Rate-limit rejection (Zenn 24h window, Twitter 4-8h cadence, API throttle 429)
|
|
80
|
+
- React-controlled input that did not update internal state (DOM looked right,
|
|
81
|
+
Save serialized old data)
|
|
82
|
+
- GitHub sync queued but not yet deployed
|
|
83
|
+
- Cloudflare / anti-bot intercept that hid content from non-logged-in viewers
|
|
84
|
+
|
|
85
|
+
If verification fails, treat the publish as NOT done and re-attempt — do not log success
|
|
86
|
+
based on the local command return value alone.
|
|
87
|
+
|
|
88
|
+
(Set CC_PUBLISH_VERIFY_DISABLE=1 to suppress this reminder.)
|
|
89
|
+
EOF
|
|
90
|
+
|
|
91
|
+
# Non-blocking reminder (exit 0). The text appears in the transcript and reminds the
|
|
92
|
+
# agent on the next turn.
|
|
93
|
+
exit 0
|
|
@@ -25,6 +25,18 @@
|
|
|
25
25
|
#
|
|
26
26
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
27
27
|
|
|
28
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
29
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
30
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
31
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
32
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
33
|
+
_nojq_warned="/tmp/cc-nojq-warned-verify-before-commit-$PPID"
|
|
34
|
+
[ -f "$_nojq_warned" ] || {
|
|
35
|
+
echo "WARNING [verify-before-commit]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
36
|
+
: > "$_nojq_warned"
|
|
37
|
+
}
|
|
38
|
+
fi
|
|
39
|
+
|
|
28
40
|
INPUT=$(cat)
|
|
29
41
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
30
42
|
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# version-bump-detector.sh — Detect Claude Code version transitions
|
|
4
|
+
# at SessionStart and surface them so the
|
|
5
|
+
# operator can correlate quota or behavior
|
|
6
|
+
# anomalies with the version change
|
|
7
|
+
# ================================================================
|
|
8
|
+
# PURPOSE:
|
|
9
|
+
# Claude Code minor versions sometimes ship silent runtime changes
|
|
10
|
+
# that operators cannot detect from within a session. The existing
|
|
11
|
+
# version-regression-warner.sh covers a curated list of known-bad
|
|
12
|
+
# versions; this hook is the dynamic complement — it tells the
|
|
13
|
+
# operator every time the running CC version changes, regardless
|
|
14
|
+
# of whether that version is on a known-bad list yet.
|
|
15
|
+
#
|
|
16
|
+
# The Pro Max quota anomaly cluster on anthropics/claude-code
|
|
17
|
+
# (~2,200 cumulative reactions across 10 open issues) names four
|
|
18
|
+
# independent runtime/date boundaries (2026-03-23, v2.1.89,
|
|
19
|
+
# v2.1.100, 2.1.1) where consumption rate changed silently for
|
|
20
|
+
# subscribers. When an operator notices "my quota feels off this
|
|
21
|
+
# week", the first useful question is "did the CC version change
|
|
22
|
+
# recently?". This hook answers it at session start.
|
|
23
|
+
#
|
|
24
|
+
# Pairs with the Pro Max Quota Anomaly Operator Field Guide (Gist
|
|
25
|
+
# 158436e88d169406593d55bd84f0d7e9) — Path 5 of the field guide is
|
|
26
|
+
# "version-bump cross-reference". This hook automates that path.
|
|
27
|
+
#
|
|
28
|
+
# TRIGGER: SessionStart
|
|
29
|
+
# MATCHER: ""
|
|
30
|
+
#
|
|
31
|
+
# OPERATOR-SIDE COMPLEMENT TO:
|
|
32
|
+
# - version-regression-warner.sh (static known-bad version table)
|
|
33
|
+
# - cache-creation-drift-detector.sh (per-request token drift)
|
|
34
|
+
#
|
|
35
|
+
# BEHAVIOR:
|
|
36
|
+
# - First run: records current version, no warning.
|
|
37
|
+
# - Subsequent run with same version: silent.
|
|
38
|
+
# - Subsequent run with different version: warns via
|
|
39
|
+
# hookSpecificOutput.additionalContext with the previous version,
|
|
40
|
+
# the current version, and pointers to investigate quota drift.
|
|
41
|
+
# - Maintains a version-history JSONL log for retrospective review.
|
|
42
|
+
#
|
|
43
|
+
# CONFIGURATION (env vars):
|
|
44
|
+
# CC_VERSION_BUMP_DISABLE set to "1" to disable entirely
|
|
45
|
+
# CC_VERSION_BUMP_STATE state file path (default: ~/.cache/cc-safe-setup/last-cc-version)
|
|
46
|
+
# CC_VERSION_BUMP_LOG history log path (default: ~/.cache/cc-safe-setup/cc-version-history.jsonl)
|
|
47
|
+
# CC_VERSION_BUMP_OVERRIDE override detected version (testing)
|
|
48
|
+
#
|
|
49
|
+
# Inspect the history:
|
|
50
|
+
# tail -20 ~/.cache/cc-safe-setup/cc-version-history.jsonl | jq .
|
|
51
|
+
# jq -s 'map(.version) | unique' ~/.cache/cc-safe-setup/cc-version-history.jsonl
|
|
52
|
+
#
|
|
53
|
+
# RELATED ISSUES (the Pro Max quota anomaly cluster):
|
|
54
|
+
# https://github.com/anthropics/claude-code/issues/16157
|
|
55
|
+
# https://github.com/anthropics/claude-code/issues/38335
|
|
56
|
+
# https://github.com/anthropics/claude-code/issues/46917
|
|
57
|
+
# https://github.com/anthropics/claude-code/issues/45756
|
|
58
|
+
# https://github.com/anthropics/claude-code/issues/41788
|
|
59
|
+
# ================================================================
|
|
60
|
+
|
|
61
|
+
set -u
|
|
62
|
+
|
|
63
|
+
[ "${CC_VERSION_BUMP_DISABLE:-0}" = "1" ] && exit 0
|
|
64
|
+
|
|
65
|
+
STATE="${CC_VERSION_BUMP_STATE:-${HOME}/.cache/cc-safe-setup/last-cc-version}"
|
|
66
|
+
LOG="${CC_VERSION_BUMP_LOG:-${HOME}/.cache/cc-safe-setup/cc-version-history.jsonl}"
|
|
67
|
+
|
|
68
|
+
mkdir -p "$(dirname "$STATE")" 2>/dev/null
|
|
69
|
+
mkdir -p "$(dirname "$LOG")" 2>/dev/null
|
|
70
|
+
|
|
71
|
+
# Detect the running Claude Code version. Allow override for tests.
|
|
72
|
+
if [ -n "${CC_VERSION_BUMP_OVERRIDE:-}" ]; then
|
|
73
|
+
CURRENT="$CC_VERSION_BUMP_OVERRIDE"
|
|
74
|
+
else
|
|
75
|
+
if ! command -v claude >/dev/null 2>&1; then
|
|
76
|
+
exit 0
|
|
77
|
+
fi
|
|
78
|
+
CURRENT=$(claude --version 2>/dev/null \
|
|
79
|
+
| grep -oE '[0-9]+\.[0-9]+\.[0-9]+' \
|
|
80
|
+
| head -n 1)
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# If we couldn't detect a version, exit silently.
|
|
84
|
+
if [ -z "$CURRENT" ]; then
|
|
85
|
+
exit 0
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Validate the version looks like semver-ish.
|
|
89
|
+
case "$CURRENT" in
|
|
90
|
+
[0-9]*.[0-9]*.[0-9]*) ;;
|
|
91
|
+
*) exit 0 ;;
|
|
92
|
+
esac
|
|
93
|
+
|
|
94
|
+
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
95
|
+
|
|
96
|
+
# Read the previously-recorded version. If the state file doesn't
|
|
97
|
+
# exist yet, this is the first run — record and exit silently.
|
|
98
|
+
if [ ! -f "$STATE" ]; then
|
|
99
|
+
echo "$CURRENT" > "$STATE"
|
|
100
|
+
printf '{"ts":"%s","version":"%s","event":"first_run"}\n' "$TS" "$CURRENT" >> "$LOG"
|
|
101
|
+
exit 0
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
PREVIOUS=$(cat "$STATE" 2>/dev/null | tr -d '[:space:]')
|
|
105
|
+
|
|
106
|
+
# Same version as last session — silent.
|
|
107
|
+
if [ "$CURRENT" = "$PREVIOUS" ]; then
|
|
108
|
+
exit 0
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# Different version — record the transition and warn.
|
|
112
|
+
echo "$CURRENT" > "$STATE"
|
|
113
|
+
printf '{"ts":"%s","version":"%s","previous":"%s","event":"version_bump"}\n' \
|
|
114
|
+
"$TS" "$CURRENT" "$PREVIOUS" >> "$LOG"
|
|
115
|
+
|
|
116
|
+
WARNING="===== CLAUDE CODE VERSION BUMP DETECTED =====
|
|
117
|
+
Previous session: ${PREVIOUS}
|
|
118
|
+
Current session: ${CURRENT}
|
|
119
|
+
|
|
120
|
+
Some CC versions ship silent runtime changes that operators cannot
|
|
121
|
+
detect from within a session. The Pro Max quota anomaly cluster on
|
|
122
|
+
anthropics/claude-code names four such version/date boundaries
|
|
123
|
+
(2026-03-23, v2.1.89, v2.1.100, 2.1.1).
|
|
124
|
+
|
|
125
|
+
If you notice unexpected quota consumption, cache_creation token
|
|
126
|
+
counts, or behavior changes in this session vs. recent sessions,
|
|
127
|
+
the version change is a candidate cause. Investigation paths:
|
|
128
|
+
|
|
129
|
+
- Snapshot a representative \`claude --print\` invocation and compare
|
|
130
|
+
cache_creation_input_tokens against your trailing baseline. The
|
|
131
|
+
cache-creation-drift-detector.sh hook automates this comparison.
|
|
132
|
+
- Run \`bunx ccusage daily\` for the last 7 days to spot per-day
|
|
133
|
+
variance correlated with the bump.
|
|
134
|
+
- Check the Claude Code release notes for ${CURRENT} at
|
|
135
|
+
https://docs.anthropic.com/en/release-notes for documented changes.
|
|
136
|
+
|
|
137
|
+
Operator field guide (Path 5 of the Pro Max Quota Anomaly guide):
|
|
138
|
+
https://gist.github.com/yurukusa/158436e88d169406593d55bd84f0d7e9
|
|
139
|
+
===== END VERSION BUMP NOTICE ====="
|
|
140
|
+
|
|
141
|
+
# Emit hookSpecificOutput so it surfaces at session start.
|
|
142
|
+
if command -v jq >/dev/null 2>&1; then
|
|
143
|
+
jq -n \
|
|
144
|
+
--arg ctx "$WARNING" \
|
|
145
|
+
'{
|
|
146
|
+
hookSpecificOutput: {
|
|
147
|
+
hookEventName: "SessionStart",
|
|
148
|
+
additionalContext: $ctx
|
|
149
|
+
}
|
|
150
|
+
}'
|
|
151
|
+
else
|
|
152
|
+
# Fallback: write to stderr if jq isn't available.
|
|
153
|
+
echo "$WARNING" >&2
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
exit 0
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# version-regression-warner.sh — Surface known silent regressions
|
|
4
|
+
# for the currently-running Claude Code version on SessionStart
|
|
5
|
+
# ================================================================
|
|
6
|
+
# PURPOSE:
|
|
7
|
+
# Some Claude Code minor versions ship documented or community-
|
|
8
|
+
# reported silent regressions that operators cannot detect from
|
|
9
|
+
# within a session. By the time an operator notices the regression,
|
|
10
|
+
# they've often spent significant time on a workflow that was
|
|
11
|
+
# broken at startup.
|
|
12
|
+
#
|
|
13
|
+
# This hook checks the current `claude --version` against a small
|
|
14
|
+
# table of known-bad versions and surfaces the relevant regression
|
|
15
|
+
# set at SessionStart, with mitigation guidance per regression.
|
|
16
|
+
#
|
|
17
|
+
# The table is small on purpose. The bar for inclusion is
|
|
18
|
+
# "documented silent failure with no in-session error or warning"
|
|
19
|
+
# — the operator's worst class of bug.
|
|
20
|
+
#
|
|
21
|
+
# TRIGGER: SessionStart
|
|
22
|
+
# MATCHER: (none)
|
|
23
|
+
#
|
|
24
|
+
# CURRENT KNOWN-BAD VERSIONS (2026-05-17):
|
|
25
|
+
#
|
|
26
|
+
# v2.1.143:
|
|
27
|
+
# - Issue #59918: --resume with -p containing full history
|
|
28
|
+
# returns empty response. Mitigation: downgrade to v2.1.138,
|
|
29
|
+
# or pass only the latest user message in -p on resume.
|
|
30
|
+
# - Issue #59921: SKILL.md description fields silently dropped
|
|
31
|
+
# above cumulative-size threshold. Mitigation: shorten
|
|
32
|
+
# descriptions or split skills into smaller plugin groups.
|
|
33
|
+
# - Issue #59942: OTel `query_source` attribute silently empty
|
|
34
|
+
# since 2026-05-13 in both claude-code CLI and Cowork.
|
|
35
|
+
# Mitigation: monitor per-attribute empty-rate metrics for
|
|
36
|
+
# sudden jumps.
|
|
37
|
+
#
|
|
38
|
+
# v2.1.141:
|
|
39
|
+
# - Issue #59042: streaming-stall regression after v2.1.140 fix.
|
|
40
|
+
# - Issue #59047: unhandled-case banner on every conversational
|
|
41
|
+
# turn.
|
|
42
|
+
#
|
|
43
|
+
# CONFIGURATION:
|
|
44
|
+
# CC_VERSION_WARNER_DISABLE — set to 1 to disable entirely
|
|
45
|
+
# CC_VERSION_WARNER_VERSION — override detected version (testing)
|
|
46
|
+
#
|
|
47
|
+
# RELATED ISSUES:
|
|
48
|
+
# https://github.com/anthropics/claude-code/issues/59918
|
|
49
|
+
# https://github.com/anthropics/claude-code/issues/59921
|
|
50
|
+
# https://github.com/anthropics/claude-code/issues/59942
|
|
51
|
+
# https://github.com/anthropics/claude-code/issues/59042
|
|
52
|
+
# https://github.com/anthropics/claude-code/issues/59047
|
|
53
|
+
# ================================================================
|
|
54
|
+
|
|
55
|
+
set -u
|
|
56
|
+
|
|
57
|
+
[ "${CC_VERSION_WARNER_DISABLE:-0}" = "1" ] && exit 0
|
|
58
|
+
|
|
59
|
+
# Detect the running Claude Code version. Allow override for tests.
|
|
60
|
+
if [ -n "${CC_VERSION_WARNER_VERSION:-}" ]; then
|
|
61
|
+
VERSION="$CC_VERSION_WARNER_VERSION"
|
|
62
|
+
else
|
|
63
|
+
if ! command -v claude >/dev/null 2>&1; then
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
# `claude --version` typically outputs something like
|
|
67
|
+
# "2.1.143 (Claude Code)" or "claude-code v2.1.143". We just
|
|
68
|
+
# want the semver. Strip everything that is not [0-9.] and
|
|
69
|
+
# take the first match.
|
|
70
|
+
VERSION=$(claude --version 2>/dev/null \
|
|
71
|
+
| grep -oE '[0-9]+\.[0-9]+\.[0-9]+' \
|
|
72
|
+
| head -n 1)
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
[ -z "$VERSION" ] && exit 0
|
|
76
|
+
|
|
77
|
+
# Build the warning text only if the version matches a known-bad
|
|
78
|
+
# version. Add new entries here as silent regressions are documented.
|
|
79
|
+
WARNING=""
|
|
80
|
+
|
|
81
|
+
case "$VERSION" in
|
|
82
|
+
"2.1.143")
|
|
83
|
+
WARNING="===== KNOWN SILENT REGRESSIONS IN v2.1.143 =====
|
|
84
|
+
You are running Claude Code v2.1.143, which has three documented
|
|
85
|
+
silent regressions that operators cannot detect from within a
|
|
86
|
+
session. Each is listed with its mitigation.
|
|
87
|
+
|
|
88
|
+
1. Issue #59918 — \`--resume\` with full \`-p\` history returns
|
|
89
|
+
empty response. No error, just finish_reason:stop with empty
|
|
90
|
+
delta. Mitigation: downgrade to v2.1.138, or pass only the
|
|
91
|
+
latest user message in -p on resume (not full history).
|
|
92
|
+
|
|
93
|
+
2. Issue #59921 — SKILL.md description fields silently dropped
|
|
94
|
+
from the available-skills system reminder when cumulative
|
|
95
|
+
description size exceeds an internal threshold. Mitigation:
|
|
96
|
+
if you have >100 skills, shorten descriptions or split into
|
|
97
|
+
smaller plugin groups. Cross-check installed-vs-visible
|
|
98
|
+
descriptions in your system prompt.
|
|
99
|
+
|
|
100
|
+
3. Issue #59942 — OTel \`query_source\` attribute silently empty
|
|
101
|
+
on \`api_request\` events and \`cost.usage\` / \`token.usage\`
|
|
102
|
+
counter metrics since 2026-05-13, in both claude-code CLI and
|
|
103
|
+
Cowork. Same shape as the v2.1.122 \`cost_usd\` drop. If you
|
|
104
|
+
rely on \`query_source\` for cost allocation, monitor your
|
|
105
|
+
pipeline's per-attribute empty-rate.
|
|
106
|
+
|
|
107
|
+
These regressions do not surface in-session. If your workflow
|
|
108
|
+
touches resume + -p, large skill collections, or OTel-based cost
|
|
109
|
+
allocation, verify behavior before relying on it.
|
|
110
|
+
===== END WARNING ====="
|
|
111
|
+
;;
|
|
112
|
+
"2.1.141")
|
|
113
|
+
WARNING="===== KNOWN REGRESSIONS IN v2.1.141 =====
|
|
114
|
+
You are running Claude Code v2.1.141, shipped a few hours after
|
|
115
|
+
v2.1.140's documented silent-failure fixes. Two regressions of the
|
|
116
|
+
same shape surfaced immediately:
|
|
117
|
+
|
|
118
|
+
1. Issue #59042 — streaming-stall regression.
|
|
119
|
+
|
|
120
|
+
2. Issue #59047 — unhandled-case banner on every conversational
|
|
121
|
+
turn.
|
|
122
|
+
|
|
123
|
+
Consider upgrading to a later patch version or pinning v2.1.138 if
|
|
124
|
+
this version's behavior blocks your workflow.
|
|
125
|
+
===== END WARNING ====="
|
|
126
|
+
;;
|
|
127
|
+
*)
|
|
128
|
+
# No known-bad regressions for this version.
|
|
129
|
+
exit 0
|
|
130
|
+
;;
|
|
131
|
+
esac
|
|
132
|
+
|
|
133
|
+
[ -z "$WARNING" ] && exit 0
|
|
134
|
+
|
|
135
|
+
jq -n \
|
|
136
|
+
--arg ctx "$WARNING" \
|
|
137
|
+
'{
|
|
138
|
+
hookSpecificOutput: {
|
|
139
|
+
hookEventName: "SessionStart",
|
|
140
|
+
additionalContext: $ctx
|
|
141
|
+
}
|
|
142
|
+
}'
|
|
143
|
+
|
|
144
|
+
exit 0
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# warn-cron-cost-trap.sh — Warn on cost-trap scheduled tasks
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# When the model calls CronCreate with a SHORT fire interval AND
|
|
7
|
+
# recurring=true, emit a cost warning. Short-interval recurring
|
|
8
|
+
# schedules are a silent money trap: every fire re-loads the whole
|
|
9
|
+
# conversation as a fresh full turn, so the per-fire cost climbs
|
|
10
|
+
# roughly quadratically with the number of fires in a session.
|
|
11
|
+
#
|
|
12
|
+
# TRIGGER: PostToolUse
|
|
13
|
+
# MATCHER: "CronCreate"
|
|
14
|
+
#
|
|
15
|
+
# WHY THIS MATTERS:
|
|
16
|
+
# A recurring CronCreate does not run cheaply in the background.
|
|
17
|
+
# Each fire is a complete turn that re-reads the accumulated
|
|
18
|
+
# conversation history, so cost per fire grows as the session
|
|
19
|
+
# grows. A */5 (every 5 min) recurring job left running overnight
|
|
20
|
+
# can fire ~200 times, each one more expensive than the last.
|
|
21
|
+
# Issue #74547 reports ~USD 500 burned by an 11-minute recurring
|
|
22
|
+
# schedule that did nothing but poll an empty directory 88 times
|
|
23
|
+
# in 16 hours. The registration itself is silent — nothing warns
|
|
24
|
+
# the operator that the interval times the growing context equals
|
|
25
|
+
# a quadratic bill.
|
|
26
|
+
#
|
|
27
|
+
# This hook is advisory. It never blocks CronCreate; it prints a
|
|
28
|
+
# one-time warning so the operator can widen the interval, set
|
|
29
|
+
# recurring=false, or move the poll to an external scheduler that
|
|
30
|
+
# does not re-load the conversation each fire.
|
|
31
|
+
#
|
|
32
|
+
# WHAT IT CHECKS:
|
|
33
|
+
# Parses .tool_input.cron and .tool_input.recurring. It derives the
|
|
34
|
+
# smallest gap (in minutes) between consecutive fires from the
|
|
35
|
+
# MINUTE field of the cron expression — the field that actually
|
|
36
|
+
# drives short intervals:
|
|
37
|
+
# * -> 1 minute (fires every minute)
|
|
38
|
+
# */N or .../N -> N minutes (step)
|
|
39
|
+
# a,b,c,... -> smallest consecutive gap, with 60-wraparound
|
|
40
|
+
# A-B (range) -> 1 minute (fires every minute within the range)
|
|
41
|
+
# single value -> 60 minutes (fires at most hourly -> safe)
|
|
42
|
+
# Warns unless recurring is explicitly false, AND the derived interval is
|
|
43
|
+
# below the threshold (default 15 minutes). An omitted recurring defaults
|
|
44
|
+
# to recurring, so the omitted short-interval case is included.
|
|
45
|
+
#
|
|
46
|
+
# DEFENSIVE BEHAVIOR:
|
|
47
|
+
# - Always exits 0 (advisory only, never blocks)
|
|
48
|
+
# - Skips silently if jq is missing
|
|
49
|
+
# - Skips silently if no cron expression is present
|
|
50
|
+
# - Treats an unparseable minute field as safe (no false alarm)
|
|
51
|
+
#
|
|
52
|
+
# CONFIGURATION (environment variables):
|
|
53
|
+
# CC_CRON_COST_TRAP_DISABLE=1 skip the hook entirely
|
|
54
|
+
# CC_CRON_COST_TRAP_THRESHOLD_MIN=N interval below N warns (default 15)
|
|
55
|
+
#
|
|
56
|
+
# RELATED ISSUES:
|
|
57
|
+
# https://github.com/anthropics/claude-code/issues/74547 (~USD 500 no-op polling spend)
|
|
58
|
+
#
|
|
59
|
+
# PAIR WITH:
|
|
60
|
+
# cron-create-receipt.sh (logs every registration for later audit)
|
|
61
|
+
# daily-cost-guard.sh (tracks accumulated spend)
|
|
62
|
+
#
|
|
63
|
+
# TRIGGER: PostToolUse MATCHER: "CronCreate"
|
|
64
|
+
# ================================================================
|
|
65
|
+
|
|
66
|
+
set -u
|
|
67
|
+
|
|
68
|
+
# Skip if disabled
|
|
69
|
+
if [ "${CC_CRON_COST_TRAP_DISABLE:-0}" = "1" ]; then
|
|
70
|
+
exit 0
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
# Skip if jq is missing — we cannot parse tool_input without it
|
|
74
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
75
|
+
exit 0
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
THRESHOLD="${CC_CRON_COST_TRAP_THRESHOLD_MIN:-15}"
|
|
79
|
+
# Numeric guard on the threshold
|
|
80
|
+
case "$THRESHOLD" in
|
|
81
|
+
''|*[!0-9]*) THRESHOLD=15 ;;
|
|
82
|
+
esac
|
|
83
|
+
|
|
84
|
+
INPUT=$(cat)
|
|
85
|
+
|
|
86
|
+
CRON_EXPR=$(printf '%s' "$INPUT" | jq -r '.tool_input.cron // empty' 2>/dev/null)
|
|
87
|
+
# Take the raw value: do NOT use jq's // default here. jq's // returns the
|
|
88
|
+
# right-hand side when the left is null OR false, so `recurring // false`
|
|
89
|
+
# would collapse an explicit `false` into the default and misfire.
|
|
90
|
+
RECURRING=$(printf '%s' "$INPUT" | jq -r '.tool_input.recurring' 2>/dev/null)
|
|
91
|
+
|
|
92
|
+
# Nothing to do if there is no cron expression
|
|
93
|
+
[ -z "$CRON_EXPR" ] && exit 0
|
|
94
|
+
|
|
95
|
+
# Only recurring schedules have the compounding trap. Exclude a schedule ONLY
|
|
96
|
+
# when recurring is explicitly false (a genuine one-shot fire). When recurring
|
|
97
|
+
# is omitted, CronCreate defaults to recurring, so an omitted short-interval
|
|
98
|
+
# registration — the most dangerous form — must still be caught.
|
|
99
|
+
[ "$RECURRING" = "false" ] && exit 0
|
|
100
|
+
|
|
101
|
+
# Extract the minute field (first whitespace-separated field)
|
|
102
|
+
MINUTE=$(printf '%s' "$CRON_EXPR" | awk '{print $1}')
|
|
103
|
+
[ -z "$MINUTE" ] && exit 0
|
|
104
|
+
|
|
105
|
+
# Derive the smallest interval (in minutes) between consecutive fires
|
|
106
|
+
# from the minute field alone. This is the practical driver of the trap.
|
|
107
|
+
INTERVAL=$(printf '%s' "$MINUTE" | awk '
|
|
108
|
+
{
|
|
109
|
+
f = $0
|
|
110
|
+
# Step form: anything containing "/N" fires every N minutes
|
|
111
|
+
if (f ~ /\//) {
|
|
112
|
+
n = f
|
|
113
|
+
sub(/.*\//, "", n)
|
|
114
|
+
if (n ~ /^[0-9]+$/ && n+0 > 0) { print n+0; next }
|
|
115
|
+
}
|
|
116
|
+
# Every minute
|
|
117
|
+
if (f == "*") { print 1; next }
|
|
118
|
+
# Comma list of explicit minutes: smallest consecutive gap with wraparound
|
|
119
|
+
if (f ~ /,/) {
|
|
120
|
+
n = split(f, parts, ",")
|
|
121
|
+
cnt = 0
|
|
122
|
+
for (i = 1; i <= n; i++) {
|
|
123
|
+
v = parts[i]
|
|
124
|
+
if (v ~ /^[0-9]+$/) { vals[cnt++] = v+0 }
|
|
125
|
+
}
|
|
126
|
+
if (cnt < 2) { print 60; next }
|
|
127
|
+
# simple insertion sort
|
|
128
|
+
for (i = 1; i < cnt; i++) {
|
|
129
|
+
key = vals[i]; j = i - 1
|
|
130
|
+
while (j >= 0 && vals[j] > key) { vals[j+1] = vals[j]; j-- }
|
|
131
|
+
vals[j+1] = key
|
|
132
|
+
}
|
|
133
|
+
mingap = 60
|
|
134
|
+
for (i = 1; i < cnt; i++) {
|
|
135
|
+
gap = vals[i] - vals[i-1]
|
|
136
|
+
if (gap < mingap) mingap = gap
|
|
137
|
+
}
|
|
138
|
+
wrap = (60 - vals[cnt-1]) + vals[0]
|
|
139
|
+
if (wrap < mingap) mingap = wrap
|
|
140
|
+
if (mingap < 1) mingap = 1
|
|
141
|
+
print mingap; next
|
|
142
|
+
}
|
|
143
|
+
# Range without step (e.g. 0-30) fires every minute within the range,
|
|
144
|
+
# so its interval is 1 minute — one of the most expensive forms.
|
|
145
|
+
if (f ~ /^[0-9]+-[0-9]+$/) { print 1; next }
|
|
146
|
+
# Single value -> at most once per hour -> safe
|
|
147
|
+
print 60
|
|
148
|
+
}
|
|
149
|
+
')
|
|
150
|
+
|
|
151
|
+
# Guard: if awk produced nothing numeric, treat as safe
|
|
152
|
+
case "$INTERVAL" in
|
|
153
|
+
''|*[!0-9]*) exit 0 ;;
|
|
154
|
+
esac
|
|
155
|
+
|
|
156
|
+
if [ "$INTERVAL" -lt "$THRESHOLD" ]; then
|
|
157
|
+
cat >&2 <<EOF
|
|
158
|
+
[warn-cron-cost-trap] COST TRAP: recurring CronCreate fires about every ${INTERVAL} min.
|
|
159
|
+
cron: "$CRON_EXPR" recurring: true
|
|
160
|
+
Each fire re-loads the whole conversation as a fresh full turn, so per-fire
|
|
161
|
+
cost grows with the session — the total climbs roughly quadratically with the
|
|
162
|
+
number of fires. Left overnight, a short-interval recurring job can fire
|
|
163
|
+
hundreds of times, each one more expensive than the last (issue #74547 burned
|
|
164
|
+
~USD 500 polling an empty directory 88 times in 16 hours).
|
|
165
|
+
Fixes: widen the interval (>= ${THRESHOLD} min), set recurring=false for a
|
|
166
|
+
one-shot, or move the poll to an external scheduler that does not re-load the
|
|
167
|
+
conversation each fire.
|
|
168
|
+
Set CC_CRON_COST_TRAP_DISABLE=1 to suppress this warning.
|
|
169
|
+
EOF
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
# Always exit 0 — advisory only, never blocks CronCreate
|
|
173
|
+
exit 0
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# webfetch-runaway-guard.sh — Cap a runaway sequence of WebFetch tool calls that burns cost
|
|
3
|
+
#
|
|
4
|
+
# Solves: When a research subagent is told to gather many sources, denying a
|
|
5
|
+
# single WebFetch is treated as "skip this one" rather than "stop and
|
|
6
|
+
# summarize" — so the agent moves to the next URL and keeps fetching. In #65684
|
|
7
|
+
# this ran ~98 WebFetch calls (~$1.15) before the user force-killed it with
|
|
8
|
+
# Ctrl+C, and the context from the earlier fetches was lost because the agent
|
|
9
|
+
# never paused to synthesize.
|
|
10
|
+
#
|
|
11
|
+
# Existing hooks miss this exact shape:
|
|
12
|
+
# - loop-detector.sh keys on the *same* command repeating; a runaway fetches
|
|
13
|
+
# a *different* URL each call, so it never matches.
|
|
14
|
+
# - api-rate-limit-tracker.sh matches Bash curl/wget/http; the WebFetch *tool*
|
|
15
|
+
# is a separate tool, not a Bash command.
|
|
16
|
+
# - session-rate-monitor.sh is advisory token-rate only and never blocks.
|
|
17
|
+
# - webfetch-domain-allow.sh is the opposite purpose (auto-approve allowlist).
|
|
18
|
+
#
|
|
19
|
+
# This counts WebFetch *tool* calls in a rolling time window (per session) and,
|
|
20
|
+
# once the count crosses a threshold, blocks with a message telling the model to
|
|
21
|
+
# stop fetching and summarize what it already has — the behavior the operator
|
|
22
|
+
# wanted when they started denying calls. A hard block (not just a warning) is
|
|
23
|
+
# what actually caps the spend, since the runaway already ignored the denials.
|
|
24
|
+
#
|
|
25
|
+
# Defaults are generous so ordinary research is untouched: it takes 50 fetches
|
|
26
|
+
# inside 5 minutes to block. The window ages out on its own, so once the model
|
|
27
|
+
# summarizes and stops, the next genuine research run starts from zero.
|
|
28
|
+
#
|
|
29
|
+
# TRIGGER: PreToolUse MATCHER: "WebFetch"
|
|
30
|
+
# Config (all optional):
|
|
31
|
+
# CC_WEBFETCH_RUNAWAY_GUARD=block block | warn | off
|
|
32
|
+
# CC_WEBFETCH_RUNAWAY_BLOCK=50 block once this many fetches fall inside the window
|
|
33
|
+
# CC_WEBFETCH_RUNAWAY_WARN=30 warn (stderr, non-blocking) at this many
|
|
34
|
+
# CC_WEBFETCH_RUNAWAY_WINDOW=300 rolling window in seconds
|
|
35
|
+
# CC_WEBFETCH_RUNAWAY_DIR state dir (default: /tmp/cc-webfetch-runaway)
|
|
36
|
+
# Related: https://github.com/anthropics/claude-code/issues/65684
|
|
37
|
+
|
|
38
|
+
INPUT=$(cat)
|
|
39
|
+
|
|
40
|
+
MODE="${CC_WEBFETCH_RUNAWAY_GUARD:-block}"
|
|
41
|
+
[ "$MODE" = "off" ] && exit 0
|
|
42
|
+
|
|
43
|
+
# Only act on the WebFetch tool. Fail open on anything unexpected.
|
|
44
|
+
TOOL=$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
45
|
+
[ "$TOOL" != "WebFetch" ] && exit 0
|
|
46
|
+
|
|
47
|
+
BLOCK_AT="${CC_WEBFETCH_RUNAWAY_BLOCK:-50}"
|
|
48
|
+
WARN_AT="${CC_WEBFETCH_RUNAWAY_WARN:-30}"
|
|
49
|
+
WINDOW="${CC_WEBFETCH_RUNAWAY_WINDOW:-300}"
|
|
50
|
+
case "$BLOCK_AT" in ''|*[!0-9]*) exit 0;; esac
|
|
51
|
+
case "$WARN_AT" in ''|*[!0-9]*) exit 0;; esac
|
|
52
|
+
case "$WINDOW" in ''|*[!0-9]*) exit 0;; esac
|
|
53
|
+
|
|
54
|
+
# Key state per session so one session's research never trips another's guard.
|
|
55
|
+
SID=$(printf '%s' "$INPUT" | jq -r '.session_id // "default"' 2>/dev/null)
|
|
56
|
+
case "$SID" in ''|*[!A-Za-z0-9_-]*) SID="default";; esac
|
|
57
|
+
|
|
58
|
+
STATE_DIR="${CC_WEBFETCH_RUNAWAY_DIR:-/tmp/cc-webfetch-runaway}"
|
|
59
|
+
mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
|
|
60
|
+
STATE="$STATE_DIR/$SID"
|
|
61
|
+
|
|
62
|
+
NOW=$(date +%s)
|
|
63
|
+
CUTOFF=$((NOW - WINDOW))
|
|
64
|
+
|
|
65
|
+
# Record this call, then keep only timestamps inside the window.
|
|
66
|
+
echo "$NOW" >> "$STATE" 2>/dev/null
|
|
67
|
+
if [ -f "$STATE" ]; then
|
|
68
|
+
awk -v c="$CUTOFF" '$1 ~ /^[0-9]+$/ && $1 >= c' "$STATE" > "$STATE.tmp" 2>/dev/null && mv "$STATE.tmp" "$STATE" 2>/dev/null
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
COUNT=$(wc -l < "$STATE" 2>/dev/null | tr -d ' ')
|
|
72
|
+
case "$COUNT" in ''|*[!0-9]*) exit 0;; esac
|
|
73
|
+
|
|
74
|
+
MINS=$((WINDOW / 60))
|
|
75
|
+
MSG="This is WebFetch call ${COUNT} within ${MINS} min. A research loop is fetching URL after URL without pausing to synthesize — in #65684 this reached ~98 fetches (~\$1.15) before it was force-killed, and the earlier results were wasted. Stop fetching now and write your answer from the sources you already have; open another fetch only if a specific gap remains. To allow a deeper sweep, raise CC_WEBFETCH_RUNAWAY_BLOCK, set CC_WEBFETCH_RUNAWAY_GUARD=warn to only warn, or =off to disable. State resets after ${WINDOW}s of no fetches: ${STATE}"
|
|
76
|
+
|
|
77
|
+
if [ "$COUNT" -ge "$BLOCK_AT" ]; then
|
|
78
|
+
if [ "$MODE" = "warn" ]; then
|
|
79
|
+
echo "webfetch-runaway-guard: $MSG" >&2
|
|
80
|
+
exit 0
|
|
81
|
+
fi
|
|
82
|
+
# block (default): structured decision so the model sees the reason.
|
|
83
|
+
jq -n --arg r "$MSG" '{decision: "block", reason: $r}'
|
|
84
|
+
exit 0
|
|
85
|
+
elif [ "$COUNT" -ge "$WARN_AT" ]; then
|
|
86
|
+
echo "webfetch-runaway-guard: WebFetch call ${COUNT} within ${MINS} min — consider summarizing what you have before fetching more (#65684). Blocks at ${BLOCK_AT}." >&2
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
exit 0
|