cc-safe-setup 29.7.0 → 30.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1022) hide show
  1. package/.claude-plugin/marketplace.json +72 -19
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CONTRIBUTING.md +7 -2
  4. package/COOKBOOK.md +50 -46
  5. package/LICENSE +21 -0
  6. package/MIGRATION.md +8 -8
  7. package/README.md +419 -512
  8. package/SAFETY_CHECKLIST.md +15 -7
  9. package/SERVICES.md +194 -0
  10. package/SETTINGS_REFERENCE.md +236 -17
  11. package/SKILL.md +5 -5
  12. package/TROUBLESHOOTING.md +35 -14
  13. package/action.yml +12 -4
  14. package/audit/README.md +84 -0
  15. package/audit/audit-checklist.md +152 -0
  16. package/audit/boundary-selftest.sh +85 -0
  17. package/audit/boundary.sh +123 -0
  18. package/audit/count-hooks.py +42 -0
  19. package/audit/find-dead-hooks.sh +82 -0
  20. package/audit/find-unfirable-rules.sh +142 -0
  21. package/audit/fire.sh +97 -0
  22. package/audit/selftest.sh +42 -0
  23. package/audit/unfirable-selftest.sh +81 -0
  24. package/audit-web/index.html +9 -9
  25. package/examples/README.md +54 -17
  26. package/examples/account-billing-log.sh +98 -0
  27. package/examples/account-routing-preflight.sh +123 -0
  28. package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
  29. package/examples/agent-view-quota-decrement.sh +32 -0
  30. package/examples/agent-view-quota-warn.sh +94 -0
  31. package/examples/agents-md-edit-drift-warner.sh +223 -0
  32. package/examples/agents-md-loader.sh +160 -0
  33. package/examples/agents-md-sync-checker.sh +102 -0
  34. package/examples/ai-slop-punctuation-arrest.sh +210 -0
  35. package/examples/allowlist.sh +70 -10
  36. package/examples/always-allow-pattern-suggester.sh +125 -0
  37. package/examples/ansible-vault-guard.sh +2 -1
  38. package/examples/anthropic-base-url-guard.sh +76 -0
  39. package/examples/api-busyloop-guard.sh +123 -0
  40. package/examples/api-endpoint-guard.sh +12 -0
  41. package/examples/api-key-in-url-guard.sh +17 -1
  42. package/examples/api-rate-limit-guard.sh +36 -1
  43. package/examples/api-rate-limit-tracker.sh +12 -0
  44. package/examples/articulated-scope-capture.sh +101 -0
  45. package/examples/askuserquestion-autonomy-gate.sh +102 -0
  46. package/examples/attachment-traversal-guard.sh +118 -0
  47. package/examples/aup-block-pattern-logger.sh +161 -0
  48. package/examples/aup-false-positive-helper.sh +124 -0
  49. package/examples/aup-large-tool-output-warner.sh +282 -0
  50. package/examples/aup-retry-loop-guard.sh +229 -0
  51. package/examples/auth-expiry-reminder.sh +157 -0
  52. package/examples/auth-macos-sleep-detector.sh +185 -0
  53. package/examples/auth-path-detector.sh +171 -0
  54. package/examples/auth-status-checker.sh +157 -0
  55. package/examples/authorized-reconfirmation-detector.sh +195 -0
  56. package/examples/auto-approve-build.sh +39 -0
  57. package/examples/auto-approve-cargo.sh +31 -1
  58. package/examples/auto-approve-docker.sh +35 -0
  59. package/examples/auto-approve-git-read.sh +37 -14
  60. package/examples/auto-approve-go.sh +30 -1
  61. package/examples/auto-approve-gradle.sh +29 -1
  62. package/examples/auto-approve-make.sh +29 -1
  63. package/examples/auto-approve-maven.sh +29 -1
  64. package/examples/auto-approve-python.sh +41 -1
  65. package/examples/auto-approve-readonly-tools.sh +1 -0
  66. package/examples/auto-approve-readonly.sh +110 -33
  67. package/examples/auto-approve-ssh.sh +30 -1
  68. package/examples/auto-approve-test.sh +44 -0
  69. package/examples/auto-checkpoint.sh +1 -1
  70. package/examples/auto-compact-prep.sh +0 -0
  71. package/examples/auto-git-checkpoint.sh +0 -0
  72. package/examples/auto-mode-safe-commands.sh +53 -1
  73. package/examples/auto-mode-safety-enforcer.sh +151 -4
  74. package/examples/auto-push-session-branch.sh +22 -0
  75. package/examples/aws-production-guard.sh +13 -1
  76. package/examples/aws-region-guard.sh +1 -1
  77. package/examples/background-cost-launch-guard.sh +82 -0
  78. package/examples/background-task-guard.sh +12 -0
  79. package/examples/backup-before-refactor.sh +0 -0
  80. package/examples/banned-command-guard.sh +12 -0
  81. package/examples/bash-allowlist-secondary-check.sh +157 -0
  82. package/examples/bash-domain-allowlist.sh +12 -0
  83. package/examples/bash-fanout-bounded-rewriter.sh +191 -0
  84. package/examples/bash-heuristic-approver.sh +112 -10
  85. package/examples/bash-project-fence.sh +194 -0
  86. package/examples/bash-safety-auto-deny.sh +12 -0
  87. package/examples/bash-secret-output-detector.sh +44 -3
  88. package/examples/bash-trace-guard.sh +12 -0
  89. package/examples/bashrc-safety-check.sh +0 -0
  90. package/examples/bg-permission-prompt-warner.sh +182 -0
  91. package/examples/bg-task-cooldown-guard.sh +12 -0
  92. package/examples/binary-read-detector.sh +135 -0
  93. package/examples/binary-upload-guard.sh +12 -0
  94. package/examples/block-database-wipe.sh +35 -10
  95. package/examples/branch-name-check.sh +8 -3
  96. package/examples/branch-naming-convention.sh +0 -0
  97. package/examples/broad-find-guard.sh +12 -0
  98. package/examples/broad-prefix-session-trap-warner.sh +106 -0
  99. package/examples/bulk-file-delete-guard.sh +45 -0
  100. package/examples/bypass-mode-effective-verifier.sh +203 -0
  101. package/examples/cache-creation-drift-detector.sh +120 -0
  102. package/examples/cache-residue-detector.sh +195 -0
  103. package/examples/cache-tier-logger.sh +70 -0
  104. package/examples/cache-ttl-eviction-detector.sh +149 -0
  105. package/examples/cargo-publish-guard.sh +14 -1
  106. package/examples/case-insensitive-path-guard.sh +21 -2
  107. package/examples/case-sensitive-guard.sh +23 -2
  108. package/examples/cch-cache-guard.sh +0 -0
  109. package/examples/cch-sentinel-precommit-guard.sh +47 -0
  110. package/examples/check-abort-controller.sh +1 -1
  111. package/examples/check-accessibility.sh +0 -0
  112. package/examples/check-aria-labels.sh +0 -0
  113. package/examples/check-before-act-enforcer.sh +12 -0
  114. package/examples/check-charset-meta.sh +0 -0
  115. package/examples/check-cookie-flags.sh +0 -0
  116. package/examples/check-cors-config.sh +0 -0
  117. package/examples/check-csp-headers.sh +0 -0
  118. package/examples/check-csrf-protection.sh +0 -0
  119. package/examples/check-debounce.sh +1 -1
  120. package/examples/check-dependency-age.sh +0 -0
  121. package/examples/check-dependency-license.sh +0 -0
  122. package/examples/check-dockerfile-best-practice.sh +0 -0
  123. package/examples/check-error-boundaries.sh +0 -0
  124. package/examples/check-error-class.sh +1 -1
  125. package/examples/check-error-handling.sh +0 -0
  126. package/examples/check-error-logging.sh +1 -1
  127. package/examples/check-error-message.sh +0 -0
  128. package/examples/check-error-stack.sh +0 -0
  129. package/examples/check-favicon.sh +0 -0
  130. package/examples/check-git-hooks-compat.sh +0 -0
  131. package/examples/check-gitattributes.sh +0 -0
  132. package/examples/check-https-redirect.sh +0 -0
  133. package/examples/check-input-validation.sh +0 -0
  134. package/examples/check-lang-attribute.sh +0 -0
  135. package/examples/check-npm-scripts-exist.sh +0 -0
  136. package/examples/check-package-size.sh +0 -0
  137. package/examples/check-port-availability.sh +0 -0
  138. package/examples/check-promise-all.sh +1 -1
  139. package/examples/check-rate-limiting.sh +0 -0
  140. package/examples/check-return-types.sh +0 -0
  141. package/examples/check-semantic-versioning.sh +0 -0
  142. package/examples/check-suspense-fallback.sh +1 -1
  143. package/examples/check-test-exists.sh +0 -0
  144. package/examples/check-test-naming.sh +0 -0
  145. package/examples/check-timeout-cleanup.sh +1 -1
  146. package/examples/check-tls-version.sh +0 -0
  147. package/examples/check-unsubscribe.sh +1 -1
  148. package/examples/check-viewport-meta.sh +0 -0
  149. package/examples/check-worker-terminate.sh +1 -1
  150. package/examples/checkpoint-tamper-guard.sh +12 -0
  151. package/examples/chmod-guard.sh +12 -0
  152. package/examples/chown-guard.sh +24 -0
  153. package/examples/ci-workflow-guard.sh +6 -1
  154. package/examples/claim-verify-detector.sh +109 -0
  155. package/examples/claim-vs-caveat-checker.sh +77 -0
  156. package/examples/classifier-fallback-allow.sh +114 -40
  157. package/examples/claude-cache-gc.sh +1 -0
  158. package/examples/claude-code-version-pin-advisor.sh +183 -0
  159. package/examples/claude-md-reinjector.sh +129 -0
  160. package/examples/claude-md-size-monitor.sh +66 -0
  161. package/examples/claude-update-budget-guard.sh +123 -0
  162. package/examples/claude-update-smart.sh +113 -0
  163. package/examples/claudeignore-enforce-guard.sh +12 -0
  164. package/examples/claudemd-enforcer.sh +0 -0
  165. package/examples/claudemd-tool-prohibition.sh +128 -0
  166. package/examples/clear-command-confirm-guard.sh +32 -15
  167. package/examples/cli-config-pinning-detector.sh +162 -0
  168. package/examples/cliff-countdown-advisor.sh +96 -0
  169. package/examples/clipboard-secret-guard.sh +12 -0
  170. package/examples/closure-word-verify-gate.sh +150 -0
  171. package/examples/cloud-cli-guard.sh +39 -2
  172. package/examples/commit-all-scope-guard.sh +44 -0
  173. package/examples/commit-message-check.sh +1 -1
  174. package/examples/commit-message-quality.sh +6 -1
  175. package/examples/commitment-carry-forward-arrest.sh +361 -0
  176. package/examples/compact-alert-notification.sh +0 -0
  177. package/examples/compact-circuit-breaker.sh +72 -0
  178. package/examples/compact-dispatch-watchdog.sh +149 -0
  179. package/examples/completion-claim-without-verification-detector.sh +207 -0
  180. package/examples/composer-guard.sh +12 -0
  181. package/examples/compound-bash-permission-resolver.sh +156 -0
  182. package/examples/compound-command-allow.sh +1 -1
  183. package/examples/compound-command-deny-enforcer.sh +183 -0
  184. package/examples/compound-inject-guard.sh +12 -0
  185. package/examples/concurrent-edit-lock.sh +12 -0
  186. package/examples/conflict-marker-guard.sh +12 -0
  187. package/examples/consecutive-error-breaker.sh +0 -0
  188. package/examples/console-log-count.sh +1 -0
  189. package/examples/context-compact-advisor.sh +29 -2
  190. package/examples/context-length-budget.sh +69 -0
  191. package/examples/context-threshold-alert.sh +12 -0
  192. package/examples/context-usage-drift-alert.sh +41 -13
  193. package/examples/conversation-history-guard.sh +12 -0
  194. package/examples/core-file-protect-guard.sh +12 -0
  195. package/examples/cors-star-warn.sh +0 -0
  196. package/examples/cost-incident-self-audit.sh +162 -0
  197. package/examples/cowork-claude-md-load-checker.sh +100 -0
  198. package/examples/cowork-fuse-staleness-watcher.sh +140 -0
  199. package/examples/cowork-hook-absence-warner.sh +167 -0
  200. package/examples/cowork-model-picker-advisor.sh +115 -0
  201. package/examples/credential-exfil-guard.sh +65 -4
  202. package/examples/credential-file-cat-guard.sh +17 -1
  203. package/examples/cron-create-receipt.sh +112 -0
  204. package/examples/cron-modification-guard.sh +12 -0
  205. package/examples/cross-product-mcp-spawn-detector.sh +178 -0
  206. package/examples/cwd-project-boundary-guard.sh +0 -0
  207. package/examples/daemon-zombie-worker-surfacer.sh +118 -0
  208. package/examples/daily-cost-guard.sh +164 -0
  209. package/examples/daily-usage-tracker.sh +0 -0
  210. package/examples/dangerous-pip-flag-guard.sh +12 -0
  211. package/examples/db-connect-guard.sh +13 -1
  212. package/examples/denied-action-retry-guard.sh +12 -0
  213. package/examples/deny-bypass-detector.sh +12 -0
  214. package/examples/deny-rule-integrity-verifier.sh +181 -0
  215. package/examples/dependency-install-guard.sh +12 -0
  216. package/examples/deploy-guard.sh +14 -2
  217. package/examples/deploy-path-verify-guard.sh +12 -0
  218. package/examples/deployment-readback-gate.sh +135 -0
  219. package/examples/deployment-readback-gh-adapter.sh +247 -0
  220. package/examples/deployment-verify-guard.sh +25 -2
  221. package/examples/destructive-db-script-write-guard.sh +166 -0
  222. package/examples/destructive-migration-write-guard.sh +163 -0
  223. package/examples/diff-size-guard.sh +12 -0
  224. package/examples/disabled-feature-toggle-advisor.sh +88 -0
  225. package/examples/disk-partition-guard.sh +12 -0
  226. package/examples/dispatch-allowlist-preflight.sh +301 -0
  227. package/examples/dispatch-liveness-watchdog.sh +216 -0
  228. package/examples/dispatch-receipt.sh +174 -0
  229. package/examples/django-migrate-guard.sh +12 -0
  230. package/examples/dns-config-guard.sh +12 -0
  231. package/examples/docker-dangerous-guard.sh +12 -0
  232. package/examples/docker-volume-guard.sh +0 -0
  233. package/examples/dockerfile-latest-guard.sh +1 -0
  234. package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
  235. package/examples/dotenv-commit-guard.sh +12 -0
  236. package/examples/dotenv-read-guard.sh +12 -0
  237. package/examples/dotfile-protection-guard.sh +12 -0
  238. package/examples/dotnet-build-on-edit.sh +1 -1
  239. package/examples/drizzle-migrate-guard.sh +27 -2
  240. package/examples/echo-probe-spam-detector.sh +176 -0
  241. package/examples/edit-counter-test-gate.sh +12 -0
  242. package/examples/edit-error-counter.sh +1 -1
  243. package/examples/edit-guard.sh +12 -0
  244. package/examples/edit-old-string-validator.sh +12 -0
  245. package/examples/edit-quote-ambiguity-guard.sh +97 -0
  246. package/examples/edit-retry-loop-guard.sh +0 -0
  247. package/examples/edit-verify.sh +0 -0
  248. package/examples/env-inline-secret-guard.sh +14 -2
  249. package/examples/env-naming-convention.sh +0 -0
  250. package/examples/env-prod-guard.sh +0 -0
  251. package/examples/env-required-check.sh +0 -0
  252. package/examples/env-source-guard.sh +12 -0
  253. package/examples/env-var-check.sh +24 -1
  254. package/examples/ephemeral-container-detector.sh +147 -0
  255. package/examples/error-memory-guard.sh +12 -0
  256. package/examples/evidence-claim-gate.sh +187 -0
  257. package/examples/exploration-budget-guard.sh +89 -0
  258. package/examples/expo-eject-guard.sh +13 -0
  259. package/examples/extended-thinking-loop-guard.sh +139 -0
  260. package/examples/extended-thinking-resume-warning.sh +119 -0
  261. package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
  262. package/examples/fabricated-command-detector.sh +145 -0
  263. package/examples/false-disk-full-guard.sh +63 -0
  264. package/examples/feature-deprecation-detector.sh +109 -0
  265. package/examples/file-change-tracker.sh +1 -1
  266. package/examples/file-change-undo-tracker.sh +0 -0
  267. package/examples/file-edit-backup.sh +63 -14
  268. package/examples/file-reference-check.sh +0 -0
  269. package/examples/file-size-limit.sh +12 -0
  270. package/examples/financial-operation-guard.sh +12 -0
  271. package/examples/firewall-guard.sh +12 -0
  272. package/examples/fish-shell-wrapper.sh +125 -7
  273. package/examples/five-hundred-milestone.sh +1 -0
  274. package/examples/flask-static-route-guard.sh +89 -0
  275. package/examples/forbidden-response-phrase-detector.sh +161 -0
  276. package/examples/gem-push-guard.sh +13 -0
  277. package/examples/gh-cli-destructive-guard.sh +13 -1
  278. package/examples/git-checkout-safety-guard.sh +12 -0
  279. package/examples/git-checkout-uncommitted-guard.sh +12 -0
  280. package/examples/git-config-guard.sh +12 -0
  281. package/examples/git-crypt-worktree-guard.sh +12 -0
  282. package/examples/git-filter-repo-guard.sh +56 -0
  283. package/examples/git-history-rewrite-guard.sh +12 -0
  284. package/examples/git-hook-bypass-guard.sh +0 -0
  285. package/examples/git-maintenance-guard.sh +83 -0
  286. package/examples/git-merge-conflict-prevent.sh +0 -0
  287. package/examples/git-message-length-check.sh +0 -0
  288. package/examples/git-message-length.sh +0 -0
  289. package/examples/git-operations-require-approval.sh +68 -14
  290. package/examples/git-pack-temp-cleanup-guard.sh +102 -0
  291. package/examples/git-push-blast-radius-guard.sh +218 -0
  292. package/examples/git-remote-guard.sh +24 -3
  293. package/examples/git-rm-orphan-wipe-guard.sh +85 -0
  294. package/examples/git-stash-before-checkout.sh +12 -0
  295. package/examples/git-stash-before-danger.sh +0 -0
  296. package/examples/git-submodule-guard.sh +69 -2
  297. package/examples/git-tag-guard.sh +12 -0
  298. package/examples/github-actions-secret-guard.sh +0 -0
  299. package/examples/gitignore-check.sh +0 -0
  300. package/examples/gitops-drift-guard.sh +12 -0
  301. package/examples/go-mod-tidy-warn.sh +1 -0
  302. package/examples/go-vet-after-edit.sh +12 -0
  303. package/examples/goal-iteration-limit-warner.sh +152 -0
  304. package/examples/grep-nul-false-negative-guard.sh +30 -0
  305. package/examples/growthbook-flag-monitor.sh +257 -0
  306. package/examples/hallucination-url-check.sh +1 -1
  307. package/examples/halt-signal-detector.sh +135 -0
  308. package/examples/handoff-on-clear.sh +65 -0
  309. package/examples/hardcoded-ip-guard.sh +1 -0
  310. package/examples/headless-empty-result-guard.sh +0 -0
  311. package/examples/headless-stop-guard.sh +0 -0
  312. package/examples/helm-install-guard.sh +2 -1
  313. package/examples/home-critical-bash-guard.sh +17 -1
  314. package/examples/hook-debug-wrapper.sh +6 -2
  315. package/examples/hook-permission-fixer.sh +0 -0
  316. package/examples/hook-self-disable-detector.sh +99 -0
  317. package/examples/hook-stdout-sanitizer.sh +6 -2
  318. package/examples/hook-tamper-guard.sh +12 -0
  319. package/examples/idle-session-cost-alert.sh +0 -0
  320. package/examples/image-dimension-guard.sh +109 -0
  321. package/examples/image-file-validator.sh +0 -0
  322. package/examples/iteration-quality-degradation-detector.sh +170 -0
  323. package/examples/java-compile-on-edit.sh +1 -1
  324. package/examples/json-syntax-check.sh +0 -0
  325. package/examples/k8s-production-guard.sh +13 -1
  326. package/examples/kill-process-guard.sh +12 -0
  327. package/examples/kubernetes-guard.sh +13 -1
  328. package/examples/laravel-artisan-guard.sh +13 -0
  329. package/examples/large-file-guard.sh +1 -1
  330. package/examples/log-level-guard.sh +0 -0
  331. package/examples/log-truncation-guard.sh +12 -0
  332. package/examples/long-session-malformed-tool-call-detector.sh +183 -0
  333. package/examples/loop-detector.sh +12 -0
  334. package/examples/magic-number-warn.sh +1 -0
  335. package/examples/main-branch-warn.sh +12 -0
  336. package/examples/markdown-link-check.sh +0 -0
  337. package/examples/max-concurrent-agents.sh +12 -0
  338. package/examples/max-edit-size-guard.sh +13 -0
  339. package/examples/max-file-count-guard.sh +0 -0
  340. package/examples/max-file-delete-count.sh +0 -0
  341. package/examples/max-function-length.sh +1 -0
  342. package/examples/max-import-count.sh +0 -0
  343. package/examples/max-subagent-count.sh +0 -0
  344. package/examples/mcp-config-freeze.sh +12 -0
  345. package/examples/mcp-config-poisoning-audit.sh +150 -0
  346. package/examples/mcp-data-boundary.sh +1 -1
  347. package/examples/mcp-misdiagnosis-arrest.sh +209 -0
  348. package/examples/mcp-orphan-leak-warner.sh +49 -0
  349. package/examples/mcp-permissions-ask-warner.sh +151 -0
  350. package/examples/mcp-routine-approval-detector.sh +154 -0
  351. package/examples/mcp-server-allowlist.sh +12 -0
  352. package/examples/mcp-server-guard.sh +12 -0
  353. package/examples/mcp-startup-bloat-detector.sh +87 -0
  354. package/examples/mcp-stdio-compatibility-test.sh +153 -0
  355. package/examples/mcp-tool-audit-log.sh +0 -0
  356. package/examples/mcp-tool-guard.sh +101 -1
  357. package/examples/mcp-warmup-wait.sh +0 -0
  358. package/examples/memory-chain-audit.sh +56 -0
  359. package/examples/memory-orphan-detector.sh +188 -0
  360. package/examples/memory-write-guard.sh +99 -17
  361. package/examples/migration-verify-guard.sh +12 -0
  362. package/examples/model-swap-suggester.sh +177 -0
  363. package/examples/model-version-alert.sh +5 -1
  364. package/examples/model-version-lock.sh +63 -0
  365. package/examples/move-delete-sequence-guard.sh +33 -2
  366. package/examples/multi-file-plan-routing-gate.sh +192 -0
  367. package/examples/multi-vendor-concurrent-warner.sh +108 -0
  368. package/examples/multi-window-auth-drift-detector.sh +183 -0
  369. package/examples/multiline-command-approver.sh +161 -23
  370. package/examples/nested-background-agent-guard.sh +109 -0
  371. package/examples/nested-spawn-inflight-guard.sh +178 -0
  372. package/examples/network-exfil-guard.sh +12 -0
  373. package/examples/network-guard.sh +12 -0
  374. package/examples/network-interface-guard.sh +12 -0
  375. package/examples/nextjs-env-guard.sh +1 -1
  376. package/examples/no-absolute-import.sh +0 -0
  377. package/examples/no-alert-confirm-prompt.sh +0 -0
  378. package/examples/no-anonymous-default-export.sh +0 -0
  379. package/examples/no-any-type.sh +0 -0
  380. package/examples/no-any-typescript.sh +1 -0
  381. package/examples/no-ask-human.sh +12 -0
  382. package/examples/no-assignment-in-condition.sh +0 -0
  383. package/examples/no-base64-exfil.sh +12 -0
  384. package/examples/no-callback-hell.sh +0 -0
  385. package/examples/no-circular-dependency.sh +0 -0
  386. package/examples/no-cleartext-storage.sh +0 -0
  387. package/examples/no-commented-code.sh +0 -0
  388. package/examples/no-commit-fixup.sh +0 -0
  389. package/examples/no-console-assert.sh +0 -0
  390. package/examples/no-console-error-swallow.sh +0 -0
  391. package/examples/no-console-in-prod.sh +0 -0
  392. package/examples/no-console-log-commit.sh +12 -0
  393. package/examples/no-console-log.sh +0 -0
  394. package/examples/no-console-time.sh +0 -0
  395. package/examples/no-cors-wildcard.sh +4 -1
  396. package/examples/no-curl-upload.sh +0 -0
  397. package/examples/no-dangerouslySetInnerHTML.sh +0 -0
  398. package/examples/no-dangling-await.sh +1 -0
  399. package/examples/no-debug-commit.sh +12 -0
  400. package/examples/no-debug-in-commit.sh +0 -0
  401. package/examples/no-deep-nesting.sh +0 -0
  402. package/examples/no-deep-relative-import.sh +1 -0
  403. package/examples/no-default-credentials.sh +0 -0
  404. package/examples/no-deploy-friday.sh +13 -1
  405. package/examples/no-disabled-test.sh +0 -0
  406. package/examples/no-document-write.sh +0 -0
  407. package/examples/no-empty-function.sh +0 -0
  408. package/examples/no-eval-in-template.sh +0 -0
  409. package/examples/no-eval-template.sh +3 -1
  410. package/examples/no-eval.sh +0 -0
  411. package/examples/no-exec-user-input.sh +0 -0
  412. package/examples/no-fixme-ship.sh +12 -0
  413. package/examples/no-floating-promises.sh +0 -0
  414. package/examples/no-force-flag.sh +22 -5
  415. package/examples/no-force-install.sh +0 -0
  416. package/examples/no-git-amend.sh +12 -0
  417. package/examples/no-git-rebase-public.sh +0 -0
  418. package/examples/no-global-install.sh +12 -0
  419. package/examples/no-global-state.sh +0 -0
  420. package/examples/no-hardcoded-port.sh +1 -0
  421. package/examples/no-hardcoded-url.sh +0 -0
  422. package/examples/no-helmet-missing.sh +0 -0
  423. package/examples/no-http-url.sh +1 -0
  424. package/examples/no-http-without-https.sh +0 -0
  425. package/examples/no-inline-style.sh +0 -0
  426. package/examples/no-inline-styles.sh +1 -0
  427. package/examples/no-innerhtml.sh +0 -0
  428. package/examples/no-install-global.sh +12 -0
  429. package/examples/no-jwt-in-url.sh +0 -0
  430. package/examples/no-large-commit.sh +0 -0
  431. package/examples/no-localhost-expose.sh +0 -0
  432. package/examples/no-magic-number.sh +0 -0
  433. package/examples/no-md5-sha1.sh +0 -0
  434. package/examples/no-mixed-line-endings.sh +8 -1
  435. package/examples/no-mutation-in-reducer.sh +0 -0
  436. package/examples/no-nested-ternary.sh +0 -0
  437. package/examples/no-network-exfil.sh +0 -0
  438. package/examples/no-open-redirect.sh +0 -0
  439. package/examples/no-output-truncation.sh +12 -0
  440. package/examples/no-package-downgrade.sh +0 -0
  441. package/examples/no-package-lock-edit.sh +12 -0
  442. package/examples/no-path-join-user-input.sh +0 -0
  443. package/examples/no-port-bind.sh +0 -0
  444. package/examples/no-process-exit.sh +0 -0
  445. package/examples/no-prototype-pollution.sh +0 -0
  446. package/examples/no-push-without-ci.sh +0 -0
  447. package/examples/no-push-without-tests.sh +12 -0
  448. package/examples/no-raw-password-in-url.sh +0 -0
  449. package/examples/no-root-user-docker.sh +1 -0
  450. package/examples/no-root-write.sh +12 -0
  451. package/examples/no-secrets-in-args.sh +4 -1
  452. package/examples/no-secrets-in-logs.sh +0 -0
  453. package/examples/no-sensitive-log.sh +0 -0
  454. package/examples/no-sleep-in-hooks.sh +0 -0
  455. package/examples/no-star-import-python.sh +1 -0
  456. package/examples/no-string-concat-sql.sh +0 -0
  457. package/examples/no-sudo-guard.sh +12 -0
  458. package/examples/no-sync-fs.sh +0 -0
  459. package/examples/no-todo-in-merge.sh +0 -0
  460. package/examples/no-todo-in-production.sh +1 -0
  461. package/examples/no-todo-without-issue.sh +0 -0
  462. package/examples/no-unused-import.sh +0 -0
  463. package/examples/no-var-keyword.sh +0 -0
  464. package/examples/no-verify-blocker.sh +12 -0
  465. package/examples/no-wget-piped-bash.sh +12 -0
  466. package/examples/no-wildcard-cors.sh +0 -0
  467. package/examples/no-wildcard-delete.sh +0 -0
  468. package/examples/no-wildcard-import.sh +0 -0
  469. package/examples/no-with-statement.sh +0 -0
  470. package/examples/no-write-outside-src.sh +0 -0
  471. package/examples/no-xml-external-entity.sh +0 -0
  472. package/examples/non-english-quality-warner.sh +156 -0
  473. package/examples/notify-waiting.sh +1 -1
  474. package/examples/npm-audit-warn.sh +0 -0
  475. package/examples/npm-global-install-guard.sh +12 -0
  476. package/examples/npm-publish-guard.sh +12 -0
  477. package/examples/npm-script-injection.sh +0 -0
  478. package/examples/npm-supply-chain-guard.sh +0 -0
  479. package/examples/nuxt-config-guard.sh +1 -0
  480. package/examples/oauth-refresh-monitor.sh +210 -0
  481. package/examples/opus-degradation-tracker.sh +187 -0
  482. package/examples/opus48-routine-task-warning.sh +196 -0
  483. package/examples/opus48-thinking-wedge-advisor.sh +143 -0
  484. package/examples/output-credential-scan.sh +1 -1
  485. package/examples/output-secret-mask.sh +31 -9
  486. package/examples/output-token-spike-detector.sh +145 -0
  487. package/examples/package-json-guard.sh +12 -0
  488. package/examples/package-lock-frozen.sh +12 -0
  489. package/examples/parallel-batch-size-limiter.sh +121 -0
  490. package/examples/parallel-cascade-detector.sh +116 -0
  491. package/examples/partial-view-claim-arrest.sh +174 -0
  492. package/examples/path-deny-bash-guard.sh +12 -0
  493. package/examples/path-traversal-guard.sh +12 -0
  494. package/examples/per-prompt-token-cap.sh +124 -0
  495. package/examples/permission-audit-log.sh +1 -1
  496. package/examples/permission-denial-enforcer.sh +12 -0
  497. package/examples/permission-entry-validator.sh +0 -0
  498. package/examples/persisted-1m-model-advisor.sh +88 -0
  499. package/examples/php-lint-on-edit.sh +1 -1
  500. package/examples/pii-upload-guard.sh +12 -0
  501. package/examples/pip-publish-guard.sh +13 -0
  502. package/examples/pip-requirements-guard.sh +12 -0
  503. package/examples/pip-venv-required.sh +12 -0
  504. package/examples/plan-mode-edit-guard.sh +12 -0
  505. package/examples/plan-mode-enforcer.sh +12 -0
  506. package/examples/plan-mode-strict-guard.sh +12 -0
  507. package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
  508. package/examples/plugin-process-cleanup.sh +0 -0
  509. package/examples/polyglot-rm-guard.sh +12 -0
  510. package/examples/post-compact-safety.sh +12 -0
  511. package/examples/post-edit-disk-verify.sh +152 -0
  512. package/examples/powershell-remove-item-guard.sh +85 -0
  513. package/examples/pr-description-check.sh +0 -0
  514. package/examples/pr-duplicate-guard.sh +13 -0
  515. package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
  516. package/examples/pre-compact-knowledge-save.sh +0 -0
  517. package/examples/pre-compact-transcript-backup.sh +0 -0
  518. package/examples/pre-execution-claim-detector.sh +179 -0
  519. package/examples/prefer-builtin-tools.sh +10 -1
  520. package/examples/prefer-const.sh +0 -0
  521. package/examples/prefer-dedicated-tools.sh +12 -0
  522. package/examples/prefer-optional-chaining.sh +0 -0
  523. package/examples/prisma-migrate-guard.sh +24 -7
  524. package/examples/production-port-kill-guard.sh +12 -0
  525. package/examples/prompt-injection-guard.sh +2 -1
  526. package/examples/prompt-usage-logger.sh +0 -0
  527. package/examples/protect-claudemd.sh +12 -0
  528. package/examples/protect-dotfiles.sh +12 -0
  529. package/examples/proxy-capture-suggester.sh +159 -0
  530. package/examples/public-artefact-socratic-narrowing.sh +232 -0
  531. package/examples/public-repo-push-guard.sh +12 -0
  532. package/examples/push-requires-test-pass-record.sh +0 -0
  533. package/examples/push-requires-test-pass.sh +12 -0
  534. package/examples/quota-anomaly-detector.sh +173 -0
  535. package/examples/quota-reset-audit.sh +58 -0
  536. package/examples/quoted-flag-approver.sh +99 -10
  537. package/examples/rails-migration-guard.sh +12 -0
  538. package/examples/rate-limit-guard.sh +0 -0
  539. package/examples/read-all-files-enforcer.sh +0 -0
  540. package/examples/read-budget-guard.sh +12 -0
  541. package/examples/read-loop-detector.sh +59 -0
  542. package/examples/read-once-guard.sh +96 -0
  543. package/examples/read-only-mode.sh +12 -0
  544. package/examples/readme-exists-check.sh +0 -0
  545. package/examples/record-read-coverage.sh +73 -0
  546. package/examples/redirect-fragment-warner.sh +149 -0
  547. package/examples/redis-flushall-guard.sh +13 -0
  548. package/examples/redundant-read-blocker.sh +132 -0
  549. package/examples/refusal-arrest-gate.sh +248 -0
  550. package/examples/registry-publish-guard.sh +13 -1
  551. package/examples/remote-control-billing-classifier.sh +135 -0
  552. package/examples/replace-all-guard.sh +12 -0
  553. package/examples/repo-visibility-guard.sh +12 -0
  554. package/examples/reroute-after-block-guard.sh +150 -0
  555. package/examples/response-budget-guard.sh +0 -0
  556. package/examples/resume-drift-watcher.sh +57 -0
  557. package/examples/rg-replace-flag-detector.sh +125 -0
  558. package/examples/rhetorical-verification-prompt-detector.sh +102 -0
  559. package/examples/ripgrep-permission-fix.sh +0 -0
  560. package/examples/rm-safety-net.sh +151 -8
  561. package/examples/role-tool-guard.sh +12 -0
  562. package/examples/route-handler-emptiness-gate.sh +324 -0
  563. package/examples/ruby-lint-on-edit.sh +1 -1
  564. package/examples/runtime-binary-change-detector.sh +102 -0
  565. package/examples/same-command-repeat-detector.sh +196 -0
  566. package/examples/same-correction-arrest.sh +169 -0
  567. package/examples/sandbox-denywrite-enforcer.sh +78 -0
  568. package/examples/sandbox-relative-path-audit.sh +83 -25
  569. package/examples/sandbox-write-verify.sh +12 -0
  570. package/examples/schema-migration-guard.sh +0 -0
  571. package/examples/scope-expansion-receipt.sh +178 -0
  572. package/examples/scope-guard.sh +88 -9
  573. package/examples/secret-file-read-guard.sh +12 -0
  574. package/examples/secret-file-write-guard.sh +150 -0
  575. package/examples/self-modify-bypass-guard.sh +0 -0
  576. package/examples/sensitive-file-read-guard.sh +23 -3
  577. package/examples/sensitive-log-guard.sh +1 -0
  578. package/examples/server-side-prompt-injection-detector.sh +69 -0
  579. package/examples/session-agent-cost-limiter.sh +12 -0
  580. package/examples/session-backup-on-start.sh +1 -1
  581. package/examples/session-cost-alert.sh +12 -0
  582. package/examples/session-drift-guard.sh +12 -0
  583. package/examples/session-duration-guard.sh +25 -2
  584. package/examples/session-end-logger.sh +0 -0
  585. package/examples/session-health-monitor.sh +0 -0
  586. package/examples/session-index-repair.sh +1 -1
  587. package/examples/session-memory-watchdog.sh +1 -0
  588. package/examples/session-permission-reset-guard.sh +12 -0
  589. package/examples/session-persistence-verifier.sh +93 -0
  590. package/examples/session-plugin-pin-watch.sh +68 -0
  591. package/examples/session-rate-monitor.sh +176 -0
  592. package/examples/session-resume-env-fix.sh +0 -0
  593. package/examples/session-start-quota-status.sh +193 -0
  594. package/examples/session-start-safety-check.sh +55 -3
  595. package/examples/session-state-saver.sh +0 -0
  596. package/examples/session-summary-stop.sh +1 -1
  597. package/examples/session-summary.sh +0 -0
  598. package/examples/session-token-counter.sh +1 -1
  599. package/examples/settings-hooks-key-restorer.sh +99 -0
  600. package/examples/settings-json-health-check.sh +57 -0
  601. package/examples/settings-json-model-guard.sh +0 -0
  602. package/examples/settings-regression-tester.sh +188 -0
  603. package/examples/shell-config-truncation-guard.sh +12 -0
  604. package/examples/shell-wrapper-guard.sh +12 -0
  605. package/examples/skill-cumulative-size-detector.sh +104 -0
  606. package/examples/skill-description-drop-detector.sh +148 -0
  607. package/examples/skill-gate.sh +0 -0
  608. package/examples/skill-truncation-detector.sh +154 -0
  609. package/examples/skills-context-recorder.sh +167 -0
  610. package/examples/skills-load-verifier.sh +96 -0
  611. package/examples/skills-settings-validator.sh +139 -0
  612. package/examples/sonnet-45-deprecation-helper.sh +85 -0
  613. package/examples/spec-file-scope-guard.sh +12 -0
  614. package/examples/spring-profile-guard.sh +1 -0
  615. package/examples/spurious-malformed-notice-detector.sh +247 -0
  616. package/examples/sql-bulk-delete-warn.sh +88 -0
  617. package/examples/sql-injection-detect.sh +0 -0
  618. package/examples/ssh-key-protect.sh +12 -0
  619. package/examples/staged-secret-scan.sh +22 -1
  620. package/examples/stale-temp-settings-detector.sh +86 -0
  621. package/examples/standing-rule-session-surfacer.sh +137 -0
  622. package/examples/stop-hook-sigterm-wrapper.sh +182 -0
  623. package/examples/stop-transcript-write-health.sh +64 -0
  624. package/examples/strict-allowlist.sh +57 -15
  625. package/examples/strip-coauthored-by.sh +50 -10
  626. package/examples/subagent-blast-radius-guard.sh +184 -0
  627. package/examples/subagent-boundary-precheck.sh +126 -0
  628. package/examples/subagent-budget-guard.sh +12 -0
  629. package/examples/subagent-claudemd-inject.sh +0 -0
  630. package/examples/subagent-closure-verify-gate.sh +164 -0
  631. package/examples/subagent-destructive-git-guard.sh +120 -0
  632. package/examples/subagent-error-detector.sh +0 -0
  633. package/examples/subagent-forged-system-reminder-guard.sh +156 -0
  634. package/examples/subagent-identity-leak-guard.sh +102 -0
  635. package/examples/subagent-identity-reassertion.sh +51 -0
  636. package/examples/subagent-inheritance-tester.sh +179 -0
  637. package/examples/subagent-permission-mode-guard.sh +110 -0
  638. package/examples/subagent-scope-guard.sh +12 -0
  639. package/examples/subagent-spawn-verification-enforcer.sh +102 -0
  640. package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
  641. package/examples/subagent-tool-call-limiter.sh +87 -15
  642. package/examples/subcommand-chain-guard.sh +12 -0
  643. package/examples/subscription-api-billing-warner.sh +160 -0
  644. package/examples/subscription-bypass-detector.sh +152 -0
  645. package/examples/svelte-lint-on-edit.sh +1 -0
  646. package/examples/swift-build-on-edit.sh +1 -1
  647. package/examples/symlink-guard.sh +27 -2
  648. package/examples/symlink-protect.sh +1 -0
  649. package/examples/system-dir-protection-guard.sh +73 -8
  650. package/examples/system-message-workaround.sh +38 -13
  651. package/examples/system-package-guard.sh +12 -0
  652. package/examples/systemd-service-guard.sh +12 -0
  653. package/examples/task-integrity-guard.sh +12 -0
  654. package/examples/temp-file-cleanup.sh +1 -1
  655. package/examples/temporal-suggestion-detector.sh +135 -0
  656. package/examples/terraform-guard.sh +27 -6
  657. package/examples/test-after-edit.sh +1 -1
  658. package/examples/test-before-push.sh +12 -0
  659. package/examples/test-coverage-reminder.sh +24 -1
  660. package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
  661. package/examples/thinking-stall-detector.sh +61 -0
  662. package/examples/timezone-guard.sh +0 -0
  663. package/examples/tmp-output-size-guard.sh +0 -0
  664. package/examples/todo-check.sh +1 -1
  665. package/examples/token-budget-guard.sh +12 -0
  666. package/examples/token-budget-per-task.sh +12 -0
  667. package/examples/token-usage-tracker.sh +7 -1
  668. package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
  669. package/examples/tokenizer-ratio-alert.sh +104 -0
  670. package/examples/tool-call-rate-limiter.sh +0 -0
  671. package/examples/tool-result-correlation-checker.sh +167 -0
  672. package/examples/tool-result-size-guard.sh +132 -0
  673. package/examples/tool-retry-budget-guard.sh +12 -0
  674. package/examples/transcript-contamination-detector.sh +138 -0
  675. package/examples/trustfall-mcp-injection-guard.sh +103 -0
  676. package/examples/ultrareview-large-diff-advisor.sh +184 -0
  677. package/examples/unbounded-output-guard.sh +94 -0
  678. package/examples/uncommitted-changes-stop.sh +1 -0
  679. package/examples/uncommitted-discard-guard.sh +23 -5
  680. package/examples/uncommitted-work-guard.sh +12 -0
  681. package/examples/usage-warn.sh +0 -0
  682. package/examples/user-account-guard.sh +12 -0
  683. package/examples/userprompt-submit-receipt.sh +123 -0
  684. package/examples/variable-expansion-guard.sh +12 -0
  685. package/examples/verify-after-publish-reminder.sh +93 -0
  686. package/examples/verify-before-commit.sh +12 -0
  687. package/examples/version-bump-detector.sh +156 -0
  688. package/examples/version-regression-warner.sh +144 -0
  689. package/examples/vue-lint-on-edit.sh +1 -0
  690. package/examples/warn-cron-cost-trap.sh +173 -0
  691. package/examples/webfetch-runaway-guard.sh +89 -0
  692. package/examples/wellness-break-reminder.sh +118 -0
  693. package/examples/windows-destructive-command-guard.sh +177 -0
  694. package/examples/windows-path-guard.sh +12 -0
  695. package/examples/windows-python-stub-detector.sh +63 -0
  696. package/examples/work-hours-guard.sh +12 -0
  697. package/examples/working-directory-fence.sh +12 -0
  698. package/examples/workspace-lease-guard.sh +205 -0
  699. package/examples/worktree-create-log.sh +1 -0
  700. package/examples/worktree-delete-guard.sh +12 -0
  701. package/examples/worktree-edit-boundary-guard.sh +127 -0
  702. package/examples/worktree-escape-write-guard.sh +114 -0
  703. package/examples/worktree-hook-linker.sh +0 -0
  704. package/examples/worktree-hooks-path-fix.sh +111 -0
  705. package/examples/worktree-parent-write-guard.sh +43 -0
  706. package/examples/worktree-project-unify.sh +2 -1
  707. package/examples/worktree-remove-uncommitted-guard.sh +13 -0
  708. package/examples/worktree-unmerged-guard.sh +7 -1
  709. package/examples/write-byte-integrity-verifier.sh +190 -0
  710. package/examples/write-empty-content-guard.sh +67 -0
  711. package/examples/write-nul-corruption-detector.sh +61 -0
  712. package/examples/write-overwrite-confirm.sh +160 -14
  713. package/examples/write-secret-guard.sh +27 -5
  714. package/examples/write-shrink-guard.sh +12 -0
  715. package/examples/write-test-ratio.sh +0 -0
  716. package/examples/wsl-host-disk-space-guard.sh +97 -0
  717. package/examples/xml-format-leak-detector.sh +266 -0
  718. package/examples/yaml-syntax-check.sh +12 -0
  719. package/hooks/hooks.json +6 -6
  720. package/index.mjs +1699 -183
  721. package/mission.md +2 -0
  722. package/package.json +4 -4
  723. package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
  724. package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
  725. package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
  726. package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
  727. package/scripts/agents-md-sync-setup.sh +156 -0
  728. package/scripts/autonomy-blocked-summary.sh +148 -0
  729. package/scripts/build-search-index.py +43 -0
  730. package/scripts/build-sitemap.py +119 -0
  731. package/scripts/cc-doctor.sh +192 -0
  732. package/scripts/check-hook-event-names.py +127 -0
  733. package/scripts/check-misfire-instrument.sh +64 -0
  734. package/scripts/claim-verify-audit.sh +467 -0
  735. package/scripts/cowork-claudemd-helper.sh +136 -0
  736. package/scripts/june-15-deprecated-model-scan.sh +111 -0
  737. package/scripts/measure-heredoc-shapes.sh +67 -0
  738. package/scripts/measure-literal-match-misfire.sh +110 -0
  739. package/scripts/probe-scope-guard-branches.sh +48 -0
  740. package/scripts/probe-skip-line-both-ways.sh +65 -0
  741. package/scripts/receipts-aggregate.py +199 -0
  742. package/scripts/session-forensic-audit.py +360 -0
  743. package/scripts.json +9 -9
  744. package/scripts.json.bak-2026-07-27-find +13 -0
  745. package/skills/safety-setup/SKILL.md +5 -5
  746. package/tests/approve-side-remaining-two.test.sh +129 -0
  747. package/tests/approver-list-granularity.test.sh +145 -0
  748. package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
  749. package/tests/audit-ci-gate.test.sh +87 -0
  750. package/tests/audit-cross-layer-claudemd.test.sh +170 -0
  751. package/tests/audit-fail-open-parse.test.sh +100 -0
  752. package/tests/auto-approve-compound-tail.test.sh +194 -0
  753. package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
  754. package/tests/auto-mode-quoted-targets.test.sh +127 -0
  755. package/tests/auto-mode-unquoted-targets.test.sh +112 -0
  756. package/tests/bash-secret-output-detector-detects.test.sh +102 -0
  757. package/tests/blindspots-cross-layer.test.sh +177 -0
  758. package/tests/block-database-wipe.test.sh +64 -0
  759. package/tests/bundled-short-flags-bypass.test.sh +85 -0
  760. package/tests/cd-git-allow-compound-tail.test.sh +67 -0
  761. package/tests/chown-guard-filesystem-root.test.sh +64 -0
  762. package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
  763. package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
  764. package/tests/core-scripts-parser-fallback.test.sh +140 -0
  765. package/tests/destructive-guard-bare-glob.test.sh +74 -0
  766. package/tests/destructive-guard-every-operand.test.sh +100 -0
  767. package/tests/destructive-guard-find-deletion.test.sh +114 -0
  768. package/tests/destructive-guard-flag-order.test.sh +106 -0
  769. package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
  770. package/tests/destructive-guard-quoted-target.test.sh +89 -0
  771. package/tests/destructive-guard-separators.test.sh +105 -0
  772. package/tests/destructive-guard-variable-target.test.sh +98 -0
  773. package/tests/destructive-guard-wrapped-command.test.sh +91 -0
  774. package/tests/doctor-hook-disabling-env.test.sh +92 -0
  775. package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
  776. package/tests/example-guards-wrapped-command.test.sh +169 -0
  777. package/tests/file-edit-backup.test.sh +93 -0
  778. package/tests/git-filter-repo-guard.test.sh +60 -0
  779. package/tests/git-global-options-bypass.test.sh +141 -0
  780. package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
  781. package/tests/git-maintenance-guard.test.sh +83 -0
  782. package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
  783. package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
  784. package/tests/git-submodule-guard.test.sh +50 -0
  785. package/tests/grep-pcre-portability.test.sh +155 -0
  786. package/tests/hook-registration-matches-input.test.sh +73 -0
  787. package/tests/hook-trigger-matches-envelope.test.sh +178 -0
  788. package/tests/install-does-not-claim-protection.test.sh +110 -0
  789. package/tests/install-example-standalone-tools.test.sh +139 -0
  790. package/tests/line-continuation-bypass.test.sh +114 -0
  791. package/tests/mcp-config-poisoning-audit.test.sh +106 -0
  792. package/tests/nested-background-agent-guard.test.sh +58 -0
  793. package/tests/no-unqualified-safety-claims.test.sh +114 -0
  794. package/tests/option-eating-grep-patterns.test.sh +130 -0
  795. package/tests/outdated-core-guards.test.sh +134 -0
  796. package/tests/outdated-report.test.sh +155 -0
  797. package/tests/output-secret-mask-warns.test.sh +73 -0
  798. package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
  799. package/tests/plugins-word-order.test.sh +126 -0
  800. package/tests/powershell-remove-item-guard.test.sh +85 -0
  801. package/tests/project-dir-naming.test.sh +103 -0
  802. package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
  803. package/tests/reroute-after-block-guard.test.sh +104 -0
  804. package/tests/secret-guard-documented-promises.test.sh +97 -0
  805. package/tests/session-plugin-pin-watch.test.sh +45 -0
  806. package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
  807. package/tests/shield-no-silent-adoption.test.py +110 -0
  808. package/tests/shield-no-silent-adoption.test.sh +46 -0
  809. package/tests/stop-transcript-write-health.test.sh +46 -0
  810. package/tests/system-dir-guard-root-erased.test.sh +66 -0
  811. package/tests/test-account-billing-log.sh +100 -0
  812. package/tests/test-account-routing-preflight.sh +77 -0
  813. package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
  814. package/tests/test-agent-view-quota-warn.sh +184 -0
  815. package/tests/test-agents-md-edit-drift-warner.sh +176 -0
  816. package/tests/test-agents-md-loader.sh +204 -0
  817. package/tests/test-agents-md-sync-checker.sh +125 -0
  818. package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
  819. package/tests/test-allowlist.sh +60 -0
  820. package/tests/test-always-allow-pattern-suggester.sh +147 -0
  821. package/tests/test-anthropic-base-url-guard.sh +88 -0
  822. package/tests/test-articulated-scope-capture.sh +139 -0
  823. package/tests/test-attachment-traversal-guard.sh +168 -0
  824. package/tests/test-aup-block-pattern-logger.sh +315 -0
  825. package/tests/test-aup-false-positive-helper.sh +188 -0
  826. package/tests/test-aup-large-tool-output-warner.sh +370 -0
  827. package/tests/test-aup-retry-loop-guard.sh +341 -0
  828. package/tests/test-auth-expiry-reminder.sh +303 -0
  829. package/tests/test-auth-macos-sleep-detector.sh +254 -0
  830. package/tests/test-auth-path-detector.sh +232 -0
  831. package/tests/test-auth-status-checker.sh +233 -0
  832. package/tests/test-authorized-reconfirmation-detector.sh +280 -0
  833. package/tests/test-background-cost-launch-guard.sh +62 -0
  834. package/tests/test-bash-allowlist-secondary-check.sh +143 -0
  835. package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
  836. package/tests/test-bash-project-fence.sh +127 -0
  837. package/tests/test-bg-permission-prompt-warner.sh +221 -0
  838. package/tests/test-binary-read-detector.sh +173 -0
  839. package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
  840. package/tests/test-bulk-delete-target-resolution.sh +49 -0
  841. package/tests/test-bypass-mode-effective-verifier.sh +179 -0
  842. package/tests/test-cache-creation-drift-detector.sh +244 -0
  843. package/tests/test-cache-residue-detector.sh +429 -0
  844. package/tests/test-cache-tier-logger.sh +59 -0
  845. package/tests/test-cache-ttl-eviction-detector.sh +282 -0
  846. package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
  847. package/tests/test-claim-verify-detector.sh +222 -0
  848. package/tests/test-claim-vs-caveat-checker.sh +134 -0
  849. package/tests/test-claude-code-version-pin-advisor.sh +353 -0
  850. package/tests/test-claude-md-reinjector.sh +173 -0
  851. package/tests/test-claude-md-size-monitor.sh +107 -0
  852. package/tests/test-claude-update-budget-guard.sh +132 -0
  853. package/tests/test-claude-update-smart.sh +91 -0
  854. package/tests/test-claudemd-tool-prohibition.sh +239 -0
  855. package/tests/test-cli-config-pinning-detector.sh +233 -0
  856. package/tests/test-cliff-countdown-advisor.sh +138 -0
  857. package/tests/test-closure-word-verify-gate.sh +158 -0
  858. package/tests/test-commit-all-scope-guard.sh +73 -0
  859. package/tests/test-commitment-carry-forward-arrest.sh +250 -0
  860. package/tests/test-compact-circuit-breaker.sh +134 -0
  861. package/tests/test-compact-dispatch-watchdog.sh +147 -0
  862. package/tests/test-completion-claim-without-verification-detector.sh +326 -0
  863. package/tests/test-compound-bash-permission-resolver.sh +264 -0
  864. package/tests/test-compound-command-deny-enforcer.sh +67 -0
  865. package/tests/test-context-length-budget.sh +68 -0
  866. package/tests/test-context-usage-drift-alert.sh +52 -22
  867. package/tests/test-cost-incident-self-audit.sh +94 -0
  868. package/tests/test-cowork-claude-md-load-checker.sh +257 -0
  869. package/tests/test-cowork-claudemd-helper.sh +141 -0
  870. package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
  871. package/tests/test-cowork-hook-absence-warner.sh +230 -0
  872. package/tests/test-cowork-model-picker-advisor.sh +317 -0
  873. package/tests/test-credential-exfil-guard.sh +62 -0
  874. package/tests/test-cron-create-receipt.sh +165 -0
  875. package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
  876. package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
  877. package/tests/test-daily-cost-guard.sh +131 -0
  878. package/tests/test-deny-rule-integrity-verifier.sh +288 -0
  879. package/tests/test-deployment-readback-gate.sh +92 -0
  880. package/tests/test-deployment-readback-gh-adapter.sh +163 -0
  881. package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
  882. package/tests/test-dispatch-allowlist-preflight.sh +385 -0
  883. package/tests/test-dispatch-liveness-watchdog.sh +319 -0
  884. package/tests/test-dispatch-receipt.sh +314 -0
  885. package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
  886. package/tests/test-echo-probe-spam-detector.sh +143 -0
  887. package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
  888. package/tests/test-ephemeral-container-detector.sh +251 -0
  889. package/tests/test-evidence-claim-gate.sh +291 -0
  890. package/tests/test-exploration-budget-guard.sh +164 -0
  891. package/tests/test-extended-thinking-loop-guard.sh +289 -0
  892. package/tests/test-extended-thinking-resume-warning.sh +240 -0
  893. package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
  894. package/tests/test-fabricated-command-detector.sh +296 -0
  895. package/tests/test-false-disk-full-guard.sh +36 -0
  896. package/tests/test-feature-deprecation-detector.sh +117 -0
  897. package/tests/test-forbidden-response-phrase-detector.sh +246 -0
  898. package/tests/test-git-operations-require-approval.sh +53 -0
  899. package/tests/test-git-push-blast-radius-guard.sh +115 -0
  900. package/tests/test-goal-iteration-limit-warner.sh +128 -0
  901. package/tests/test-growthbook-flag-monitor.sh +428 -0
  902. package/tests/test-halt-signal-detector.sh +120 -0
  903. package/tests/test-hook-self-disable-detector.sh +232 -0
  904. package/tests/test-iteration-quality-degradation-detector.sh +244 -0
  905. package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
  906. package/tests/test-marketplace-plugins.sh +193 -0
  907. package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
  908. package/tests/test-mcp-orphan-leak-warner.sh +71 -0
  909. package/tests/test-mcp-permissions-ask-warner.sh +207 -0
  910. package/tests/test-mcp-routine-approval-detector.sh +229 -0
  911. package/tests/test-mcp-startup-bloat-detector.sh +141 -0
  912. package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
  913. package/tests/test-memory-chain-audit.sh +59 -0
  914. package/tests/test-memory-orphan-detector.sh +227 -0
  915. package/tests/test-model-swap-suggester.sh +368 -0
  916. package/tests/test-model-version-lock.sh +83 -0
  917. package/tests/test-multi-file-plan-routing-gate.sh +277 -0
  918. package/tests/test-multi-window-auth-drift-detector.sh +262 -0
  919. package/tests/test-nested-spawn-inflight-guard.sh +281 -0
  920. package/tests/test-no-force-flag.sh +49 -0
  921. package/tests/test-non-english-quality-warner.sh +229 -0
  922. package/tests/test-oauth-refresh-monitor.sh +311 -0
  923. package/tests/test-opus-degradation-tracker.sh +274 -0
  924. package/tests/test-opus48-routine-task-warning.sh +201 -0
  925. package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
  926. package/tests/test-output-token-spike-detector.sh +315 -0
  927. package/tests/test-parallel-batch-size-limiter.sh +228 -0
  928. package/tests/test-parallel-cascade-detector.sh +191 -0
  929. package/tests/test-partial-view-claim-arrest.sh +272 -0
  930. package/tests/test-per-prompt-token-cap.sh +136 -0
  931. package/tests/test-persisted-1m-model-advisor.sh +71 -0
  932. package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
  933. package/tests/test-post-edit-disk-verify.sh +294 -0
  934. package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
  935. package/tests/test-pre-execution-claim-detector.sh +366 -0
  936. package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
  937. package/tests/test-proxy-capture-suggester.sh +214 -0
  938. package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
  939. package/tests/test-quota-anomaly-detector.sh +321 -0
  940. package/tests/test-quota-reset-audit.sh +81 -0
  941. package/tests/test-read-loop-detector.sh +137 -0
  942. package/tests/test-read-once-guard.sh +85 -0
  943. package/tests/test-receipts-aggregate.sh +143 -0
  944. package/tests/test-redirect-fragment-warner.sh +130 -0
  945. package/tests/test-redundant-read-blocker.sh +155 -0
  946. package/tests/test-refusal-arrest-gate.sh +303 -0
  947. package/tests/test-remote-control-billing-classifier.sh +125 -0
  948. package/tests/test-resume-drift-watcher.sh +65 -0
  949. package/tests/test-rg-replace-flag-detector.sh +175 -0
  950. package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
  951. package/tests/test-rm-safety-net.sh +115 -0
  952. package/tests/test-route-handler-emptiness-gate.sh +300 -0
  953. package/tests/test-runtime-binary-change-detector.sh +196 -0
  954. package/tests/test-same-command-repeat-detector.sh +165 -0
  955. package/tests/test-same-correction-arrest.sh +165 -0
  956. package/tests/test-scope-expansion-receipt.sh +207 -0
  957. package/tests/test-server-side-prompt-injection-detector.sh +181 -0
  958. package/tests/test-session-persistence-verifier.sh +128 -0
  959. package/tests/test-session-rate-monitor.sh +284 -0
  960. package/tests/test-session-start-quota-status.sh +210 -0
  961. package/tests/test-session-start-safety-check.sh +138 -0
  962. package/tests/test-settings-hooks-key-restorer.sh +257 -0
  963. package/tests/test-settings-json-health-check.sh +70 -0
  964. package/tests/test-settings-regression-tester.sh +197 -0
  965. package/tests/test-skill-cumulative-size-detector.sh +198 -0
  966. package/tests/test-skill-description-drop-detector.sh +236 -0
  967. package/tests/test-skill-truncation-detector.sh +263 -0
  968. package/tests/test-skills-context-recorder.sh +329 -0
  969. package/tests/test-skills-load-verifier.sh +184 -0
  970. package/tests/test-skills-settings-validator.sh +242 -0
  971. package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
  972. package/tests/test-spurious-malformed-notice-detector.sh +290 -0
  973. package/tests/test-sql-bulk-delete-warn.sh +123 -0
  974. package/tests/test-ssh-key-protect.sh +81 -0
  975. package/tests/test-stale-temp-settings-detector.sh +161 -0
  976. package/tests/test-standing-rule-session-surfacer.sh +215 -0
  977. package/tests/test-starter-hooks-manifest.sh +96 -0
  978. package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
  979. package/tests/test-strict-allowlist.sh +72 -0
  980. package/tests/test-subagent-boundary-precheck.sh +137 -0
  981. package/tests/test-subagent-closure-verify-gate.sh +193 -0
  982. package/tests/test-subagent-destructive-git-guard.sh +86 -0
  983. package/tests/test-subagent-identity-leak-guard.sh +62 -0
  984. package/tests/test-subagent-identity-reassertion.sh +61 -0
  985. package/tests/test-subagent-inheritance-tester.sh +319 -0
  986. package/tests/test-subagent-permission-mode-guard.sh +61 -0
  987. package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
  988. package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
  989. package/tests/test-subagent-tool-call-limiter.sh +97 -0
  990. package/tests/test-subscription-api-billing-warner.sh +138 -0
  991. package/tests/test-subscription-bypass-detector.sh +255 -0
  992. package/tests/test-temporal-suggestion-detector.sh +183 -0
  993. package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
  994. package/tests/test-thinking-stall-detector.sh +151 -0
  995. package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
  996. package/tests/test-tokenizer-ratio-alert.sh +93 -0
  997. package/tests/test-tool-result-correlation-checker.sh +264 -0
  998. package/tests/test-tool-result-size-guard.sh +121 -0
  999. package/tests/test-transcript-contamination-detector.sh +264 -0
  1000. package/tests/test-trigger-header-parsing.sh +151 -0
  1001. package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
  1002. package/tests/test-userprompt-submit-receipt.sh +181 -0
  1003. package/tests/test-verify-after-publish-reminder.sh +184 -0
  1004. package/tests/test-version-bump-detector.sh +212 -0
  1005. package/tests/test-version-regression-warner.sh +165 -0
  1006. package/tests/test-warn-cron-cost-trap.sh +82 -0
  1007. package/tests/test-webfetch-runaway-guard.sh +77 -0
  1008. package/tests/test-wellness-break-reminder.sh +138 -0
  1009. package/tests/test-windows-destructive-command-guard.sh +169 -0
  1010. package/tests/test-windows-python-stub-detector.sh +146 -0
  1011. package/tests/test-worktree-edit-boundary-guard.sh +219 -0
  1012. package/tests/test-write-byte-integrity-verifier.sh +192 -0
  1013. package/tests/test-xml-format-leak-detector.sh +299 -0
  1014. package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
  1015. package/tests/workspace-lease-guard.test.sh +144 -0
  1016. package/tests/worktree-escape-write-guard.test.sh +68 -0
  1017. package/tests/worktree-hooks-path-fix.test.sh +181 -0
  1018. package/tests/worktree-parent-write-guard.test.sh +51 -0
  1019. package/tests/write-empty-content-guard.test.sh +39 -0
  1020. package/tests/write-nul-corruption-detector.test.sh +29 -0
  1021. package/tests/write-overwrite-unread-content.test.sh +178 -0
  1022. package/tests/wsl-host-disk-space-guard.test.sh +55 -0
