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,48 @@
1
+ #!/bin/bash
2
+ # file-recycle-bin.sh — Move deleted files to recycle bin instead of permanent deletion
3
+ #
4
+ # Solves: No undo for file operations during Claude Code sessions (#39949).
5
+ # When Claude deletes or overwrites files, they're gone permanently
6
+ # unless git tracked. This hook intercepts rm commands and moves
7
+ # files to a session recycle bin.
8
+ #
9
+ # How it works: PreToolUse hook on Bash that intercepts rm commands,
10
+ # copies target files to .claude/recycle-bin/ before allowing deletion.
11
+ # Restore with: cp .claude/recycle-bin/<file> <original-path>
12
+ #
13
+ # TRIGGER: PreToolUse
14
+ # MATCHER: "Bash"
15
+
16
+ set -euo pipefail
17
+
18
+ INPUT=$(cat)
19
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
20
+ [ -z "$COMMAND" ] && exit 0
21
+
22
+ # Only intercept rm commands (not rm -rf which destructive-guard handles)
23
+ if ! echo "$COMMAND" | grep -qE '^\s*rm\s'; then
24
+ exit 0
25
+ fi
26
+
27
+ # Skip if destructive-guard would catch it (rm -rf /, rm -rf ~, etc.)
28
+ if echo "$COMMAND" | grep -qE 'rm\s+(-[rf]+\s+)*(/|~|\$HOME)'; then
29
+ exit 0 # Let destructive-guard handle these
30
+ fi
31
+
32
+ # Extract file paths from rm command (simple extraction)
33
+ FILES=$(echo "$COMMAND" | sed 's/^[[:space:]]*rm[[:space:]]*//' | sed 's/-[rfiv]*//g' | tr ' ' '\n' | grep -v '^$' | grep -v '^-')
34
+
35
+ BIN_DIR=".claude/recycle-bin"
36
+ mkdir -p "$BIN_DIR"
37
+
38
+ for FILE in $FILES; do
39
+ if [ -f "$FILE" ]; then
40
+ BASENAME=$(basename "$FILE")
41
+ TIMESTAMP=$(date +%H%M%S)
42
+ cp "$FILE" "$BIN_DIR/${TIMESTAMP}-${BASENAME}" 2>/dev/null || true
43
+ echo "Backed up: $FILE -> $BIN_DIR/${TIMESTAMP}-${BASENAME}" >&2
44
+ fi
45
+ done
46
+
47
+ # Allow the rm to proceed (files are backed up)
48
+ exit 0
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Bash"
2
4
  INPUT=$(cat)
3
5
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
4
6
  CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
@@ -1,3 +1,5 @@
1
+ #
2
+ # TRIGGER: Notification MATCHER: ""
1
3
  INPUT=$(cat)
2
4
  SETTINGS="$HOME/.claude/settings.local.json"
3
5
  [[ ! -f "$SETTINGS" ]] && exit 0
@@ -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)
@@ -1,3 +1,5 @@
1
+ #
2
+ # TRIGGER: PreToolUse MATCHER: "Bash"
1
3
  INPUT=$(cat)
2
4
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
3
5
  [[ -z "$COMMAND" ]] && exit 0
@@ -23,6 +23,8 @@
23
23
  # }]
24
24
  # }
25
25
  # }
26
+ #
27
+ # TRIGGER: PreToolUse MATCHER: "Bash"
26
28
 
27
29
  INPUT=$(cat)
28
30
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -14,6 +14,8 @@
14
14
  # }]
15
15
  # }
16
16
  # }
17
+ #
18
+ # TRIGGER: PreToolUse MATCHER: "Bash"
17
19
 
18
20
  INPUT=$(cat)
