cc-safe-setup 29.6.32 → 29.6.36

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 (415) hide show
  1. package/COOKBOOK.md +70 -0
  2. package/README.md +6 -2
  3. package/examples/absolute-rule-enforcer.sh +42 -0
  4. package/examples/allow-claude-settings.sh +2 -0
  5. package/examples/allow-git-hooks-dir.sh +2 -0
  6. package/examples/allow-protected-dirs.sh +2 -0
  7. package/examples/allowlist.sh +2 -0
  8. package/examples/ansible-vault-guard.sh +2 -0
  9. package/examples/auto-approve-build.sh +2 -0
  10. package/examples/auto-approve-compound-git.sh +2 -0
  11. package/examples/auto-approve-docker.sh +2 -0
  12. package/examples/auto-approve-git-read.sh +2 -0
  13. package/examples/auto-approve-python.sh +2 -0
  14. package/examples/auto-approve-readonly-tools.sh +2 -0
  15. package/examples/auto-approve-ssh.sh +2 -0
  16. package/examples/auto-approve-test.sh +2 -0
  17. package/examples/auto-checkpoint.sh +2 -0
  18. package/examples/auto-git-checkpoint.sh +2 -0
  19. package/examples/auto-mode-safe-commands.sh +2 -0
  20. package/examples/auto-snapshot.sh +2 -0
  21. package/examples/backup-before-refactor.sh +2 -0
  22. package/examples/banned-command-guard.sh +3 -3
  23. package/examples/bash-domain-allowlist.sh +72 -0
  24. package/examples/bash-safety-auto-deny.sh +56 -0
  25. package/examples/bash-secret-output-detector.sh +68 -0
  26. package/examples/bash-timeout-guard.sh +2 -0
  27. package/examples/bashrc-safety-check.sh +59 -0
  28. package/examples/bg-task-cooldown-guard.sh +46 -0
  29. package/examples/block-database-wipe.sh +2 -0
  30. package/examples/branch-name-check.sh +2 -0
  31. package/examples/branch-naming-convention.sh +2 -0
  32. package/examples/cargo-publish-guard.sh +2 -0
  33. package/examples/check-abort-controller.sh +2 -0
  34. package/examples/check-accessibility.sh +2 -0
  35. package/examples/check-aria-labels.sh +2 -0
  36. package/examples/check-async-await-consistency.sh +2 -0
  37. package/examples/check-before-act-enforcer.sh +47 -0
  38. package/examples/check-charset-meta.sh +2 -0
  39. package/examples/check-cleanup-effect.sh +2 -0
  40. package/examples/check-content-type.sh +2 -0
  41. package/examples/check-controlled-input.sh +2 -0
  42. package/examples/check-cookie-flags.sh +2 -0
  43. package/examples/check-cors-config.sh +2 -0
  44. package/examples/check-csp-headers.sh +2 -0
  45. package/examples/check-csrf-protection.sh +2 -0
  46. package/examples/check-debounce.sh +2 -0
  47. package/examples/check-dependency-age.sh +2 -0
  48. package/examples/check-dependency-license.sh +2 -0
  49. package/examples/check-dockerfile-best-practice.sh +2 -0
  50. package/examples/check-error-boundaries.sh +2 -0
  51. package/examples/check-error-class.sh +2 -0
  52. package/examples/check-error-handling.sh +2 -0
  53. package/examples/check-error-logging.sh +2 -0
  54. package/examples/check-error-message.sh +2 -0
  55. package/examples/check-error-page.sh +2 -0
  56. package/examples/check-error-stack.sh +2 -0
  57. package/examples/check-favicon.sh +2 -0
  58. package/examples/check-form-validation.sh +2 -0
  59. package/examples/check-git-hooks-compat.sh +2 -0
  60. package/examples/check-https-redirect.sh +2 -0
  61. package/examples/check-image-optimization.sh +2 -0
  62. package/examples/check-input-validation.sh +2 -0
  63. package/examples/check-key-prop.sh +2 -0
  64. package/examples/check-lang-attribute.sh +2 -0
  65. package/examples/check-lazy-loading.sh +2 -0
  66. package/examples/check-loading-state.sh +2 -0
  67. package/examples/check-memo-deps.sh +2 -0
  68. package/examples/check-meta-description.sh +2 -0
  69. package/examples/check-npm-scripts-exist.sh +2 -0
  70. package/examples/check-null-check.sh +2 -0
  71. package/examples/check-package-size.sh +2 -0
  72. package/examples/check-pagination.sh +2 -0
  73. package/examples/check-port-availability.sh +2 -0
  74. package/examples/check-promise-all.sh +2 -0
  75. package/examples/check-prop-types.sh +2 -0
  76. package/examples/check-rate-limiting.sh +2 -0
  77. package/examples/check-responsive-design.sh +2 -0
  78. package/examples/check-retry-logic.sh +2 -0
  79. package/examples/check-return-types.sh +2 -0
  80. package/examples/check-semantic-html.sh +2 -0
  81. package/examples/check-semantic-versioning.sh +2 -0
  82. package/examples/check-suspense-fallback.sh +2 -0
  83. package/examples/check-test-naming.sh +2 -0
  84. package/examples/check-timeout-cleanup.sh +2 -0
  85. package/examples/check-tls-version.sh +2 -0
  86. package/examples/check-type-coercion.sh +2 -0
  87. package/examples/check-unsubscribe.sh +2 -0
  88. package/examples/check-viewport-meta.sh +2 -0
  89. package/examples/check-worker-terminate.sh +2 -0
  90. package/examples/checkpoint-tamper-guard.sh +2 -0
  91. package/examples/chmod-guard.sh +2 -0
  92. package/examples/chown-guard.sh +2 -0
  93. package/examples/ci-workflow-guard.sh +59 -0
  94. package/examples/classifier-fallback-allow.sh +2 -0
  95. package/examples/claude-cache-gc.sh +15 -0
  96. package/examples/claudeignore-enforce-guard.sh +60 -0
  97. package/examples/claudemd-enforcer.sh +2 -0
  98. package/examples/claudemd-violation-detector.sh +36 -0
  99. package/examples/clear-command-confirm-guard.sh +21 -0
  100. package/examples/commit-message-check.sh +2 -0
  101. package/examples/compact-blocker.sh +25 -0
  102. package/examples/composer-guard.sh +2 -0
  103. package/examples/compound-command-allow.sh +2 -0
  104. package/examples/consecutive-failure-circuit-breaker.sh +49 -0
  105. package/examples/console-log-count.sh +2 -0
  106. package/examples/context-compact-advisor.sh +16 -0
  107. package/examples/core-file-protect-guard.sh +91 -0
  108. package/examples/cors-star-warn.sh +2 -0
  109. package/examples/credential-exfil-guard.sh +2 -0
  110. package/examples/credential-file-cat-guard.sh +2 -0
  111. package/examples/cron-modification-guard.sh +40 -0
  112. package/examples/cwd-drift-detector.sh +47 -0
  113. package/examples/cwd-project-boundary-guard.sh +50 -0
  114. package/examples/denied-action-retry-guard.sh +41 -0
  115. package/examples/dependency-install-guard.sh +2 -0
  116. package/examples/deploy-guard.sh +2 -0
  117. package/examples/deploy-path-verify-guard.sh +62 -0
  118. package/examples/deployment-verify-guard.sh +81 -0
  119. package/examples/django-migrate-guard.sh +2 -0
  120. package/examples/docker-volume-guard.sh +2 -0
  121. package/examples/dockerfile-latest-guard.sh +2 -0
  122. package/examples/dotenv-commit-guard.sh +44 -0
  123. package/examples/dotenv-example-sync.sh +55 -0
  124. package/examples/dotnet-build-on-edit.sh +2 -0
  125. package/examples/drizzle-migrate-guard.sh +2 -0
  126. package/examples/edit-counter-test-gate.sh +44 -0
  127. package/examples/edit-error-counter.sh +2 -0
  128. package/examples/edit-guard.sh +2 -0
  129. package/examples/edit-old-string-validator.sh +37 -0
  130. package/examples/edit-retry-loop-guard.sh +2 -0
  131. package/examples/edit-verify.sh +2 -0
  132. package/examples/encoding-preserve-guard.sh +34 -0
  133. package/examples/enforce-tests.sh +2 -0
  134. package/examples/env-inherit-guard.sh +2 -0
  135. package/examples/env-inline-secret-guard.sh +36 -0
  136. package/examples/env-prod-guard.sh +2 -0
  137. package/examples/env-required-check.sh +2 -0
  138. package/examples/env-var-check.sh +2 -0
  139. package/examples/expo-eject-guard.sh +2 -0
  140. package/examples/export-overwrite-guard.sh +29 -0
  141. package/examples/file-change-tracker.sh +2 -0
  142. package/examples/file-change-undo-tracker.sh +46 -0
  143. package/examples/file-recycle-bin.sh +48 -0
  144. package/examples/file-size-limit.sh +2 -0
  145. package/examples/five-hundred-milestone.sh +2 -0
  146. package/examples/flask-debug-guard.sh +2 -0
  147. package/examples/gem-push-guard.sh +2 -0
  148. package/examples/git-checkout-safety-guard.sh +2 -0
  149. package/examples/git-config-guard.sh +2 -0
  150. package/examples/git-crypt-worktree-guard.sh +36 -0
  151. package/examples/git-hook-bypass-guard.sh +2 -0
  152. package/examples/git-merge-conflict-prevent.sh +2 -0
  153. package/examples/git-message-length.sh +2 -0
  154. package/examples/git-operations-require-approval.sh +99 -0
  155. package/examples/git-show-flag-sanitizer.sh +41 -0
  156. package/examples/git-stash-before-danger.sh +2 -0
  157. package/examples/git-submodule-guard.sh +2 -0
  158. package/examples/git-tag-guard.sh +2 -0
  159. package/examples/github-actions-secret-guard.sh +59 -0
  160. package/examples/gitignore-check.sh +2 -0
  161. package/examples/gitops-drift-guard.sh +53 -0
  162. package/examples/go-mod-tidy-warn.sh +2 -0
  163. package/examples/hallucination-url-check.sh +2 -0
  164. package/examples/hardcoded-ip-guard.sh +2 -0
  165. package/examples/headless-empty-result-guard.sh +46 -0
  166. package/examples/headless-stop-guard.sh +43 -0
  167. package/examples/helm-install-guard.sh +2 -0
  168. package/examples/issue-draft-redact-guard.sh +45 -0
  169. package/examples/java-compile-on-edit.sh +2 -0
  170. package/examples/k8s-production-guard.sh +77 -0
  171. package/examples/laravel-artisan-guard.sh +2 -0
  172. package/examples/large-file-guard.sh +2 -0
  173. package/examples/line-ending-guard.sh +30 -0
  174. package/examples/log-level-guard.sh +2 -0
  175. package/examples/magic-number-warn.sh +2 -0
  176. package/examples/max-edit-size-guard.sh +2 -0
  177. package/examples/max-file-count-guard.sh +2 -0
  178. package/examples/max-file-delete-count.sh +2 -0
  179. package/examples/max-function-length.sh +2 -0
  180. package/examples/max-import-count.sh +2 -0
  181. package/examples/max-subagent-count.sh +2 -0
  182. package/examples/mcp-orphan-process-guard.sh +39 -0
  183. package/examples/mcp-server-allowlist.sh +45 -0
  184. package/examples/mcp-tool-audit-log.sh +41 -0
  185. package/examples/mcp-tool-guard.sh +2 -0
  186. package/examples/migration-verify-guard.sh +44 -0
  187. package/examples/monorepo-scope-guard.sh +2 -0
  188. package/examples/network-exfil-guard.sh +61 -0
  189. package/examples/network-guard.sh +2 -0
  190. package/examples/nextjs-env-guard.sh +2 -0
  191. package/examples/no-absolute-import.sh +2 -0
  192. package/examples/no-alert-confirm-prompt.sh +2 -0
  193. package/examples/no-any-type.sh +2 -0
  194. package/examples/no-any-typescript.sh +2 -0
  195. package/examples/no-assignment-in-condition.sh +2 -0
  196. package/examples/no-callback-hell.sh +2 -0
  197. package/examples/no-catch-all-route.sh +2 -0
  198. package/examples/no-circular-dependency.sh +2 -0
  199. package/examples/no-class-in-functional.sh +2 -0
  200. package/examples/no-cleartext-storage.sh +2 -0
  201. package/examples/no-commented-code.sh +2 -0
  202. package/examples/no-commit-fixup.sh +2 -0
  203. package/examples/no-console-assert.sh +2 -0
  204. package/examples/no-console-error-swallow.sh +2 -0
  205. package/examples/no-console-in-prod.sh +2 -0
  206. package/examples/no-console-log.sh +2 -0
  207. package/examples/no-console-time.sh +2 -0
  208. package/examples/no-cors-wildcard.sh +2 -0
  209. package/examples/no-curl-upload.sh +2 -0
  210. package/examples/no-dangerouslySetInnerHTML.sh +2 -0
  211. package/examples/no-dangling-await.sh +2 -0
  212. package/examples/no-debug-in-commit.sh +2 -0
  213. package/examples/no-deep-nesting.sh +2 -0
  214. package/examples/no-deep-relative-import.sh +2 -0
  215. package/examples/no-default-credentials.sh +2 -0
  216. package/examples/no-deprecated-api.sh +2 -0
  217. package/examples/no-direct-dom-manipulation.sh +2 -0
  218. package/examples/no-disabled-test.sh +2 -0
  219. package/examples/no-document-cookie.sh +2 -0
  220. package/examples/no-document-write.sh +2 -0
  221. package/examples/no-empty-function.sh +2 -0
  222. package/examples/no-eval-in-template.sh +2 -0
  223. package/examples/no-eval-template.sh +2 -0
  224. package/examples/no-eval.sh +2 -0
  225. package/examples/no-exec-user-input.sh +2 -0
  226. package/examples/no-expose-internal-ids.sh +2 -0
  227. package/examples/no-floating-promises.sh +2 -0
  228. package/examples/no-force-install.sh +2 -0
  229. package/examples/no-git-rebase-public.sh +2 -0
  230. package/examples/no-global-state.sh +2 -0
  231. package/examples/no-hardcoded-port.sh +2 -0
  232. package/examples/no-hardcoded-url.sh +2 -0
  233. package/examples/no-helmet-missing.sh +2 -0
  234. package/examples/no-http-url.sh +2 -0
  235. package/examples/no-http-without-https.sh +2 -0
  236. package/examples/no-index-as-key.sh +2 -0
  237. package/examples/no-infinite-scroll-mem.sh +2 -0
  238. package/examples/no-inline-event-handler.sh +2 -0
  239. package/examples/no-inline-handler.sh +2 -0
  240. package/examples/no-inline-style.sh +2 -0
  241. package/examples/no-inline-styles.sh +2 -0
  242. package/examples/no-innerhtml.sh +2 -0
  243. package/examples/no-install-global.sh +2 -0
  244. package/examples/no-jwt-in-url.sh +2 -0
  245. package/examples/no-large-commit.sh +2 -0
  246. package/examples/no-localhost-expose.sh +2 -0
  247. package/examples/no-long-switch.sh +2 -0
  248. package/examples/no-magic-number.sh +2 -0
  249. package/examples/no-md5-sha1.sh +2 -0
  250. package/examples/no-memory-leak-interval.sh +2 -0
  251. package/examples/no-mixed-line-endings.sh +2 -0
  252. package/examples/no-mutation-in-reducer.sh +2 -0
  253. package/examples/no-mutation-observer-leak.sh +2 -0
  254. package/examples/no-nested-subscribe.sh +2 -0
  255. package/examples/no-nested-ternary.sh +2 -0
  256. package/examples/no-network-exfil.sh +2 -0
  257. package/examples/no-new-array-fill.sh +2 -0
  258. package/examples/no-object-freeze-mutation.sh +2 -0
  259. package/examples/no-open-redirect.sh +2 -0
  260. package/examples/no-output-truncation.sh +44 -0
  261. package/examples/no-package-downgrade.sh +2 -0
  262. package/examples/no-package-lock-edit.sh +2 -0
  263. package/examples/no-path-join-user-input.sh +2 -0
  264. package/examples/no-port-bind.sh +2 -0
  265. package/examples/no-process-exit.sh +2 -0
  266. package/examples/no-prototype-pollution.sh +2 -0
  267. package/examples/no-push-without-ci.sh +2 -0
  268. package/examples/no-raw-ref.sh +2 -0
  269. package/examples/no-redundant-fragment.sh +2 -0
  270. package/examples/no-render-in-loop.sh +2 -0
  271. package/examples/no-root-user-docker.sh +2 -0
  272. package/examples/no-root-write.sh +2 -0
  273. package/examples/no-secrets-in-args.sh +2 -0
  274. package/examples/no-secrets-in-logs.sh +2 -0
  275. package/examples/no-sensitive-log.sh +2 -0
  276. package/examples/no-side-effects-in-render.sh +2 -0
  277. package/examples/no-sleep-in-hooks.sh +2 -0
  278. package/examples/no-star-import-python.sh +2 -0
  279. package/examples/no-string-concat-sql.sh +2 -0
  280. package/examples/no-sudo-guard.sh +2 -0
  281. package/examples/no-sync-external-call.sh +2 -0
  282. package/examples/no-sync-fs.sh +2 -0
  283. package/examples/no-table-layout.sh +2 -0
  284. package/examples/no-throw-string.sh +2 -0
  285. package/examples/no-todo-in-merge.sh +2 -0
  286. package/examples/no-todo-in-production.sh +2 -0
  287. package/examples/no-todo-without-issue.sh +2 -0
  288. package/examples/no-triple-slash-ref.sh +2 -0
  289. package/examples/no-unreachable-code.sh +2 -0
  290. package/examples/no-unused-import.sh +2 -0
  291. package/examples/no-unused-state.sh +2 -0
  292. package/examples/no-var-keyword.sh +2 -0
  293. package/examples/no-wildcard-cors.sh +2 -0
  294. package/examples/no-wildcard-import.sh +2 -0
  295. package/examples/no-window-location.sh +2 -0
  296. package/examples/no-with-statement.sh +2 -0
  297. package/examples/no-write-outside-src.sh +2 -0
  298. package/examples/no-xml-external-entity.sh +2 -0
  299. package/examples/notify-waiting.sh +2 -0
  300. package/examples/npm-audit-warn.sh +2 -0
  301. package/examples/npm-publish-guard.sh +2 -0
  302. package/examples/npm-script-injection.sh +2 -0
  303. package/examples/npm-supply-chain-guard.sh +92 -0
  304. package/examples/nuxt-config-guard.sh +2 -0
  305. package/examples/output-secret-mask.sh +2 -0
  306. package/examples/package-json-guard.sh +2 -0
  307. package/examples/parallel-session-guard.sh +2 -0
  308. package/examples/path-traversal-guard.sh +2 -0
  309. package/examples/permission-audit-log.sh +2 -0
  310. package/examples/permission-entry-validator.sh +48 -0
  311. package/examples/permission-pattern-auto-allow.sh +50 -0
  312. package/examples/php-lint-on-edit.sh +2 -0
  313. package/examples/pip-publish-guard.sh +2 -0
  314. package/examples/plain-language-danger-warn.sh +37 -0
  315. package/examples/plan-mode-enforcer.sh +2 -0
  316. package/examples/plugin-process-cleanup.sh +50 -0
  317. package/examples/polyglot-rm-guard.sh +59 -0
  318. package/examples/pr-description-check.sh +2 -0
  319. package/examples/pre-compact-knowledge-save.sh +53 -0
  320. package/examples/pre-compact-transcript-export.sh +85 -0
  321. package/examples/prefer-builtin-tools.sh +2 -0
  322. package/examples/prefer-const.sh +2 -0
  323. package/examples/prefer-dedicated-tools.sh +55 -0
  324. package/examples/prefer-optional-chaining.sh +2 -0
  325. package/examples/prisma-migrate-guard.sh +2 -0
  326. package/examples/prompt-injection-detector.sh +2 -0
  327. package/examples/prompt-length-guard.sh +2 -0
  328. package/examples/protect-dotfiles.sh +2 -0
  329. package/examples/public-repo-push-guard.sh +58 -0
  330. package/examples/push-requires-test-pass-record.sh +2 -0
  331. package/examples/push-requires-test-pass.sh +2 -0
  332. package/examples/rails-migration-guard.sh +2 -0
  333. package/examples/rate-limit-guard.sh +2 -0
  334. package/examples/read-all-files-enforcer.sh +51 -0
  335. package/examples/read-audit-log.sh +34 -0
  336. package/examples/readme-exists-check.sh +2 -0
  337. package/examples/redis-flushall-guard.sh +2 -0
  338. package/examples/rm-safety-net.sh +2 -0
  339. package/examples/role-tool-guard.sh +69 -0
  340. package/examples/ruby-lint-on-edit.sh +2 -0
  341. package/examples/schema-migration-guard.sh +57 -0
  342. package/examples/scope-guard.sh +2 -0
  343. package/examples/secret-file-read-guard.sh +74 -0
  344. package/examples/self-modify-bypass-guard.sh +54 -0
  345. package/examples/sensitive-log-guard.sh +2 -0
  346. package/examples/session-checkpoint.sh +2 -0
  347. package/examples/session-duration-guard.sh +51 -0
  348. package/examples/session-end-logger.sh +57 -0
  349. package/examples/session-error-rate-monitor.sh +65 -0
  350. package/examples/session-health-monitor.sh +61 -0
  351. package/examples/session-memory-watchdog.sh +17 -0
  352. package/examples/session-permission-reset-guard.sh +39 -0
  353. package/examples/session-resume-env-fix.sh +49 -0
  354. package/examples/session-state-saver.sh +2 -0
  355. package/examples/session-summary-stop.sh +2 -0
  356. package/examples/session-summary.sh +2 -0
  357. package/examples/session-token-counter.sh +2 -0
  358. package/examples/settings-auto-backup.sh +53 -0
  359. package/examples/settings-mutation-detector.sh +45 -0
  360. package/examples/shell-wrapper-guard.sh +2 -0
  361. package/examples/skill-gate.sh +2 -0
  362. package/examples/skill-injection-detector.sh +41 -0
  363. package/examples/spec-file-scope-guard.sh +69 -0
  364. package/examples/spring-profile-guard.sh +2 -0
  365. package/examples/sql-injection-detect.sh +2 -0
  366. package/examples/subagent-budget-guard.sh +2 -0
  367. package/examples/subagent-claudemd-inject.sh +45 -0
  368. package/examples/subagent-context-size-guard.sh +26 -0
  369. package/examples/subagent-tool-call-limiter.sh +48 -0
  370. package/examples/svelte-lint-on-edit.sh +2 -0
  371. package/examples/swift-build-on-edit.sh +2 -0
  372. package/examples/symlink-protect.sh +12 -0
  373. package/examples/system-message-workaround.sh +44 -0
  374. package/examples/system-package-guard.sh +2 -0
  375. package/examples/temp-file-cleanup-stop.sh +28 -0
  376. package/examples/temp-file-cleanup.sh +2 -0
  377. package/examples/terminal-state-restore.sh +23 -0
  378. package/examples/test-after-edit.sh +2 -0
  379. package/examples/test-before-commit.sh +13 -14
  380. package/examples/test-before-push.sh +2 -0
  381. package/examples/test-exit-code-verify.sh +2 -0
  382. package/examples/timeout-guard.sh +2 -0
  383. package/examples/timezone-guard.sh +2 -0
  384. package/examples/tmp-output-size-guard.sh +46 -0
  385. package/examples/todo-check.sh +2 -0
  386. package/examples/todo-deadline-warn.sh +48 -0
  387. package/examples/token-budget-per-task.sh +55 -0
  388. package/examples/token-spike-alert.sh +51 -0
  389. package/examples/token-usage-tracker.sh +14 -0
  390. package/examples/turbo-cache-guard.sh +2 -0
  391. package/examples/uncommitted-changes-stop.sh +2 -0
  392. package/examples/uncommitted-work-shield.sh +37 -0
  393. package/examples/usage-warn.sh +2 -0
  394. package/examples/verify-before-commit.sh +2 -0
  395. package/examples/virtual-cwd-helper.sh +40 -0
  396. package/examples/vue-lint-on-edit.sh +2 -0
  397. package/examples/webfetch-domain-allow.sh +96 -0
  398. package/examples/worktree-delete-guard.sh +43 -0
  399. package/examples/worktree-memory-guard.sh +47 -0
  400. package/examples/worktree-path-validator.sh +42 -0
  401. package/examples/worktree-project-unify.sh +19 -0
  402. package/examples/worktree-unmerged-guard.sh +2 -0
  403. package/examples/write-overwrite-confirm.sh +40 -0
  404. package/examples/write-secret-guard.sh +2 -0
  405. package/examples/write-shrink-guard.sh +46 -0
  406. package/examples/write-test-ratio.sh +2 -0
  407. package/index.mjs +631 -138
  408. package/package.json +2 -2
  409. package/scripts/generate-categories.mjs +206 -0
  410. package/scripts.json +4 -1
  411. package/test.sh.new_tests +0 -0
  412. package/test.sh.patch +0 -0
  413. package/tests/test-core-file-protect-guard.sh +73 -0
  414. package/tests/test-deployment-verify-guard.sh +74 -0
  415. package/tests/test-git-operations-require-approval.sh +65 -0