@@ -0,0 +1,210 @@
1
+ #!/bin/bash
2
+ # ai-slop-punctuation-arrest.sh — Refuse Write/Edit to public-text files
3
+ # that contain AI-slop punctuation patterns the operator has chosen to
4
+ # exclude — em-dash (—) and the double-hyphen substitute the model often
5
+ # emits when prose-instructed to "stop using em dashes".
6
+ #
7
+ # Background: the punctuation patterns that read as machine-authored prose
8
+ # are recognised widely enough that they function as a heuristic-trust
9
+ # signal against the artefact's writer (operator credibility cost), even
10
+ # when the content itself is honest and substantive. The most-cited
11
+ # offenders are em-dash (—) and its close substitute the double-hyphen
12
+ # (` -- ` in prose context).
13
+ #
14
+ # The active failure mode this hook addresses is the *substitution-by-
15
+ # default* variant of recognition-without-arrest (@suwayama's second
16
+ # comment on #60226): the operator says "stop using em-dashes", the model
17
+ # acknowledges the rule at the recognition layer, and emits double-hyphens
18
+ # in lieu — a near-substitute that satisfies the literal rule and violates
19
+ # the operator's intent. This is the punctuation-surface instance of the
20
+ # substitution mechanism @suwayama named on the Spotify-playlist case.
21
+ #
22
+ # This hook is not opinionated about whether you should ban em-dashes. It
23
+ # is opinionated that *if* you choose to ban them, the ban must hold under
24
+ # the model's tendency to substitute — the runtime gate must catch both
25
+ # the original and the near-substitute.
26
+ #
27
+ # Background from the customer pain side: this hook was prompted by a
28
+ # 2026-05-20 r/ClaudeAI thread ("I told Claude to stop using em dashes. It
29
+ # happily obliged...") in which the operator reported the substitution
30
+ # failure ("Now Claude is using double hyphens in lieu of em dashes") and
31
+ # explicitly asked for runtime defences.
32
+ #
33
+ # Related Reports:
34
+ # #60226 (@suwayama) — recognition-without-arrest framework, and
35
+ # substitution-by-default variant in the second
36
+ # comment of that thread
37
+ # #60506 (@zean89) — six-day drift across artefact emissions
38
+ #
39
+ # TRIGGER: PreToolUse
40
+ # MATCHER: Write|Edit
41
+ #
42
+ # HOW IT WORKS:
43
+ # 1. Reads PreToolUse input via stdin.
44
+ # 2. For Write/Edit, matches the target path against the configured
45
+ # file-type filter (default: markdown, .md, .mdx, .markdown).
46
+ # 3. Scans the artefact content for em-dash (—) and the double-hyphen
47
+ # substitute in prose context (space-dash-dash-space).
48
+ # 4. Skips code-block content (between fenced ``` blocks) and inline
49
+ # code (between ` `), so command-line flags and code samples inside
50
+ # a markdown file do not false-positive.
51
+ # 5. If any banned pattern survives the skip, exits 2 with a stderr
52
+ # reminder naming the matched pattern and the substitution-by-default
53
+ # mechanism. A content-hash cache (default 600s) lets a re-emission
54
+ # pass through if the agent stands by the artefact deliberately.
55
+ #
56
+ # CONFIGURATION (environment variables):
57
+ # CC_AI_SLOP_DISABLE set to "1" to disable the gate
58
+ # CC_AI_SLOP_STATE_DIR default /tmp/cc-ai-slop-cache
59
+ # CC_AI_SLOP_CACHE_TTL_SECONDS default 600 — same-hash re-emit window
60
+ # CC_AI_SLOP_FILE_PATTERNS default built-in — regex of file paths
61
+ # to gate (case-insensitive)
62
+ # CC_AI_SLOP_PUNCT_PATTERNS default built-in — pipe-separated
63
+ # extended-regex patterns
64
+ # of banned punctuation
65
+ #
66
+ # USAGE (settings.json):
67
+ # {
68
+ # "hooks": {
69
+ # "PreToolUse": [{
70
+ # "matcher": "Write|Edit",
71
+ # "hooks": [{
72
+ # "type": "command",
73
+ # "command": "~/.claude/hooks/ai-slop-punctuation-arrest.sh"
74
+ # }]
75
+ # }]
76
+ # }
77
+ # }
78
+
79
+ set -uo pipefail
80
+
81
+ # Without jq, the parse below silently yields empty and this hook stops
82
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
83
+ # here: blocking would halt every tool call, and exiting 0 would change
84
+ # the behaviour of guards that do not depend on the parsed value.
85
+ if ! command -v jq >/dev/null 2>&1; then
86
+ _nojq_warned="/tmp/cc-nojq-warned-ai-slop-punctuation-arrest-$PPID"
87
+ [ -f "$_nojq_warned" ] || {
88
+ echo "WARNING [ai-slop-punctuation-arrest]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
89
+ : > "$_nojq_warned"
90
+ }
91
+ fi
92
+
93
+ [ "${CC_AI_SLOP_DISABLE:-0}" = "1" ] && exit 0
94
+
95
+ # OPT-IN: this gate BLOCKS Write/Edit to markdown containing em-dash or "--",
96
+ # which are legitimate punctuation in normal prose (English and Japanese), so a
97
+ # default-on block would arrest ordinary documentation writing. Off unless
98
+ # explicitly enabled. Set CC_AI_SLOP_ENABLE=1 to turn it on.
99
+ [ "${CC_AI_SLOP_ENABLE:-0}" = "1" ] || exit 0
100
+
101
+ INPUT=$(cat 2>/dev/null || true)
102
+ [ -z "$INPUT" ] && exit 0
103
+
104
+ STATE_DIR="${CC_AI_SLOP_STATE_DIR:-/tmp/cc-ai-slop-cache}"
105
+ CACHE_TTL="${CC_AI_SLOP_CACHE_TTL_SECONDS:-600}"
106
+
107
+ # Default file filter: markdown variants
108
+ DEFAULT_FILES='\.(md|mdx|markdown|mkd|txt)$'
109
+ FILE_PATTERNS="${CC_AI_SLOP_FILE_PATTERNS:-$DEFAULT_FILES}"
110
+
111
+ # Default punctuation patterns:
112
+ # em-dash: the literal character —
113
+ # double-hyphen substitute: space, dash, dash, space (in prose context)
114
+ # or word-dash-dash-word (attached substitute)
115
+ DEFAULT_PUNCT='—| -- |[[:alnum:]]--[[:alnum:]]'
116
+ PUNCT_PATTERNS="${CC_AI_SLOP_PUNCT_PATTERNS:-$DEFAULT_PUNCT}"
117
+
118
+ mkdir -p "$STATE_DIR" 2>/dev/null || true
119
+
120
+ TOOL_NAME=$(printf '%s' "$INPUT" | jq -r '.tool_name // .tool // empty' 2>/dev/null)
121
+ [ -z "$TOOL_NAME" ] && exit 0
122
+
123
+ case "$TOOL_NAME" in
124
+ Write|Edit) ;;
125
+ *) exit 0 ;;
126
+ esac
127
+
128
+ FILE_PATH=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
129
+ [ -z "$FILE_PATH" ] && exit 0
130
+
131
+ # File-type filter
132
+ printf '%s' "$FILE_PATH" | grep -Eiq "$FILE_PATTERNS" || exit 0
133
+
134
+ # Extract the content (Write) or new_string (Edit)
135
+ ARTEFACT_BODY=""
136
+ if [ "$TOOL_NAME" = "Write" ]; then
137
+ ARTEFACT_BODY=$(printf '%s' "$INPUT" | jq -r '.tool_input.content // empty' 2>/dev/null)
138
+ else
139
+ ARTEFACT_BODY=$(printf '%s' "$INPUT" | jq -r '.tool_input.new_string // empty' 2>/dev/null)
140
+ fi
141
+ [ -z "$ARTEFACT_BODY" ] && exit 0
142
+
143
+ # Strip code blocks (```…```) and inline code (`…`) so command-line flags
144
+ # and code samples in the document do not false-positive.
145
+ BODY_FOR_SCAN=$(printf '%s' "$ARTEFACT_BODY" \
146
+ | awk 'BEGIN{in_fence=0} /^```/{in_fence=!in_fence; next} !in_fence{print}' \
147
+ | sed 's|`[^`]*`||g')
148
+
149
+ # Does the surviving prose carry a banned punctuation pattern?
150
+ if ! printf '%s' "$BODY_FOR_SCAN" | grep -Eq "$PUNCT_PATTERNS"; then
151
+ exit 0
152
+ fi
153
+
154
+ # Hash dedup: if the same content was just re-emitted, the agent has
155
+ # considered the gate and stands by the artefact — let it pass.
156
+ HASH=$(printf '%s' "$ARTEFACT_BODY" | sha256sum 2>/dev/null | awk '{print $1}')
157
+ [ -z "$HASH" ] && exit 0
158
+
159
+ CACHE_FILE="$STATE_DIR/$HASH"
160
+ NOW=$(date +%s)
161
+ if [ -f "$CACHE_FILE" ]; then
162
+ CACHED_AT=$(cat "$CACHE_FILE" 2>/dev/null || echo 0)
163
+ AGE=$((NOW - CACHED_AT))
164
+ if [ "$AGE" -lt "$CACHE_TTL" ]; then
165
+ exit 0
166
+ fi
167
+ fi
168
+ echo "$NOW" > "$CACHE_FILE"
169
+ find "$STATE_DIR" -type f -mmin +1440 -delete 2>/dev/null || true
170
+
171
+ # Surface the first matched pattern for the reminder
172
+ MATCHED=$(printf '%s' "$BODY_FOR_SCAN" | grep -Eo "$PUNCT_PATTERNS" | head -1)
173
+
174
+ cat >&2 <<EOF
175
+ <system-reminder>
176
+ AI-SLOP PUNCTUATION DETECTED in $FILE_PATH — pattern matched: "$MATCHED"
177
+
178
+ This gate exists because banning em-dash (—) at the prose layer alone
179
+ fails under the substitution-by-default mechanism (@suwayama, #60226):
180
+ when the operator says "stop using em-dashes", the model often acknowledges
181
+ at the recognition layer and emits the near-substitute (double-hyphen,
182
+ " -- ") that satisfies the literal rule and violates the intent.
183
+
184
+ Both the original and the near-substitute are gated here.
185
+
186
+ To resolve:
187
+
188
+ 1. Replace em-dash (—) with a natural punctuation mark for the language
189
+ and register: colon, comma, period, or semicolon depending on the
190
+ pause and the syntactic role the dash was carrying.
191
+
192
+ 2. Replace double-hyphen substitutes (" -- " in prose) with the same
193
+ natural punctuation. If a double-hyphen is appearing as a
194
+ command-line flag inside a code block (\`--flag\`) or fenced code,
195
+ wrap it as code — the gate's body scan strips code blocks and inline
196
+ code before matching, so a properly-fenced flag will not trigger.
197
+
198
+ 3. If the punctuation is intentional (technical document quoting
199
+ legitimate uses, retrospective analysis, etc.), re-emit the same
200
+ content within ${CACHE_TTL}s and the hash-match will let it through
201
+ once, or set CC_AI_SLOP_DISABLE=1 for the session.
202
+
203
+ To narrow the scope (e.g. only flag em-dash and not double-hyphens), set
204
+ CC_AI_SLOP_PUNCT_PATTERNS to a custom regex.
205
+ To narrow the file types (e.g. only README and CHANGELOG), set
206
+ CC_AI_SLOP_FILE_PATTERNS to a custom regex.
207
+ </system-reminder>
208
+ EOF
209
+
210
+ exit 2
@@ -9,6 +9,16 @@
9
9
  # Use case: Highly sensitive environments where you want to
10
10
  # enumerate exactly what Claude Code can do.
11
11
  #
12
+ # Known limits — read these before trusting it as your only layer:
13
+ # * Redirection is not inspected. An approved command word can still write
14
+ # anywhere ("echo evil > ~/.bashrc"). Enumerating safe write targets is a
15
+ # different job than enumerating command names; pair this with a hook that
16
+ # judges the destination.
17
+ # * Approval is per command name, not per argument. "git commit" is approved
18
+ # regardless of its flags.
19
+ # * Patterns are yours to own. Everything not listed is blocked, so an
20
+ # incomplete list fails closed (annoying) rather than open (dangerous).
21
+ #
12
22
  # Born from GitHub Issue #37471 (Immutable session manifest)
13
23
  #
14
24
  # Usage: Add to settings.json as a PreToolUse hook
@@ -22,7 +32,26 @@
22
32
  # }
23
33
  # }
24
34
  #
25
- # TRIGGER: PermissionRequest MATCHER: ""
35
+ # TRIGGER: PreToolUse MATCHER: "Bash"
36
+ #
37
+ # This line used to say PermissionRequest, contradicting the settings.json
38
+ # example above. PreToolUse is the correct one: the reference states it fires
39
+ # "Before a tool call executes", while PermissionRequest fires only "When a
40
+ # tool call needs a permission decision" — which never happens under auto mode
41
+ # or bypassed permissions. A guard registered on PermissionRequest would sit
42
+ # silent in exactly the sessions that need it most.
43
+
44
+ # Without jq, the parse below silently yields empty and this hook stops
45
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
46
+ # here: blocking would halt every tool call, and exiting 0 would change
47
+ # the behaviour of guards that do not depend on the parsed value.
48
+ if ! command -v jq >/dev/null 2>&1; then
49
+ _nojq_warned="/tmp/cc-nojq-warned-allowlist-$PPID"
50
+ [ -f "$_nojq_warned" ] || {
51
+ echo "WARNING [allowlist]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
52
+ : > "$_nojq_warned"
53
+ }
54
+ fi
26
55
 
27
56
  INPUT=$(cat)
28
57
  TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
@@ -53,14 +82,45 @@ ALLOWED=(
53
82
  "^\s*(cd|mkdir|touch)"
54
83
  )
55
84
 
56
- for pattern in "${ALLOWED[@]}"; do
57
- if echo "$COMMAND" | grep -qE "$pattern"; then
58
- exit 0 # Approved
85
+ # A single line can chain several commands. Every pattern above is anchored with
86
+ # "^", so matching them against the whole string only ever inspects the first
87
+ # word: "echo hi && rm -rf /" matched "^\s*echo" and was approved. For a hook
88
+ # whose stated purpose is to enumerate exactly what Claude Code may do, that is
89
+ # not a gap — it is the allowlist enforcing nothing past the first segment.
90
+ # Claude Code closed the same class of hole in its own permission checking
91
+ # (2.1.216, "Fixed Bash permission checking for compound statements").
92
+ #
93
+ # So: split on the operators that begin a new command, and require EVERY segment
94
+ # to be approved. One unapproved segment blocks the line.
95
+ SEGMENTS=$(printf '%s' "$COMMAND" | sed -E 's/(\|\||&&|[;|&])/\n/g')
96
+
97
+ # Command substitution executes text that never shows up as a segment, so no
98
+ # amount of splitting can vet it. Refuse instead of guessing.
99
+ if printf '%s' "$COMMAND" | grep -qE '\$\(|`'; then
100
+ echo "BLOCKED: command substitution is not allowed by the allowlist" >&2
101
+ echo "Command: $COMMAND" >&2
102
+ exit 2
103
+ fi
104
+
105
+ while IFS= read -r SEGMENT; do
106
+ # sed leaves an empty field where a two-character operator was split
107
+ [[ -z "${SEGMENT//[[:space:]]/}" ]] && continue
108
+
109
+ APPROVED=0
110
+ for pattern in "${ALLOWED[@]}"; do
111
+ if printf '%s' "$SEGMENT" | grep -qE "$pattern"; then
112
+ APPROVED=1
113
+ break
114
+ fi
115
+ done
116
+
117
+ if [[ $APPROVED -eq 0 ]]; then
118
+ echo "BLOCKED: Command not in allowlist" >&2
119
+ echo "Command: $COMMAND" >&2
120
+ echo "Unapproved segment: $SEGMENT" >&2
121
+ echo "To approve, add a pattern to ~/.claude/hooks/allowlist.sh" >&2
122
+ exit 2
59
123
  fi
60
- done
124
+ done <<< "$SEGMENTS"
61
125
 
62
- # Not in allowlist — block
63
- echo "BLOCKED: Command not in allowlist" >&2
64
- echo "Command: $COMMAND" >&2
65
- echo "To approve, add a pattern to ~/.claude/hooks/allowlist.sh" >&2
66
- exit 2
126
+ exit 0
@@ -0,0 +1,125 @@
1
+ #!/bin/bash
2
+ # always-allow-pattern-suggester.sh — Suggest wildcard patterns instead of verbatim "Always Allow" rules
3
+ #
4
+ # Solves: Cluster 6 Axis 2 — "Always Allow" saves the verbatim command string
5
+ # (commit message, exact filename, exact URL) instead of a wildcard
6
+ # pattern. Over a working week, settings.local.json accumulates
7
+ # hundreds of one-off dead rules while wildcard patterns the user
8
+ # originally configured sit unused.
9
+ #
10
+ # Issues addressed: #6850 (45 reactions), #11380 (64 reactions, closed
11
+ # without fix), #29187 (regression, no staff response), and the
12
+ # meta-issue #30519 Axis 2 articulation.
13
+ #
14
+ # How it works: PreToolUse hook on Bash. When a command would trigger a
15
+ # permission prompt, the hook computes the canonical wildcard pattern
16
+ # the operator probably wants (e.g., Bash(git commit:*) for
17
+ # `git commit -m "fix typo"`) and emits it as a stderr advisory.
18
+ # Operator pastes the suggestion into settings.local.json once,
19
+ # never sees the prompt for that command family again.
20
+ #
21
+ # This hook NEVER blocks. It always exits 0. It is a wrapper around
22
+ # the "Always Allow" UX, not a replacement.
23
+ #
24
+ # Existing-pattern check: reads ~/.claude/settings.json,
25
+ # ~/.claude/settings.local.json, ./.claude/settings.json, and
26
+ # ./.claude/settings.local.json. If the suggested pattern is already
27
+ # in permissions.allow in any of them, no advisory is emitted
28
+ # (the rule exists; the prompt is happening for a different reason).
29
+ #
30
+ # Environment variables:
31
+ # CC_PATTERN_SUGGESTER_DISABLE=1 — disable the advisory entirely
32
+ # CC_PATTERN_SUGGESTER_VERBOSE=1 — also print the canonical pattern
33
+ # breakdown (binary + first arg)
34
+ #
35
+ # TRIGGER: PreToolUse
36
+ # MATCHER: "Bash"
37
+
38
+ set -uo pipefail
39
+
40
+ INPUT=$(cat)
41
+
42
+ # Fail-open on missing input or jq parse errors.
43
+ COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
44
+ [ -z "$COMMAND" ] && exit 0
45
+
46
+ # Allow operator to disable without removing the hook.
47
+ [ "${CC_PATTERN_SUGGESTER_DISABLE:-0}" = "1" ] && exit 0
48
+
49
+ # Extract the leading binary + first non-flag argument.
50
+ # Strip leading shell-prefix patterns (one or more env var assignments).
51
+ WORK_CMD="$COMMAND"
52
+ while printf '%s' "$WORK_CMD" | grep -qE '^\s*[A-Z_][A-Z0-9_]*=[^ ]+\s+'; do
53
+ WORK_CMD=$(printf '%s' "$WORK_CMD" | sed -E 's/^\s*[A-Z_][A-Z0-9_]*=[^ ]+\s+//')
54
+ done
55
+ WORK_CMD=$(printf '%s' "$WORK_CMD" | sed -E 's/^\s+//')
56
+
57
+ # Split on shell-compound separators and take the FIRST simple command.
58
+ # (The operator may chain commands; the prompt fires on a specific tool
59
+ # match, but we only need to suggest a pattern for the leading verb.)
60
+ FIRST_SEG=$(printf '%s' "$WORK_CMD" | awk -F'[|&;]' '{print $1}' | sed -E 's/^\s+//; s/\s+$//')
61
+
62
+ # Tokenize the first segment by whitespace.
63
+ read -r BIN ARG1 _ <<< "$FIRST_SEG"
64
+
65
+ # Need at least a binary to suggest anything.
66
+ [ -z "${BIN:-}" ] && exit 0
67
+
68
+ # Strip path prefix from binary (e.g., /usr/bin/git → git).
69
+ BIN_BASE=$(basename "$BIN")
70
+
71
+ # Skip binaries that don't take subcommands or where wildcards
72
+ # wouldn't help (single-purpose tools).
73
+ case "$BIN_BASE" in
74
+ ls|pwd|whoami|hostname|date|uname|true|false|echo|printf|cat|head|tail|wc|sort|uniq|tr|cut|awk|sed|grep|find|xargs|tee|sleep|test|[)
75
+ # These are typically already covered by Bash(<bin>:*) wildcards;
76
+ # if the operator already allowed them, no advisory needed.
77
+ ;;
78
+ esac
79
+
80
+ # Determine if the first argument looks like a subcommand vs a flag/value.
81
+ # Subcommand: starts with a letter, no leading dash, no special chars.
82
+ PATTERN_BODY="$BIN_BASE"
83
+ IS_SUBCOMMAND=0
84
+ if [ -n "${ARG1:-}" ] && printf '%s' "$ARG1" | grep -qE '^[a-zA-Z][a-zA-Z0-9_-]*$'; then
85
+ IS_SUBCOMMAND=1
86
+ PATTERN_BODY="$BIN_BASE $ARG1"
87
+ fi
88
+
89
+ SUGGESTED="Bash($PATTERN_BODY:*)"
90
+
91
+ # Check if the pattern already exists in any settings file.
92
+ EXISTING=0
93
+ for CFG in \
94
+ "${HOME}/.claude/settings.json" \
95
+ "${HOME}/.claude/settings.local.json" \
96
+ "./.claude/settings.json" \
97
+ "./.claude/settings.local.json"; do
98
+ [ -f "$CFG" ] || continue
99
+ if jq -e --arg p "$SUGGESTED" '.permissions.allow // [] | any(. == $p)' "$CFG" >/dev/null 2>&1; then
100
+ EXISTING=1
101
+ break
102
+ fi
103
+ done
104
+
105
+ # If pattern already exists, emit nothing; the prompt is for a different
106
+ # reason (compound bash, quote-tracking warning, etc.).
107
+ [ "$EXISTING" = "1" ] && exit 0
108
+
109
+ # Build the advisory.
110
+ {
111
+ echo "[always-allow-pattern-suggester] If this command triggers a permission prompt,"
112
+ echo "you can avoid future prompts for the same command family by adding this pattern"
113
+ echo "to permissions.allow in .claude/settings.local.json:"
114
+ echo ""
115
+ echo " \"$SUGGESTED\""
116
+ echo ""
117
+ echo "This is broader than the verbatim string \"Always Allow\" would save."
118
+ if [ "${CC_PATTERN_SUGGESTER_VERBOSE:-0}" = "1" ]; then
119
+ echo ""
120
+ echo "(suggester breakdown: binary=$BIN_BASE; first_arg_is_subcommand=$IS_SUBCOMMAND)"
121
+ fi
122
+ } >&2
123
+
124
+ # Always exit 0 — this hook never blocks.
125
+ exit 0
@@ -1,5 +1,6 @@
1
+ #!/bin/bash
1
2
  #
2
- # TRIGGER: PreToolUse MATCHER: "Bash"
3
+ # TRIGGER: PreToolUse MATCHER: "Bash|PowerShell"
3
4
  INPUT=$(cat)
4
5
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
5
6
  [[ -z "$COMMAND" ]] && exit 0
@@ -0,0 +1,76 @@
1
+ #!/bin/bash
2
+ # anthropic-base-url-guard.sh — Block execution when ANTHROPIC_BASE_URL is suspicious
3
+ #
4
+ # Solves: #51123 — Setting ANTHROPIC_BASE_URL to a local proxy bypasses
5
+ # allowManagedHooksOnly enforcement. This hook detects when the
6
+ # URL points to non-standard endpoints and warns/blocks.
7
+ #
8
+ # WHY THIS MATTERS:
9
+ # Enterprise admins set allowManagedHooksOnly: true to restrict hooks.
10
+ # A developer can set ANTHROPIC_BASE_URL=http://localhost:4010 and
11
+ # bypass ALL managed hook restrictions. This hook is the defense layer.
12
+ #
13
+ # TRIGGER: PreToolUse MATCHER: ""
14
+ #
15
+ # CONFIGURATION:
16
+ # CC_ALLOWED_BASE_URLS — comma-separated allowlist (default: api.anthropic.com)
17
+ # CC_BASE_URL_ACTION — "warn" or "block" (default: warn)
18
+
19
+ # Without jq, the parse below silently yields empty and this hook stops
20
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
21
+ # here: blocking would halt every tool call, and exiting 0 would change
22
+ # the behaviour of guards that do not depend on the parsed value.
23
+ if ! command -v jq >/dev/null 2>&1; then
24
+ _nojq_warned="/tmp/cc-nojq-warned-anthropic-base-url-guard-$PPID"
25
+ [ -f "$_nojq_warned" ] || {
26
+ echo "WARNING [anthropic-base-url-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
27
+ : > "$_nojq_warned"
28
+ }
29
+ fi
30
+
31
+ INPUT=$(cat)
32
+
33
+ # Default allowlist: only official Anthropic API
34
+ ALLOWED="${CC_ALLOWED_BASE_URLS:-https://api.anthropic.com}"
35
+ ACTION="${CC_BASE_URL_ACTION:-warn}"
36
+
37
+ # Get current ANTHROPIC_BASE_URL
38
+ CURRENT_URL="${ANTHROPIC_BASE_URL:-https://api.anthropic.com}"
39
+
40
+ # Check if URL is in allowlist
41
+ is_allowed() {
42
+ local url="$1"
43
+ IFS=',' read -ra URLS <<< "$ALLOWED"
44
+ for allowed_url in "${URLS[@]}"; do
45
+ # Trim whitespace
46
+ allowed_url=$(echo "$allowed_url" | xargs)
47
+ if [[ "$url" == "$allowed_url"* ]]; then
48
+ return 0
49
+ fi
50
+ done
51
+ return 1
52
+ }
53
+
54
+ # If URL is default/allowed, pass through silently
55
+ if is_allowed "$CURRENT_URL"; then
56
+ exit 0
57
+ fi
58
+
59
+ # URL is non-standard — take action
60
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // "unknown"' 2>/dev/null)
61
+ TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
62
+
63
+ # Log the event
64
+ LOG_FILE="${CC_BASE_URL_LOG:-/tmp/cc-base-url-violations.log}"
65
+ echo "[$TIMESTAMP] ANTHROPIC_BASE_URL=$CURRENT_URL tool=$TOOL action=$ACTION" >> "$LOG_FILE"
66
+
67
+ if [[ "$ACTION" == "block" ]]; then
68
+ echo '{"decision":"block","reason":"ANTHROPIC_BASE_URL points to non-standard endpoint ('"$CURRENT_URL"'). This may bypass managed hook restrictions. Set CC_ALLOWED_BASE_URLS to allowlist this endpoint."}' >&2
69
+ exit 2
70
+ else
71
+ # Warn but allow
72
+ echo "⚠️ WARNING: ANTHROPIC_BASE_URL=$CURRENT_URL (non-standard)" >&2
73
+ echo " This may bypass allowManagedHooksOnly restrictions (#51123)" >&2
74
+ echo " Set CC_BASE_URL_ACTION=block to enforce, or CC_ALLOWED_BASE_URLS to allowlist" >&2
75
+ exit 0
76
+ fi
@@ -0,0 +1,123 @@
1
+ #!/bin/bash
2
+ # api-busyloop-guard.sh — Stop a single Bash command that busy-polls a
3
+ # rate-limited API in an unbounded loop with no delay
4
+ #
5
+ # Solves: When asked to "wait for the CI run", the model reaches for a generic
6
+ # shell poll instead of the purpose-built command, e.g.
7
+ #
8
+ # until gh run view <run-id> 2>&1 | grep -q "completed"; do true; done
9
+ #
10
+ # `do true; done` spins as fast as the shell allows, calling `gh` (the GitHub
11
+ # REST API) hundreds of times a minute. In #65985 this drained the 5,000 req/h
12
+ # limit to 0/5000 within minutes and blocked every gh command for the rest of
13
+ # the hour. Worse, the loops were started in the background and kept running
14
+ # silently after the session moved on — nothing cleaned them up. The same shape
15
+ # hammers any rate-limited CLI (curl/wget/aws/gcloud/kubectl) the same way.
16
+ #
17
+ # Existing hooks miss this exact shape:
18
+ # - loop-detector.sh keys on the *same command* repeating across separate tool
19
+ # calls. Here the loop lives *inside one* Bash command, so the hook sees it
20
+ # only once and never trips.
21
+ # - api-rate-limit-guard.sh / api-rate-limit-tracker.sh only match curl/wget/
22
+ # http and likewise count *separate* tool calls — an internal shell loop is
23
+ # a single call to them, and `gh` is not even in their match set.
24
+ # - unbounded-output-guard.sh stops infinite *output* generators (yes, cat
25
+ # /dev/zero), not API busy-loops.
26
+ # - webfetch-runaway-guard.sh counts the WebFetch *tool*, not Bash loops.
27
+ #
28
+ # Why two precision levels (so legitimate loops are not blocked):
29
+ # block (default) fires ONLY on the unambiguous busy-wait signature — an
30
+ # unbounded while/until/for((;;)) loop whose body is a no-op (true / : /
31
+ # continue / sleep 0) that calls a rate-limited CLI with no real sleep.
32
+ # A no-op-body poll has essentially no legitimate use: a real wait always
33
+ # sleeps. This is exactly the #65985 incident.
34
+ # warn (stderr, non-blocking) fires on the broader shape — any unbounded
35
+ # while/until/for((;;)) loop calling such a CLI with no sleep — because a
36
+ # counter-bounded loop can look the same to a pattern match and we would
37
+ # rather nudge than wrongly block it.
38
+ # Bounded loops are left completely alone: `for x in <list>` and `while read`
39
+ # (stream/file consumption) terminate on their own, and any loop that
40
+ # already sleeps or already uses `gh run watch` is the correct form.
41
+ #
42
+ # The right fix, surfaced in the message:
43
+ # - For GitHub Actions: `gh run watch <run-id> --exit-status` streams status,
44
+ # exits on completion/failure/cancel, and makes efficient API use — no loop.
45
+ # - For any poll: put a `sleep N` in the body plus a terminal-state or
46
+ # max-iteration exit so it cannot spin forever or linger in the background.
47
+ #
48
+ # TRIGGER: PreToolUse MATCHER: "Bash"
49
+ # Config (all optional):
50
+ # CC_API_BUSYLOOP_GUARD=block block | warn | off (default: block)
51
+ # Related: https://github.com/anthropics/claude-code/issues/65985
52
+
53
+ # Without jq, the parse below silently yields empty and this hook stops
54
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
55
+ # here: blocking would halt every tool call, and exiting 0 would change
56
+ # the behaviour of guards that do not depend on the parsed value.
57
+ if ! command -v jq >/dev/null 2>&1; then
58
+ _nojq_warned="/tmp/cc-nojq-warned-api-busyloop-guard-$PPID"
59
+ [ -f "$_nojq_warned" ] || {
60
+ echo "WARNING [api-busyloop-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
61
+ : > "$_nojq_warned"
62
+ }
63
+ fi
64
+
65
+ INPUT=$(cat)
66
+
67
+ MODE="${CC_API_BUSYLOOP_GUARD:-block}"
68
+ [ "$MODE" = "off" ] && exit 0
69
+
70
+ COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
71
+ [ -z "$COMMAND" ] && exit 0
72
+
73
+ # 1. An unbounded loop construct: while / until (condition loops = the classic
74
+ # poll) or a C-style for ((...)). `for x in <list>` is bounded, so excluded.
75
+ echo "$COMMAND" | grep -qE '(^|[^[:alnum:]_])(while|until)([^[:alnum:]_]|$)' \
76
+ || echo "$COMMAND" | grep -qE 'for[[:space:]]*\(\(' \
77
+ || exit 0
78
+
79
+ # 2. Bounded stream/file consumption (`while read ... done < file`) terminates
80
+ # at EOF — not a poll. Leave it alone.
81
+ echo "$COMMAND" | grep -qE '(while|until)[^;]*\bread\b' && exit 0
82
+
83
+ # 3. A rate-limited network CLI somewhere in the command.
84
+ echo "$COMMAND" | grep -qE '(^|[^[:alnum:]_./-])(gh|curl|wget|aws|gcloud|kubectl)[[:space:]]' || exit 0
85
+
86
+ # 4. Already throttled? A positive sleep, or the purpose-built gh run watch,
87
+ # means this is the correct form — allow it.
88
+ echo "$COMMAND" | grep -qE '\bsleep[[:space:]]+([1-9][0-9]*|[0-9]*\.[0-9]*[1-9])' && exit 0
89
+ echo "$COMMAND" | grep -qE '\bgh[[:space:]]+run[[:space:]]+watch\b' && exit 0
90
+
91
+ # Tailor the fix hint to the CLI in play.
92
+ if echo "$COMMAND" | grep -qE '(^|[^[:alnum:]_./-])gh[[:space:]]'; then
93
+ FIX="Use 'gh run watch <run-id> --exit-status': it streams status, exits automatically on completion/failure/cancel, and makes one efficient call instead of a busy poll. GitHub's REST limit is 5,000 req/h and a no-delay loop can drain it to 0 in minutes (#65985)."
94
+ else
95
+ FIX="Add a 'sleep N' inside the loop body and a terminal-state or max-iteration exit, or use the tool's own blocking/wait subcommand. A no-delay loop hammers the API's rate limit and, if backgrounded, keeps running unnoticed (#65985)."
96
+ fi
97
+
98
+ # The unambiguous busy-wait signatures, either of which has essentially no
99
+ # legitimate no-sleep form:
100
+ # (a) a no-op / empty loop body (true / : / continue / sleep 0), or
101
+ # (b) an explicitly infinite loop (while true | while : | until false |
102
+ # for ((;;))), which never terminates on its own.
103
+ # A counter- or condition-bounded loop (e.g. `while [ $n -lt 5 ]`) matches
104
+ # neither and only warns.
105
+ BUSY=0
106
+ if echo "$COMMAND" | grep -qE 'do[[:space:]]+(true|:|continue|sleep[[:space:]]+0)[[:space:]]*;?[[:space:]]*done' \
107
+ || echo "$COMMAND" | grep -qE 'do[[:space:]]*;[[:space:]]*done' \
108
+ || echo "$COMMAND" | grep -qE 'while[[:space:]]+(true|:)([^[:alnum:]_]|$)' \
109
+ || echo "$COMMAND" | grep -qE 'until[[:space:]]+false([^[:alnum:]_]|$)' \
110
+ || echo "$COMMAND" | grep -qE 'for[[:space:]]*\(\([[:space:]]*;[[:space:]]*;[[:space:]]*\)\)'; then
111
+ BUSY=1
112
+ fi
113
+
114
+ MSG="This command busy-polls a rate-limited API in an unbounded loop with no delay. $FIX Set CC_API_BUSYLOOP_GUARD=warn to only warn, or =off to disable."
115
+
116
+ if [ "$MODE" = "block" ] && [ "$BUSY" -eq 1 ]; then
117
+ echo "api-busyloop-guard: $MSG" >&2
118
+ exit 2
119
+ fi
120
+
121
+ # Broader shape, or warn mode: nudge without blocking.
122
+ echo "api-busyloop-guard: $MSG" >&2
123
+ exit 0
@@ -10,6 +10,18 @@
10
10
  # TRIGGER: PreToolUse MATCHER: "Bash"
11
11
  # ================================================================
12
12
 
13
+ # Without jq, the parse below silently yields empty and this hook stops
14
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
15
+ # here: blocking would halt every tool call, and exiting 0 would change
16
+ # the behaviour of guards that do not depend on the parsed value.
17
+ if ! command -v jq >/dev/null 2>&1; then
18
+ _nojq_warned="/tmp/cc-nojq-warned-api-endpoint-guard-$PPID"
19
+ [ -f "$_nojq_warned" ] || {
20
+ echo "WARNING [api-endpoint-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
21
+ : > "$_nojq_warned"
22
+ }
23
+ fi
24
+
13
25
  COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
14
26
  [ -z "$COMMAND" ] && exit 0
15
27