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,54 @@
1
+ #!/bin/bash
2
+ # self-modify-bypass-guard.sh — Auto-allow .claude/ writes in bypass mode
3
+ #
4
+ # Solves: Self-modification guard prompts for .claude/ writes even when
5
+ # bypassPermissions is active (#40463). The guard fires before
6
+ # hooks/permissions are evaluated.
7
+ #
8
+ # How it works: PermissionRequest hook that detects .claude/ write prompts
9
+ # and auto-allows them when the project uses bypassPermissions mode.
10
+ # Exempts security-sensitive paths (settings.json, CLAUDE.md).
11
+ #
12
+ # TRIGGER: PermissionRequest
13
+ # MATCHER: ""
14
+
15
+ set -euo pipefail
16
+
17
+ INPUT=$(cat)
18
+
19
+ # Extract the permission request details
20
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
21
+ FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
22
+
23
+ # Only handle Edit/Write to .claude/ paths
24
+ case "$TOOL" in
25
+ Edit|Write) ;;
26
+ *) exit 0 ;;
27
+ esac
28
+
29
+ case "$FILE" in
30
+ .claude/*|*/.claude/*) ;;
31
+ *) exit 0 ;;
32
+ esac
33
+
34
+ # Security-sensitive files: always prompt (don't auto-allow)
35
+ BASENAME=$(basename "$FILE")
36
+ case "$BASENAME" in
37
+ settings.json|settings.local.json|CLAUDE.md)
38
+ # Let the default prompt handle these
39
+ exit 0 ;;
40
+ esac
41
+
42
+ # Check if bypassPermissions is configured
43
+ SETTINGS=".claude/settings.json"
44
+ if [ -f "$SETTINGS" ]; then
45
+ MODE=$(jq -r '.defaultMode // empty' "$SETTINGS" 2>/dev/null)
46
+ if [ "$MODE" = "bypassPermissions" ]; then
47
+ # Auto-allow: output hookSpecificOutput to approve
48
+ echo '{"hookSpecificOutput":{"hookEventName":"PermissionRequest","allow":true}}'
49
+ exit 0
50
+ fi
51
+ fi
52
+
53
+ # Not in bypass mode — let default prompt handle it
54
+ 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
@@ -19,6 +19,8 @@
19
19
  #
20
20
  # Recovery: Add to CLAUDE.md:
21
21
  # "If ~/.claude/checkpoints/ has a file for this project, read it first."
22
+ #
23
+ # TRIGGER: Stop MATCHER: ""
22
24
 
23
25
  INPUT=$(cat)
24
26
  REASON=$(echo "$INPUT" | jq -r '.stop_reason // empty' 2>/dev/null)
@@ -0,0 +1,51 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # session-duration-guard.sh — Warn on long-running sessions
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Model quality degrades in very long sessions due to context
7
+ # accumulation, compaction artifacts, and attention dilution.
8
+ # This hook warns at configurable thresholds and suggests
9
+ # saving state + starting fresh.
10
+ #
11
+ # Based on 700+ hours of autonomous operation experience.
12
+ #
13
+ # TRIGGER: PostToolUse
14
+ # MATCHER: "" (all tools)
15
+ #
16
+ # CONFIG:
17
+ # CC_SESSION_WARN_HOURS=2 (warn after 2 hours, default)
18
+ # CC_SESSION_CRITICAL_HOURS=4 (critical after 4 hours, default)
19
+ # ================================================================
20
+
21
+ MARKER="/tmp/cc-session-start-$$"
22
+ WARN_HOURS="${CC_SESSION_WARN_HOURS:-2}"
23
+ CRITICAL_HOURS="${CC_SESSION_CRITICAL_HOURS:-4}"
24
+
25
+ # Create marker on first run
26
+ if [ ! -f "$MARKER" ]; then
27
+ date +%s > "$MARKER"
28
+ exit 0
29
+ fi
30
+
31
+ # Check every 50 tool calls (not every call)
32
+ COUNTER="/tmp/cc-duration-counter-$$"
33
+ COUNT=$(cat "$COUNTER" 2>/dev/null || echo 0)
34
+ COUNT=$((COUNT + 1))
35
+ echo "$COUNT" > "$COUNTER"
36
+ [ $((COUNT % 50)) -ne 0 ] && exit 0
37
+
38
+ START=$(cat "$MARKER" 2>/dev/null || echo 0)
39
+ NOW=$(date +%s)
40
+ ELAPSED=$(( (NOW - START) / 3600 ))
41
+ ELAPSED_MIN=$(( (NOW - START) / 60 ))
42
+
43
+ if [ "$ELAPSED" -ge "$CRITICAL_HOURS" ]; then
44
+ echo "⚠ CRITICAL: Session running for ${ELAPSED_MIN} minutes (${ELAPSED}+ hours)." >&2
45
+ echo " Model quality typically degrades after ${CRITICAL_HOURS} hours." >&2
46
+ echo " Save your state and start a new session: /compact then resume later." >&2
47
+ elif [ "$ELAPSED" -ge "$WARN_HOURS" ]; then
48
+ echo "NOTE: Session running for ${ELAPSED_MIN} minutes. Consider saving state." >&2
49
+ fi
50
+
51
+ exit 0
@@ -0,0 +1,57 @@
1
+ #!/bin/bash
2
+ # session-end-logger.sh — Log session activity at exit
3
+ #
4
+ # Solves: No built-in session audit trail. When a session ends,
5
+ # there's no record of what was done unless you manually check
6
+ # git log or conversation history (#40010).
7
+ #
8
+ # How it works: SessionEnd hook that captures recent git commits,
9
+ # modified files, and session metadata into a structured log file.
10
+ #
11
+ # TRIGGER: SessionEnd
12
+ # MATCHER: ""
13
+ #
14
+ # Usage:
15
+ # {
16
+ # "hooks": {
17
+ # "SessionEnd": [{
18
+ # "hooks": [{ "type": "command", "command": "~/.claude/hooks/session-end-logger.sh" }]
19
+ # }]
20
+ # }
21
+ # }
22
+
23
+ INPUT=$(cat)
24
+ SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null)
25
+
26
+ LOG_DIR=".claude/session-logs"
27
+ mkdir -p "$LOG_DIR"
28
+ LOG_FILE="$LOG_DIR/$(date '+%Y-%m-%d').md"
29
+
30
+ {
31
+ echo ""
32
+ echo "## Session $SESSION_ID — $(date '+%H:%M')"
33
+ echo ""
34
+
35
+ # Recent git activity
36
+ if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
37
+ COMMITS=$(git log --oneline --since="1 hour ago" 2>/dev/null)
38
+ if [ -n "$COMMITS" ]; then
39
+ echo "### Commits"
40
+ echo '```'
41
+ echo "$COMMITS"
42
+ echo '```'
43
+ fi
44
+
45
+ CHANGED=$(git diff --name-only HEAD~5..HEAD 2>/dev/null | head -20)
46
+ if [ -n "$CHANGED" ]; then
47
+ echo "### Changed files"
48
+ echo '```'
49
+ echo "$CHANGED"
50
+ echo '```'
51
+ fi
52
+ fi
53
+
54
+ echo ""
55
+ } >> "$LOG_FILE"
56
+
57
+ exit 0
@@ -0,0 +1,65 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # session-error-rate-monitor.sh — Detect session quality degradation
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Long sessions (6+ hours) show quality decay: more errors,
7
+ # ignored instructions, and destructive actions. This hook
8
+ # tracks the error rate over a rolling window and warns when
9
+ # it exceeds a threshold, suggesting a session restart.
10
+ #
11
+ # How it works:
12
+ # - Counts tool calls and errors (exit code != 0) in a state file
13
+ # - Calculates error rate over last N tool calls
14
+ # - Warns (stderr) when error rate exceeds threshold
15
+ # - Does NOT block — purely advisory (exit 0 always)
16
+ #
17
+ # TRIGGER: PostToolUse
18
+ # MATCHER: "Bash"
19
+ #
20
+ # CONFIG:
21
+ # CC_ERROR_RATE_WINDOW=20 (rolling window size)
22
+ # CC_ERROR_RATE_THRESHOLD=40 (% error rate to trigger warning)
23
+ #
24
+ # See: https://github.com/anthropics/claude-code/issues/32963
25
+ # ================================================================
26
+
27
+ INPUT=$(cat)
28
+ EXIT_CODE=$(echo "$INPUT" | jq -r '.tool_result.exit_code // "0"' 2>/dev/null)
29
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
30
+
31
+ # Only track Bash tool calls
32
+ [[ "$TOOL" != "Bash" ]] && exit 0
33
+
34
+ WINDOW=${CC_ERROR_RATE_WINDOW:-20}
35
+ THRESHOLD=${CC_ERROR_RATE_THRESHOLD:-40}
36
+ STATE_DIR="${HOME}/.claude/state"
37
+ mkdir -p "$STATE_DIR"
38
+ STATE_FILE="$STATE_DIR/error-rate-history.log"
39
+
40
+ # Record result: 0=success, 1=error
41
+ if [ "$EXIT_CODE" = "0" ]; then
42
+ echo "0" >> "$STATE_FILE"
43
+ else
44
+ echo "1" >> "$STATE_FILE"
45
+ fi
46
+
47
+ # Keep only last N entries
48
+ TOTAL=$(wc -l < "$STATE_FILE" 2>/dev/null || echo "0")
49
+ if [ "$TOTAL" -gt "$WINDOW" ]; then
50
+ tail -n "$WINDOW" "$STATE_FILE" > "$STATE_FILE.tmp"
51
+ mv "$STATE_FILE.tmp" "$STATE_FILE"
52
+ fi
53
+
54
+ # Calculate error rate
55
+ if [ "$TOTAL" -ge "$WINDOW" ]; then
56
+ ERRORS=$(tail -n "$WINDOW" "$STATE_FILE" | grep -c "^1$" || echo "0")
57
+ RATE=$(( ERRORS * 100 / WINDOW ))
58
+
59
+ if [ "$RATE" -ge "$THRESHOLD" ]; then
60
+ echo "⚠ Session quality alert: ${RATE}% error rate over last ${WINDOW} commands (threshold: ${THRESHOLD}%)" >&2
61
+ echo " Consider: /compact or starting a fresh session" >&2
62
+ fi
63
+ fi
64
+
65
+ exit 0
@@ -0,0 +1,61 @@
1
+ #!/bin/bash
2
+ # session-health-monitor.sh — Monitor session health metrics
3
+ #
4
+ # Solves: Long-running sessions degrade silently — context fills up,
5
+ # tool calls slow down, errors accumulate. No visibility into
6
+ # session health until it's too late.
7
+ #
8
+ # How it works: PreToolUse hook that tracks session metrics:
9
+ # - Tool call count (proxy for context usage)
10
+ # - Error rate (consecutive failures)
11
+ # - Session duration
12
+ # Warns at configurable thresholds.
13
+ #
14
+ # TRIGGER: PreToolUse
15
+ # MATCHER: ""
16
+ #
17
+ # Usage:
18
+ # {
19
+ # "hooks": {
20
+ # "PreToolUse": [{
21
+ # "hooks": [{ "type": "command", "command": "~/.claude/hooks/session-health-monitor.sh" }]
22
+ # }]
23
+ # }
24
+ # }
25
+
26
+ STATE="/tmp/cc-health-$$"
27
+
28
+ # Initialize on first call
29
+ if [ ! -f "$STATE" ]; then
30
+ echo "start=$(date +%s) calls=0 errors=0" > "$STATE"
31
+ fi
32
+
33
+ # Read current state
34
+ eval $(cat "$STATE")
35
+ calls=$((calls + 1))
36
+
37
+ # Update state
38
+ echo "start=$start calls=$calls errors=$errors" > "$STATE"
39
+
40
+ # Check thresholds
41
+ DURATION=$(( ($(date +%s) - start) / 60 ))
42
+
43
+ if [ "$calls" -eq 50 ]; then
44
+ echo "ℹ Session health: 50 tool calls, ${DURATION}m elapsed." >&2
45
+ fi
46
+
47
+ if [ "$calls" -eq 150 ]; then
48
+ echo "⚠ Session health: 150 tool calls, ${DURATION}m elapsed. Context may be getting full." >&2
49
+ echo "Consider saving state and starting a fresh session." >&2
50
+ fi
51
+
52
+ if [ "$calls" -ge 250 ] && [ $((calls % 50)) -eq 0 ]; then
53
+ echo "🔴 Session health: $calls tool calls, ${DURATION}m elapsed. Performance may be degraded." >&2
54
+ fi
55
+
56
+ # Duration warning
57
+ if [ "$DURATION" -ge 120 ] && [ $((calls % 100)) -eq 0 ]; then
58
+ echo "⏰ Session running for ${DURATION}m. Long sessions accumulate context drift." >&2
59
+ fi
60
+
61
+ exit 0
@@ -0,0 +1,17 @@
1
+ MAX_RSS_MB="${CC_MAX_RSS_MB:-4096}"
2
+ CHECK_INTERVAL=300
3
+ (
4
+ while true; do
5
+ sleep "$CHECK_INTERVAL"
6
+ pgrep -f "claude" | while read pid; do
7
+ RSS_KB=$(ps -o rss= -p "$pid" 2>/dev/null | tr -d ' ')
8
+ [ -z "$RSS_KB" ] && continue
9
+ RSS_MB=$((RSS_KB / 1024))
10
+ if [ "$RSS_MB" -gt "$MAX_RSS_MB" ]; then
11
+ echo "[$(date -Iseconds)] PID $pid: ${RSS_MB}MB > ${MAX_RSS_MB}MB limit" >> ~/.claude/memory-watchdog.log
12
+ kill -15 "$pid" 2>/dev/null
13
+ fi
14
+ done
15
+ done
16
+ ) &
17
+ exit 0
@@ -0,0 +1,39 @@
1
+ #!/bin/bash
2
+ # session-permission-reset-guard.sh — Override session-cached permissions
3
+ #
4
+ # Solves: Sandbox mode caching session-level permissions (#40384).
5
+ # After approving a command once, sandbox caches the approval
6
+ # for the entire session, bypassing the allow list.
7
+ #
8
+ # How it works: PreToolUse hook that enforces per-invocation checks
9
+ # for specified commands, regardless of session cache state.
10
+ # Acts as a secondary permission layer outside the caching system.
11
+ #
12
+ # CONFIG:
13
+ # CC_ALWAYS_CHECK_COMMANDS="git commit:git push:npm publish:cargo install"
14
+ #
15
+ # TRIGGER: PreToolUse
16
+ # MATCHER: "Bash"
17
+
18
+ INPUT=$(cat)
19
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
20
+ [ -z "$COMMAND" ] && exit 0
21
+
22
+ # Commands that should always require hook-level check
23
+ ALWAYS_CHECK="${CC_ALWAYS_CHECK_COMMANDS:-git commit:git push:npm publish:cargo install:pip install}"
24
+
25
+ IFS=':' read -ra PATTERNS <<< "$ALWAYS_CHECK"
26
+ for pattern in "${PATTERNS[@]}"; do
27
+ # Match the pattern anywhere in the command (including chained commands)
28
+ if echo "$COMMAND" | grep -qiF "$pattern"; then
29
+ echo "HOOK CHECK: '$pattern' detected — hook-level review." >&2
30
+ echo "Command: $COMMAND" >&2
31
+ echo "" >&2
32
+ echo "This hook enforces per-invocation checks regardless of" >&2
33
+ echo "session permission caching. To allow, remove this pattern" >&2
34
+ echo "from CC_ALWAYS_CHECK_COMMANDS." >&2
35
+ exit 2
36
+ fi
37
+ done
38
+
39
+ exit 0
@@ -0,0 +1,49 @@
1
+ #!/bin/bash
2
+ # session-resume-env-fix.sh — Fix CLAUDE_ENV_FILE path on session resume
3
+ #
4
+ # Solves: CLAUDE_ENV_FILE points to startup session directory, but Bash
5
+ # tool loads from resumed session directory (#40391, #24775).
6
+ # Environment variables written by SessionStart hooks are lost.
7
+ #
8
+ # How it works: SessionStart hook that detects resume (source="resume")
9
+ # and copies/symlinks env files from the startup session directory
10
+ # to the resumed session directory.
11
+ #
12
+ # TRIGGER: SessionStart
13
+ # MATCHER: ""
14
+
15
+ set -euo pipefail
16
+
17
+ INPUT=$(cat)
18
+ SOURCE=$(echo "$INPUT" | jq -r '.source // empty' 2>/dev/null)
19
+ SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty' 2>/dev/null)
20
+
21
+ # Only act on resume events
22
+ [ "$SOURCE" = "resume" ] || exit 0
23
+ [ -n "$SESSION_ID" ] || exit 0
24
+ [ -n "${CLAUDE_ENV_FILE:-}" ] || exit 0
25
+
26
+ # Extract the startup session directory from CLAUDE_ENV_FILE
27
+ STARTUP_DIR=$(dirname "$CLAUDE_ENV_FILE")
28
+ ENV_BASE=$(dirname "$STARTUP_DIR")
29
+
30
+ # Construct the resumed session directory
31
+ RESUME_DIR="${ENV_BASE}/${SESSION_ID}"
32
+
33
+ # If they're the same, no fix needed
34
+ [ "$STARTUP_DIR" != "$RESUME_DIR" ] || exit 0
35
+
36
+ # Create resumed session directory if missing
37
+ mkdir -p "$RESUME_DIR"
38
+
39
+ # Copy all env files from startup dir to resumed dir
40
+ for envfile in "$STARTUP_DIR"/*.sh; do
41
+ [ -f "$envfile" ] || continue
42
+ BASENAME=$(basename "$envfile")
43
+ if [ ! -f "$RESUME_DIR/$BASENAME" ]; then
44
+ cp "$envfile" "$RESUME_DIR/$BASENAME"
45
+ echo "Copied env file to resumed session: $BASENAME" >&2
46
+ fi
47
+ done
48
+
49
+ exit 0
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Bash"
2
4
  INPUT=$(cat)
3
5
  TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
4
6
  STATE_DIR="${HOME}/.claude"
@@ -17,6 +17,8 @@
17
17
  # }]
18
18
  # }
19
19
  # }
20
+ #
21
+ # TRIGGER: PreToolUse MATCHER: "Bash"
20
22
 
21
23
  INPUT=$(cat)
22
24
 
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ #
3
+ # TRIGGER: PreToolUse MATCHER: "Bash"
2
4
  echo "" >&2
3
5
  echo "=== Session Summary ===" >&2
4
6
  BRANCH=$(git branch --show-current 2>/dev/null)
@@ -24,6 +24,8 @@
24
24
  # CC_TOOL_WARN_100 — threshold 1 (default: 100)
25
25
  # CC_TOOL_WARN_200 — threshold 2 (default: 200)
26
26
  # CC_TOOL_WARN_500 — threshold 3 (default: 500)
27
+ #
28
+ # TRIGGER: PreToolUse MATCHER: "Bash"
27
29
 
28
30
  INPUT=$(cat)
29
31
  TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
@@ -0,0 +1,53 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # settings-auto-backup.sh — Auto-backup settings on session start
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # Claude Code auto-updates have been observed silently wiping
7
+ # settings.json, settings.local.json, and plugin state. (#40714)
8
+ # This hook creates rolling backups on every session start and
9
+ # warns if settings appear to have been reset.
10
+ #
11
+ # TRIGGER: Notification
12
+ # MATCHER: "SessionStart"
13
+ #
14
+ # BACKUPS: ~/.claude/settings-backups/
15
+ # ================================================================
16
+
17
+ BACKUP_DIR="$HOME/.claude/settings-backups"
18
+ mkdir -p "$BACKUP_DIR"
19
+
20
+ TIMESTAMP=$(date +%Y%m%d-%H%M%S)
21
+ BACKED_UP=0
22
+
23
+ # Backup settings files
24
+ for f in settings.json settings.local.json; do
25
+ SRC="$HOME/.claude/$f"
26
+ if [ -f "$SRC" ] && [ -s "$SRC" ]; then
27
+ cp "$SRC" "$BACKUP_DIR/${f%.json}-${TIMESTAMP}.json"
28
+ BACKED_UP=$((BACKED_UP + 1))
29
+ fi
30
+ done
31
+
32
+ # Keep only last 10 backups per file type
33
+ for prefix in settings settings.local; do
34
+ ls -t "$BACKUP_DIR/${prefix}-"*.json 2>/dev/null | tail -n +11 | xargs rm -f 2>/dev/null
35
+ done
36
+
37
+ # Detect suspicious settings reset
38
+ SETTINGS="$HOME/.claude/settings.json"
39
+ if [ -f "$SETTINGS" ]; then
40
+ KEY_COUNT=$(jq 'keys | length' "$SETTINGS" 2>/dev/null || echo 0)
41
+ if [ "$KEY_COUNT" -le 1 ]; then
42
+ LATEST_BACKUP=$(ls -t "$BACKUP_DIR/settings-"*.json 2>/dev/null | head -2 | tail -1)
43
+ if [ -n "$LATEST_BACKUP" ]; then
44
+ BACKUP_KEYS=$(jq 'keys | length' "$LATEST_BACKUP" 2>/dev/null || echo 0)
45
+ if [ "$BACKUP_KEYS" -gt "$KEY_COUNT" ]; then
46
+ echo "⚠ Settings may have been reset ($KEY_COUNT keys vs $BACKUP_KEYS in backup)" >&2
47
+ echo " Restore: cp '$LATEST_BACKUP' '$SETTINGS'" >&2
48
+ fi
49
+ fi
50
+ fi
51
+ fi
52
+
53
+ exit 0
@@ -0,0 +1,45 @@
1
+ #!/bin/bash
2
+ # settings-mutation-detector.sh — Detect unauthorized changes to Claude settings files
3
+ #
4
+ # Solves: Claude Code can modify its own settings files during
5
+ # a session, potentially disabling safety hooks or
6
+ # changing permissions without user awareness.
7
+ #
8
+ # How it works: On first run, takes a hash of key settings files.
9
+ # On subsequent runs, compares the current hash. If changed,
10
+ # warns the user. This catches silent permission escalation
11
+ # or hook removal.
12
+ #
13
+ # TRIGGER: PostToolUse
14
+ # MATCHER: ""
15
+
16
+ set -euo pipefail
17
+
18
+ HASH_FILE="/tmp/claude-settings-hash-$$"
19
+
20
+ # Files to monitor
21
+ SETTINGS_FILES=""
22
+ for f in \
23
+ ".claude/settings.json" \
24
+ ".claude/settings.local.json" \
25
+ "${HOME}/.claude/settings.json" \
26
+ "${HOME}/.claude/settings.local.json"; do
27
+ [ -f "$f" ] && SETTINGS_FILES="$SETTINGS_FILES $f"
28
+ done
29
+
30
+ [ -z "$SETTINGS_FILES" ] && exit 0
31
+
32
+ # Calculate current hash
33
+ CURRENT_HASH=$(cat $SETTINGS_FILES 2>/dev/null | md5sum | cut -d' ' -f1)
34
+
35
+ if [ -f "$HASH_FILE" ]; then
36
+ PREV_HASH=$(cat "$HASH_FILE")
37
+ if [ "$CURRENT_HASH" != "$PREV_HASH" ]; then
38
+ echo "WARNING: Claude settings files were modified during this session!" >&2
39
+ echo " Files monitored: $SETTINGS_FILES" >&2
40
+ echo " Review changes to ensure hooks and permissions are intact." >&2
41
+ fi
42
+ fi
43
+
44
+ echo "$CURRENT_HASH" > "$HASH_FILE"
45
+ exit 0
@@ -13,6 +13,8 @@
13
13
  # This hook unwraps interpreter one-liners and checks the inner command.
14
14
  #
15
15
  # Usage: PreToolUse hook on "Bash"
16
+ #
17
+ # TRIGGER: PreToolUse MATCHER: "Bash"
16
18
 
17
19
  INPUT=$(cat)
18
20
  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
  INPUT=$(cat)
3
5
  TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
4
6
  [[ "$TOOL" != "Skill" ]] && exit 0
@@ -0,0 +1,41 @@
1
+ #!/bin/bash
2
+ # skill-injection-detector.sh — Detect silently injected skills/plugins
3
+ #
4
+ # Solves: Skills and plugins from claude.ai silently injected into Claude Code
5
+ # sessions (#39686). External tool definitions bloat context and
6
+ # can override local behavior without user awareness.
7
+ #
8
+ # How it works: Notification hook that monitors for unexpected skill/plugin
9
+ # loading messages. Warns when tools are loaded from external sources.
10
+ # Also checks MCP config for unexpected servers.
11
+ #
12
+ # TRIGGER: PreToolUse
13
+ # MATCHER: ""
14
+
15
+ set -euo pipefail
16
+
17
+ INPUT=$(cat)
18
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
19
+
20
+ # Check MCP tool calls for unexpected servers
21
+ if [ "$TOOL" = "Bash" ]; then
22
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
23
+ # Detect MCP server addition
24
+ if echo "$COMMAND" | grep -qE 'claude\s+mcp\s+add'; then
25
+ echo "WARNING: MCP server addition detected." >&2
26
+ echo "Command: $COMMAND" >&2
27
+ echo "Verify this server is expected before proceeding." >&2
28
+ fi
29
+ fi
30
+
31
+ # Check for skill/plugin invocation from unexpected sources
32
+ if echo "$INPUT" | jq -e '.tool_input.skill // empty' 2>/dev/null | grep -qv '^$'; then
33
+ SKILL=$(echo "$INPUT" | jq -r '.tool_input.skill' 2>/dev/null)
34
+ # Check if skill is local
35
+ if [ ! -f ".claude/skills/${SKILL}/SKILL.md" ] && [ ! -f ".claude/skills/${SKILL}.md" ]; then
36
+ echo "WARNING: Skill '$SKILL' invoked but not found locally." >&2
37
+ echo "This may be an externally injected skill." >&2
38
+ fi
39
+ fi
40
+
41
+ exit 0