@@ -0,0 +1,59 @@
1
+ #!/bin/bash
2
+ # ci-workflow-guard.sh — Prevent dangerous CI/CD workflow modifications
3
+ #
4
+ # Solves: Claude modifying CI workflows to add `--no-verify`, skip tests,
5
+ # disable security scanning, or add overly broad permissions.
6
+ # A compromised workflow can exfiltrate secrets or deploy malicious code.
7
+ #
8
+ # How it works: PostToolUse hook on Edit/Write that checks workflow files
9
+ # for dangerous patterns after modification.
10
+ #
11
+ # TRIGGER: PostToolUse
12
+ # MATCHER: "Edit|Write"
13
+
14
+ set -euo pipefail
15
+
16
+ INPUT=$(cat)
17
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
18
+ case "$TOOL" in Edit|Write) ;; *) exit 0 ;; esac
19
+
20
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
21
+ [ -z "$FILE" ] && exit 0
22
+
23
+ # Only check CI workflow files
24
+ case "$FILE" in
25
+ .github/workflows/*.yml|.github/workflows/*.yaml) ;;
26
+ .gitlab-ci.yml|.circleci/config.yml|Jenkinsfile) ;;
27
+ */.github/workflows/*.yml) ;;
28
+ *) exit 0 ;;
29
+ esac
30
+
31
+ [ -f "$FILE" ] || exit 0
32
+
33
+ WARNINGS=""
34
+
35
+ # Check for dangerous patterns
36
+ if grep -qE 'permissions:\s*write-all|permissions:\s*\{[^}]*contents:\s*write' "$FILE" 2>/dev/null; then
37
+ WARNINGS="${WARNINGS} - Broad write permissions detected\n"
38
+ fi
39
+
40
+ if grep -qE '--no-verify|--skip-tests|--no-check|SKIP_CI|skip ci|\[ci skip\]' "$FILE" 2>/dev/null; then
41
+ WARNINGS="${WARNINGS} - Test/verification skip detected\n"
42
+ fi
43
+
44
+ if grep -qE 'curl.*\|.*sh|wget.*\|.*bash|bash\s*<\(curl' "$FILE" 2>/dev/null; then
45
+ WARNINGS="${WARNINGS} - Remote script execution (curl|sh) detected\n"
46
+ fi
47
+
48
+ if grep -qE 'dangerously-skip-permissions|--force|--no-verify' "$FILE" 2>/dev/null; then
49
+ WARNINGS="${WARNINGS} - Safety bypass flags detected\n"
50
+ fi
51
+
52
+ if [ -n "$WARNINGS" ]; then
53
+ echo "WARNING: Potentially dangerous CI workflow changes:" >&2
54
+ echo " File: $FILE" >&2
55
+ echo -e "$WARNINGS" >&2
56
+ echo " Review these changes carefully before committing." >&2
57
+ fi
58
+
59
+ exit 0
@@ -19,6 +19,8 @@
19
19
  # }]
20
20
  # }
21
21
  # }
22
+ #
23
+ # TRIGGER: PermissionRequest MATCHER: ""
22
24
 
23
25
  INPUT=$(cat)
24
26
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -0,0 +1,15 @@
1
+ CLAUDE_DIR="$HOME/.claude"
2
+ MAX_AGE_DAYS="${CC_GC_MAX_AGE:-30}"
3
+ MAX_SIZE_MB="${CC_GC_MAX_SIZE:-500}"
4
+ DRY_RUN="${CC_GC_DRY_RUN:-0}"
5
+ find "$CLAUDE_DIR/projects" -name "*.jsonl" -mtime +"$MAX_AGE_DAYS" -type f 2>/dev/null | while read f; do
6
+ [ "$DRY_RUN" = "1" ] && echo " [dry-run] would delete: $f" >&2 && continue
7
+ rm "$f"
8
+ done
9
+ find "$CLAUDE_DIR/projects" -maxdepth 1 -type d -empty -delete 2>/dev/null
10
+ find "$CLAUDE_DIR" -path "*/tool-results/*" -mtime +"$MAX_AGE_DAYS" -type f -delete 2>/dev/null
11
+ TOTAL_MB=$(du -sm "$CLAUDE_DIR" 2>/dev/null | cut -f1)
12
+ if [ "$TOTAL_MB" -gt "$MAX_SIZE_MB" ] 2>/dev/null; then
13
+ echo "~/.claude is ${TOTAL_MB}MB (cap: ${MAX_SIZE_MB}MB)" >&2
14
+ fi
15
+ exit 0
@@ -0,0 +1,60 @@
1
+ #!/bin/bash
2
+ # claudeignore-enforce-guard.sh — Enforce .claudeignore at the tool level
3
+ #
4
+ # Solves: .claudeignore patterns not blocking Read/Edit/Grep tool calls (#16704).
5
+ # Claude can directly access files listed in .claudeignore via tool calls.
6
+ # This hook enforces ignore rules that the built-in system misses.
7
+ #
8
+ # How it works: PreToolUse hook on Read/Edit/Write/Grep that checks if the
9
+ # target file matches any pattern in .claudeignore. Uses glob-style matching.
10
+ #
11
+ # TRIGGER: PreToolUse
12
+ # MATCHER: "Read|Edit|Write|Grep|Glob"
13
+
14
+ set -euo pipefail
15
+
16
+ INPUT=$(cat)
17
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
18
+
19
+ # Extract file path based on tool type
20
+ case "$TOOL" in
21
+ Read|Edit|Write)
22
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
23
+ ;;
24
+ Grep|Glob)
25
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.path // empty' 2>/dev/null)
26
+ ;;
27
+ *) exit 0 ;;
28
+ esac
29
+
30
+ [ -z "$FILE" ] && exit 0
31
+
32
+ # Find .claudeignore in project root or current directory
33
+ IGNORE_FILE=""
34
+ for candidate in ".claudeignore" "../.claudeignore" "../../.claudeignore"; do
35
+ if [ -f "$candidate" ]; then
36
+ IGNORE_FILE="$candidate"
37
+ break
38
+ fi
39
+ done
40
+
41
+ [ -z "$IGNORE_FILE" ] && exit 0
42
+
43
+ # Check each pattern in .claudeignore
44
+ while IFS= read -r pattern || [ -n "$pattern" ]; do
45
+ # Skip empty lines and comments
46
+ [[ -z "$pattern" || "$pattern" == \#* ]] && continue
47
+ # Strip trailing whitespace
48
+ pattern=$(echo "$pattern" | sed 's/[[:space:]]*$//')
49
+ [ -z "$pattern" ] && continue
50
+
51
+ # Match: exact path, basename, or glob
52
+ BASENAME=$(basename "$FILE")
53
+ if [[ "$FILE" == $pattern ]] || [[ "$BASENAME" == $pattern ]] || [[ "$FILE" == */$pattern ]]; then
54
+ echo "BLOCKED: File '$FILE' matches .claudeignore pattern '$pattern'." >&2
55
+ echo "This file is excluded from Claude Code access." >&2
56
+ exit 2
57
+ fi
58
+ done < "$IGNORE_FILE"
59
+
60
+ exit 0
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PostToolUse MATCHER: "Bash"
2
4
  INPUT=$(cat)