19
21
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -0,0 +1,36 @@
1
+ #!/bin/bash
2
+ # git-crypt-worktree-guard.sh — Block worktree creation in git-crypt repos
3
+ #
4
+ # Solves: When Claude creates a worktree in a git-crypt repo,
5
+ # the smudge filter fails because git-crypt hasn't been
6
+ # unlocked in the new worktree. This produces destructive
7
+ # commits that delete all encrypted files (#38538).
8
+ #
9
+ # How it works: Before git worktree add, checks if the repo
10
+ # uses git-crypt (.gitattributes contains filter=git-crypt).
11
+ # If yes, blocks the worktree creation with a warning.
12
+ #
13
+ # TRIGGER: PreToolUse
14
+ # MATCHER: "Bash"
15
+
16
+ set -euo pipefail
17
+ INPUT=$(cat)
18
+
19
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
20
+ [ -z "$COMMAND" ] && exit 0
21
+
22
+ # Only check git worktree add
23
+ if ! echo "$COMMAND" | grep -qE 'git\s+worktree\s+add'; then
24
+ exit 0
25
+ fi
26
+
27
+ # Check if repo uses git-crypt
28
+ if [ -f ".gitattributes" ] && grep -q "filter=git-crypt" .gitattributes 2>/dev/null; then
29
+ echo "BLOCKED: Cannot create worktree in a git-crypt repo." >&2
30
+ echo "git-crypt is not automatically unlocked in new worktrees." >&2
31
+ echo "This would produce destructive commits that delete all encrypted files." >&2
32
+ echo "Work in the main repo instead, or manually run 'git-crypt unlock' in the worktree first." >&2
33
+ exit 2
34
+ fi
35
+
36
+ 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
  if echo "$COMMAND" | grep -qE "git\s+(commit|push|merge).*--no-verify"; then echo "WARNING: --no-verify bypasses git hooks" >&2; fi
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Bash"
2
4
  INPUT=$(cat)
3
5
  CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
