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,169 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# plugin-hooks-json-bloat-detector.sh — Detect duplicated hook
|
|
4
|
+
# registrations inside plugin hooks.json files (additive growth
|
|
5
|
+
# from the multi-agent dispatch path).
|
|
6
|
+
# ================================================================
|
|
7
|
+
# PURPOSE:
|
|
8
|
+
# Issue #64022 documents a class where a plugin's
|
|
9
|
+
# `hooks/hooks.json` registrations multiply additively in
|
|
10
|
+
# multi-agent sessions (observed 1× → 122× per hook). At high
|
|
11
|
+
# multiples every hook fires N times per tool call and tool
|
|
12
|
+
# output is corrupted. The reporter's plugin had no additive
|
|
13
|
+
# writer; the only mechanism that fits is the harness re-running
|
|
14
|
+
# its plugin-hook load/merge and appending instead of replacing.
|
|
15
|
+
#
|
|
16
|
+
# The growth is silent until output corruption surfaces it. This
|
|
17
|
+
# hook scans every installed plugin's hooks.json at session
|
|
18
|
+
# start, counts duplicate command-string registrations within
|
|
19
|
+
# each file, and warns when a single command appears more than a
|
|
20
|
+
# threshold (default 5 times) — well below the 122× blowup but
|
|
21
|
+
# well above any legitimate "one event, one command, multiple
|
|
22
|
+
# matchers" registration shape.
|
|
23
|
+
#
|
|
24
|
+
# DETECTION MODEL:
|
|
25
|
+
# SessionStart fires once per session. We walk every
|
|
26
|
+
# `~/.claude/plugins/cache/**/hooks/hooks.json` (plus the canonical
|
|
27
|
+
# `~/.claude/plugins/marketplace/**/hooks/hooks.json` if it exists),
|
|
28
|
+
# parse each JSON, and within each file count how many times each
|
|
29
|
+
# distinct command string appears across all event types. If any
|
|
30
|
+
# command string appears more than CC_PLUGIN_HOOKS_BLOAT_THRESHOLD
|
|
31
|
+
# times in a single hooks.json, emit a warning identifying the
|
|
32
|
+
# plugin path, the command, and the duplicate count.
|
|
33
|
+
#
|
|
34
|
+
# We deliberately ignore the cross-plugin case (the same command
|
|
35
|
+
# appearing in two different plugins is legitimate) and the
|
|
36
|
+
# multi-event case (the same command registered for PreToolUse
|
|
37
|
+
# AND PostToolUse — count each event-bucket separately).
|
|
38
|
+
#
|
|
39
|
+
# CLUSTER:
|
|
40
|
+
# Candidate cluster #21 — Plugin lifecycle integrity gap
|
|
41
|
+
# Sub-axis 21A — additive hook-registration growth (#64022).
|
|
42
|
+
#
|
|
43
|
+
# TRIGGER: SessionStart MATCHER: ""
|
|
44
|
+
#
|
|
45
|
+
# ENV:
|
|
46
|
+
# CC_PLUGIN_HOOKS_BLOAT_THRESHOLD default 5 (warn when same command appears >5×)
|
|
47
|
+
# CC_PLUGIN_HOOKS_BLOAT_DISABLE non-empty → silent
|
|
48
|
+
# CC_PLUGIN_HOOKS_BLOAT_QUIET non-empty → silent
|
|
49
|
+
# CC_PLUGIN_HOOKS_BLOAT_ROOT default $HOME/.claude/plugins
|
|
50
|
+
# CC_PLUGIN_HOOKS_BLOAT_STATE_DIR default /tmp/cc-plugin-hooks-bloat
|
|
51
|
+
# ================================================================
|
|
52
|
+
|
|
53
|
+
set -u
|
|
54
|
+
|
|
55
|
+
# Disable / quiet
|
|
56
|
+
if [ -n "${CC_PLUGIN_HOOKS_BLOAT_DISABLE:-}" ] || [ -n "${CC_PLUGIN_HOOKS_BLOAT_QUIET:-}" ]; then
|
|
57
|
+
exit 0
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
THRESHOLD="${CC_PLUGIN_HOOKS_BLOAT_THRESHOLD:-5}"
|
|
61
|
+
PLUGINS_ROOT="${CC_PLUGIN_HOOKS_BLOAT_ROOT:-$HOME/.claude/plugins}"
|
|
62
|
+
STATE_DIR="${CC_PLUGIN_HOOKS_BLOAT_STATE_DIR:-/tmp/cc-plugin-hooks-bloat}"
|
|
63
|
+
WARN_FILE="$STATE_DIR/last-warn"
|
|
64
|
+
|
|
65
|
+
mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
|
|
66
|
+
|
|
67
|
+
# If plugin root doesn't exist, nothing to scan
|
|
68
|
+
[ -d "$PLUGINS_ROOT" ] || exit 0
|
|
69
|
+
|
|
70
|
+
# Need jq for JSON parsing; fail-soft if missing
|
|
71
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
72
|
+
exit 0
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Read input (Claude Code passes session context on stdin; we don't use it for
|
|
76
|
+
# this detector, but consume it so the harness doesn't block).
|
|
77
|
+
INPUT=$(cat 2>/dev/null || true)
|
|
78
|
+
|
|
79
|
+
# Track findings across all plugin hooks.json files
|
|
80
|
+
declare -a FINDINGS=()
|
|
81
|
+
|
|
82
|
+
# Walk every hooks.json under the plugins tree
|
|
83
|
+
while IFS= read -r -d '' HOOKS_FILE; do
|
|
84
|
+
# Skip if not a file (broken symlink etc.)
|
|
85
|
+
[ -f "$HOOKS_FILE" ] || continue
|
|
86
|
+
|
|
87
|
+
# Skip if the file is not valid JSON (fail-soft, do not warn on broken files
|
|
88
|
+
# — those are a separate problem)
|
|
89
|
+
if ! jq -e . "$HOOKS_FILE" >/dev/null 2>&1; then
|
|
90
|
+
continue
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Extract every hook command string, grouped per event-bucket so that the
|
|
94
|
+
# same command legitimately registered for PreToolUse AND PostToolUse
|
|
95
|
+
# doesn't trip the detector. Output format: "<event>\t<command>"
|
|
96
|
+
EVENT_CMDS=$(jq -r '
|
|
97
|
+
(.hooks // {}) | to_entries[] |
|
|
98
|
+
.key as $event |
|
|
99
|
+
(.value // []) | .[] |
|
|
100
|
+
((.hooks // []) | .[]) |
|
|
101
|
+
select(.command != null) |
|
|
102
|
+
($event + "\t" + (.command | tostring))
|
|
103
|
+
' "$HOOKS_FILE" 2>/dev/null) || continue
|
|
104
|
+
|
|
105
|
+
[ -z "$EVENT_CMDS" ] && continue
|
|
106
|
+
|
|
107
|
+
# Count duplicates per event+command pair
|
|
108
|
+
DUPES=$(printf '%s\n' "$EVENT_CMDS" | sort | uniq -c | awk -v t="$THRESHOLD" '$1 > t {print $0}')
|
|
109
|
+
|
|
110
|
+
if [ -n "$DUPES" ]; then
|
|
111
|
+
# Strip the canonical install root prefix for readability in the warning
|
|
112
|
+
DISPLAY_PATH="${HOOKS_FILE#$PLUGINS_ROOT/}"
|
|
113
|
+
FINDINGS+=("$DISPLAY_PATH")
|
|
114
|
+
FINDINGS+=("$DUPES")
|
|
115
|
+
FINDINGS+=("---")
|
|
116
|
+
fi
|
|
117
|
+
done < <(find "$PLUGINS_ROOT" -type f -name 'hooks.json' -path '*/hooks/*' -print0 2>/dev/null)
|
|
118
|
+
|
|
119
|
+
# No findings → silent exit
|
|
120
|
+
if [ "${#FINDINGS[@]}" -eq 0 ]; then
|
|
121
|
+
exit 0
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Debounce: only warn once per hour even if the session restarts repeatedly
|
|
125
|
+
NOW_S=$(date +%s)
|
|
126
|
+
LAST_WARN=0
|
|
127
|
+
if [ -f "$WARN_FILE" ]; then
|
|
128
|
+
LAST_WARN=$(cat "$WARN_FILE" 2>/dev/null || echo 0)
|
|
129
|
+
fi
|
|
130
|
+
HOUR_AGO=$((NOW_S - 3600))
|
|
131
|
+
if [ "$LAST_WARN" -gt "$HOUR_AGO" ] 2>/dev/null; then
|
|
132
|
+
exit 0
|
|
133
|
+
fi
|
|
134
|
+
printf '%s' "$NOW_S" > "$WARN_FILE" 2>/dev/null
|
|
135
|
+
|
|
136
|
+
# Emit advisory warning
|
|
137
|
+
cat >&2 <<EOF
|
|
138
|
+
|
|
139
|
+
⚠️ Plugin hooks.json bloat detected — duplicate hook registrations.
|
|
140
|
+
|
|
141
|
+
One or more installed plugins have a hooks.json file where the same command
|
|
142
|
+
string appears more than ${THRESHOLD} times within a single event bucket.
|
|
143
|
+
This is the fingerprint of the additive growth pattern documented in
|
|
144
|
+
anthropics/claude-code Issue #64022 — the harness's plugin-hook load/merge
|
|
145
|
+
path can re-run and append instead of replacing, causing each hook to fire
|
|
146
|
+
N times per tool call.
|
|
147
|
+
|
|
148
|
+
Findings:
|
|
149
|
+
EOF
|
|
150
|
+
|
|
151
|
+
for line in "${FINDINGS[@]}"; do
|
|
152
|
+
printf ' %s\n' "$line" >&2
|
|
153
|
+
done
|
|
154
|
+
|
|
155
|
+
cat >&2 <<EOF
|
|
156
|
+
|
|
157
|
+
What to do:
|
|
158
|
+
|
|
159
|
+
1. Restore canonical hooks.json from the plugin source (a fresh
|
|
160
|
+
reinstall of the plugin from its canonical marketplace usually works).
|
|
161
|
+
2. If the file regrows after restoration, file the recurrence against
|
|
162
|
+
anthropics/claude-code Issue #64022 with your version and a count.
|
|
163
|
+
3. Lower this hook's threshold if the false-positive rate is acceptable
|
|
164
|
+
for your environment (export CC_PLUGIN_HOOKS_BLOAT_THRESHOLD=3).
|
|
165
|
+
|
|
166
|
+
This warning is advisory. Set CC_PLUGIN_HOOKS_BLOAT_DISABLE=1 to silence.
|
|
167
|
+
EOF
|
|
168
|
+
|
|
169
|
+
exit 0
|
|
File without changes
|
|
@@ -21,6 +21,18 @@
|
|
|
21
21
|
# }
|
|
22
22
|
# }
|
|
23
23
|
|
|
24
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
25
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
26
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
27
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
28
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
29
|
+
_nojq_warned="/tmp/cc-nojq-warned-polyglot-rm-guard-$PPID"
|
|
30
|
+
[ -f "$_nojq_warned" ] || {
|
|
31
|
+
echo "WARNING [polyglot-rm-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
32
|
+
: > "$_nojq_warned"
|
|
33
|
+
}
|
|
34
|
+
fi
|
|
35
|
+
|
|
24
36
|
INPUT=$(cat)
|
|
25
37
|
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
26
38
|
[ -z "$CMD" ] && exit 0
|
|
@@ -27,6 +27,18 @@
|
|
|
27
27
|
#
|
|
28
28
|
# Config: CC_POST_COMPACT_GUARD=10 (block for first 10 calls after compact)
|
|
29
29
|
|
|
30
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
31
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
32
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
33
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
34
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
35
|
+
_nojq_warned="/tmp/cc-nojq-warned-post-compact-safety-$PPID"
|
|
36
|
+
[ -f "$_nojq_warned" ] || {
|
|
37
|
+
echo "WARNING [post-compact-safety]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
38
|
+
: > "$_nojq_warned"
|
|
39
|
+
}
|
|
40
|
+
fi
|
|
41
|
+
|
|
30
42
|
INPUT=$(cat)
|
|
31
43
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
32
44
|
[ -z "$COMMAND" ] && exit 0
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# post-edit-disk-verify.sh — Catch "Edit/Write reported success but didn't
|
|
3
|
+
# persist to disk" silent failures at the tool boundary.
|
|
4
|
+
#
|
|
5
|
+
# Solves: anthropics/claude-code#61303 — Windows MAX_PATH(260) + isolated
|
|
6
|
+
# worktree + deep nested path yielded an `Edit`/`Write` that reported success
|
|
7
|
+
# in-tool while the filesystem still showed the original content. The agent's
|
|
8
|
+
# `Read` reflected the "edited" state; the disk did not. A defensive
|
|
9
|
+
# verification step inside the dispatched subagent caught it, but the failure
|
|
10
|
+
# mode was invisible until that defensive step fired.
|
|
11
|
+
#
|
|
12
|
+
# The structural class is broader than the MAX_PATH trigger: any condition
|
|
13
|
+
# under which the harness reports a successful write but the on-disk content
|
|
14
|
+
# diverges from the claimed write should be caught at the tool boundary, not
|
|
15
|
+
# at the next session's read.
|
|
16
|
+
#
|
|
17
|
+
# Type: PostToolUse hook on Edit and Write.
|
|
18
|
+
#
|
|
19
|
+
# Decision rule:
|
|
20
|
+
#
|
|
21
|
+
# exit 0 — verification passed, or hook does not apply
|
|
22
|
+
# exit 2 — verification failed; stderr explains why and Claude sees it
|
|
23
|
+
#
|
|
24
|
+
# The hook is intentionally permissive on edge cases (Edit with no content
|
|
25
|
+
# field, ephemeral files, non-regular files) and intentionally strict on the
|
|
26
|
+
# specific divergence shape #61303 names.
|
|
27
|
+
#
|
|
28
|
+
# Configuration env vars:
|
|
29
|
+
#
|
|
30
|
+
# CC_POST_EDIT_VERIFY_DISABLE=1 — skip the hook entirely
|
|
31
|
+
# CC_POST_EDIT_VERIFY_QUIET=1 — exit 0 even on detected divergence,
|
|
32
|
+
# but still write the divergence to
|
|
33
|
+
# ~/.claude/receipts/post-edit-divergence.jsonl
|
|
34
|
+
# for audit (the "observe but don't gate"
|
|
35
|
+
# mode useful for first-week deployment)
|
|
36
|
+
|
|
37
|
+
set -u
|
|
38
|
+
|
|
39
|
+
# Read tool input from stdin (Claude Code passes a JSON envelope).
|
|
40
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
41
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
42
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
43
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
44
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
45
|
+
_nojq_warned="/tmp/cc-nojq-warned-post-edit-disk-verify-$PPID"
|
|
46
|
+
[ -f "$_nojq_warned" ] || {
|
|
47
|
+
echo "WARNING [post-edit-disk-verify]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
48
|
+
: > "$_nojq_warned"
|
|
49
|
+
}
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
INPUT=$(cat)
|
|
53
|
+
|
|
54
|
+
TOOL=$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
55
|
+
[[ -z "$TOOL" ]] && exit 0
|
|
56
|
+
[[ "$TOOL" != "Edit" && "$TOOL" != "Write" ]] && exit 0
|
|
57
|
+
|
|
58
|
+
# Honor the global disable.
|
|
59
|
+
[[ "${CC_POST_EDIT_VERIFY_DISABLE:-0}" == "1" ]] && exit 0
|
|
60
|
+
|
|
61
|
+
FILE=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty' 2>/dev/null)
|
|
62
|
+
[[ -z "$FILE" ]] && exit 0
|
|
63
|
+
|
|
64
|
+
# Helper: append a divergence record to the receipt log.
|
|
65
|
+
# Defined before first use — the missing-after-write path below calls it.
|
|
66
|
+
_record_divergence() {
|
|
67
|
+
local file="$1"
|
|
68
|
+
local tool="$2"
|
|
69
|
+
local kind="$3"
|
|
70
|
+
local msg="$4"
|
|
71
|
+
local dir="${CC_POST_EDIT_VERIFY_RECEIPT_DIR:-$HOME/.claude/receipts}"
|
|
72
|
+
mkdir -p "$dir" 2>/dev/null || return 0
|
|
73
|
+
local ts
|
|
74
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
75
|
+
# The missing-after-write path calls this for a file that does not exist,
|
|
76
|
+
# so guard the redirection to avoid a leaked "No such file" shell error.
|
|
77
|
+
local file_size=0
|
|
78
|
+
[ -f "$file" ] && file_size=$(wc -c < "$file" 2>/dev/null || echo 0)
|
|
79
|
+
printf '{"ts":"%s","tool":"%s","file":"%s","kind":"%s","file_size":%s}\n' \
|
|
80
|
+
"$ts" "$tool" "$file" "$kind" "$file_size" \
|
|
81
|
+
>> "$dir/post-edit-divergence.jsonl" 2>/dev/null || true
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# File must exist (Write may have created it; Edit always operates on existing).
|
|
85
|
+
[[ ! -e "$FILE" ]] && {
|
|
86
|
+
# If the tool reported success on a Write to a path that doesn't exist
|
|
87
|
+
# post-call, that is itself a divergence.
|
|
88
|
+
if [[ "$TOOL" == "Write" ]]; then
|
|
89
|
+
msg="post-edit-disk-verify: $TOOL claimed success on $FILE but file does not exist on disk (silent fail-to-persist; see anthropics/claude-code#61303)"
|
|
90
|
+
_record_divergence "$FILE" "$TOOL" "missing-after-write" "$msg"
|
|
91
|
+
if [[ "${CC_POST_EDIT_VERIFY_QUIET:-0}" != "1" ]]; then
|
|
92
|
+
echo "$msg" >&2
|
|
93
|
+
exit 2
|
|
94
|
+
fi
|
|
95
|
+
fi
|
|
96
|
+
exit 0
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# Regular file only (skip symlinks, sockets, devices).
|
|
100
|
+
[[ ! -f "$FILE" ]] && exit 0
|
|
101
|
+
|
|
102
|
+
# --- Check 1: Write with claimed content vs actual on-disk size ---
|
|
103
|
+
# If a Write claimed N bytes but disk shows much less, that is the
|
|
104
|
+
# strongest single signal of silent fail-to-persist.
|
|
105
|
+
if [[ "$TOOL" == "Write" ]]; then
|
|
106
|
+
CLAIMED=$(printf '%s' "$INPUT" | jq -r '.tool_input.content // ""' 2>/dev/null)
|
|
107
|
+
CLAIMED_LEN=${#CLAIMED}
|
|
108
|
+
ACTUAL_LEN=$(wc -c < "$FILE" 2>/dev/null || echo 0)
|
|
109
|
+
|
|
110
|
+
# Only fire when claimed content is non-trivial (avoid empty-write false positives).
|
|
111
|
+
if [[ "$CLAIMED_LEN" -gt 100 ]]; then
|
|
112
|
+
# Allow up to 2x slack for CRLF / encoding / final newline differences,
|
|
113
|
+
# but a >50% shortfall is highly suggestive of fail-to-persist.
|
|
114
|
+
if [[ "$ACTUAL_LEN" -lt $((CLAIMED_LEN / 2)) ]]; then
|
|
115
|
+
msg="post-edit-disk-verify: Write to $FILE claimed $CLAIMED_LEN bytes but disk shows $ACTUAL_LEN bytes (>50% shortfall — likely silent fail-to-persist per anthropics/claude-code#61303). Check Windows MAX_PATH (260) on Windows, deep worktrees, or filesystem encoding."
|
|
116
|
+
_record_divergence "$FILE" "$TOOL" "size-shortfall" "$msg"
|
|
117
|
+
if [[ "${CC_POST_EDIT_VERIFY_QUIET:-0}" != "1" ]]; then
|
|
118
|
+
echo "$msg" >&2
|
|
119
|
+
exit 2
|
|
120
|
+
fi
|
|
121
|
+
fi
|
|
122
|
+
fi
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
# --- Check 2: Edit with no diff in git ---
|
|
126
|
+
# If an Edit reported success on a git-tracked file and produces no diff,
|
|
127
|
+
# either the Edit was a no-op (legitimate) or the change failed to persist.
|
|
128
|
+
# The hook treats a "claimed-non-trivial Edit with no diff" as the latter.
|
|
129
|
+
if [[ "$TOOL" == "Edit" ]]; then
|
|
130
|
+
NEW=$(printf '%s' "$INPUT" | jq -r '.tool_input.new_string // ""' 2>/dev/null)
|
|
131
|
+
OLD=$(printf '%s' "$INPUT" | jq -r '.tool_input.old_string // ""' 2>/dev/null)
|
|
132
|
+
|
|
133
|
+
# Only check if old_string != new_string (a real claimed change).
|
|
134
|
+
if [[ -n "$NEW" && "$NEW" != "$OLD" ]]; then
|
|
135
|
+
# Find git root for the file's directory.
|
|
136
|
+
FILE_DIR=$(dirname "$FILE")
|
|
137
|
+
if git -C "$FILE_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
138
|
+
# File is in a git repo. Check whether the new_string appears in
|
|
139
|
+
# the on-disk content. If not, the Edit did not persist.
|
|
140
|
+
if ! grep -F -q -- "$NEW" "$FILE" 2>/dev/null; then
|
|
141
|
+
msg="post-edit-disk-verify: Edit on $FILE claimed to insert content that is not found in the on-disk file (silent fail-to-persist per anthropics/claude-code#61303). Either the Edit did not land, or in-tool Read is showing stale-cached content."
|
|
142
|
+
_record_divergence "$FILE" "$TOOL" "edit-not-in-file" "$msg"
|
|
143
|
+
if [[ "${CC_POST_EDIT_VERIFY_QUIET:-0}" != "1" ]]; then
|
|
144
|
+
echo "$msg" >&2
|
|
145
|
+
exit 2
|
|
146
|
+
fi
|
|
147
|
+
fi
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
exit 0
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# powershell-remove-item-guard.sh — Block PowerShell recursive deletion that traverses junctions
|
|
3
|
+
#
|
|
4
|
+
# Solves: Remove-Item -Recurse -Force on pnpm worktrees traverses NTFS junctions,
|
|
5
|
+
# permanently deleting user profile folders and source code (#29249).
|
|
6
|
+
# Also prevents wholesale C: drive deletion via PowerShell (#41708).
|
|
7
|
+
#
|
|
8
|
+
# How it works: Intercepts shell-tool commands containing PowerShell Remove-Item patterns.
|
|
9
|
+
# Hard blocks refuse with exit 2. Measured 2026-09-19 on 2.1.278, PreToolUse,
|
|
10
|
+
# against a do-nothing control: a body of {"decision":"block"} does refuse, and
|
|
11
|
+
# {"decision":"DENY"} and {"decision":"deny"} are both ignored - the hook runs,
|
|
12
|
+
# prints its reason, exits 0, and the command goes through anyway.
|
|
13
|
+
# Hard-blocks when -Recurse targets system directories, user profiles, or paths
|
|
14
|
+
# that could traverse NTFS junctions (node_modules, .pnpm). For -Recurse -Force on
|
|
15
|
+
# any other absolute drive/UNC path it asks for confirmation instead of blocking —
|
|
16
|
+
# the case that destroyed ~34 client video files in #64310 (D:\Clientes\...) where
|
|
17
|
+
# -Force bypassed the Recycle Bin and no confirmation was requested.
|
|
18
|
+
#
|
|
19
|
+
# TRIGGER: PreToolUse
|
|
20
|
+
# MATCHER: "Bash|PowerShell"
|
|
21
|
+
# Claude Code's PowerShell tool is separate from Bash. Register with
|
|
22
|
+
# matcher "Bash|PowerShell" so Remove-Item run through the native
|
|
23
|
+
# PowerShell tool is inspected too — a Bash-only matcher never fires
|
|
24
|
+
# on the PowerShell tool (#69397). The command is read from
|
|
25
|
+
# tool_input.command, which both tools populate.
|
|
26
|
+
|
|
27
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
28
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
29
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
30
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
31
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
32
|
+
_nojq_warned="/tmp/cc-nojq-warned-powershell-remove-item-guard-$PPID"
|
|
33
|
+
[ -f "$_nojq_warned" ] || {
|
|
34
|
+
echo "WARNING [powershell-remove-item-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
35
|
+
: > "$_nojq_warned"
|
|
36
|
+
}
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
INPUT=$(cat)
|
|
40
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
41
|
+
[ -z "$COMMAND" ] && exit 0
|
|
42
|
+
|
|
43
|
+
# Only check commands containing Remove-Item or ri (PowerShell alias)
|
|
44
|
+
echo "$COMMAND" | grep -qiE '(Remove-Item|ri\s|del\s).*-Recurse' || exit 0
|
|
45
|
+
|
|
46
|
+
# Block if targeting system-critical paths
|
|
47
|
+
if echo "$COMMAND" | grep -qiE 'Remove-Item.*-Recurse.*(/|\\)(Users|Windows|Program Files|System32|C:\\|/mnt/c)'; then
|
|
48
|
+
echo "BLOCKED: Remove-Item -Recurse targeting system directory. NTFS junctions can traverse to user profiles (#29249)." >&2
|
|
49
|
+
exit 2
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# Block if targeting node_modules with -Force (junction traversal risk)
|
|
53
|
+
if echo "$COMMAND" | grep -qiE 'Remove-Item.*-Recurse.*-Force.*(node_modules|\.pnpm|worktree)'; then
|
|
54
|
+
echo "BLOCKED: Remove-Item -Recurse -Force on directory with potential NTFS junctions. Use rimraf or manual junction resolution first (#29249)." >&2
|
|
55
|
+
exit 2
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Block if targeting home directory patterns
|
|
59
|
+
if echo "$COMMAND" | grep -qiE 'Remove-Item.*-Recurse.*(\$HOME|\$env:USERPROFILE|~\/|~\\)'; then
|
|
60
|
+
echo "BLOCKED: Remove-Item -Recurse targeting home directory. Risk of irreversible data loss (#41708)." >&2
|
|
61
|
+
exit 2
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# Confirm before -Recurse -Force on any other absolute drive/UNC path.
|
|
65
|
+
# The hard blocks above only cover system, junction, and home targets. The case
|
|
66
|
+
# that destroyed ~34 client video files in #64310 was Remove-Item -Recurse -Force on
|
|
67
|
+
# an ordinary data path (D:\Clientes\...) — none of the above matched, -Force bypassed
|
|
68
|
+
# the Recycle Bin, and no confirmation was requested (SSD/TRIM made it unrecoverable).
|
|
69
|
+
# Use "ask" rather than a hard block so routine build/dependency cleanup just gets one
|
|
70
|
+
# confirmation instead of being denied; relative paths (./build) don't trigger at all.
|
|
71
|
+
# VERSION NOTE (measured 2026-08-13 on 2.1.228; this comment used to say the
|
|
72
|
+
# reverse): #77212 reported that under bypassPermissions an "ask" is silently
|
|
73
|
+
# auto-approved, so this confirmation would never appear. It does not reproduce
|
|
74
|
+
# on 2.1.228 — interactively the confirmation appears under both
|
|
75
|
+
# --dangerously-skip-permissions and --permission-mode auto, and non-interactively
|
|
76
|
+
# (claude -p) the call is refused rather than approved. Control: with the hook
|
|
77
|
+
# removed, both permissive modes ran the command unprompted. Older builds may
|
|
78
|
+
# still match the report; check your own --version. What does not change: an
|
|
79
|
+
# "ask" needs someone present to answer it, so in genuinely unattended runs the
|
|
80
|
+
# hard blocks above (exit 2) are what hold.
|
|
81
|
+
if echo "$COMMAND" | grep -qiE '\-Force' \
|
|
82
|
+
&& echo "$COMMAND" | grep -qiE '[A-Za-z]:[\\/]|\\\\[A-Za-z0-9]'; then
|
|
83
|
+
printf '%s\n' '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":"Confirm: Remove-Item -Recurse -Force on an absolute path. -Force bypasses the Recycle Bin and is unrecoverable on SSD/TRIM. Verify the target path is correct (and that any move/copy finished) before deleting (#64310)."}}'
|
|
84
|
+
exit 0
|
|
85
|
+
fi
|
|
File without changes
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
3
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
4
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
5
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
6
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
7
|
+
_nojq_warned="/tmp/cc-nojq-warned-pr-duplicate-guard-$PPID"
|
|
8
|
+
[ -f "$_nojq_warned" ] || {
|
|
9
|
+
echo "WARNING [pr-duplicate-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
10
|
+
: > "$_nojq_warned"
|
|
11
|
+
}
|
|
12
|
+
fi
|
|
13
|
+
|
|
1
14
|
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
2
15
|
[ -z "$COMMAND" ] && exit 0
|
|
3
16
|
echo "$COMMAND" | grep -qE '\bgh\s+pr\s+create\b' || exit 0
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# pre-bash-sed-line-ending-windows.sh — Block sed -i on Windows/Git Bash
|
|
3
|
+
#
|
|
4
|
+
# Solves: sed -i silently converts CRLF→LF on Windows (#63715).
|
|
5
|
+
# The conversion is invisible in file content but breaks
|
|
6
|
+
# tools expecting CRLF (XML manifests, .NET configs, batch
|
|
7
|
+
# files). Reporter lost 4 hours debugging an XML parser
|
|
8
|
+
# that failed silently after sed edited it.
|
|
9
|
+
#
|
|
10
|
+
# How it works: PreToolUse hook on Bash tool that detects sed -i
|
|
11
|
+
# patterns on Windows/Git Bash environments and blocks the call
|
|
12
|
+
# with a structured suggestion (Edit tool, PowerShell Set-Content,
|
|
13
|
+
# or manual dos2unix/unix2dos preservation).
|
|
14
|
+
#
|
|
15
|
+
# Linux/macOS environments are skipped — sed -i is safe there.
|
|
16
|
+
#
|
|
17
|
+
# Override: Set CC_ALLOW_SED_LINE_ENDING_CHANGE=1 to bypass when
|
|
18
|
+
# the LF conversion is intentional (e.g., converting a Windows
|
|
19
|
+
# file to Unix line endings on purpose).
|
|
20
|
+
#
|
|
21
|
+
# TRIGGER: PreToolUse
|
|
22
|
+
# MATCHER: Bash
|
|
23
|
+
|
|
24
|
+
set -euo pipefail
|
|
25
|
+
|
|
26
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
27
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
28
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
29
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
30
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
31
|
+
_nojq_warned="/tmp/cc-nojq-warned-pre-bash-sed-line-ending-windows-$PPID"
|
|
32
|
+
[ -f "$_nojq_warned" ] || {
|
|
33
|
+
echo "WARNING [pre-bash-sed-line-ending-windows]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
34
|
+
: > "$_nojq_warned"
|
|
35
|
+
}
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
INPUT=$(cat)
|
|
39
|
+
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null || echo "")
|
|
40
|
+
[ -z "$CMD" ] && exit 0
|
|
41
|
+
|
|
42
|
+
# Detect Windows/Git Bash environment. uname -s returns MINGW*/MSYS*/CYGWIN*
|
|
43
|
+
# on Git Bash, MSYS2, and Cygwin respectively. Linux/macOS are skipped because
|
|
44
|
+
# sed -i preserves the original LF line endings there.
|
|
45
|
+
case "$(uname -s 2>/dev/null)" in
|
|
46
|
+
MINGW*|MSYS*|CYGWIN*)
|
|
47
|
+
;;
|
|
48
|
+
*)
|
|
49
|
+
exit 0
|
|
50
|
+
;;
|
|
51
|
+
esac
|
|
52
|
+
|
|
53
|
+
# Match `sed -i`, `sed -i ''`, `sed --in-place`. Pattern allows leading flags
|
|
54
|
+
# like `sed -E -i` and ensures -i is a complete flag (not part of -inplace=...).
|
|
55
|
+
if echo "$CMD" | grep -qE '\bsed\b[^|;&]*[[:space:]]-(i\b|-in-place)'; then
|
|
56
|
+
# Honor explicit opt-in for intentional LF conversion.
|
|
57
|
+
if [ "${CC_ALLOW_SED_LINE_ENDING_CHANGE:-}" = "1" ]; then
|
|
58
|
+
echo "[INFO] sed -i allowed via CC_ALLOW_SED_LINE_ENDING_CHANGE=1" >&2
|
|
59
|
+
exit 0
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
cat >&2 <<'EOF'
|
|
63
|
+
BLOCKED: sed -i on Windows/Git Bash silently converts CRLF to LF line endings.
|
|
64
|
+
|
|
65
|
+
This breaks files that expect CRLF (XML manifests, .NET configs, batch files,
|
|
66
|
+
.csproj, .vbproj, .sln, .reg files, etc.) without any warning or error. The
|
|
67
|
+
content looks identical in every visual inspection. Documented at
|
|
68
|
+
anthropics/claude-code#63715 with a 4-hour XML manifest debugging incident.
|
|
69
|
+
|
|
70
|
+
Use one of these instead:
|
|
71
|
+
|
|
72
|
+
1. The Edit tool — preserves the file's existing line endings.
|
|
73
|
+
|
|
74
|
+
2. PowerShell:
|
|
75
|
+
(Get-Content file) -replace 'pattern','replacement' | Set-Content file
|
|
76
|
+
Or with -NoNewline to avoid adding a trailing newline.
|
|
77
|
+
|
|
78
|
+
3. Manual line-ending preservation:
|
|
79
|
+
dos2unix file && sed -i 's/old/new/g' file && unix2dos file
|
|
80
|
+
|
|
81
|
+
If you intentionally want to convert this file to LF, bypass with:
|
|
82
|
+
CC_ALLOW_SED_LINE_ENDING_CHANGE=1 sed -i ...
|
|
83
|
+
EOF
|
|
84
|
+
exit 2
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
exit 0
|
|
File without changes
|
|
File without changes
|