3
5
  TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
4
6
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -0,0 +1,36 @@
1
+ #!/bin/bash
2
+ # claudemd-violation-detector.sh — Remind critical CLAUDE.md rules after tool use
3
+ #
4
+ # Solves: Claude ignores CLAUDE.md instructions, especially after
5
+ # context compaction or in long sessions (#40930).
6
+ #
7
+ # How it works: After each tool use, extracts and prints
8
+ # critical rules (ABSOLUTE/MUST NEVER/NEVER/禁止) from CLAUDE.md
9
+ # as a reminder. Runs every N tool calls to avoid noise.
10
+ #
11
+ # TRIGGER: PostToolUse
12
+ # MATCHER: ""
13
+
14
+ set -euo pipefail
15
+
16
+ # Rate limit: only remind every 20 tool calls
17
+ COUNTER_FILE="/tmp/claudemd-reminder-counter"
18
+ COUNT=$(cat "$COUNTER_FILE" 2>/dev/null || echo "0")
19
+ COUNT=$((COUNT + 1))
20
+ echo "$COUNT" > "$COUNTER_FILE"
21
+ [ $((COUNT % 20)) -ne 0 ] && exit 0
22
+
23
+ # Find CLAUDE.md
24
+ CLAUDEMD=""
25
+ for candidate in "CLAUDE.md" ".claude/CLAUDE.md" "../CLAUDE.md"; do
26
+ [ -f "$candidate" ] && CLAUDEMD="$candidate" && break
27
+ done
28
+ [ -z "$CLAUDEMD" ] && exit 0
29
+
30
+ # Extract critical rules
31
+ RULES=$(grep -iE '(ABSOLUTE|MUST NEVER|NEVER DO|禁止|絶対)' "$CLAUDEMD" 2>/dev/null | head -5 || true)
32
+ [ -z "$RULES" ] && exit 0
33
+
34
+ echo "📋 CLAUDE.md critical rules reminder:" >&2
35
+ echo "$RULES" >&2
36
+ exit 0
@@ -0,0 +1,21 @@
1
+ #!/bin/bash
2
+ # clear-command-confirm-guard.sh — Block accidental /clear command
3
+ #
4
+ # Solves: /clear destroys all conversation context with zero
5
+ # confirmation. Prefix matching means /c + Enter can
6
+ # accidentally trigger /clear instead of /commit or /compact (#40931).
7
+ #
8
+ # How it works: Blocks /clear entirely. Use /compact to reduce
9
+ # context without losing it.
10
+ #
11
+ # TRIGGER: UserPromptSubmit
12
+ # MATCHER: "^/clear$"
13
+
14
+ INPUT=$(cat)
15
+ PROMPT=$(echo "$INPUT" | jq -r '.prompt // empty' 2>/dev/null)
16
+
17
+ if echo "$PROMPT" | grep -qE '^/clear$'; then
18
+ echo "BLOCKED: /clear permanently destroys all context. Use /compact instead to reduce context safely." >&2
19
+ exit 2
20
+ fi
21
+ exit 0
@@ -24,6 +24,8 @@
24
24
  #