4
6
  [ -z "$CONTENT" ] && 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
  echo "$COMMAND" | grep -qE "git\s+commit\s+-m" || exit 0; MSG=$(echo "$COMMAND" | grep -oP "(?<=-m\s[\x27\x22])[^\x27\x22]+"); [ ${#MSG} -lt 10 ] && echo "WARNING: Commit message too short (${#MSG} chars)" >&2
@@ -0,0 +1,99 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # git-operations-require-approval.sh — Block git write operations
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Claude Code sometimes ignores CLAUDE.md rules about git commit,
7
+ # push, and branch creation — performing these operations without
8
+ # user approval. This hook enforces the restriction at process level.
9
+ #
10
+ # Blocks:
11
+ # git commit, git push (including --force), git checkout -b,
12
+ # git switch -c, git branch <name>
13
+ #
14
+ # Does NOT block:
15
+ # git status, git log, git diff, git show, git branch (list),
16
+ # git fetch, git stash, git add
17
+ #
18
+ # Handles compound commands (&&, ;, ||) by checking each segment.
19
+ #
20
+ # See: https://github.com/anthropics/claude-code/issues/40695
21
+ #
22
+ # TRIGGER: PreToolUse MATCHER: "Bash"
23
+ # ================================================================
24
+
25
+ INPUT=$(cat)
26
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
27
+
28
+ [ -z "$COMMAND" ] && exit 0
29
+
30
+ # Skip if the command is inside echo/printf (not actual execution)
31
+ echo "$COMMAND" | grep -qE '^\s*(echo|printf)\s' && exit 0
32
+
33
+ # Check each segment of compound commands
34
+ check_segment() {
35
+ local seg="$1"
36
+ # Trim whitespace
37
+ seg=$(echo "$seg" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
38
+ [ -z "$seg" ] && return 0
39
+
40
+ # git commit
41
+ if echo "$seg" | grep -qE '\bgit\s+commit\b'; then
42
+ echo "BLOCKED: git commit requires explicit user approval." >&2
43
+ echo "Command: $seg" >&2
44
+ echo "" >&2
45
+ echo "See: https://github.com/anthropics/claude-code/issues/40695" >&2
46
+ return 1
47
+ fi
48
+
49
+ # git push (including force variants)
50
+ if echo "$seg" | grep -qE '\bgit\s+push\b'; then
51
+ echo "BLOCKED: git push requires explicit user approval." >&2
52
+ echo "Command: $seg" >&2
53
+ echo "" >&2
54
+ echo "See: https://github.com/anthropics/claude-code/issues/40695" >&2
55
+ return 1
56
+ fi
57
+
58
+ # git checkout -b (branch creation)
59
+ if echo "$seg" | grep -qE '\bgit\s+checkout\s+(-b|--branch)\b'; then
60
+ echo "BLOCKED: git branch creation requires explicit user approval." >&2
61
+ echo "Command: $seg" >&2
62
+ return 1
63
+ fi
64
+
65
+ # git switch -c / --create (branch creation)
66
+ if echo "$seg" | grep -qE '\bgit\s+switch\s+(-c|--create)\b'; then
67
+ echo "BLOCKED: git branch creation requires explicit user approval." >&2
68
+ echo "Command: $seg" >&2
69
+ return 1
70
+ fi
71
+
72
+ # git branch <name> (creation, not listing)
73
+ # git branch without flags or with only -a/-r/-l/--list is listing
74
+ if echo "$seg" | grep -qE '\bgit\s+branch\s'; then
75
+ # Allow listing flags
76
+ if echo "$seg" | grep -qE '\bgit\s+branch\s+(-[arl]|--list|--merged|--no-merged|--contains|-v|--verbose|-d|--delete|-D)\b'; then
77
+ return 0
78
+ fi
79
+ # If it has a name argument after "git branch", it's creation
80
+ local args
81
+ args=$(echo "$seg" | sed 's/.*\bgit\s\+branch\s\+//')
82
+ if [ -n "$args" ] && ! echo "$args" | grep -qE '^\s*$'; then
83
+ echo "BLOCKED: git branch creation requires explicit user approval." >&2
84
+ echo "Command: $seg" >&2
85
+ return 1
86
+ fi
87
+ fi
88
+
89
+ return 0
90
+ }
91
+
92
+ # Split on && ; || and check each part
93
+ while IFS= read -r segment; do
94
+ if ! check_segment "$segment"; then
95
+ exit 2
96
+ fi
97
+ done < <(echo "$COMMAND" | sed 's/&&/\n/g; s/;/\n/g; s/||/\n/g')
98
+
99
+ exit 0
@@ -0,0 +1,41 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # git-show-flag-sanitizer.sh — Strip invalid --no-stat from git show
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Claude Code frequently runs `git show <ref> --no-stat`, but --no-stat
7
+ # is not a valid git-show flag. The command fails with exit code 128,
8
+ # wasting context on error output and retries.
9
+ # This hook silently rewrites the command to remove --no-stat.
10
+ #
11
+ # TRIGGER: PreToolUse
12
+ # MATCHER: "Bash"
13
+ #
14
+ # See: https://github.com/anthropics/claude-code/issues/13071
15
+ # ================================================================
16
+
17
+ INPUT=$(cat)
18
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
19
+ [ -z "$COMMAND" ] && exit 0
20
+
21
+ # Only act on git show commands containing --no-stat
22
+ case "$COMMAND" in
23
+ *git\ show*--no-stat*|*git\ show*--no-stat*) ;;
24
+ *) exit 0 ;;
25
+ esac
26
+
27
+ # Remove --no-stat flag (handles multiple spaces)
28
+ NEW_COMMAND=$(echo "$COMMAND" | sed 's/ --no-stat//')
29
+
30
+ # Collapse any double spaces left behind
31
+ NEW_COMMAND=$(echo "$NEW_COMMAND" | sed 's/ */ /g')
32
+
33
+ jq -n --arg cmd "$NEW_COMMAND" '{
34
+ hookSpecificOutput: {
35
+ hookEventName: "PreToolUse",
36
+ permissionDecision: "allow",
37
+ updatedInput: { command: $cmd }
38
+ }
39
+ }'
40
+
41
+ exit 0
@@ -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)
@@ -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
  if echo "$COMMAND" | grep -qE '\bgit\s+submodule\s+(deinit|rm)\b'; then
@@ -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
  if echo "$COMMAND" | grep -qE 'git\s+tag\s+(-a\s+|-d\s+)?v'; then
