cc-safe-setup 29.6.32 → 29.6.33

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 (384) 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/commit-message-check.sh +2 -0
  99. package/examples/compact-blocker.sh +25 -0
  100. package/examples/composer-guard.sh +2 -0
  101. package/examples/compound-command-allow.sh +2 -0
  102. package/examples/consecutive-failure-circuit-breaker.sh +49 -0
  103. package/examples/console-log-count.sh +2 -0
  104. package/examples/context-compact-advisor.sh +16 -0
  105. package/examples/cors-star-warn.sh +2 -0
  106. package/examples/credential-exfil-guard.sh +2 -0
  107. package/examples/credential-file-cat-guard.sh +2 -0
  108. package/examples/cron-modification-guard.sh +40 -0
  109. package/examples/cwd-project-boundary-guard.sh +50 -0
  110. package/examples/denied-action-retry-guard.sh +41 -0
  111. package/examples/dependency-install-guard.sh +2 -0
  112. package/examples/deploy-guard.sh +2 -0
  113. package/examples/deploy-path-verify-guard.sh +62 -0
  114. package/examples/django-migrate-guard.sh +2 -0
  115. package/examples/docker-volume-guard.sh +2 -0
  116. package/examples/dockerfile-latest-guard.sh +2 -0
  117. package/examples/dotenv-commit-guard.sh +44 -0
  118. package/examples/dotenv-example-sync.sh +55 -0
  119. package/examples/dotnet-build-on-edit.sh +2 -0
  120. package/examples/drizzle-migrate-guard.sh +2 -0
  121. package/examples/edit-counter-test-gate.sh +44 -0
  122. package/examples/edit-error-counter.sh +2 -0
  123. package/examples/edit-guard.sh +2 -0
  124. package/examples/edit-retry-loop-guard.sh +2 -0
  125. package/examples/edit-verify.sh +2 -0
  126. package/examples/enforce-tests.sh +2 -0
  127. package/examples/env-inherit-guard.sh +2 -0
  128. package/examples/env-inline-secret-guard.sh +36 -0
  129. package/examples/env-prod-guard.sh +2 -0
  130. package/examples/env-required-check.sh +2 -0
  131. package/examples/env-var-check.sh +2 -0
  132. package/examples/expo-eject-guard.sh +2 -0
  133. package/examples/export-overwrite-guard.sh +29 -0
  134. package/examples/file-change-tracker.sh +2 -0
  135. package/examples/file-change-undo-tracker.sh +46 -0
  136. package/examples/file-recycle-bin.sh +48 -0
  137. package/examples/file-size-limit.sh +2 -0
  138. package/examples/five-hundred-milestone.sh +2 -0
  139. package/examples/flask-debug-guard.sh +2 -0
  140. package/examples/gem-push-guard.sh +2 -0
  141. package/examples/git-checkout-safety-guard.sh +2 -0
  142. package/examples/git-config-guard.sh +2 -0
  143. package/examples/git-hook-bypass-guard.sh +2 -0
  144. package/examples/git-merge-conflict-prevent.sh +2 -0
  145. package/examples/git-message-length.sh +2 -0
  146. package/examples/git-show-flag-sanitizer.sh +41 -0
  147. package/examples/git-stash-before-danger.sh +2 -0
  148. package/examples/git-submodule-guard.sh +2 -0
  149. package/examples/git-tag-guard.sh +2 -0
  150. package/examples/github-actions-secret-guard.sh +59 -0
  151. package/examples/gitignore-check.sh +2 -0
  152. package/examples/gitops-drift-guard.sh +53 -0
  153. package/examples/go-mod-tidy-warn.sh +2 -0
  154. package/examples/hallucination-url-check.sh +2 -0
  155. package/examples/hardcoded-ip-guard.sh +2 -0
  156. package/examples/headless-empty-result-guard.sh +46 -0
  157. package/examples/headless-stop-guard.sh +43 -0
  158. package/examples/helm-install-guard.sh +2 -0
  159. package/examples/issue-draft-redact-guard.sh +45 -0
  160. package/examples/java-compile-on-edit.sh +2 -0
  161. package/examples/k8s-production-guard.sh +77 -0
  162. package/examples/laravel-artisan-guard.sh +2 -0
  163. package/examples/large-file-guard.sh +2 -0
  164. package/examples/log-level-guard.sh +2 -0
  165. package/examples/magic-number-warn.sh +2 -0
  166. package/examples/max-edit-size-guard.sh +2 -0
  167. package/examples/max-file-count-guard.sh +2 -0
  168. package/examples/max-file-delete-count.sh +2 -0
  169. package/examples/max-function-length.sh +2 -0
  170. package/examples/max-import-count.sh +2 -0
  171. package/examples/max-subagent-count.sh +2 -0
  172. package/examples/mcp-orphan-process-guard.sh +39 -0
  173. package/examples/mcp-server-allowlist.sh +45 -0
  174. package/examples/mcp-tool-audit-log.sh +41 -0
  175. package/examples/mcp-tool-guard.sh +2 -0
  176. package/examples/migration-verify-guard.sh +44 -0
  177. package/examples/monorepo-scope-guard.sh +2 -0
  178. package/examples/network-exfil-guard.sh +61 -0
  179. package/examples/network-guard.sh +2 -0
  180. package/examples/nextjs-env-guard.sh +2 -0
  181. package/examples/no-absolute-import.sh +2 -0
  182. package/examples/no-alert-confirm-prompt.sh +2 -0
  183. package/examples/no-any-type.sh +2 -0
  184. package/examples/no-any-typescript.sh +2 -0
  185. package/examples/no-assignment-in-condition.sh +2 -0
  186. package/examples/no-callback-hell.sh +2 -0
  187. package/examples/no-catch-all-route.sh +2 -0
  188. package/examples/no-circular-dependency.sh +2 -0
  189. package/examples/no-class-in-functional.sh +2 -0
  190. package/examples/no-cleartext-storage.sh +2 -0
  191. package/examples/no-commented-code.sh +2 -0
  192. package/examples/no-commit-fixup.sh +2 -0
  193. package/examples/no-console-assert.sh +2 -0
  194. package/examples/no-console-error-swallow.sh +2 -0
  195. package/examples/no-console-in-prod.sh +2 -0
  196. package/examples/no-console-log.sh +2 -0
  197. package/examples/no-console-time.sh +2 -0
  198. package/examples/no-cors-wildcard.sh +2 -0
  199. package/examples/no-curl-upload.sh +2 -0
  200. package/examples/no-dangerouslySetInnerHTML.sh +2 -0
  201. package/examples/no-dangling-await.sh +2 -0
  202. package/examples/no-debug-in-commit.sh +2 -0
  203. package/examples/no-deep-nesting.sh +2 -0
  204. package/examples/no-deep-relative-import.sh +2 -0
  205. package/examples/no-default-credentials.sh +2 -0
  206. package/examples/no-deprecated-api.sh +2 -0
  207. package/examples/no-direct-dom-manipulation.sh +2 -0
  208. package/examples/no-disabled-test.sh +2 -0
  209. package/examples/no-document-cookie.sh +2 -0
  210. package/examples/no-document-write.sh +2 -0
  211. package/examples/no-empty-function.sh +2 -0
  212. package/examples/no-eval-in-template.sh +2 -0
  213. package/examples/no-eval-template.sh +2 -0
  214. package/examples/no-eval.sh +2 -0
  215. package/examples/no-exec-user-input.sh +2 -0
  216. package/examples/no-expose-internal-ids.sh +2 -0
  217. package/examples/no-floating-promises.sh +2 -0
  218. package/examples/no-force-install.sh +2 -0
  219. package/examples/no-git-rebase-public.sh +2 -0
  220. package/examples/no-global-state.sh +2 -0
  221. package/examples/no-hardcoded-port.sh +2 -0
  222. package/examples/no-hardcoded-url.sh +2 -0
  223. package/examples/no-helmet-missing.sh +2 -0
  224. package/examples/no-http-url.sh +2 -0
  225. package/examples/no-http-without-https.sh +2 -0
  226. package/examples/no-index-as-key.sh +2 -0
  227. package/examples/no-infinite-scroll-mem.sh +2 -0
  228. package/examples/no-inline-event-handler.sh +2 -0
  229. package/examples/no-inline-handler.sh +2 -0
  230. package/examples/no-inline-style.sh +2 -0
  231. package/examples/no-inline-styles.sh +2 -0
  232. package/examples/no-innerhtml.sh +2 -0
  233. package/examples/no-install-global.sh +2 -0
  234. package/examples/no-jwt-in-url.sh +2 -0
  235. package/examples/no-large-commit.sh +2 -0
  236. package/examples/no-localhost-expose.sh +2 -0
  237. package/examples/no-long-switch.sh +2 -0
  238. package/examples/no-magic-number.sh +2 -0
  239. package/examples/no-md5-sha1.sh +2 -0
  240. package/examples/no-memory-leak-interval.sh +2 -0
  241. package/examples/no-mixed-line-endings.sh +2 -0
  242. package/examples/no-mutation-in-reducer.sh +2 -0
  243. package/examples/no-mutation-observer-leak.sh +2 -0
  244. package/examples/no-nested-subscribe.sh +2 -0
  245. package/examples/no-nested-ternary.sh +2 -0
  246. package/examples/no-network-exfil.sh +2 -0
  247. package/examples/no-new-array-fill.sh +2 -0
  248. package/examples/no-object-freeze-mutation.sh +2 -0
  249. package/examples/no-open-redirect.sh +2 -0
  250. package/examples/no-output-truncation.sh +44 -0
  251. package/examples/no-package-downgrade.sh +2 -0
  252. package/examples/no-package-lock-edit.sh +2 -0
  253. package/examples/no-path-join-user-input.sh +2 -0
  254. package/examples/no-port-bind.sh +2 -0
  255. package/examples/no-process-exit.sh +2 -0
  256. package/examples/no-prototype-pollution.sh +2 -0
  257. package/examples/no-push-without-ci.sh +2 -0
  258. package/examples/no-raw-ref.sh +2 -0
  259. package/examples/no-redundant-fragment.sh +2 -0
  260. package/examples/no-render-in-loop.sh +2 -0
  261. package/examples/no-root-user-docker.sh +2 -0
  262. package/examples/no-root-write.sh +2 -0
  263. package/examples/no-secrets-in-args.sh +2 -0
  264. package/examples/no-secrets-in-logs.sh +2 -0
  265. package/examples/no-sensitive-log.sh +2 -0
  266. package/examples/no-side-effects-in-render.sh +2 -0
  267. package/examples/no-sleep-in-hooks.sh +2 -0
  268. package/examples/no-star-import-python.sh +2 -0
  269. package/examples/no-string-concat-sql.sh +2 -0
  270. package/examples/no-sudo-guard.sh +2 -0
  271. package/examples/no-sync-external-call.sh +2 -0
  272. package/examples/no-sync-fs.sh +2 -0
  273. package/examples/no-table-layout.sh +2 -0
  274. package/examples/no-throw-string.sh +2 -0
  275. package/examples/no-todo-in-merge.sh +2 -0
  276. package/examples/no-todo-in-production.sh +2 -0
  277. package/examples/no-todo-without-issue.sh +2 -0
  278. package/examples/no-triple-slash-ref.sh +2 -0
  279. package/examples/no-unreachable-code.sh +2 -0
  280. package/examples/no-unused-import.sh +2 -0
  281. package/examples/no-unused-state.sh +2 -0
  282. package/examples/no-var-keyword.sh +2 -0
  283. package/examples/no-wildcard-cors.sh +2 -0
  284. package/examples/no-wildcard-import.sh +2 -0
  285. package/examples/no-window-location.sh +2 -0
  286. package/examples/no-with-statement.sh +2 -0
  287. package/examples/no-write-outside-src.sh +2 -0
  288. package/examples/no-xml-external-entity.sh +2 -0
  289. package/examples/notify-waiting.sh +2 -0
  290. package/examples/npm-audit-warn.sh +2 -0
  291. package/examples/npm-publish-guard.sh +2 -0
  292. package/examples/npm-script-injection.sh +2 -0
  293. package/examples/npm-supply-chain-guard.sh +92 -0
  294. package/examples/nuxt-config-guard.sh +2 -0
  295. package/examples/output-secret-mask.sh +2 -0
  296. package/examples/package-json-guard.sh +2 -0
  297. package/examples/parallel-session-guard.sh +2 -0
  298. package/examples/path-traversal-guard.sh +2 -0
  299. package/examples/permission-audit-log.sh +2 -0
  300. package/examples/permission-entry-validator.sh +48 -0
  301. package/examples/php-lint-on-edit.sh +2 -0
  302. package/examples/pip-publish-guard.sh +2 -0
  303. package/examples/plain-language-danger-warn.sh +37 -0
  304. package/examples/plan-mode-enforcer.sh +2 -0
  305. package/examples/plugin-process-cleanup.sh +50 -0
  306. package/examples/polyglot-rm-guard.sh +59 -0
  307. package/examples/pr-description-check.sh +2 -0
  308. package/examples/pre-compact-knowledge-save.sh +53 -0
  309. package/examples/pre-compact-transcript-export.sh +85 -0
  310. package/examples/prefer-builtin-tools.sh +2 -0
  311. package/examples/prefer-const.sh +2 -0
  312. package/examples/prefer-dedicated-tools.sh +55 -0
  313. package/examples/prefer-optional-chaining.sh +2 -0
  314. package/examples/prisma-migrate-guard.sh +2 -0
  315. package/examples/prompt-injection-detector.sh +2 -0
  316. package/examples/prompt-length-guard.sh +2 -0
  317. package/examples/protect-dotfiles.sh +2 -0
  318. package/examples/public-repo-push-guard.sh +58 -0
  319. package/examples/push-requires-test-pass-record.sh +2 -0
  320. package/examples/push-requires-test-pass.sh +2 -0
  321. package/examples/rails-migration-guard.sh +2 -0
  322. package/examples/rate-limit-guard.sh +2 -0
  323. package/examples/read-all-files-enforcer.sh +51 -0
  324. package/examples/readme-exists-check.sh +2 -0
  325. package/examples/redis-flushall-guard.sh +2 -0
  326. package/examples/rm-safety-net.sh +2 -0
  327. package/examples/role-tool-guard.sh +69 -0
  328. package/examples/ruby-lint-on-edit.sh +2 -0
  329. package/examples/schema-migration-guard.sh +57 -0
  330. package/examples/scope-guard.sh +2 -0
  331. package/examples/secret-file-read-guard.sh +74 -0
  332. package/examples/self-modify-bypass-guard.sh +54 -0
  333. package/examples/sensitive-log-guard.sh +2 -0
  334. package/examples/session-checkpoint.sh +2 -0
  335. package/examples/session-end-logger.sh +57 -0
  336. package/examples/session-error-rate-monitor.sh +65 -0
  337. package/examples/session-health-monitor.sh +61 -0
  338. package/examples/session-memory-watchdog.sh +17 -0
  339. package/examples/session-permission-reset-guard.sh +39 -0
  340. package/examples/session-resume-env-fix.sh +49 -0
  341. package/examples/session-state-saver.sh +2 -0
  342. package/examples/session-summary-stop.sh +2 -0
  343. package/examples/session-summary.sh +2 -0
  344. package/examples/session-token-counter.sh +2 -0
  345. package/examples/shell-wrapper-guard.sh +2 -0
  346. package/examples/skill-gate.sh +2 -0
  347. package/examples/skill-injection-detector.sh +41 -0
  348. package/examples/spec-file-scope-guard.sh +69 -0
  349. package/examples/spring-profile-guard.sh +2 -0
  350. package/examples/sql-injection-detect.sh +2 -0
  351. package/examples/subagent-budget-guard.sh +2 -0
  352. package/examples/subagent-claudemd-inject.sh +45 -0
  353. package/examples/subagent-tool-call-limiter.sh +48 -0
  354. package/examples/svelte-lint-on-edit.sh +2 -0
  355. package/examples/swift-build-on-edit.sh +2 -0
  356. package/examples/system-message-workaround.sh +44 -0
  357. package/examples/system-package-guard.sh +2 -0
  358. package/examples/temp-file-cleanup.sh +2 -0
  359. package/examples/terminal-state-restore.sh +23 -0
  360. package/examples/test-after-edit.sh +2 -0
  361. package/examples/test-before-commit.sh +2 -0
  362. package/examples/test-before-push.sh +2 -0
  363. package/examples/test-exit-code-verify.sh +2 -0
  364. package/examples/timeout-guard.sh +2 -0
  365. package/examples/timezone-guard.sh +2 -0
  366. package/examples/tmp-output-size-guard.sh +46 -0
  367. package/examples/todo-check.sh +2 -0
  368. package/examples/todo-deadline-warn.sh +48 -0
  369. package/examples/token-budget-per-task.sh +55 -0
  370. package/examples/token-usage-tracker.sh +14 -0
  371. package/examples/turbo-cache-guard.sh +2 -0
  372. package/examples/uncommitted-changes-stop.sh +2 -0
  373. package/examples/uncommitted-work-shield.sh +37 -0
  374. package/examples/usage-warn.sh +2 -0
  375. package/examples/verify-before-commit.sh +2 -0
  376. package/examples/vue-lint-on-edit.sh +2 -0
  377. package/examples/webfetch-domain-allow.sh +96 -0
  378. package/examples/worktree-memory-guard.sh +47 -0
  379. package/examples/worktree-project-unify.sh +19 -0
  380. package/examples/worktree-unmerged-guard.sh +2 -0
  381. package/examples/write-overwrite-confirm.sh +40 -0
  382. package/examples/write-secret-guard.sh +2 -0
  383. package/examples/write-test-ratio.sh +2 -0
  384. package/package.json +2 -2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  FILE=$(cat | jq -r ".tool_input.file_path // empty" 2>/dev/null); case "$FILE" in *test*|*spec*) exit 0;; esac; echo "$CONTENT" | grep -qE "console\.(log|warn)" && echo "NOTE: console statement in non-test file" >&2