25
25
  # The "if" field (v2.1.85+) skips this hook for non-commit commands.
26
26
  # Without "if", the hook still works — it checks internally and exits early.
27
+ #
28
+ # TRIGGER: PreToolUse MATCHER: "Bash"
27
29
 
28
30
  INPUT=$(cat)
29
31
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -0,0 +1,25 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # compact-blocker.sh — Block auto-compaction entirely
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Power users who manage context manually (file-backed plans,
7
+ # checkpoint scripts) lose nuanced context when auto-compaction
8
+ # fires. This hook blocks compaction via exit code 2.
9
+ #
10
+ # For conditional blocking (e.g., only during plan mode), modify
11
+ # the guard condition below.
12
+ #
13
+ # TRIGGER: PreCompact
14
+ # MATCHER: (none — PreCompact has no matcher)
15
+ #
16
+ # DECISION: exit 2 = block compaction
17
+ #
18
+ # See: https://github.com/anthropics/claude-code/issues/6689
19
+ # ================================================================
20
+
21
+ # Unconditional block — compaction never fires
22
+ # To make it conditional, add logic here:
23
+ # e.g., [ -f /tmp/allow-compact ] && exit 0
24
+ echo '{"decision":"block","reason":"auto-compaction disabled by compact-blocker hook"}' >&2
25
+ exit 2
@@ -17,6 +17,8 @@
17
17
  # }
18
18
  # }
19
19
  # ================================================================
20
+ #
21
+ # TRIGGER: PreToolUse MATCHER: "Bash"
20
22
 
21
23
  INPUT=$(cat)
22
24
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -23,6 +23,8 @@
23
23
  # }]
24
24
  # }
25
25
  # }
26
+ #
27
+ # TRIGGER: PermissionRequest MATCHER: ""
26
28
 
27
29
  INPUT=$(cat)
28
30
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -0,0 +1,49 @@
1
+ #!/bin/bash
2
+ # consecutive-failure-circuit-breaker.sh — Stop after repeated failures
3
+ #
4
+ # Solves: Claude escalating to destructive actions after repeated failures (#31946).
5
+ # Without this, Claude retries failing commands dozens of times,
6
+ # eventually trying increasingly dangerous alternatives.
7
+ #
8
+ # How it works: PostToolUse hook on Bash that tracks consecutive non-zero
9
+ # exit codes. After CC_MAX_CONSECUTIVE_FAILURES (default 3), blocks
10
+ # further Bash calls until a success resets the counter.
11
+ #
12
+ # TRIGGER: PostToolUse
13
+ # MATCHER: "Bash"
14
+
15
+ set -euo pipefail
16
+
17
+ INPUT=$(cat)
18
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
19
+ [ "$TOOL" != "Bash" ] && exit 0
20
+
21
+ EXIT_CODE=$(echo "$INPUT" | jq -r '.tool_result.exitCode // "0"' 2>/dev/null)
22
+ MAX_FAILURES="${CC_MAX_CONSECUTIVE_FAILURES:-3}"
23
+ COUNTER_FILE="/tmp/claude-consecutive-failures-${PPID:-0}"
24
+
25
+ if [ "$EXIT_CODE" = "0" ]; then
26
+ # Success — reset counter
27
+ echo "0" > "$COUNTER_FILE"
28
+ exit 0
29
+ fi
30
+
31
+ # Failure — increment counter
32
+ COUNT=$(cat "$COUNTER_FILE" 2>/dev/null || echo 0)
33
+ COUNT=$((COUNT + 1))
34
+ echo "$COUNT" > "$COUNTER_FILE"
35
+
36
+ if [ "$COUNT" -ge "$MAX_FAILURES" ]; then
37
+ echo "CIRCUIT BREAKER: $COUNT consecutive Bash failures detected." >&2
38
+ echo "" >&2
39
+ echo "Stop and reassess your approach. Repeated failures often lead to" >&2
40
+ echo "increasingly risky workarounds. Consider:" >&2
41
+ echo " 1. Read the error messages carefully" >&2
42
+ echo " 2. Check your assumptions" >&2
43
+ echo " 3. Try a completely different approach" >&2
44
+ echo " 4. Ask the user for help" >&2
45
+ # Don't block (exit 0) — just warn strongly via stderr
46
+ # PostToolUse can't block, but the warning enters context
47
+ fi
48
+
49
+ exit 0
@@ -1,3 +1,5 @@
1
+ #
2
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
1
3
  INPUT=$(cat)
2
4
  FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
3
5
  [[ -z "$FILE" ]] && exit 0
@@ -0,0 +1,16 @@
1
+ INPUT=$(cat)
2
+ COUNTER="/tmp/cc-tool-count-$$"
3
+ COUNT=$(cat "$COUNTER" 2>/dev/null || echo 0)
4
+ COUNT=$((COUNT + 1))
5
+ echo "$COUNT" > "$COUNTER"
6
+ THRESHOLD="${CC_COMPACT_THRESHOLD:-50}"
7
+ if [ "$((COUNT % THRESHOLD))" -eq 0 ]; then
8
+ TRANSCRIPT=$(ls -t ~/.claude/projects/*/sessions/*/transcript.jsonl 2>/dev/null | head -1)
9
+ if [ -f "$TRANSCRIPT" ]; then
10
+ SIZE_KB=$(($(wc -c < "$TRANSCRIPT") / 1024))
11
+ if [ "$SIZE_KB" -gt 200 ]; then
12
+ echo "Context ~${SIZE_KB}KB ($COUNT calls). Consider /compact." >&2
13
+ fi
14
+ fi
15
+ fi
16
+ exit 0
@@ -0,0 +1,91 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # core-file-protect-guard.sh — Block edits to core/config/rules files
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Claude Code sometimes makes unprompted architectural changes to
7
+ # game rules, configuration files, and core logic files. This hook
8
+ # blocks modifications to files matching configurable glob patterns.
9
+ #
10
+ # Protects files matching CC_PROTECTED_FILES patterns (colon-separated).
11
+ # Default: "*rules*:*config*:*core*"
12
+ #
13
+ # Catches:
14
+ # - Edit/Write tool targeting protected files
15
+ # - Bash commands using sed -i or awk -i on protected files
16
+ #
17
+ # See: https://github.com/anthropics/claude-code/issues/40788
18
+ #
19
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write|Bash"
20
+ #
21
+ # Configuration:
22
+ # CC_PROTECTED_FILES — colon-separated glob patterns
23
+ # Default: "*rules*:*config*:*core*"
24
+ # ================================================================
25
+
26
+ INPUT=$(cat)
27
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
28
+
29
+ # Configurable protected file patterns (colon-separated globs)
30
+ PROTECTED="${CC_PROTECTED_FILES:-*rules*:*config*:*core*}"
31
+
32
+ # Convert colon-separated globs to a function that checks a filename
33
+ matches_protected() {
34
+ local filepath="$1"
35
+ local basename
36
+ basename=$(basename "$filepath")
37
+
38
+ IFS=':' read -ra PATTERNS <<< "$PROTECTED"
39
+ for pattern in "${PATTERNS[@]}"; do
40
+ # Use bash glob matching (case-insensitive via shopt)
41
+ if [[ "$basename" == $pattern ]] || [[ "$filepath" == *$pattern* ]]; then
42
+ return 0
43
+ fi
44
+ done
45
+ return 1
46
+ }
47
+
48
+ # Handle Edit/Write tools
49
+ if [[ "$TOOL" == "Edit" || "$TOOL" == "Write" ]]; then
50
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
51
+ [ -z "$FILE" ] && exit 0
52
+
53
+ if matches_protected "$FILE"; then
54
+ echo "BLOCKED: Cannot modify protected file: $FILE" >&2
55
+ echo "" >&2
56
+ echo "Protected patterns: $PROTECTED" >&2
57
+ echo "Configure with CC_PROTECTED_FILES env var." >&2
58
+ echo "" >&2
59
+ echo "See: https://github.com/anthropics/claude-code/issues/40788" >&2
60
+ exit 2
61
+ fi
62
+ exit 0
63
+ fi
64
+
65
+ # Handle Bash tool — check for sed -i / awk -i targeting protected files
66
+ if [[ "$TOOL" == "Bash" ]]; then
67
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
68
+ [ -z "$COMMAND" ] && exit 0
69
+
70
+ # Skip echo/printf
71
+ echo "$COMMAND" | grep -qE '^\s*(echo|printf)\s' && exit 0
72
+
73
+ # Check for sed -i or awk -i inplace targeting protected files
74
+ if echo "$COMMAND" | grep -qE '(sed\s+-i|awk\s+-i\s+inplace)'; then
75
+ # Extract potential file arguments from the command
76
+ IFS=':' read -ra PATTERNS <<< "$PROTECTED"
77
+ for pattern in "${PATTERNS[@]}"; do
78
+ if echo "$COMMAND" | grep -qE "$pattern"; then
79
+ echo "BLOCKED: In-place edit targets protected file pattern: $pattern" >&2
80
+ echo "" >&2
81
+ echo "Command: $COMMAND" >&2
82
+ echo "Protected patterns: $PROTECTED" >&2
83
+ echo "" >&2
84
+ echo "See: https://github.com/anthropics/claude-code/issues/40788" >&2
85
+ exit 2
86
+ fi
87
+ done
88
+ fi
89
+ fi
90
+
91
+ exit 0
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Bash"
2
4
  COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
3
5
  [ -z "$COMMAND" ] && exit 0
4
6
  # PostToolUse matcher: Edit|Write
@@ -21,6 +21,8 @@
21
21
  # }]
22
22
  # }
23
23
  # }
24
+ #
25
+ # TRIGGER: PreToolUse MATCHER: "Bash"
24
26
 
25
27
  INPUT=$(cat)
26
28
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -18,6 +18,8 @@
18
18
  # }]
19
19
  # }
20
20
  # }
21
+ #
22
+ # TRIGGER: PreToolUse MATCHER: "Bash"
21
23
 
22
24
  INPUT=$(cat)
23
25
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -0,0 +1,40 @@
1
+ #!/bin/bash
2
+ # cron-modification-guard.sh — Block unreviewed cron job modifications
3
+ #
4
+ # Solves: Claude creating cron jobs that sabotage live services (#40421).
5
+ # A cron job that polls 200 content IDs against a single-connection
6
+ # proxy caused stream resets every 10 minutes for days.
7
+ #
8
+ # Why this matters:
9
+ # Cron jobs are persistent, invisible, and run unattended. A bad cron
10
+ # can cause sustained damage long after the session ends. This hook
11
+ # blocks crontab edits, /etc/cron.d writes, and systemd timer creation.
12
+ #
13
+ # TRIGGER: PreToolUse
14
+ # MATCHER: "Bash"
15
+
16
+ INPUT=$(cat)
17
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
18
+ [ -z "$COMMAND" ] && exit 0
19
+
20
+ # Detect cron/timer modifications
21
+ if echo "$COMMAND" | grep -qEi '(crontab\s+-[elr]|crontab\s+[^-]|systemctl\s+(enable|start|restart)\s+.*\.timer|(^|\s|;|&&|\|)at\s+)'; then
22
+ echo "BLOCKED: Cron/timer modification requires manual review." >&2
23
+ echo "" >&2
24
+ echo "Command: $COMMAND" >&2
25
+ echo "" >&2
26
+ echo "Cron jobs are persistent and run unattended. Before creating one:" >&2
27
+ echo " 1. Will this interfere with live services?" >&2
28
+ echo " 2. Does it access shared resources (DB, API, proxy)?" >&2
29
+ echo " 3. What happens if it fails silently?" >&2
30
+ exit 2
31
+ fi
32
+
33
+ # Also catch writing to cron directories
34
+ if echo "$COMMAND" | grep -qE '>\s*/etc/cron\.|tee\s+/etc/cron\.'; then
35
+ echo "BLOCKED: Direct write to cron directory." >&2
36
+ echo "Command: $COMMAND" >&2
37
+ exit 2
38
+ fi
39
+
40
+ exit 0
@@ -0,0 +1,47 @@
1
+ #!/bin/bash
2
+ # cwd-drift-detector.sh — Warn when destructive commands run outside project root
3
+ #
4
+ # Solves: Claude frequently loses track of which directory
5
+ # it is in, risking destructive commands in the wrong
6
+ # location (#1669). git reset --hard in the wrong
7
+ # directory can destroy unrelated work.
8
+ #
9
+ # How it works: For destructive commands (git reset, rm -rf,
10
+ # git clean, git checkout -- .), checks if the current
11
+ # directory looks like a project root (has .git, package.json,
12
+ # etc). Warns if it doesn't.
13
+ #
14
+ # TRIGGER: PreToolUse
15
+ # MATCHER: "Bash"
16
+
17
+ set -euo pipefail
18
+ INPUT=$(cat)
19
+
20
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
21
+ [ -z "$COMMAND" ] && exit 0
22
+
23
+ # Only check destructive commands
24
+ if ! echo "$COMMAND" | grep -qE '(git\s+(reset|clean|checkout\s+--|push\s+--force)|rm\s+-rf|DROP\s+TABLE|DROP\s+DATABASE)'; then
25
+ exit 0
26
+ fi
27
+
28
+ # Check if we're in a project root
29
+ CWD=$(pwd)
30
+ IS_PROJECT=false
31
+
32
+ for marker in .git package.json Cargo.toml go.mod pyproject.toml Makefile; do
33
+ if [ -e "$CWD/$marker" ]; then
34
+ IS_PROJECT=true
35
+ break
36
+ fi
37
+ done
38
+
39
+ if [ "$IS_PROJECT" = false ]; then
40
+ echo "WARNING: Destructive command detected outside project root." >&2
41
+ echo " CWD: $CWD" >&2
42
+ echo " Command: $(echo "$COMMAND" | head -c 100)" >&2
43
+ echo " No project markers (.git, package.json, etc) found." >&2
44
+ echo " Verify you are in the correct directory." >&2
45
+ fi
46
+
47
+ exit 0
@@ -0,0 +1,50 @@
1
+ #!/bin/bash
2
+ # cwd-project-boundary-guard.sh — Warn when cd leaves the project directory
3
+ #
4
+ # Solves: Claude navigating to system directories or other projects
5
+ # and making changes outside the intended scope. Especially
6
+ # dangerous with auto-approve, where writes to /etc or
7
+ # other projects go unchallenged.
8
+ #
9
+ # How it works: CwdChanged hook that tracks the project root and warns
10
+ # when the working directory moves outside it.
11
+ #
12
+ # CONFIG:
13
+ # CC_PROJECT_ROOT (auto-detected if not set)
14
+ #
15
+ # TRIGGER: CwdChanged
16
+ # MATCHER: "" (CwdChanged has no matcher support)
17
+
18
+ set -euo pipefail
19
+
20
+ INPUT=$(cat)
21
+ NEW_CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null)
22
+ [ -z "$NEW_CWD" ] && exit 0
23
+
24
+ # Determine project root
25
+ PROJECT_ROOT="${CC_PROJECT_ROOT:-}"
26
+ if [ -z "$PROJECT_ROOT" ]; then
27
+ # Auto-detect: find nearest .git directory
28
+ PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "")
29
+ fi
30
+ [ -z "$PROJECT_ROOT" ] && exit 0
31
+
32
+ # Normalize paths
33
+ PROJECT_ROOT=$(realpath "$PROJECT_ROOT" 2>/dev/null || echo "$PROJECT_ROOT")
34
+ NEW_CWD=$(realpath "$NEW_CWD" 2>/dev/null || echo "$NEW_CWD")
35
+
36
+ # Check if new cwd is inside project
37
+ case "$NEW_CWD" in
38
+ "$PROJECT_ROOT"|"$PROJECT_ROOT"/*)
39
+ # Inside project — OK
40
+ exit 0
41
+ ;;
42
+ *)
43
+ echo "WARNING: Working directory left project boundary." >&2
44
+ echo " Project: $PROJECT_ROOT" >&2
45
+ echo " New cwd: $NEW_CWD" >&2
46
+ echo " Changes outside the project may affect other systems." >&2
47
+ ;;
48
+ esac
49
+
50
+ exit 0
@@ -0,0 +1,41 @@
1
+ #!/bin/bash
2
+ # denied-action-retry-guard.sh — Block re-attempts of denied tool calls
3
+ #
4
+ # Solves: Model retries the same operation after user explicitly denied it (#40156).
5
+ # Claude asks "shall I git push?", user says no, Claude tries git push anyway.
6
+ #
7
+ # How it works: PreToolUse hook that tracks denied operations via a state file.
8
+ # When a tool call is blocked (exit 2 from any hook), the command signature
9
+ # is recorded. If the same signature appears again, it's auto-blocked.
10
+ #
11
+ # TRIGGER: PreToolUse
12
+ # MATCHER: "Bash|Edit|Write"
13
+
14
+ set -euo pipefail
15
+
16
+ INPUT=$(cat)
17
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
18
+ COMMAND=""
19
+
20
+ case "$TOOL" in
21
+ Bash) COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null) ;;
22
+ Edit|Write) COMMAND=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null) ;;
23
+ *) exit 0 ;;
24
+ esac
25
+
26
+ [ -z "$COMMAND" ] && exit 0
27
+
28
+ DENY_FILE="/tmp/claude-denied-actions-${PPID:-0}"
29
+
30
+ # Check if this action was previously denied
31
+ if [ -f "$DENY_FILE" ]; then
32
+ # Normalize: take first 80 chars as signature
33
+ SIG=$(echo "$COMMAND" | head -c 80 | md5sum | cut -d' ' -f1)
34
+ if grep -q "$SIG" "$DENY_FILE" 2>/dev/null; then
35
+ echo "BLOCKED: This action was previously denied in this session." >&2
36
+ echo "Do not retry denied actions. Try a different approach." >&2
37
+ exit 2
38
+ fi
39
+ fi
40
+
41
+ exit 0
@@ -16,6 +16,8 @@
16
16
  # - Packages in ALLOWLIST (customize below)
17
17
  #
18
18
  # Usage: Add to settings.json as a PreToolUse hook on "Bash"
19
+ #
20
+ # TRIGGER: PreToolUse MATCHER: "Bash"
19
21
 
20
22
  INPUT=$(cat)
21
23
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -17,6 +17,8 @@
17
17
  # }]
18
18
  # }
19
19
  # }
20
+ #
21
+ # TRIGGER: PreToolUse MATCHER: "Bash"
20
22
 
21
23
  INPUT=$(cat)
22
24
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)