@@ -0,0 +1,59 @@
1
+ #!/bin/bash
2
+ # github-actions-secret-guard.sh — Prevent hardcoded secrets in GitHub Actions workflows
3
+ #
4
+ # Solves: Claude writes API keys, tokens, or passwords directly into
5
+ # .github/workflows/*.yml files instead of using ${{ secrets.NAME }}.
6
+ # These get committed and pushed to public/private repos.
7
+ #
8
+ # How it works: PostToolUse hook on Edit/Write that checks if the target
9
+ # is a GitHub Actions workflow file, then scans for patterns that look
10
+ # like hardcoded secrets instead of ${{ secrets.* }} references.
11
+ #
12
+ # TRIGGER: PostToolUse
13
+ # MATCHER: "Edit|Write"
14
+
15
+ set -euo pipefail
16
+
17
+ INPUT=$(cat)
18
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
19
+ case "$TOOL" in Edit|Write) ;; *) exit 0 ;; esac
20
+
21
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
22
+ [ -z "$FILE" ] && exit 0
23
+
24
+ # Only check GitHub Actions workflow files
25
+ case "$FILE" in
26
+ .github/workflows/*.yml|.github/workflows/*.yaml) ;;
27
+ */.github/workflows/*.yml|*/.github/workflows/*.yaml) ;;
28
+ *) exit 0 ;;
29
+ esac
30
+
31
+ [ -f "$FILE" ] || exit 0
32
+
33
+ # Check for hardcoded secret patterns (not using ${{ secrets.* }})
34
+ ISSUES=""
35
+
36
+ # API keys / tokens in env or with: blocks
37
+ if grep -nE '(APIKEY|API_KEY|TOKEN|SECRET|PASSWORD|PRIVATE_KEY)\s*[:=]\s*["\x27]?[A-Za-z0-9+/=_-]{20,}' "$FILE" 2>/dev/null | grep -v '\${{' | head -3 | grep -q .; then
38
+ ISSUES="${ISSUES}Hardcoded API key/token found (use \${{ secrets.NAME }} instead)\n"
39
+ fi
40
+
41
+ # Bearer tokens
42
+ if grep -nE 'Bearer\s+[A-Za-z0-9._-]{20,}' "$FILE" 2>/dev/null | grep -v '\${{' | head -1 | grep -q .; then
43
+ ISSUES="${ISSUES}Hardcoded Bearer token found\n"
44
+ fi
45
+
46
+ # AWS credentials
47
+ if grep -nE 'AKIA[0-9A-Z]{16}' "$FILE" 2>/dev/null | head -1 | grep -q .; then
48
+ ISSUES="${ISSUES}AWS access key ID found in workflow\n"
49
+ fi
50
+
51
+ if [ -n "$ISSUES" ]; then
52
+ echo "WARNING: Potential secrets in GitHub Actions workflow:" >&2
53
+ echo " File: $FILE" >&2
54
+ echo -e " $ISSUES" >&2
55
+ echo " Use \${{ secrets.NAME }} instead of hardcoded values." >&2
56
+ echo " Add secrets via: gh secret set NAME --body 'value'" >&2
57
+ fi
58
+
59
+ 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
  echo "$COMMAND" | grep -qE '^\s*git\s+add' || exit 0
@@ -0,0 +1,53 @@
1
+ #!/bin/bash
2
+ # gitops-drift-guard.sh — Warn when editing infrastructure files without PR
3
+ #
4
+ # Solves: Claude directly modifying Terraform, Kubernetes manifests, or
5
+ # Helm values on the default branch instead of creating a PR.
6
+ # In GitOps workflows, direct commits to main trigger immediate
7
+ # infrastructure changes.
8
+ #
9
+ # How it works: PreToolUse hook on Edit/Write that checks if the target
10
+ # file is an infrastructure file AND the current branch is main/master.
11
+ # Warns that changes should go through a PR for review.
12
+ #
13
+ # TRIGGER: PreToolUse
14
+ # MATCHER: "Edit|Write"
15
+
16
+ set -euo pipefail
17
+
18
+ INPUT=$(cat)
19
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
20
+ case "$TOOL" in Edit|Write) ;; *) exit 0 ;; esac
21
+
22
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
23
+ [ -z "$FILE" ] && exit 0
24
+
25
+ # Check if this is an infrastructure file
26
+ IS_INFRA=false
27
+ case "$FILE" in
28
+ *.tf|*.tfvars) IS_INFRA=true ;; # Terraform
29
+ */k8s/*.yaml|*/k8s/*.yml) IS_INFRA=true ;; # Kubernetes manifests
30
+ */helm/**/values*.yaml) IS_INFRA=true ;; # Helm values
31
+ */charts/**/*.yaml) IS_INFRA=true ;; # Helm charts
32
+ .github/workflows/*.yml) IS_INFRA=true ;; # CI/CD workflows
33
+ Dockerfile*|docker-compose*.yml) IS_INFRA=true ;; # Docker
34
+ */argocd/*.yaml) IS_INFRA=true ;; # ArgoCD
35
+ */flux/*.yaml) IS_INFRA=true ;; # Flux
36
+ ansible/*.yml|*/playbooks/*.yml) IS_INFRA=true ;; # Ansible
37
+ esac
38
+
39
+ $IS_INFRA || exit 0
40
+
41
+ # Check if we're on a protected branch
42
+ BRANCH=$(git branch --show-current 2>/dev/null || echo "")
43
+ case "$BRANCH" in
44
+ main|master|production|release|release/*)
45
+ echo "WARNING: Editing infrastructure file on protected branch '$BRANCH'." >&2
46
+ echo " File: $FILE" >&2
47
+ echo " In GitOps workflows, changes to $BRANCH trigger immediate deployment." >&2
48
+ echo " Consider creating a feature branch and PR instead." >&2
49
+ # Warning only — change to exit 2 to block
50
+ ;;
51
+ esac
52
+
53
+ exit 0
@@ -1,3 +1,5 @@
1
+ #
2
+ # TRIGGER: PostToolUse MATCHER: "Bash"
1
3
  INPUT=$(cat)
2
4
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
3
5
  [[ -z "$COMMAND" ]] && exit 0
@@ -21,6 +21,8 @@
21
21
  # }
22
22
  # }
23
23
  # ================================================================
24
+ #
25
+ # TRIGGER: PreToolUse MATCHER: "Bash"
24
26
 
25
27
  INPUT=$(cat)
26
28
  TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
@@ -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,46 @@
1
+ #!/bin/bash
2
+ # headless-empty-result-guard.sh — Detect empty results in headless mode
3
+ #
4
+ # Solves: claude -p exits with empty result when stream is interrupted (#40432).
5
+ # stop_reason: "tool_use" with result: "" is treated as success,
6
+ # but the model was actually mid-generation.
7
+ #
8
+ # How it works: Stop hook that checks environment for headless indicators
9
+ # and warns if the session produced no visible output. In CI/automation,
10
+ # this can trigger a retry or alert.
11
+ #
12
+ # CONFIG:
13
+ # CC_HEADLESS_MARKER="/tmp/claude-headless-result"
14
+ # Set this in your CI script to check after claude -p exits.
15
+ #
16
+ # TRIGGER: Stop
17
+ # MATCHER: ""
18
+
19
+ set -euo pipefail
20
+
21
+ INPUT=$(cat)
22
+
23
+ # Check if we're in headless/print mode
24
+ # Indicators: CLAUDE_PRINT_MODE env var, or no TTY
25
+ if [ -z "${CLAUDE_PRINT_MODE:-}" ] && [ -t 0 ]; then
26
+ # Interactive mode — skip
27
+ exit 0
28
+ fi
29
+
30
+ # Check for empty/incomplete result indicators
31
+ STOP_REASON=$(echo "$INPUT" | jq -r '.stop_reason // empty' 2>/dev/null)
32
+ RESULT=$(echo "$INPUT" | jq -r '.result // empty' 2>/dev/null)
33
+
34
+ MARKER="${CC_HEADLESS_MARKER:-/tmp/claude-headless-result-${PPID:-0}}"
35
+
36
+ if [ "$STOP_REASON" = "tool_use" ] || [ -z "$RESULT" ]; then
37
+ echo "WARNING: Headless session ended with incomplete result." >&2
38
+ echo " stop_reason: ${STOP_REASON:-unknown}" >&2
39
+ echo " result length: ${#RESULT}" >&2
40
+ echo " This may indicate a stream interruption, not a completed task." >&2
41
+ echo "incomplete" > "$MARKER"
42
+ else
43
+ echo "complete" > "$MARKER"
44
+ fi
45
+
46
+ exit 0
@@ -0,0 +1,43 @@
1
+ #!/bin/bash
2
+ # headless-stop-guard.sh — Skip Stop hooks in headless (-p) mode
3
+ #
4
+ # Solves: Stop hook causes empty result in print mode (#38651).
5
+ # Any Stop hook (even no-op) causes `claude -p` to return
6
+ # empty string instead of the model's response.
7
+ #
8
+ # How it works: Detects headless mode via parent process inspection
9
+ # and exits immediately, preventing the Stop hook from interfering
10
+ # with result collection.
11
+ #
12
+ # TRIGGER: Stop
13
+ # MATCHER: ""
14
+ #
15
+ # Usage: Use as a wrapper around your actual Stop hook:
16
+ # {
17
+ # "hooks": {
18
+ # "Stop": [{
19
+ # "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/headless-stop-guard.sh ~/.claude/hooks/my-stop-hook.sh" }]
20
+ # }]
21
+ # }
22
+ # }
23
+ #
24
+ # Or set CC_HEADLESS=1 in your wrapper script before `claude -p`.
25
+
26
+ # Method 1: Environment variable (most reliable)
27
+ [ "$CC_HEADLESS" = "1" ] && exit 0
28
+
29
+ # Method 2: Parent process detection
30
+ PARENT_CMD=$(ps -o args= -p $PPID 2>/dev/null || true)
31
+ if echo "$PARENT_CMD" | grep -qE '\bclaude\b.*\s-p\b'; then
32
+ exit 0
33
+ fi
34
+
35
+ # Not headless — run the wrapped hook if provided
36
+ TARGET="$1"
37
+ if [ -n "$TARGET" ] && [ -f "$TARGET" ]; then
38
+ shift
39
+ cat | bash "$TARGET" "$@"
40
+ exit $?
41
+ fi
42
+
43
+ exit 0
@@ -1,3 +1,5 @@
1
+ #
2
+ # TRIGGER: PreToolUse MATCHER: "Bash"
1
3
  INPUT=$(cat)
2
4
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
3
5
  [[ -z "$COMMAND" ]] && exit 0
@@ -0,0 +1,45 @@
1
+ #!/bin/bash
2
+ # issue-draft-redact-guard.sh — Redact sensitive info from public issue drafts
3
+ #
4
+ # Solves: Claude drafting public bug reports with sensitive project info (#29121).
5
+ # Internal org names, private URLs, IP addresses, and file paths
6
+ # get included in gh issue create commands.
7
+ #
8
+ # How it works: PreToolUse hook on Bash that intercepts gh issue/pr create
9
+ # commands and scans the body for sensitive patterns.
10
+ #
11
+ # TRIGGER: PreToolUse
12
+ # MATCHER: "Bash"
13
+
14
+ set -euo pipefail
15
+
16
+ INPUT=$(cat)
17
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
18
+ [ -z "$COMMAND" ] && exit 0
19
+
20
+ # Only check issue/PR creation commands
21
+ if ! echo "$COMMAND" | grep -qE 'gh\s+(issue|pr)\s+create'; then
22
+ exit 0
23
+ fi
24
+
25
+ # Scan for sensitive patterns in the command body
26
+ SENSITIVE_PATTERNS=(
27
+ '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' # IP addresses
28
+ '(internal|private|corp|staging)\.[a-z]+\.[a-z]+' # Internal domains
29
+ '/home/[a-zA-Z]+/' # Home directory paths
30
+ '/Users/[a-zA-Z]+/' # macOS home paths
31
+ 'password|passwd|secret_key|private_key' # Secret keywords
32
+ )
33
+
34
+ for pattern in "${SENSITIVE_PATTERNS[@]}"; do
35
+ if echo "$COMMAND" | grep -qEi "$pattern"; then
36
+ MATCH=$(echo "$COMMAND" | grep -oEi "$pattern" | head -1)
37
+ echo "WARNING: Sensitive pattern detected in issue draft." >&2
38
+ echo "Pattern match: $MATCH" >&2
39
+ echo "Review and redact before posting publicly." >&2
40
+ # Warn but don't block — user may intentionally include their own info
41
+ break
42
+ fi
43
+ done
44
+
45
+ exit 0
@@ -17,6 +17,8 @@
17
17
  # }
18
18
  # }
19
19
  # ================================================================
20
+ #
21
+ # TRIGGER: PreToolUse MATCHER: "Bash"
20
22
 
21
23
  INPUT=$(cat)
22
24
  FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)