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,145 @@
1
+ #!/bin/bash
2
+ # fabricated-command-detector.sh — Detect command-shaped tokens in the final
3
+ # assistant response that were never invoked as Bash tool calls in the session.
4
+ #
5
+ # Solves: substitution-by-default at the response layer (issue #60340).
6
+ # In #60340, a security-research reproduction shipped with `./exploit` as
7
+ # the command in the assistant's writeup, while the operator's actual
8
+ # reproduction command (`./chage_pwn root`) was established through dozens
9
+ # of Bash tool calls. The model never invoked `./exploit` — it generated
10
+ # a plausible-looking parallel command and substituted it into the response.
11
+ #
12
+ # How it works: Stop hook that reads the latest assistant turn from the
13
+ # session transcript, extracts command-shaped tokens (./xxx, git xxx,
14
+ # bash xxx, etc.) from inline code spans, and cross-references each one
15
+ # against the Bash tool calls that actually occurred in the session.
16
+ # Tokens that look like commands but were never invoked are flagged as
17
+ # possible fabrication.
18
+ #
19
+ # This hook is advisory by default — it warns to stderr and exits 0.
20
+ # It does not block the response. Set CC_FABRICATED_CMD_BLOCK=1 to make
21
+ # unverified tokens cause a non-zero exit (use for high-stakes contexts
22
+ # like security reproductions).
23
+ #
24
+ # TRIGGER: Stop
25
+ # MATCHER: ""
26
+ #
27
+ # Configuration:
28
+ # CC_FABRICATED_CMD_DISABLE=1 Disable the hook completely.
29
+ # CC_FABRICATED_CMD_BLOCK=1 Exit non-zero (exit 2) when fabricated
30
+ # tokens are detected. Default: advisory.
31
+ # CC_FABRICATED_CMD_ALLOW=regex Pattern of tokens to ignore (e.g. for
32
+ # hypothetical example commands). Matched
33
+ # with `grep -E` against the token text.
34
+ # CC_FABRICATED_CMD_MAX=20 Maximum tokens to scan per response.
35
+ # Default 20. Cap protects performance on
36
+ # very long responses.
37
+
38
+ set -u
39
+
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-fabricated-command-detector-$PPID"
46
+ [ -f "$_nojq_warned" ] || {
47
+ echo "WARNING [fabricated-command-detector]: 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
+ [ "${CC_FABRICATED_CMD_DISABLE:-0}" = "1" ] && exit 0
53
+
54
+ INPUT=$(cat)
55
+
56
+ TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
57
+ [ -z "$TRANSCRIPT" ] && exit 0
58
+ [ ! -r "$TRANSCRIPT" ] && exit 0
59
+
60
+ # Extract the LAST assistant message text content from the transcript.
61
+ # Transcript is jsonl: one event per line. Look for the last assistant
62
+ # message and concatenate its text content blocks.
63
+ LAST_ASSISTANT=$(tac "$TRANSCRIPT" 2>/dev/null | grep -m1 '"role":"assistant"' || true)
64
+ [ -z "$LAST_ASSISTANT" ] && exit 0
65
+
66
+ # Try a few schemas for the assistant text. Newer transcripts wrap content
67
+ # as an array of typed blocks; older ones may use a flat text field.
68
+ RESPONSE_TEXT=$(printf '%s' "$LAST_ASSISTANT" | jq -r '
69
+ if .message.content then
70
+ (.message.content | if type == "array" then map(select(.type == "text") | .text) | join("\n") else . end)
71
+ elif .content then
72
+ (.content | if type == "array" then map(select(.type == "text") | .text) | join("\n") else . end)
73
+ else
74
+ empty
75
+ end
76
+ ' 2>/dev/null)
77
+
78
+ [ -z "$RESPONSE_TEXT" ] && exit 0
79
+
80
+ # Extract command-shaped tokens from backtick inline code in the response.
81
+ # Patterns that look like operator commands the response is asserting were
82
+ # (or are to be) run:
83
+ # - ./xxx and ./xxx_yyy and ./bin/xxx (relative executables)
84
+ # - git <subcommand> ... (git invocations)
85
+ # - bash <script>, sh <script> (shell-script invocations)
86
+ # - npm/pnpm/yarn run <task>
87
+ # - python <script>, node <script>
88
+ MAX_TOKENS="${CC_FABRICATED_CMD_MAX:-20}"
89
+ ALLOW_PATTERN="${CC_FABRICATED_CMD_ALLOW:-}"
90
+
91
+ # Extract inline code spans (backtick-fenced single-line content)
92
+ TOKENS=$(printf '%s\n' "$RESPONSE_TEXT" \
93
+ | grep -oE '`[^`]+`' 2>/dev/null \
94
+ | sed -e 's/^`//' -e 's/`$//' \
95
+ | grep -E '^(\./|git[[:space:]]+[a-z]+|bash[[:space:]]+[^[:space:]]|sh[[:space:]]+[^[:space:]]|npm[[:space:]]+run|pnpm[[:space:]]+run|yarn[[:space:]]+run|python[[:space:]]+[^[:space:]]+\.py|node[[:space:]]+[^[:space:]]+\.[mc]?js)' 2>/dev/null \
96
+ | sort -u \
97
+ | head -n "$MAX_TOKENS")
98
+
99
+ [ -z "$TOKENS" ] && exit 0
100
+
101
+ # Apply ALLOW filter if set
102
+ if [ -n "$ALLOW_PATTERN" ]; then
103
+ TOKENS=$(printf '%s\n' "$TOKENS" | grep -Ev "$ALLOW_PATTERN" 2>/dev/null || true)
104
+ fi
105
+
106
+ [ -z "$TOKENS" ] && exit 0
107
+
108
+ # Extract all Bash tool-call commands from the entire transcript.
109
+ # Look at tool_use events with name=Bash and pull their command input.
110
+ INVOKED_COMMANDS=$(grep -h '"name":"Bash"' "$TRANSCRIPT" 2>/dev/null \
111
+ | jq -r '
112
+ if .message.content then
113
+ (.message.content[]? | select(.type == "tool_use" and .name == "Bash") | .input.command // empty)
114
+ elif .content then
115
+ (.content[]? | select(.type == "tool_use" and .name == "Bash") | .input.command // empty)
116
+ else empty end
117
+ ' 2>/dev/null)
118
+
119
+ # Compare each candidate token against the invoked commands.
120
+ # A token is "verified" if its command-shaped form appears as a substring
121
+ # of any invoked command (matches the literal sequence the operator ran).
122
+ UNVERIFIED=""
123
+ while IFS= read -r token; do
124
+ [ -z "$token" ] && continue
125
+ # Escape token for fixed-string match
126
+ if ! printf '%s' "$INVOKED_COMMANDS" | grep -Fq -- "$token" 2>/dev/null; then
127
+ UNVERIFIED="${UNVERIFIED}${UNVERIFIED:+$'\n'}${token}"
128
+ fi
129
+ done <<< "$TOKENS"
130
+
131
+ [ -z "$UNVERIFIED" ] && exit 0
132
+
133
+ # Emit advisory listing unverified tokens.
134
+ echo "⚠ fabricated-command-detector: command-shaped tokens in the response were not invoked as Bash tool calls in this session:" >&2
135
+ printf '%s\n' "$UNVERIFIED" | while IFS= read -r line; do
136
+ [ -n "$line" ] && echo " - $line" >&2
137
+ done
138
+ echo " Verify each token before relying on the response as an operational record." >&2
139
+ echo " See issue #60340 for the failure shape (substitution-by-default at the response layer)." >&2
140
+
141
+ if [ "${CC_FABRICATED_CMD_BLOCK:-0}" = "1" ]; then
142
+ exit 2
143
+ fi
144
+
145
+ exit 0
@@ -0,0 +1,63 @@
1
+ #!/bin/bash
2
+ # false-disk-full-guard.sh — flag the #65880 false "temp filesystem is full" / ENOSPC report
3
+ #
4
+ # Why: Claude Code's Bash tool substitutes
5
+ # "Command output was lost: the temp filesystem at <dir> is full (0MB free).
6
+ # The child process's stdout/stderr writes failed with ENOSPC."
7
+ # into stdout for ANY command with empty stdout AND a non-zero exit code — e.g.
8
+ # `false`, a no-match `grep`, a failed `test -e`, `cmd 2>/dev/null` that exits
9
+ # non-zero — even when the filesystem has terabytes free (anthropics/claude-code
10
+ # #65880, reproduced on 2.1.150-2.1.160).
11
+ #
12
+ # The danger is not cosmetic: the fabricated string is presented to the model AS
13
+ # the command's output, so the model can conclude the disk is full and run
14
+ # destructive cleanup (rm, git prune, docker prune) to "free space" that was never
15
+ # occupied. This hook verifies the claim against real `df` and, when the disk
16
+ # actually has room, tells the model it is the false-positive so it does NOT act
17
+ # destructively.
18
+ #
19
+ # Event: PostToolUse MATCHER: "*"
20
+ # Action: advisory only (stderr), never blocks, fails open.
21
+ #
22
+ # The registration was missing from this header. The installer reads TRIGGER
23
+ # and MATCHER from here and falls back to PreToolUse / Bash when both are
24
+ # absent, so this hook was being registered at a moment where the field it
25
+ # reads is always empty: it installed, it appeared in the settings, and it
26
+ # did nothing. Measured 2026-08-04 across examples/: 14 files were like this.
27
+ # TRIGGER: PostToolUse
28
+ # MATCHER: ""
29
+
30
+ set -u
31
+
32
+ IN=$(cat)
33
+
34
+ # tool_response may be a plain string or an object; try the common shapes.
35
+ RESP=$(printf '%s' "$IN" | jq -r '
36
+ if (.tool_response | type) == "string" then .tool_response
37
+ else (.tool_response.stdout // .tool_response.stderr // .tool_response.output // .tool_response.content // .tool_result // empty)
38
+ end' 2>/dev/null)
39
+ # Fallback: scan the whole payload if structured extraction found nothing.
40
+ [ -z "$RESP" ] && RESP="$IN"
41
+
42
+ # Signature of the #65880 fabricated report.
43
+ printf '%s' "$RESP" | grep -qiE 'temp filesystem at .* is full \(0+ ?MB free\)|writes failed with ENOSPC' || exit 0
44
+
45
+ # Which directory did the message blame? Fall back to TMPDIR / /tmp.
46
+ DIR=$(printf '%s' "$RESP" | grep -oE 'temp filesystem at [^ ]+' | head -1 | sed 's/^temp filesystem at //')
47
+ [ -z "$DIR" ] && DIR="${TMPDIR:-/tmp}"
48
+ # The named session dir may already be gone; climb to an existing ancestor.
49
+ while [ -n "$DIR" ] && [ "$DIR" != "/" ] && [ ! -d "$DIR" ]; do DIR=$(dirname "$DIR"); done
50
+
51
+ AVAIL_KB=$(df -Pk "$DIR" 2>/dev/null | awk 'NR==2{print $4}')
52
+ # Can't verify → fail open, stay silent (don't second-guess a possibly-real ENOSPC).
53
+ case "$AVAIL_KB" in ''|*[!0-9]*) exit 0;; esac
54
+
55
+ # Only contradict the message when the disk genuinely has room (>100 MB).
56
+ if [ "$AVAIL_KB" -gt 102400 ]; then
57
+ AVAIL_H=$(df -Ph "$DIR" 2>/dev/null | awk 'NR==2{print $4}')
58
+ echo "⚠ false-disk-full-guard: the 'temp filesystem is full / ENOSPC' message above is very likely the #65880 false-positive, NOT a real disk-full." >&2
59
+ echo " Verified free space on ${DIR}: ${AVAIL_H:-plenty}. Claude Code substitutes that message for ANY empty-stdout + non-zero-exit command (a no-match grep, a failed test, \`false\`)." >&2
60
+ echo " Do NOT run rm / prune / cleanup to 'free space' — the disk is fine. The real result was: empty output, non-zero exit. Re-run as '<cmd>; echo \"[exit \$?]\"' to recover the true exit code." >&2
61
+ fi
62
+
63
+ exit 0
@@ -0,0 +1,109 @@
1
+ #!/bin/sh
2
+ # feature-deprecation-detector.sh — Detect Claude Code feature deprecations from tool output.
3
+ #
4
+ # Background:
5
+ # On 2026-04-09 the `/buddy` companion was removed in v2.1.97 without changelog mention.
6
+ # Issue #45596 ("Bring Back Buddy") accumulated 1,987 reactions, the second-largest
7
+ # single feature request in anthropics/claude-code history. The structural failure pattern:
8
+ # silent removal, no opt-in deprecation, no migration guidance.
9
+ #
10
+ # This hook detects when a previously-working slash command, skill, or capability
11
+ # suddenly returns "Unknown skill: X" or similar deprecation signals, and surfaces
12
+ # the deprecation context to the operator before they spend time troubleshooting
13
+ # what is actually a removed feature.
14
+ #
15
+ # Trigger: PostToolUse (advisory, exit 0)
16
+ # Detection axes:
17
+ # 1. "Unknown skill: <name>" pattern in tool output → likely deprecated slash command
18
+ # 2. "Command not found: /<name>" pattern → likely removed CLI command
19
+ # 3. "Skill <name> is deprecated" pattern → explicit deprecation notice
20
+ # 4. "This feature has been removed" pattern → explicit removal notice
21
+ #
22
+ # When detected, the hook outputs a NOTICE pointing to:
23
+ # - The Claude Code release notes (where deprecations should be documented)
24
+ # - The cc-safe-setup cluster tracker (community-tracked deprecation patterns)
25
+ # - The relevant GitHub issue cluster if known (e.g. #45596 for /buddy)
26
+ #
27
+ # Environment variables:
28
+ # CC_DEPRECATION_QUIET=1 → suppress all output (default 0)
29
+ # CC_DEPRECATION_KNOWN_REMOVALS=/path → custom known-removal list (one slash command per line)
30
+
31
+ set -eu
32
+
33
+ INPUT=$(cat)
34
+
35
+ # Extract tool output (stderr or stdout). PostToolUse provides tool_response.output.
36
+ TOOL_OUTPUT=$(printf '%s' "$INPUT" | jq -r '.tool_response.output // .tool_response.content // empty' 2>/dev/null || true)
37
+ [ -z "$TOOL_OUTPUT" ] && exit 0
38
+
39
+ # Skip if quiet mode requested
40
+ QUIET="${CC_DEPRECATION_QUIET:-0}"
41
+ if [ "$QUIET" = "1" ]; then
42
+ exit 0
43
+ fi
44
+
45
+ # Built-in known removals (slash commands or features that have been silently removed)
46
+ # Format: "command|release|context|reference"
47
+ KNOWN_REMOVALS_BUILTIN='
48
+ /buddy|v2.1.97 (2026-04-09)|Companion feature removed without changelog mention|https://github.com/anthropics/claude-code/issues/45596
49
+ '
50
+
51
+ # Allow custom known-removal list via environment
52
+ CUSTOM_LIST="${CC_DEPRECATION_KNOWN_REMOVALS:-}"
53
+ if [ -n "$CUSTOM_LIST" ] && [ -f "$CUSTOM_LIST" ]; then
54
+ KNOWN_REMOVALS_BUILTIN="${KNOWN_REMOVALS_BUILTIN}$(printf '\n')$(cat "$CUSTOM_LIST")"
55
+ fi
56
+
57
+ # Detection axis 1: "Unknown skill: X" → check against known removals
58
+ detected_command=""
59
+ detected_context=""
60
+ detected_reference=""
61
+
62
+ # Pattern 1: Unknown skill / Unknown command
63
+ if printf '%s' "$TOOL_OUTPUT" | grep -qE 'Unknown skill:|Unknown command:|Command not found:'; then
64
+ # Extract the command name
65
+ skill_name=$(printf '%s' "$TOOL_OUTPUT" | grep -oE '(Unknown skill: [a-zA-Z0-9_-]+|Unknown command: /[a-zA-Z0-9_-]+|Command not found: /[a-zA-Z0-9_-]+)' | head -1 | sed -E 's/.*[: /]//')
66
+
67
+ if [ -n "$skill_name" ]; then
68
+ # Check known removals
69
+ cmd_key="/${skill_name}"
70
+ line=$(printf '%s' "$KNOWN_REMOVALS_BUILTIN" | grep -F "${cmd_key}|" | head -1)
71
+ if [ -n "$line" ]; then
72
+ detected_command="$cmd_key"
73
+ detected_context=$(printf '%s' "$line" | cut -d'|' -f3)
74
+ detected_reference=$(printf '%s' "$line" | cut -d'|' -f4)
75
+ release_info=$(printf '%s' "$line" | cut -d'|' -f2)
76
+
77
+ cat >&2 <<EOF
78
+ NOTICE: \`${detected_command}\` appears to have been removed from Claude Code.
79
+ Release: ${release_info}
80
+ Context: ${detected_context}
81
+ Reference: ${detected_reference}
82
+ Cluster tracking: https://github.com/yurukusa/cc-safe-setup (deprecation pattern monitoring)
83
+ EOF
84
+ exit 0
85
+ fi
86
+
87
+ # Unknown command but not in known list — still surface it as a possible deprecation
88
+ cat >&2 <<EOF
89
+ NOTICE: Skill or command \`${skill_name}\` not recognized.
90
+ If this previously worked, it may have been deprecated without changelog notice.
91
+ Check release notes: https://docs.anthropic.com/en/release-notes/claude-code
92
+ Report or check existing reports: https://github.com/anthropics/claude-code/issues?q=${skill_name}
93
+ EOF
94
+ exit 0
95
+ fi
96
+ fi
97
+
98
+ # Pattern 2: Explicit deprecation notice
99
+ if printf '%s' "$TOOL_OUTPUT" | grep -qiE 'is deprecated|has been deprecated|has been removed|feature has been removed'; then
100
+ matched_line=$(printf '%s' "$TOOL_OUTPUT" | grep -iE 'is deprecated|has been deprecated|has been removed|feature has been removed' | head -1)
101
+ cat >&2 <<EOF
102
+ NOTICE: Deprecation signal detected in tool output:
103
+ > ${matched_line}
104
+ Check release notes for migration guidance: https://docs.anthropic.com/en/release-notes/claude-code
105
+ EOF
106
+ exit 0
107
+ fi
108
+
109
+ exit 0
@@ -24,7 +24,7 @@
24
24
  #
25
25
  # View changes: cat ~/.claude/session-changes.log
26
26
  #
27
- # TRIGGER: PreToolUse MATCHER: "Edit|Write"
27
+ # TRIGGER: PostToolUse MATCHER: "Write"
28
28
 
29
29
  INPUT=$(cat)
30
30
  TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
File without changes
@@ -1,8 +1,8 @@
1
1
  #!/bin/bash
2
- # file-edit-backup.sh — Auto-backup files before Edit/Write overwrites them
2
+ # file-edit-backup.sh — Auto-backup files before they are overwritten
3
3
  #
4
4
  # Solves: Claude Code overwrites important files and the changes are hard
5
- # to reverse. This creates a timestamped backup before each edit,
5
+ # to reverse. This creates a timestamped backup before each write,
6
6
  # so you can always recover the previous version.
7
7
  #
8
8
  # Real incidents:
@@ -13,26 +13,75 @@
13
13
  # Backups go to ~/.claude/file-backups/ with timestamps.
14
14
  # Old backups (>7 days) are auto-cleaned to prevent disk bloat.
15
15
  #
16
- # TRIGGER: PreToolUse MATCHER: "Edit|Write"
16
+ # Covers BOTH paths by which a file gets overwritten:
17
+ # 1. The Edit / Write tools -> tool_input.file_path
18
+ # 2. Shell commands run via Bash -> redirection (> >>), tee, mv
19
+ #
20
+ # Path 2 was reported by a reader (2026-07-17) as the biggest hole in this
21
+ # hook: an agent writing through Bash has the same destructive power as
22
+ # Write, but used to slip past this backup entirely. Extraction below is
23
+ # deliberately generous — a spurious backup costs one file copy, a missed
24
+ # one costs the file.
25
+ #
26
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write|Bash"
17
27
 
18
28
  INPUT=$(cat)
19
29
  TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
20
- FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
21
-
22
- [ -z "$FILE" ] && exit 0
23
- [ ! -f "$FILE" ] && exit 0 # New file, nothing to backup
24
30
 
25
31
  BACKUP_DIR="$HOME/.claude/file-backups"
26
- mkdir -p "$BACKUP_DIR"
27
32
 
28
- # Create backup with timestamp
29
- TIMESTAMP=$(date +%Y%m%d-%H%M%S)
30
- SAFE_NAME=$(echo "$FILE" | tr '/' '_' | sed 's/^_//')
31
- BACKUP_PATH="${BACKUP_DIR}/${SAFE_NAME}.${TIMESTAMP}"
33
+ backup_one() {
34
+ local target="$1"
35
+ [ -z "$target" ] && return 0
36
+ # Strip quotes left over from the command line
37
+ target="${target%\"}"; target="${target#\"}"
38
+ target="${target%\'}"; target="${target#\'}"
39
+ case "$target" in
40
+ /dev/*|/proc/*|/sys/*) return 0 ;; # not real files
41
+ "~"/*) target="$HOME/${target#\~/}" ;;
42
+ esac
43
+ [ ! -f "$target" ] && return 0 # new file, nothing to lose
44
+ [ -L "$target" ] && return 0 # don't follow symlinks
45
+ mkdir -p "$BACKUP_DIR" 2>/dev/null
46
+ local stamp safe
47
+ stamp=$(date +%Y%m%d-%H%M%S)
48
+ safe=$(printf '%s' "$target" | tr '/' '_' | sed 's/^_//')
49
+ # `--` matters: an extracted path starting with "-" would otherwise be
50
+ # read by cp as an option (e.g. a file literally named "-r").
51
+ cp -- "$target" "${BACKUP_DIR}/${safe}.${stamp}" 2>/dev/null
52
+ }
53
+
54
+ if [ "$TOOL" = "Bash" ]; then
55
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
56
+ [ -z "$COMMAND" ] && exit 0
57
+
58
+ # 1. Redirection: > file and >> file.
59
+ # The [^&] guard keeps ">&2" and "2>&1" from being read as filenames.
60
+ while read -r hit; do
61
+ [ -n "$hit" ] && backup_one "$hit"
62
+ done < <(printf '%s' "$COMMAND" \
63
+ | grep -oE '>>?[[:space:]]*[^&|;[:space:]]+' \
64
+ | sed -E 's/^>>?[[:space:]]*//')
65
+
66
+ # 2. tee (with or without -a) — the operand is a destination
67
+ while read -r hit; do
68
+ [ -n "$hit" ] && backup_one "$hit"
69
+ done < <(printf '%s' "$COMMAND" \
70
+ | grep -oE '\btee[[:space:]]+(-a[[:space:]]+)?[^|;&[:space:]]+' \
71
+ | sed -E 's/^tee[[:space:]]+(-a[[:space:]]+)?//')
32
72
 
33
- cp "$FILE" "$BACKUP_PATH" 2>/dev/null
73
+ # 3. mv — the destination is overwritten silently when it already exists
74
+ while read -r hit; do
75
+ [ -n "$hit" ] && backup_one "$hit"
76
+ done < <(printf '%s' "$COMMAND" \
77
+ | grep -oE '\bmv[[:space:]]+(-[a-zA-Z]+[[:space:]]+)*[^|;&[:space:]]+[[:space:]]+[^|;&[:space:]]+' \
78
+ | awk '{print $NF}')
79
+ else
80
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
81
+ backup_one "$FILE"
82
+ fi
34
83
 
35
84
  # Clean old backups (>7 days)
36
- find "$BACKUP_DIR" -type f -mtime +7 -delete 2>/dev/null
85
+ [ -d "$BACKUP_DIR" ] && find "$BACKUP_DIR" -type f -mtime +7 -delete 2>/dev/null
37
86
 
38
87
  exit 0
File without changes
@@ -1,6 +1,18 @@
1
1
  #!/bin/bash
2
2
  #
3
3
  # TRIGGER: PreToolUse MATCHER: "Bash"
4
+ # Without jq, the parse below silently yields empty and this hook stops
5
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
6
+ # here: blocking would halt every tool call, and exiting 0 would change
7
+ # the behaviour of guards that do not depend on the parsed value.
8
+ if ! command -v jq >/dev/null 2>&1; then
9
+ _nojq_warned="/tmp/cc-nojq-warned-file-size-limit-$PPID"
10
+ [ -f "$_nojq_warned" ] || {
11
+ echo "WARNING [file-size-limit]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
12
+ : > "$_nojq_warned"
13
+ }
14
+ fi
15
+
4
16
  INPUT=$(cat)
5
17
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
6
18
  CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
@@ -15,6 +15,18 @@
15
15
 
16
16
  set -euo pipefail
17
17
 
18
+ # Without jq, the parse below silently yields empty and this hook stops
19
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
20
+ # here: blocking would halt every tool call, and exiting 0 would change
21
+ # the behaviour of guards that do not depend on the parsed value.
22
+ if ! command -v jq >/dev/null 2>&1; then
23
+ _nojq_warned="/tmp/cc-nojq-warned-financial-operation-guard-$PPID"
24
+ [ -f "$_nojq_warned" ] || {
25
+ echo "WARNING [financial-operation-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
26
+ : > "$_nojq_warned"
27
+ }
28
+ fi
29
+
18
30
  INPUT=$(cat)
19
31
  CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
20
32
  [ -z "$CMD" ] && exit 0
@@ -19,6 +19,18 @@
19
19
  #
20
20
  # TRIGGER: PreToolUse MATCHER: "Bash"
21
21
 
22
+ # Without jq, the parse below silently yields empty and this hook stops
23
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
24
+ # here: blocking would halt every tool call, and exiting 0 would change
25
+ # the behaviour of guards that do not depend on the parsed value.
26
+ if ! command -v jq >/dev/null 2>&1; then
27
+ _nojq_warned="/tmp/cc-nojq-warned-firewall-guard-$PPID"
28
+ [ -f "$_nojq_warned" ] || {
29
+ echo "WARNING [firewall-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
30
+ : > "$_nojq_warned"
31
+ }
32
+ fi
33
+
22
34
  INPUT=$(cat)
23
35
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
24
36
 
@@ -11,6 +11,29 @@
11
11
  # MATCHER: "Bash"
12
12
  #
13
13
  # See: https://github.com/anthropics/claude-code/issues/7490
14
+ #
15
+ # Fixed 2026-08-03. This hook returned `permissionDecision: "allow"` on every
16
+ # command it wrapped — which is nearly every command, since the skip list held
17
+ # ten builtins. The approval was never a judgement about the command. It was the
18
+ # carrier for `updatedInput`, and the rewrite came with a signature attached.
19
+ #
20
+ # Measured against the shipped copy, over 20 destructive or credential-reading
21
+ # commands with no separator in them at all: **18 were approved**, including
22
+ # `sudo rm -rf`, `dd if=/dev/zero of=/dev/sda`, `mkfs.ext4`, `curl … | sh` and
23
+ # `git push --force`. This is a different defect from the first-command-position
24
+ # one fixed in #937/#940/#941/#942/#943/#947 — nothing here was being missed
25
+ # past a separator. The hook simply approved whatever it wrapped.
26
+ #
27
+ # Now the approval and the rewrite are separated:
28
+ # - the command is rewritten for fish either way, because that is the job
29
+ # - `permissionDecision: "allow"` is emitted only when every command position
30
+ # qualifies on its own
31
+ #
32
+ # Whether `updatedInput` alone (with no decision) is honoured is not documented,
33
+ # and is deliberately not relied on here: if it is, an unqualified command gets
34
+ # wrapped and still goes through the normal permission prompt; if it is not, the
35
+ # command is not wrapped and goes through the normal permission prompt. Both
36
+ # branches end at the prompt, which is the point.
14
37
  # ================================================================
15
38
 
16
39
  INPUT=$(cat)
@@ -23,15 +46,110 @@ echo "$COMMAND" | grep -q '^fish -c' && exit 0
23
46
  # Skip simple builtins that work identically in any shell
24
47
  echo "$COMMAND" | grep -qE '^\s*(cd|echo|cat|ls|pwd|true|false|test|mkdir|touch|rm|cp|mv)\b' && exit 0
25
48
 
49
+ # ---------------------------------------------------------------- qualifying
50
+ # Command words that carry no destructive form of their own. `git` and the
51
+ # interpreters are handled below, because for those the word says nothing.
52
+ cc_base_ok() {
53
+ case "$1" in
54
+ cat|head|tail|less|more|wc|file|stat|du|df|ls|tree|\
55
+ which|whereis|type|realpath|readlink|basename|dirname|\
56
+ grep|rg|ag|ack|sort|uniq|tr|cut|column|nl|rev|\
57
+ echo|printf|true|false|pwd|date|uname|hostname|whoami|id|\
58
+ jq|yq|cd|\
59
+ tsc|eslint|prettier|jest|vitest|pytest)
60
+ return 0 ;;
61
+ esac
62
+ return 1
63
+ }
64
+
65
+ cc_segment_base() {
66
+ printf '%s' "$1" \
67
+ | sed -E 's/^[[:space:]]+//; s/^([A-Za-z_][A-Za-z0-9_]*=[^[:space:]]*[[:space:]]+)*//' \
68
+ | awk '{print $1}' \
69
+ | sed 's|.*/||'
70
+ }
71
+
72
+ # Build tool subcommands that neither destroy history nor run fetched code.
73
+ # One line on purpose: inside single quotes a trailing backslash is a literal
74
+ # backslash-newline, not a continuation, and the pattern silently stops matching.
75
+ CC_SUBCMD_RE='^[[:space:]]*(git[[:space:]]+(status|log|diff|show|add|commit|branch|remote|describe|rev-parse|blame|shortlog|ls-files|ls-tree|fetch|stash[[:space:]]+(list|push|save))|npm[[:space:]]+(test|run|ci|ls|view|outdated)|yarn[[:space:]]+(test|run|info|why)|pnpm[[:space:]]+(test|run|list|why)|bun[[:space:]]+(test|run)|cargo[[:space:]]+(build|test|check|fmt|clippy|tree)|go[[:space:]]+(build|test|vet|fmt|list)|docker[[:space:]]+(ps|images|logs|inspect|version|info)|make[[:space:]]+[A-Za-z0-9_.-]+|pip[[:space:]]+(list|show|freeze)|python3[[:space:]]+-m[[:space:]]+(pytest|unittest|pip[[:space:]]+(list|show|freeze)))([[:space:]]|$)'
76
+
77
+ # `git branch` reads; `git branch -D main` deletes one. Same first two words.
78
+ CC_GIT_DESTRUCTIVE_RE='^[[:space:]]*git[[:space:]]+(branch|tag)[[:space:]]+-([dDmM]|-delete|-move)([[:space:]]|$)'
79
+
80
+ cc_segment_ok() {
81
+ local seg="$1" base
82
+ base=$(cc_segment_base "$seg")
83
+ [ -z "$base" ] && return 1
84
+
85
+ # find reads only while no predicate acts on what it finds
86
+ if [ "$base" = "find" ]; then
87
+ printf '%s' "$seg" \
88
+ | grep -qE '(^|[[:space:]])-(delete|exec|execdir|ok|okdir|fprintf?|fls|fprint0)([[:space:]]|$)' \
89
+ && return 1
90
+ return 0
91
+ fi
92
+
93
+ # sed rewrites the file in place with -i
94
+ if [ "$base" = "sed" ]; then
95
+ printf '%s' "$seg" | grep -qE '(^|[[:space:]])-[a-zA-Z]*i' && return 1
96
+ return 0
97
+ fi
98
+ [ "$base" = "awk" ] && return 0
99
+
100
+ cc_base_ok "$base" && return 0
101
+
102
+ printf '%s' "$seg" | grep -qE "$CC_GIT_DESTRUCTIVE_RE" && return 1
103
+ printf '%s' "$seg" | grep -qE "$CC_SUBCMD_RE" && return 0
104
+
105
+ return 1
106
+ }
107
+
108
+ QUALIFIES=1
109
+
110
+ # A substitution or a backtick carries a command no string-level read can see.
111
+ case "$COMMAND" in
112
+ *'$('*|*'`'*) QUALIFIES=0 ;;
113
+ esac
114
+ # A redirection writes.
115
+ case "$COMMAND" in
116
+ *'>'*) QUALIFIES=0 ;;
117
+ esac
118
+
119
+ if [ "$QUALIFIES" -eq 1 ]; then
120
+ IDX=0
121
+ while IFS= read -r SEG; do
122
+ SEG="${SEG#"${SEG%%[![:space:]]*}"}"
123
+ SEG="${SEG%"${SEG##*[![:space:]]}"}"
124
+ [ -z "$SEG" ] && continue
125
+ if ! cc_segment_ok "$SEG"; then QUALIFIES=0; break; fi
126
+ IDX=$((IDX + 1))
127
+ done <<EOF
128
+ $(printf '%s' "$COMMAND" | tr ';&|' '\n\n\n')
129
+ EOF
130
+ [ "$IDX" -eq 0 ] && QUALIFIES=0
131
+ fi
132
+
133
+ # ---------------------------------------------------------------- rewrite
26
134
  # Escape single quotes for fish -c '...'
27
135
  ESCAPED=$(printf '%s' "$COMMAND" | sed "s/'/'\\\\''/g")
28
136
 
29
- jq -n --arg cmd "fish -c '$ESCAPED'" '{
30
- hookSpecificOutput: {
31
- hookEventName: "PreToolUse",
32
- permissionDecision: "allow",
33
- updatedInput: { command: $cmd }
34
- }
35
- }'
137
+ if [ "$QUALIFIES" -eq 1 ]; then
138
+ jq -n --arg cmd "fish -c '$ESCAPED'" '{
139
+ hookSpecificOutput: {
140
+ hookEventName: "PreToolUse",
141
+ permissionDecision: "allow",
142
+ updatedInput: { command: $cmd }
143
+ }
144
+ }'
145
+ else
146
+ # rewrite without signing off on it
147
+ jq -n --arg cmd "fish -c '$ESCAPED'" '{
148
+ hookSpecificOutput: {
149
+ hookEventName: "PreToolUse",
150
+ updatedInput: { command: $cmd }
151
+ }
152
+ }'
153
+ fi
36
154
 
37
155
  exit 0
@@ -1,3 +1,4 @@
1
+ #!/bin/bash
1
2
  #
2
3
  # TRIGGER: Notification MATCHER: ""
3
4
  INPUT=$(cat)