@@ -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,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "console\.(time|timeEnd|timeLog)" && echo "NOTE: console.time left in code" >&2
@@ -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
@@ -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 'curl\s+.*(-X\s+POST|-d\s+@|--data-binary|--upload-file)'; then
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -q "dangerouslySetInnerHTML" && echo "WARNING: XSS risk via dangerouslySetInnerHTML" >&2
@@ -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
@@ -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
  echo "$COMMAND" | grep -qE 'git\s+commit' || exit 0
4
6
  git diff --cached 2>/dev/null | grep -qE '^\+.*(debugger|pdb\.set_trace)' && echo "WARNING: Debug in staged" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  DEPTH=$(echo "$CONTENT" | awk "{n=0; for(i=1;i<=length;i++) if(substr(\$0,i,1)==\"{\") n++; if(n>m) m=n} END{print m}"); [ "$DEPTH" -gt 4 ] && echo "NOTE: Deep nesting ($DEPTH levels)" >&2
@@ -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
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qiE "password.*admin|pass.*1234|secret.*default" && echo "WARNING: Default credentials" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on deprecated Node.js APIs" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on direct DOM in React" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "\.(skip|only)\(|xit\(|xdescribe\(" && echo "WARNING: Disabled/focused test detected" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on direct document.cookie access" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "document\.write\(" && echo "WARNING: document.write XSS risk" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "(function|=>)\s*\{[\s\n]*\}" && echo "NOTE: Empty function body" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "\$\{.*eval|new Function" && echo "WARNING: eval in template" >&2
@@ -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
@@ -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,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "exec\(.*req\.|spawn\(.*req\." && echo "WARNING: exec with user input — command injection" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on exposing database IDs" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "^\s+\w+\.\w+\(" && echo "$CONTENT" | grep -q "await\|\.then\|\.catch" || echo "$CONTENT" | grep -qE "async" && echo "NOTE: Check for unhandled promises" >&2
@@ -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 '\b(npm|pip|yarn)\s+install\s+.*--force'; 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+rebase" && git log --oneline origin/$(git branch --show-current 2>/dev/null) 2>/dev/null | head -1 | grep -q .; then echo "WARNING: Rebasing pushed branch" >&2; fi
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "^(let|var)\s+\w+\s*=" && echo "NOTE: Module-level mutable state — consider encapsulation" >&2
@@ -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
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  if echo "$CONTENT" | grep -qE "http://localhost:[0-9]+|http://127\.0\.0\.1"; then echo "NOTE: Hardcoded localhost URL — use env var instead" >&2; fi
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "express\(\)" && ! echo "$CONTENT" | grep -q "helmet" && echo "NOTE: Express without helmet()" >&2
@@ -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
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "http://[^l]" && ! echo "$CONTENT" | grep -q "localhost" && echo "NOTE: http:// without TLS" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on using index as React key" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on infinite scroll without virtualization" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on onclick= in HTML" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on inline event handlers" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
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,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
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "\.innerHTML\s*=" && echo "WARNING: innerHTML XSS risk" >&2
@@ -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 'npm\s+install\s+-g\s|npm\s+i\s+-g\s'; then
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qiE "token=eyJ|\?jwt=" && echo "WARNING: JWT in URL params" >&2
@@ -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
  [ -z "$COMMAND" ] && 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 "0\.0\.0\.0|INADDR_ANY|--host\s+0"; then echo "WARNING: Binding to all interfaces exposes service to network" >&2; fi
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on switch with 10+ cases" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
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: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qiE "createHash\(.*(md5|sha1)" && echo "WARNING: Weak hash (md5/sha1)" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on setInterval without clearInterval" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  if echo "$CONTENT" | grep -qP "\r\n" && echo "$CONTENT" | grep -qP "[^\r]\n"; then echo "NOTE: Mixed line endings (CRLF + LF)" >&2; fi
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "(state\.\w+\s*=|\.push\(|\.splice\()" && echo "$CONTENT" | grep -q "reducer\|Reducer" && echo "WARNING: Direct state mutation in reducer" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on MutationObserver without disconnect" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on nested event subscriptions" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "\?.*\?.*:" && echo "NOTE: Nested ternary detected — use if/else" >&2
@@ -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 'curl\s+.*(-X\s+POST|--data|--upload-file|-F\s).*[^localhost]'; then
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on Array constructor pitfalls" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on mutating frozen objects" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "redirect\(req\.(query|params|body)" && echo "WARNING: Open redirect risk" >&2
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+ # no-output-truncation.sh — Block piped tail/head that discards command output
3
+ #
4
+ # Solves: Claude pipes long-running command output through tail/head,
5
+ # discarding errors and falsely reporting success (#39945).
6
+ # Example: `npm test 2>&1 | tail -3` hides crash messages.
7
+ #
8
+ # How it works: PreToolUse hook on Bash that detects commands piped
9
+ # through tail/head and warns or blocks. Suggests redirecting to a
10
+ # file instead: `cmd > /tmp/output.log 2>&1 && tail -20 /tmp/output.log`
11
+ #
12
+ # TRIGGER: PreToolUse
13
+ # MATCHER: "Bash"
14
+ #
15
+ # Usage:
16
+ # {
17
+ # "hooks": {
18
+ # "PreToolUse": [{
19
+ # "matcher": "Bash",
20
+ # "hooks": [{ "type": "command", "command": "~/.claude/hooks/no-output-truncation.sh" }]
21
+ # }]
22
+ # }
23
+ # }
24
+
25
+ INPUT=$(cat)
26
+ CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
27
+ [ -z "$CMD" ] && exit 0
28
+
29
+ # Detect destructive output truncation patterns:
30
+ # command | tail -N (discards beginning)
31
+ # command | head -N (discards end)
32
+ # command 2>&1 | tail (discards stderr too)
33
+ if echo "$CMD" | grep -qE '\|\s*(tail|head)\s+-[0-9]'; then
34
+ # Check if it's a build/test/install command being truncated
35
+ DANGEROUS_CMDS="npm test|npm run|yarn test|pnpm test|pytest|cargo test|go test|make|mvn|gradle|node .*\\.js|python .*\\.py|bash .*\\.sh"
36
+ if echo "$CMD" | grep -qE "($DANGEROUS_CMDS).*\|\s*(tail|head)"; then
37
+ echo "BLOCKED: Do not pipe build/test output through tail/head — this discards errors." >&2
38
+ echo "Instead, redirect to a file:" >&2
39
+ echo " cmd > /tmp/output.log 2>&1; echo \"Exit: \$?\"; tail -30 /tmp/output.log" >&2
40
+ exit 2
41
+ fi
42
+ fi
43
+
44
+ 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 "npm\s+install\s+\S+@[0-9]" && echo "$COMMAND" | grep -qE "@[0-1]\."; then echo "WARNING: Possible package downgrade" >&2; fi
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Bash"
2
4
  FILE=$(cat | jq -r '.tool_input.file_path // empty' 2>/dev/null)
3
5
  [ -z "$FILE" ] && exit 0
4
6
  case "$FILE" in */package-lock.json|*/yarn.lock|*/pnpm-lock.yaml|*/Cargo.lock)
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "path\.(join|resolve)\(.*req\." && echo "WARNING: Path traversal risk" >&2
@@ -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 '(--port|--listen|-p\s+\d|0\.0\.0\.0|INADDR_ANY|nc\s+-l)'; then
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "process\.exit\(" && echo "NOTE: process.exit() may cause issues in library code" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "$CONTENT" | grep -qE "__proto__|Object\.assign\(\{\}," && echo "WARNING: Potential prototype pollution" >&2
@@ -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
  [ -z "$COMMAND" ] && exit 0
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on raw DOM refs in React" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on unnecessary React fragments" >&2
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Edit|Write"
2
4
  CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
3
5
  [ -z "$CONTENT" ] && exit 0
4
6
  echo "NOTE: Warn on render calls in loops" >&2
@@ -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
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Bash"
2
4
  FILE=$(cat | jq -r '.tool_input.file_path // empty' 2>/dev/null)
3
5
  [ -z "$FILE" ] && exit 0
4
6
  case "$FILE" in /etc/*|/usr/*|/bin/*|/sbin/*|/boot/*|/sys/*|/proc/*)
@@ -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
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PostToolUse MATCHER: "Bash"
2
4
  OUTPUT=$(cat | jq -r '.tool_result // empty' 2>/dev/null)
3
5
  [ -z "$OUTPUT" ] && exit 0
4
6
  echo "$OUTPUT" | grep -qiE 'password|api.key|secret.key|bearer\s+[a-zA-Z0-9]' && echo "WARNING: Secret in output" >&2
@@ -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 -qiE "console\.\(log\|warn\|error\).*password|log.*token|print.*secret"; then echo "WARNING: Logging sensitive data" >&2; fi