@claudeye/linux-arm64 1.0.7 → 1.0.8

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 (268) hide show
  1. package/assets/dist/hooks-api.d.ts +43 -0
  2. package/assets/dist/hooks-api.js +1 -0
  3. package/assets/dist/index.d.ts +2 -0
  4. package/assets/dist/index.js +1 -1
  5. package/assets/dist/loader.js +2 -2
  6. package/assets/standalone/.next/BUILD_ID +1 -1
  7. package/assets/standalone/.next/app-path-routes-manifest.json +2 -1
  8. package/assets/standalone/.next/build-manifest.json +8 -8
  9. package/assets/standalone/.next/prerender-manifest.json +27 -3
  10. package/assets/standalone/.next/routes-manifest.json +12 -6
  11. package/assets/standalone/.next/server/app/_global-error/page/build-manifest.json +5 -5
  12. package/assets/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +14 -1
  13. package/assets/standalone/.next/server/app/_global-error/page.js +5 -5
  14. package/assets/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  15. package/assets/standalone/.next/server/app/_global-error.html +1 -1
  16. package/assets/standalone/.next/server/app/_global-error.rsc +7 -7
  17. package/assets/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  18. package/assets/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  19. package/assets/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  20. package/assets/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  21. package/assets/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  22. package/assets/standalone/.next/server/app/_not-found/page/build-manifest.json +5 -5
  23. package/assets/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +2 -2
  24. package/assets/standalone/.next/server/app/_not-found/page.js +6 -7
  25. package/assets/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  26. package/assets/standalone/.next/server/app/_not-found.html +2 -2
  27. package/assets/standalone/.next/server/app/_not-found.rsc +27 -30
  28. package/assets/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +27 -30
  29. package/assets/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  30. package/assets/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +12 -15
  31. package/assets/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  32. package/assets/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  33. package/assets/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  34. package/assets/standalone/.next/server/app/api/completed-history/route.js +2 -2
  35. package/assets/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
  36. package/assets/standalone/.next/server/app/api/queue-item/route.js +2 -2
  37. package/assets/standalone/.next/server/app/api/queue-status/route.js +2 -2
  38. package/assets/standalone/.next/server/app/dashboard/[viewName]/page/build-manifest.json +5 -5
  39. package/assets/standalone/.next/server/app/dashboard/[viewName]/page/server-reference-manifest.json +5 -5
  40. package/assets/standalone/.next/server/app/dashboard/[viewName]/page.js +8 -9
  41. package/assets/standalone/.next/server/app/dashboard/[viewName]/page_client-reference-manifest.js +1 -1
  42. package/assets/standalone/.next/server/app/dashboard/page/build-manifest.json +5 -5
  43. package/assets/standalone/.next/server/app/dashboard/page/server-reference-manifest.json +5 -5
  44. package/assets/standalone/.next/server/app/dashboard/page.js +9 -10
  45. package/assets/standalone/.next/server/app/dashboard/page_client-reference-manifest.js +1 -1
  46. package/assets/standalone/.next/server/app/index.html +1 -0
  47. package/assets/standalone/.next/server/app/index.meta +15 -0
  48. package/assets/standalone/.next/server/app/index.rsc +22 -0
  49. package/assets/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +6 -0
  50. package/assets/standalone/.next/server/app/index.segments/_full.segment.rsc +22 -0
  51. package/assets/standalone/.next/server/app/index.segments/_head.segment.rsc +6 -0
  52. package/assets/standalone/.next/server/app/index.segments/_index.segment.rsc +12 -0
  53. package/assets/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -0
  54. package/assets/standalone/.next/server/app/login/page/build-manifest.json +5 -5
  55. package/assets/standalone/.next/server/app/login/page/server-reference-manifest.json +3 -3
  56. package/assets/standalone/.next/server/app/login/page.js +6 -7
  57. package/assets/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  58. package/assets/standalone/.next/server/app/login.html +2 -2
  59. package/assets/standalone/.next/server/app/login.rsc +30 -34
  60. package/assets/standalone/.next/server/app/login.segments/_full.segment.rsc +30 -34
  61. package/assets/standalone/.next/server/app/login.segments/_head.segment.rsc +4 -4
  62. package/assets/standalone/.next/server/app/login.segments/_index.segment.rsc +12 -15
  63. package/assets/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  64. package/assets/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  65. package/assets/standalone/.next/server/app/login.segments/login.segment.rsc +3 -3
  66. package/assets/standalone/.next/server/app/page/build-manifest.json +5 -5
  67. package/assets/standalone/.next/server/app/page/server-reference-manifest.json +2 -2
  68. package/assets/standalone/.next/server/app/page.js +7 -8
  69. package/assets/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  70. package/assets/standalone/.next/server/app/policies/page/app-paths-manifest.json +3 -0
  71. package/assets/standalone/.next/server/app/{hooks → policies}/page/build-manifest.json +5 -5
  72. package/assets/standalone/.next/server/app/{hooks → policies}/page/server-reference-manifest.json +36 -24
  73. package/assets/standalone/.next/server/app/{hooks → policies}/page.js +9 -10
  74. package/assets/standalone/.next/server/app/policies/page_client-reference-manifest.js +3 -0
  75. package/assets/standalone/.next/server/app/project/[name]/page/build-manifest.json +5 -5
  76. package/assets/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +2 -2
  77. package/assets/standalone/.next/server/app/project/[name]/page.js +7 -9
  78. package/assets/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  79. package/assets/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +5 -5
  80. package/assets/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  81. package/assets/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +10 -10
  82. package/assets/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +8 -9
  83. package/assets/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  84. package/assets/standalone/.next/server/app/projects/page/app-paths-manifest.json +3 -0
  85. package/assets/standalone/.next/server/app/projects/page/build-manifest.json +18 -0
  86. package/assets/standalone/.next/server/app/projects/page/next-font-manifest.json +6 -0
  87. package/assets/standalone/.next/server/app/projects/page/react-loadable-manifest.json +1 -0
  88. package/assets/standalone/.next/server/app/projects/page/server-reference-manifest.json +29 -0
  89. package/assets/standalone/.next/server/app/projects/page.js +18 -0
  90. package/assets/standalone/.next/server/app/projects/page_client-reference-manifest.js +3 -0
  91. package/assets/standalone/.next/server/app/queue/page/build-manifest.json +5 -5
  92. package/assets/standalone/.next/server/app/queue/page/server-reference-manifest.json +4 -4
  93. package/assets/standalone/.next/server/app/queue/page.js +8 -9
  94. package/assets/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
  95. package/assets/standalone/.next/server/app-paths-manifest.json +2 -1
  96. package/assets/standalone/.next/server/chunks/[root-of-the-server]__0-_qfa9._.js +1 -1
  97. package/assets/standalone/.next/server/chunks/[root-of-the-server]__0.lwwrp._.js +3 -0
  98. package/assets/standalone/.next/server/chunks/[root-of-the-server]__072w.g0._.js +1 -1
  99. package/assets/standalone/.next/server/chunks/[root-of-the-server]__08lgurx._.js +1 -1
  100. package/assets/standalone/.next/server/chunks/[root-of-the-server]__0bps8pa._.js +1 -1
  101. package/assets/standalone/.next/server/chunks/[root-of-the-server]__0f_5ws6._.js +1 -1
  102. package/assets/standalone/.next/server/chunks/[root-of-the-server]__0g72weg._.js +1 -1
  103. package/assets/standalone/.next/server/chunks/[root-of-the-server]__0ld-~9t._.js +1 -1
  104. package/assets/standalone/.next/server/chunks/[root-of-the-server]__0ndqa7s._.js +8 -3
  105. package/assets/standalone/.next/server/chunks/{[root-of-the-server]__0wkrejt._.js → [root-of-the-server]__0rtkhr~._.js} +1 -1
  106. package/assets/standalone/.next/server/chunks/{[root-of-the-server]__031vvrp._.js → [root-of-the-server]__0tlbu6c._.js} +1 -1
  107. package/assets/standalone/.next/server/chunks/[root-of-the-server]__0vfmej5._.js +4 -0
  108. package/assets/standalone/.next/server/chunks/_04cgd3m._.js +11 -0
  109. package/assets/standalone/.next/server/chunks/_0aylu-q._.js +2 -2
  110. package/assets/standalone/.next/server/chunks/_0h9z2~x._.js +11 -0
  111. package/assets/standalone/.next/server/chunks/_0lq2_wn._.js +2 -2
  112. package/assets/standalone/.next/server/chunks/_0oqawqx._.js +2 -2
  113. package/assets/standalone/.next/server/chunks/_0vt409y._.js +2 -2
  114. package/assets/standalone/.next/server/chunks/lib_0a9kq7-._.js +11 -0
  115. package/assets/standalone/.next/server/chunks/lib_0b2.9p5._.js +11 -0
  116. package/assets/standalone/.next/server/chunks/lib_13x.g8a._.js +11 -0
  117. package/assets/standalone/.next/server/chunks/lib_eval-queue_ts_08t8vgq._.js +1 -1
  118. package/assets/standalone/.next/server/chunks/lib_eval-queue_ts_0h8e7f.._.js +1 -1
  119. package/assets/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0l15kkr.js +1 -1
  120. package/assets/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
  121. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-_oq51._.js +4 -0
  122. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-om19y._.js +11 -0
  123. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-wbic0._.js +45 -0
  124. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__02l2rag._.js +3 -0
  125. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__04qo1w2._.js +4 -0
  126. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__07ifmkx._.js +3 -0
  127. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__09y6src._.js +4 -0
  128. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__09y7ni.._.js +3 -0
  129. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bubgf_._.js +4 -0
  130. package/assets/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0l897tw._.js → [root-of-the-server]__0iv48_z._.js} +2 -2
  131. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0j7bj94._.js +3 -0
  132. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0m0x9dt._.js +4 -0
  133. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oy2.6r._.js +3 -0
  134. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pw0g9c._.js +4 -0
  135. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rm4qtt._.js +4 -0
  136. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0sn21jm._.js +3 -0
  137. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0spfsp5._.js +4 -0
  138. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0sq7snp._.js +3 -0
  139. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0uz88bg._.js +3 -0
  140. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0x7-awk._.js +4 -0
  141. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0zva2n_._.js +4 -0
  142. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__1370kzv._.js +4 -0
  143. package/assets/standalone/.next/server/chunks/ssr/_02_tcps._.js +32 -0
  144. package/assets/standalone/.next/server/chunks/ssr/_04.u7zx._.js +3 -0
  145. package/assets/standalone/.next/server/chunks/ssr/_06383ya._.js +3 -0
  146. package/assets/standalone/.next/server/chunks/ssr/_0kfjwwu._.js +1 -1
  147. package/assets/standalone/.next/server/chunks/ssr/_0km.fsf._.js +3 -0
  148. package/assets/standalone/.next/server/chunks/ssr/_0x26hbi._.js +3 -0
  149. package/assets/standalone/.next/server/chunks/ssr/{_0_ia8tm._.js → _0xg44oj._.js} +2 -2
  150. package/assets/standalone/.next/server/chunks/ssr/_11ou~_x._.js +3 -0
  151. package/assets/standalone/.next/server/chunks/ssr/app_04qfs8z._.js +1 -1
  152. package/assets/standalone/.next/server/chunks/ssr/app_05evmdg._.js +1 -1
  153. package/assets/standalone/.next/server/chunks/ssr/app_07izk21._.js +1 -1
  154. package/assets/standalone/.next/server/chunks/ssr/app_0uosk1e._.js +1 -1
  155. package/assets/standalone/.next/server/chunks/ssr/app_13f0ohr._.js +1 -1
  156. package/assets/standalone/.next/server/chunks/ssr/app_actions_compute-dashboard_ts_13cb_9d._.js +1 -1
  157. package/assets/standalone/.next/server/chunks/ssr/app_global-error_tsx_0m9qisk._.js +3 -0
  158. package/assets/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +3 -0
  159. package/assets/standalone/.next/server/chunks/ssr/app_login_page_tsx_0z71ad3._.js +1 -1
  160. package/assets/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +8 -0
  161. package/assets/standalone/.next/server/chunks/ssr/{app_loading_tsx_05semg5._.js → app_projects_loading_tsx_13veom4._.js} +2 -2
  162. package/assets/standalone/.next/server/chunks/ssr/app_queue_queue-client_tsx_0c0olxv._.js +1 -1
  163. package/assets/standalone/.next/server/chunks/ssr/node_modules_next_dist_0~3yv~8._.js +3 -0
  164. package/assets/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0s-cxl7.js → node_modules_next_dist_esm_build_templates_app-page_06pwt.d.js} +3 -3
  165. package/assets/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0j.ij4e.js → node_modules_next_dist_esm_build_templates_app-page_091vo_-.js} +3 -3
  166. package/assets/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0a_7sdg.js +4 -0
  167. package/assets/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0blr8v-.js → node_modules_next_dist_esm_build_templates_app-page_0ef3uwk.js} +3 -3
  168. package/assets/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0_4obh1.js → node_modules_next_dist_esm_build_templates_app-page_0ft_6~o.js} +3 -3
  169. package/assets/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0rc3ul_.js → node_modules_next_dist_esm_build_templates_app-page_0j79~gv.js} +3 -3
  170. package/assets/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0za6ylf.js → node_modules_next_dist_esm_build_templates_app-page_0pbja1x.js} +3 -3
  171. package/assets/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0r6o0i2.js +4 -0
  172. package/assets/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_13mo15i.js → node_modules_next_dist_esm_build_templates_app-page_0w9nerp.js} +3 -3
  173. package/assets/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0xv8hin.js → node_modules_next_dist_esm_build_templates_app-page_11y81~_.js} +3 -3
  174. package/assets/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0cmo95h.js → node_modules_next_dist_esm_build_templates_app-page_12or2kf.js} +3 -3
  175. package/assets/standalone/.next/server/middleware-build-manifest.js +8 -8
  176. package/assets/standalone/.next/server/pages/404.html +2 -2
  177. package/assets/standalone/.next/server/pages/500.html +1 -1
  178. package/assets/standalone/.next/server/server-reference-manifest.js +1 -1
  179. package/assets/standalone/.next/server/server-reference-manifest.json +82 -52
  180. package/assets/standalone/.next/static/chunks/0.~t6_2r7n04x.js +4 -0
  181. package/assets/standalone/.next/static/chunks/01q52wg_amm60.js +2 -0
  182. package/assets/standalone/.next/static/chunks/07tkt19hty~w~.js +1 -0
  183. package/assets/standalone/.next/static/chunks/08eqdulekk8l-.js +1 -0
  184. package/assets/standalone/.next/static/chunks/0_s0luks5tay-.js +1 -0
  185. package/assets/standalone/.next/static/chunks/0c0j9cso1kkr_.css +1 -0
  186. package/assets/standalone/.next/static/chunks/0dji_r0j6sq~f.js +1 -0
  187. package/assets/standalone/.next/static/chunks/0h2.~bz5i.4.g.js +1 -0
  188. package/assets/standalone/.next/static/chunks/0l8ej7oju~.oy.js +1 -0
  189. package/assets/standalone/.next/static/chunks/{053grpfc7gghs.js → 0nc3no0r1i66_.js} +1 -1
  190. package/assets/standalone/.next/static/chunks/0tp7ck~nhe8-g.js +3 -0
  191. package/assets/standalone/.next/static/chunks/0tyw4u3~2isbh.js +1 -0
  192. package/assets/standalone/.next/static/chunks/{0h4bq73pogmtb.js → 0u95dh6lcl7tm.js} +31 -1
  193. package/assets/standalone/.next/static/chunks/0y8d5uz5f1m~..js +6 -0
  194. package/assets/standalone/.next/static/chunks/10qr1cqizt~sp.js +1 -0
  195. package/assets/standalone/.next/static/chunks/{0lkh25hviflid.js → 11nnvwnj7e__0.js} +1 -1
  196. package/assets/standalone/.next/static/chunks/14trwlfhtz63l.js +1 -0
  197. package/assets/standalone/.next/static/chunks/{04aem330ymbdp.js → 150i0n26fnvso.js} +1 -1
  198. package/assets/standalone/.next/static/chunks/15fklyav5py5m.js +1 -0
  199. package/assets/standalone/.next/static/chunks/162jxog7oodad.js +1 -0
  200. package/assets/standalone/.next/static/chunks/17.b3suj8zjjj.js +1 -0
  201. package/assets/standalone/.next/static/chunks/{turbopack-05k-ytyhplqy7.js → turbopack-0.w3uhj.ln7pt.js} +1 -1
  202. package/assets/standalone/README.md +119 -5
  203. package/assets/standalone/design-docs/custom-hooks.md +722 -0
  204. package/assets/standalone/design-docs/e2e-hook-testing.md +420 -0
  205. package/assets/standalone/package.json +4 -2
  206. package/assets/standalone/vitest.config.e2e.mts +21 -0
  207. package/bin/claudeye +0 -0
  208. package/package.json +1 -1
  209. package/assets/standalone/.next/server/app/hooks/page/app-paths-manifest.json +0 -3
  210. package/assets/standalone/.next/server/app/hooks/page_client-reference-manifest.js +0 -3
  211. package/assets/standalone/.next/server/chunks/[root-of-the-server]__0_03u6.._.js +0 -4
  212. package/assets/standalone/.next/server/chunks/[root-of-the-server]__0ynza7q._.js +0 -3
  213. package/assets/standalone/.next/server/chunks/_0fx1kj9._.js +0 -7
  214. package/assets/standalone/.next/server/chunks/_12qi01p._.js +0 -7
  215. package/assets/standalone/.next/server/chunks/lib_0it0qxy._.js +0 -7
  216. package/assets/standalone/.next/server/chunks/lib_0k3u5ri._.js +0 -7
  217. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-j~_e.._.js +0 -3
  218. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__00fve8g._.js +0 -36
  219. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__028-6zz._.js +0 -3
  220. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__02x4-91._.js +0 -4
  221. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__06tqxbp._.js +0 -4
  222. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__08a4wva._.js +0 -3
  223. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0a-4fjm._.js +0 -33
  224. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cnf9rp._.js +0 -3
  225. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0dsucx_._.js +0 -4
  226. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e9ohz2._.js +0 -4
  227. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0fltiz1._.js +0 -4
  228. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ksoh6e._.js +0 -3
  229. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ni-as.._.js +0 -4
  230. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0tsew7c._.js +0 -4
  231. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0x5abxa._.js +0 -3
  232. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0yi-883._.js +0 -4
  233. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__0zn.1q2._.js +0 -3
  234. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__10_wjge._.js +0 -4
  235. package/assets/standalone/.next/server/chunks/ssr/[root-of-the-server]__11xi38p._.js +0 -7
  236. package/assets/standalone/.next/server/chunks/ssr/_03l0_j6._.js +0 -3
  237. package/assets/standalone/.next/server/chunks/ssr/_050qnuh._.js +0 -3
  238. package/assets/standalone/.next/server/chunks/ssr/_0_~1-jh._.js +0 -3
  239. package/assets/standalone/.next/server/chunks/ssr/_0ndt7tj._.js +0 -3
  240. package/assets/standalone/.next/server/chunks/ssr/_0uig1kl._.js +0 -3
  241. package/assets/standalone/.next/server/chunks/ssr/_0vc9nu-._.js +0 -32
  242. package/assets/standalone/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0k77kol.js +0 -3
  243. package/assets/standalone/.next/server/chunks/ssr/app_hooks_hooks-client_tsx_0n~.yoz._.js +0 -3
  244. package/assets/standalone/.next/server/chunks/ssr/node_modules_0gyjybr._.js +0 -3
  245. package/assets/standalone/.next/server/chunks/ssr/node_modules_next_dist_client_components_06j6hww._.js +0 -33
  246. package/assets/standalone/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js +0 -3
  247. package/assets/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0~flnue.js +0 -4
  248. package/assets/standalone/.next/static/chunks/0-06jeyuuf3mf.js +0 -1
  249. package/assets/standalone/.next/static/chunks/0.z9o1xk80npg.js +0 -2
  250. package/assets/standalone/.next/static/chunks/01xlw8hd842-c.js +0 -1
  251. package/assets/standalone/.next/static/chunks/09f624.buk6jr.js +0 -1
  252. package/assets/standalone/.next/static/chunks/0g5cvlv5.8drd.js +0 -3
  253. package/assets/standalone/.next/static/chunks/0g~w.4hiyi_1j.js +0 -1
  254. package/assets/standalone/.next/static/chunks/0il8_19l.4u-p.js +0 -1
  255. package/assets/standalone/.next/static/chunks/0j1-mgai_b50s.css +0 -1
  256. package/assets/standalone/.next/static/chunks/0ljjv.c03-d.y.js +0 -1
  257. package/assets/standalone/.next/static/chunks/0n6vo_gsuay4v.js +0 -4
  258. package/assets/standalone/.next/static/chunks/0nntcr2py4m14.js +0 -1
  259. package/assets/standalone/.next/static/chunks/0sp_gwqc7ka~z.js +0 -1
  260. package/assets/standalone/.next/static/chunks/0z0dljl8fz7.-.js +0 -1
  261. package/assets/standalone/.next/static/chunks/0z9fpf50h7mcq.js +0 -1
  262. package/assets/standalone/.next/static/chunks/115dplafwys-z.js +0 -31
  263. package/assets/standalone/.next/static/chunks/119bhqt_bddam.js +0 -1
  264. /package/assets/standalone/.next/server/app/{hooks → policies}/page/next-font-manifest.json +0 -0
  265. /package/assets/standalone/.next/server/app/{hooks → policies}/page/react-loadable-manifest.json +0 -0
  266. /package/assets/standalone/.next/static/{l1G516WtxNj1aLrIr5STH → 5FBEWHgw7h8OR_JoJzccY}/_buildManifest.js +0 -0
  267. /package/assets/standalone/.next/static/{l1G516WtxNj1aLrIr5STH → 5FBEWHgw7h8OR_JoJzccY}/_clientMiddlewareManifest.js +0 -0
  268. /package/assets/standalone/.next/static/{l1G516WtxNj1aLrIr5STH → 5FBEWHgw7h8OR_JoJzccY}/_ssgManifest.js +0 -0
@@ -0,0 +1,722 @@
1
+ STATUS: COMPLETED
2
+
3
+ # Custom Hooks Design
4
+
5
+ ## Instructions for the Implementing Agent
6
+
7
+ 1. **Branch** — create a fresh branch from the latest `main` before making any changes:
8
+ ```bash
9
+ git checkout main && git pull && git checkout -b feat/custom-hooks
10
+ ```
11
+
12
+ 2. **Verify each step** — after implementing each logical unit (policy params mechanism,
13
+ schema on `BuiltinPolicyDefinition`, per-policy wiring, custom hooks registry,
14
+ loader integration, CLI flag), verify it compiles and existing tests still pass before
15
+ moving to the next step. Do not batch all changes and verify at the end.
16
+
17
+ 3. **Keep the checklist current** — after completing each checklist item at the bottom of
18
+ this document, immediately mark it `[x]`. Do not defer checklist updates to the end.
19
+ The checklist is the source of truth for progress — if it is not marked, it is not done.
20
+
21
+ 4. **Unit tests** — every new piece of logic must have unit tests:
22
+ - Param merging (project → local → global precedence, scalar override, array union for `enabledPolicies`)
23
+ - Each parameterized builtin policy (default behavior unchanged, custom param applied correctly)
24
+ - `customHooks` registry (`.add()`, `getCustomHooks()`, `globalThis` isolation)
25
+ - Hook handler loading `customHooksPath` from config and registering custom hooks
26
+ - `--list-hooks` output with params and custom hooks section
27
+
28
+ 5. **Documentation** — update `README.md` with:
29
+ - `policyParams` config reference for each parameterized policy
30
+ - `--custom-hooks <path>` CLI flag
31
+ - `customHooks.add()` authoring guide with a complete example
32
+
33
+ 6. **Changelog** — add an entry to `CHANGELOG.md` under a new `## [1.0.8-beta.0]` heading
34
+ describing both features (policy params + custom JS hooks).
35
+
36
+ 7. **Version** — bump `package.json` version to `1.0.8-beta.0`. Also update the version in
37
+ any platform-specific `packages/*/package.json` files if they carry their own version field.
38
+
39
+ ---
40
+
41
+ ## Problem / Motivation
42
+
43
+ Claudeye's builtin policies cover the common security baseline, but they're all-or-nothing
44
+ today:
45
+
46
+ - `block-sudo` blocks *all* sudo — you can't say "allow `sudo systemctl status`"
47
+ - `sanitize-api-keys` covers OpenAI/GitHub/AWS — you can't add your company's key format
48
+ - `block-read-outside-cwd` has no path allowlist
49
+ - `block-push-master` assumes `main`/`master` — you can't configure other protected branches
50
+
51
+ And there's no way to add entirely new logic: "deny writes unless a Jira ticket is in the
52
+ prompt", "call our internal approval API before destructive Bash", "notify Slack on every
53
+ session end."
54
+
55
+ Two distinct needs, both unsolved today:
56
+
57
+ 1. **Configure existing policies** — tune behavior without writing code
58
+ 2. **Fully custom hooks** — arbitrary logic tied to any hook event
59
+
60
+ ---
61
+
62
+ ## Goals & Non-Goals
63
+
64
+ ### Goals
65
+ - Params for builtin policies with sensible defaults — users who configure nothing get
66
+ identical behavior to today
67
+ - Custom hook logic in a `hooks.js` file using the same authoring experience as `eval.js`
68
+ - Same `allow` / `deny` / `instruct` semantics throughout
69
+ - Minimal ceremony: one config file, one optional code file
70
+ - Project-local additions on top of global config
71
+
72
+ ### Non-Goals
73
+ - GUI editor (CLI-first)
74
+ - Hook sharing / marketplace
75
+ - Sandboxing custom JS (user-trusted code, full user privileges)
76
+ - Hot reloading (hooks load fresh per event — acceptable given the ephemeral process model)
77
+ - Per-custom-hook configuration via `policyParams` (deferred — see open items)
78
+
79
+ ---
80
+
81
+ ## Architecture
82
+
83
+ ```
84
+ Claude Code event fires
85
+ → claudeye --hook <EventType>
86
+ → load ~/.claudeye/hooks-config.json (merged with .claudeye/hooks-config.json)
87
+ → register builtin policies with their resolved params
88
+ → register custom JS hooks (auto-discovered hooks.js files)
89
+ → evaluate all in priority order
90
+ → first deny short-circuits; instruct accumulates
91
+ → write response to stdout
92
+ ```
93
+
94
+ Two layers, evaluated in order:
95
+
96
+ ```
97
+ [1] Builtin policies (with params) → fast, well-tested, security-critical
98
+ [2] Custom JS hook modules → full power, async, arbitrary logic
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Part 1: Policy Params
104
+
105
+ ### Mechanism
106
+
107
+ `PolicyContext` gains an optional `params` field:
108
+
109
+ ```ts
110
+ interface PolicyContext {
111
+ eventType: HookEventType;
112
+ payload: Record<string, unknown>;
113
+ toolName?: string;
114
+ toolInput?: Record<string, unknown>;
115
+ session?: SessionMetadata;
116
+ params?: Record<string, unknown>;
117
+ }
118
+ ```
119
+
120
+ Each parameterizable builtin declares a schema with required default values on its
121
+ `BuiltinPolicyDefinition`. At load time, Claudeye merges `policyParams[policy.name]` from
122
+ config over those defaults and injects the result into `ctx.params`. Policy functions read
123
+ `ctx.params` directly — no null-guarding needed since defaults are always applied first.
124
+
125
+ ```ts
126
+ function blockSudo(ctx: PolicyContext): PolicyResult {
127
+ const cmd = getCommand(ctx);
128
+ if (!/\bsudo\b/.test(cmd)) return allow();
129
+
130
+ const allowPatterns = ctx.params!.allowPatterns as string[];
131
+ if (allowPatterns.some((p) => matchesAllowedCommand(cmd, p))) return allow();
132
+
133
+ return deny("sudo command blocked by claudeye");
134
+ }
135
+ ```
136
+
137
+ > **Implementation note — `allowPatterns` matching:** patterns must be matched against the
138
+ > parsed command (executable + arguments as tokens), not the raw command string. Raw-string
139
+ > glob matching allows bypass via appended shell operators (e.g. `sudo systemctl status x; rm -rf /`
140
+ > matches `sudo systemctl status *`). See adversarial review finding #3.
141
+
142
+ ### Schema definition
143
+
144
+ ```ts
145
+ interface BuiltinPolicyDefinition {
146
+ name: string;
147
+ description: string;
148
+ fn: PolicyFunction;
149
+ match: PolicyMatcher;
150
+ defaultEnabled: boolean;
151
+ category: string;
152
+ beta?: boolean;
153
+ params?: PolicyParamsSchema;
154
+ }
155
+
156
+ interface PolicyParamsSchema {
157
+ [paramName: string]: {
158
+ type: "string" | "number" | "boolean" | "string[]" | "pattern[]";
159
+ description: string;
160
+ default: unknown; // every param must ship with a default
161
+ };
162
+ }
163
+ ```
164
+
165
+ ### Builtin policies with params
166
+
167
+ | Policy | Param | Type | Default |
168
+ |---|---|---|---|
169
+ | `block-sudo` | `allowPatterns` | `string[]` | `[]` |
170
+ | `block-rm-rf` | `allowPaths` | `string[]` | `[]` |
171
+ | `block-read-outside-cwd` | `allowPaths` | `string[]` | `[]` |
172
+ | `block-push-master` | `protectedBranches` | `string[]` | `["main", "master"]` |
173
+ | `block-work-on-main` | `protectedBranches` | `string[]` | `["main", "master"]` |
174
+ | `sanitize-api-keys` | `additionalPatterns` | `pattern[]` | `[]` |
175
+ | `block-secrets-write` | `additionalPatterns` | `string[]` | `[]` |
176
+ | `warn-large-file-write` | `thresholdKb` | `number` | `1024` |
177
+
178
+ ### Config shape
179
+
180
+ `policyParams` is a new top-level key in `hooks-config.json`, keyed by builtin policy name:
181
+
182
+ ```json
183
+ {
184
+ "enabledPolicies": ["block-sudo", "block-push-master", "sanitize-api-keys"],
185
+ "policyParams": {
186
+ "block-sudo": {
187
+ "allowPatterns": ["sudo systemctl status", "sudo journalctl"]
188
+ },
189
+ "block-push-master": {
190
+ "protectedBranches": ["main", "release", "prod"]
191
+ },
192
+ "sanitize-api-keys": {
193
+ "additionalPatterns": [
194
+ { "regex": "myco_[A-Za-z0-9]{32}", "label": "MyCo internal API key" }
195
+ ]
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ ### Config scopes and merge strategy
202
+
203
+ Three config files, evaluated in priority order:
204
+
205
+ ```
206
+ [1] .claudeye/hooks-config.json ← project (committed to repo)
207
+ [2] .claudeye/hooks-config.local.json ← local (gitignored, personal overrides)
208
+ [3] ~/.claudeye/hooks-config.json ← global (user-level fallback)
209
+ ```
210
+
211
+ **`enabledPolicies`** — union across all three. A policy enabled at any level is active.
212
+
213
+ **`policyParams`** — per-policy, first level that defines it wins entirely. No merging of
214
+ values. If `block-sudo` has params in the project config, those are used as-is; the local
215
+ and global params for `block-sudo` are ignored.
216
+
217
+ ```
218
+ project: block-sudo → { allowPatterns: ["sudo apt-get update"] }
219
+ global: block-sudo → { allowPatterns: ["sudo systemctl status"] }
220
+
221
+ resolved: { allowPatterns: ["sudo apt-get update"] } ← project wins, global ignored
222
+ ```
223
+
224
+ ```
225
+ project: (no block-sudo params)
226
+ local: (no block-sudo params)
227
+ global: block-sudo → { allowPatterns: ["sudo systemctl status"] }
228
+
229
+ resolved: { allowPatterns: ["sudo systemctl status"] } ← falls through to global
230
+ ```
231
+
232
+ This means to change a policy's params for a project, you own the full value — you can't
233
+ partially extend the global list. That's intentional: explicit is better than surprising
234
+ concatenation.
235
+
236
+ ### `--list-hooks` display
237
+
238
+ Configured params are shown as a summary line beneath each policy:
239
+
240
+ ```
241
+ ✓ block-sudo Block sudo commands
242
+ allowPatterns: ["sudo systemctl status", "sudo journalctl"]
243
+ ✓ block-push-master Block pushing to main/master
244
+ protectedBranches: ["main", "release", "prod"]
245
+ ```
246
+
247
+ Unknown keys in `policyParams` (e.g. typos) are flagged here — not at hook-fire time.
248
+
249
+ ---
250
+
251
+ ## Part 2: Custom JS Hooks
252
+
253
+ ### API design
254
+
255
+ Modeled after the `--evals` pattern. Users import `customHooks` and the decision helpers
256
+ from `claudeye`, call `.add()` to register hooks as side effects, then export `customHooks`.
257
+ The registry is backed by `globalThis` — same mechanism as the evals dashboard/alert registries.
258
+
259
+ The three decision helpers — `allow()`, `deny(message)`, `instruct(message)` — are the same
260
+ helpers used internally by every builtin policy. Custom hook authors use these instead of
261
+ returning raw objects. The `deny()` message is prefixed with `"Blocked by claudeye:"` in the
262
+ evaluator output, consistent with builtin policy deny messages.
263
+
264
+ ```js
265
+ // my-hooks.js
266
+ import { customHooks, allow, deny, instruct } from 'claudeye';
267
+ import { checkApproval } from './approval-client.js'; // local module — works fine
268
+
269
+ customHooks.add({
270
+ name: "require-ticket-on-commit",
271
+ description: "Block git commits until CURRENT_TICKET env var is set",
272
+ match: { events: ["PreToolUse"] },
273
+ fn: async (ctx) => {
274
+ if (ctx.toolName !== "Bash") return allow();
275
+ const cmd = ctx.toolInput?.command ?? "";
276
+ if (!cmd.includes("git commit")) return allow();
277
+
278
+ if (!process.env.CURRENT_TICKET) {
279
+ return instruct("Set CURRENT_TICKET env var before committing.");
280
+ }
281
+ return allow();
282
+ },
283
+ });
284
+
285
+ customHooks.add({
286
+ name: "approval-gate",
287
+ description: "Call internal approval API before destructive Bash",
288
+ match: { events: ["PreToolUse"] },
289
+ fn: async (ctx) => {
290
+ if (ctx.toolName !== "Bash") return allow();
291
+ const cmd = ctx.toolInput?.command ?? "";
292
+ if (!/rm|drop|truncate/i.test(cmd)) return allow();
293
+
294
+ const approved = await checkApproval(cmd, ctx.session?.sessionId);
295
+ return approved
296
+ ? allow()
297
+ : deny("Destructive command requires approval — visit approvals.internal");
298
+ },
299
+ });
300
+
301
+ export { customHooks };
302
+ ```
303
+
304
+ ### Providing the hooks file
305
+
306
+ The path to the hooks file is given explicitly via `--custom-hooks <path>` when installing
307
+ hooks. It is stored in `hooks-config.json` and read by the hook handler at event-fire time.
308
+
309
+ ```bash
310
+ claudeye --install-hooks --custom-hooks ./my-hooks.js
311
+ ```
312
+
313
+ `hooks-config.json` stores the resolved absolute path:
314
+
315
+ ```json
316
+ {
317
+ "enabledPolicies": ["block-sudo"],
318
+ "customHooksPath": "/home/alice/myproject/my-hooks.js"
319
+ }
320
+ ```
321
+
322
+ To update or remove:
323
+
324
+ ```bash
325
+ claudeye --install-hooks --custom-hooks ./new-hooks.js # replace path
326
+ claudeye --install-hooks --remove-custom-hooks # clear
327
+ ```
328
+
329
+ ### Loading
330
+
331
+ Same loader as `--evals eval.js` (`lib/evals/loader.ts`), applied to `customHooksPath`:
332
+
333
+ 1. **ESM/CJS compat** — writes temp `.mjs` files so Node always treats the file as ESM
334
+ 2. **`import { ... } from 'claudeye'`** — rewrites to the actual dist path via an ESM shim,
335
+ so `customHooks` resolves to the same `globalThis`-backed registry instance
336
+ 3. **Transitive imports** — recursively rewrites all local relative imports reachable from
337
+ the entry file, so `import { checkApproval } from './approval-client.js'` works exactly
338
+ as the user expects
339
+
340
+ After import, the hook handler reads the registered hooks from the `globalThis` registry.
341
+
342
+ ### Registry and `customHooks` object
343
+
344
+ New singleton in `src/hooks/custom-hooks-registry.ts`, mirroring the evals registry pattern:
345
+
346
+ ```ts
347
+ // src/hooks/custom-hooks-registry.ts
348
+ const REGISTRY_KEY = "__claudeye_custom_hooks__";
349
+
350
+ export const customHooks = {
351
+ add(hook: CustomHook): void {
352
+ const g = globalThis as Record<string, unknown>;
353
+ if (!Array.isArray(g[REGISTRY_KEY])) g[REGISTRY_KEY] = [];
354
+ (g[REGISTRY_KEY] as CustomHook[]).push(hook);
355
+ },
356
+ };
357
+
358
+ export function getCustomHooks(): CustomHook[] {
359
+ const g = globalThis as Record<string, unknown>;
360
+ return Array.isArray(g[REGISTRY_KEY]) ? (g[REGISTRY_KEY] as CustomHook[]) : [];
361
+ }
362
+ ```
363
+
364
+ `customHooks` is exported from the `claudeye` package alongside `createApp`.
365
+
366
+ ### `CustomHook` type and decision helpers
367
+
368
+ ```ts
369
+ export interface CustomHook {
370
+ name: string;
371
+ description?: string;
372
+ match?: {
373
+ events?: HookEventType[];
374
+ };
375
+ fn: (ctx: PolicyContext) => PolicyResult | Promise<PolicyResult>;
376
+ }
377
+
378
+ // Decision helpers — use these instead of returning raw objects
379
+ export function allow(): PolicyResult;
380
+ export function deny(message: string): PolicyResult;
381
+ export function instruct(message: string): PolicyResult;
382
+ ```
383
+
384
+ The helpers are the same functions used internally by every builtin policy, now exported as
385
+ part of the public API. The `deny(message)` output is prefixed with `"Blocked by claudeye:"`
386
+ by the evaluator — consistent with how builtin deny messages are surfaced to Claude.
387
+
388
+ Tool filtering is the hook's responsibility — inspect `ctx.toolName` and `ctx.toolInput`
389
+ inside `fn`. The framework only filters by event type.
390
+
391
+ ### Failure modes
392
+
393
+ | Failure | Behavior |
394
+ |---|---|
395
+ | `customHooksPath` not set | Skip — no custom hooks, builtins run normally |
396
+ | File not found at path | Log to `~/.claudeye/hook.log`, skip, builtins run normally |
397
+ | Import / syntax error | Log to `~/.claudeye/hook.log`, skip entire file, builtins run normally |
398
+ | `fn` throws at runtime | Log error, treat as `allow` for that hook only |
399
+ | `fn` exceeds 10s | Timeout, treat as `allow`, log warning |
400
+
401
+ Fail-open throughout. See exospherehost/claudeye#154 for future fail-closed support.
402
+
403
+ ### `--list-hooks` display
404
+
405
+ ```
406
+ Claudeye Hook Policies (user)
407
+
408
+ Status Name Description
409
+ ────── ─────────────────────────────────────────────────────────────
410
+ ✓ block-sudo Block sudo commands
411
+ allowPatterns: ["sudo systemctl status"]
412
+ ✓ block-push-master Block pushing to main/master
413
+
414
+ ── Custom Hooks (/home/alice/myproject/my-hooks.js) ───────────────
415
+ ✓ require-ticket-on-commit Block git commits without ticket
416
+ ✓ approval-gate Approval gate for destructive commands
417
+ ```
418
+
419
+ ---
420
+
421
+ ## Unified Config Shape
422
+
423
+ ```ts
424
+ interface HooksConfig {
425
+ enabledPolicies: string[];
426
+ llm?: LlmConfig;
427
+ policyParams?: {
428
+ [builtinPolicyName: string]: Record<string, unknown>;
429
+ };
430
+ customHooksPath?: string; // absolute path, set via --custom-hooks <path>
431
+ }
432
+ ```
433
+
434
+ ---
435
+
436
+ ## Decisions
437
+
438
+ | Topic | Decision |
439
+ |---|---|
440
+ | Every param has a default | Yes — unconfigured users get identical behavior to today |
441
+ | Config scopes | Three levels: project → local → global (priority order) |
442
+ | Config merging | `enabledPolicies`: union across all levels. `policyParams`: per-policy, first level that defines it wins entirely — no value merging. |
443
+ | Declarative JSON rules | Dropped — params cover no-code tuning; `hooks.js` covers custom logic |
444
+ | JS loading mechanism | Reuse `lib/evals/loader.ts` verbatim — same as `eval.js`, handles ESM compat + transitive imports |
445
+ | Custom hooks API | `import { customHooks } from 'claudeye'` → `customHooks.add()` → `export { customHooks }` |
446
+ | Custom hooks path | Explicit via `--custom-hooks <path>`, stored as `customHooksPath` in `hooks-config.json` |
447
+ | Unknown `policyParams` keys | Warn in `--list-hooks`, silent at fire time |
448
+ | Custom hook failures | Fail-open — tracked in #154 for future fail-closed support |
449
+ | Per-custom-hook params (`ctx.params`) | Deferred |
450
+
451
+ ---
452
+
453
+ ## Implementation Checklist
454
+
455
+ Mark each item `[x]` as you complete it. Do not move to the next section until all items in
456
+ the current section are checked and the project compiles cleanly.
457
+
458
+ ---
459
+
460
+ ### 1. Branch setup
461
+ - [x] `git checkout main && git pull`
462
+ - [x] `git checkout -b feat/custom-hooks`
463
+ - [x] Confirm `npm run build` (or equivalent) passes on clean main before any changes
464
+
465
+ ---
466
+
467
+ ### 2. Type definitions — `src/hooks/policy-types.ts`
468
+ - [x] Add `params?: Record<string, unknown>` to `PolicyContext`
469
+ - [x] Add `PolicyParamsSchema` interface with `type`, `description`, `default` per param key
470
+ - [x] Add `params?: PolicyParamsSchema` field to `BuiltinPolicyDefinition`
471
+ - [x] Add `policyParams?: Record<string, Record<string, unknown>>` to `HooksConfig`
472
+ - [x] Add `customHooksPath?: string` to `HooksConfig`
473
+ - [x] Verify project still compiles after type changes
474
+
475
+ ---
476
+
477
+ ### 3. Config loading — `src/hooks/hooks-config.ts`
478
+ - [x] Implement three-scope config discovery: project (`.claudeye/hooks-config.json`) → local (`.claudeye/hooks-config.local.json`) → global (`~/.claudeye/hooks-config.json`)
479
+ - [x] `enabledPolicies`: union across all three scopes (dedup)
480
+ - [x] `policyParams`: per-policy key, first scope that defines it wins entirely — no merging of values
481
+ - [x] `customHooksPath`: first scope that defines it wins
482
+ - [x] Expose a `readMergedHooksConfig(cwd?: string): HooksConfig` function that returns the fully merged result
483
+ - [x] Existing `readHooksConfig()` remains unchanged for callers that only need the global file
484
+ - [x] Verify project still compiles
485
+
486
+ ---
487
+
488
+ ### 4. Parameterize builtin policies — `src/hooks/builtin-policies.ts`
489
+
490
+ For each policy below: add `params` schema to its `BuiltinPolicyDefinition` entry and update the function body to read from `ctx.params` (never null-guard — defaults are always pre-applied by the evaluator).
491
+
492
+ - [x] `block-sudo` — param: `allowPatterns: string[]`, default `[]`. Match against parsed argv tokens, not raw string (see Open Items — allowPatterns safety)
493
+ - [x] `block-rm-rf` — param: `allowPaths: string[]`, default `[]`
494
+ - [x] `block-read-outside-cwd` — param: `allowPaths: string[]`, default `[]`
495
+ - [x] `block-push-master` — param: `protectedBranches: string[]`, default `["main", "master"]`. Replace hardcoded branch names with param value
496
+ - [x] `block-work-on-main` — param: `protectedBranches: string[]`, default `["main", "master"]`
497
+ - [x] `sanitize-api-keys` — param: `additionalPatterns: { regex: string; label: string }[]`, default `[]`
498
+ - [x] `block-secrets-write` — param: `additionalPatterns: string[]`, default `[]`
499
+ - [x] `warn-large-file-write` — param: `thresholdKb: number`, default `1024`
500
+ - [x] Verify that all policies with no user-provided params behave identically to before
501
+
502
+ ---
503
+
504
+ ### 5. Params injection — `src/hooks/policy-evaluator.ts`
505
+ - [x] Before calling each policy's `fn`, resolve `ctx.params` by merging `policyParams[policy.name]` over the policy's declared schema defaults
506
+ - [x] Use `readMergedHooksConfig()` (from step 3) instead of `readHooksConfig()` when loading config inside the evaluator
507
+ - [x] Verify project still compiles
508
+
509
+ ---
510
+
511
+ ### 6. Custom hooks registry — `src/hooks/custom-hooks-registry.ts` (new file)
512
+ - [x] Create `globalThis`-backed registry under key `__claudeye_custom_hooks__`
513
+ - [x] Implement `customHooks.add(hook: CustomHook): void`
514
+ - [x] Implement `getCustomHooks(): CustomHook[]`
515
+ - [x] Implement `clearCustomHooks(): void` (needed for test isolation)
516
+ - [x] Export `customHooks` object and `getCustomHooks`, `clearCustomHooks` functions
517
+ - [x] Verify project still compiles
518
+
519
+ ---
520
+
521
+ ### 7. Package exports
522
+ - [x] Export `customHooks` from the main `claudeye` package entry point
523
+ - [x] Export `allow`, `deny`, `instruct` helper functions from the main entry point (move them out of `builtin-policies.ts` or re-export them — they must be the same functions, not copies)
524
+ - [x] Export `CustomHook` type from the main entry point
525
+ - [x] Export `PolicyContext`, `PolicyResult`, `HookEventType` if not already exported (users need these for type annotations in their hooks file)
526
+ - [x] Verify `import { customHooks, allow, deny, instruct } from 'claudeye'` resolves correctly in a test import
527
+ - [x] Verify the ESM shim in the loader (`createEsmShim`) exports `allow`, `deny`, `instruct` alongside `customHooks` and `createApp`
528
+
529
+ ---
530
+
531
+ ### 8. Custom hooks loader — `src/hooks/custom-hooks-loader.ts` (new file)
532
+ - [x] Read `customHooksPath` from merged config; if absent, return early (no custom hooks)
533
+ - [x] Resolve the path to absolute
534
+ - [x] Check file exists; if not, log a warning to `~/.claudeye/hook.log` and return
535
+ - [x] Adapt `lib/evals/loader.ts` for the hook handler context: set a `__CLAUDEYE_LOADING_HOOKS__` flag on `globalThis` before import (parallel to `__CLAUDEYE_LOADING_EVALS__`), clear it after
536
+ - [x] Rewrite `from 'claudeye'` imports to the actual dist path so `customHooks` resolves to the same `globalThis` registry instance
537
+ - [x] Handle transitive relative imports (same recursive rewrite as the evals loader)
538
+ - [x] Clean up all temp `.mjs` files in a `finally` block
539
+ - [x] On import/syntax error: catch, log full error to `~/.claudeye/hook.log`, continue without crashing
540
+ - [x] After successful load, call `getCustomHooks()` and return the registered hooks
541
+ - [x] Verify project still compiles
542
+
543
+ ---
544
+
545
+ ### 9. Hook handler wiring — `src/hooks/handler.ts`
546
+ - [x] After registering builtin policies, call the custom hooks loader
547
+ - [x] Register each loaded custom hook into the policy registry with a `custom/` name prefix (prevents name collision with builtins)
548
+ - [x] Custom hooks run in layer 2 (after builtins) — verify priority ordering
549
+ - [x] Verify project still compiles
550
+
551
+ ---
552
+
553
+ ### 10. CLI — `src/hooks/manager.ts` and `src/cli-mode.ts`
554
+ - [x] Add `--custom-hooks <path>` flag to `installHooks()` — resolve to absolute path and write to `customHooksPath` in global `hooks-config.json`
555
+ - [x] Add `--remove-custom-hooks` flag — clears `customHooksPath` from config
556
+ - [x] Print the resolved hooks file path in the post-install summary
557
+ - [x] Add both flags to the CLI help text in `src/cli-mode.ts`
558
+ - [x] Verify project still compiles
559
+
560
+ ---
561
+
562
+ ### 11. `--list-hooks` display — `src/hooks/manager.ts`
563
+ - [x] Beneath each enabled policy that has user-configured params, print a summary line showing the active param values
564
+ - [x] Detect unknown keys in `policyParams` (keys that don't match any known policy schema param); print a warning line for each
565
+ - [x] If `customHooksPath` is set: attempt to load the file and show a "Custom Hooks" section beneath builtins
566
+ - [x] Each custom hook shows: status (`✓` / `✗ ERR`), declared name, description
567
+ - [x] On load failure: show `✗ ERR <name> failed to load: <error message>`
568
+ - [x] If `customHooksPath` is set but file does not exist: show a clear warning
569
+ - [x] Verify project still compiles
570
+
571
+ ---
572
+
573
+ ### 12. Unit tests — policy params
574
+
575
+ File: `__tests__/hooks/hooks-config.test.ts`
576
+ - [x] Test: no config files present → returns empty defaults
577
+ - [x] Test: only global config → returns global values
578
+ - [x] Test: project + global, `policyParams` defined in project → project values used, global values for that policy ignored
579
+ - [x] Test: project + global, policy absent in project → falls through to global
580
+ - [x] Test: all three scopes present, each with different `policyParams` entries → correct precedence
581
+ - [x] Test: `enabledPolicies` union across all three scopes, deduplication works
582
+ - [x] Test: `customHooksPath` — first scope that defines it wins
583
+
584
+ File: `__tests__/hooks/builtin-policies.test.ts`
585
+ - [x] Test: each parameterized policy with no `ctx.params` set behaves identically to current behavior (regression guard)
586
+ - [x] Test: `block-sudo` with `allowPatterns: ["sudo systemctl status"]` — matching command is allowed
587
+ - [x] Test: `block-sudo` with `allowPatterns` — non-matching sudo is still denied
588
+ - [x] Test: `block-rm-rf` with `allowPaths` — allowed path passes, unlisted path denied
589
+ - [x] Test: `block-read-outside-cwd` with `allowPaths` — listed path allowed
590
+ - [x] Test: `block-push-master` with `protectedBranches: ["main", "release"]` — `release` is now blocked, non-listed branch is not
591
+ - [x] Test: `block-work-on-main` with custom `protectedBranches`
592
+ - [x] Test: `sanitize-api-keys` with `additionalPatterns` — custom pattern triggers deny
593
+ - [x] Test: `block-secrets-write` with `additionalPatterns`
594
+ - [x] Test: `warn-large-file-write` with custom `thresholdKb`
595
+
596
+ File: `__tests__/hooks/policy-evaluator.test.ts`
597
+ - [x] Test: params are correctly resolved from schema defaults when no `policyParams` in config
598
+ - [x] Test: params from config correctly override schema defaults before `fn` is called
599
+ - [x] Test: unknown `policyParams` key does not crash the evaluator
600
+
601
+ ---
602
+
603
+ ### 13. Unit tests — custom hooks registry
604
+
605
+ New file: `__tests__/hooks/custom-hooks-registry.test.ts`
606
+ - [x] Test: `customHooks.add()` registers a hook into the globalThis registry
607
+ - [x] Test: `getCustomHooks()` returns all registered hooks in insertion order
608
+ - [x] Test: multiple `.add()` calls accumulate correctly
609
+ - [x] Test: `clearCustomHooks()` empties the registry (verify test isolation)
610
+ - [x] Test: registry survives across module re-imports (globalThis persistence)
611
+
612
+ ---
613
+
614
+ ### 14. Unit tests — custom hooks loader
615
+
616
+ New file: `__tests__/hooks/custom-hooks-loader.test.ts`
617
+ - [x] Test: `customHooksPath` absent in config → returns empty array, no error
618
+ - [x] Test: `customHooksPath` set but file does not exist → logs warning, returns empty array
619
+ - [x] Test: valid hooks file with one `customHooks.add()` call → hook registered and returned
620
+ - [x] Test: hooks file with import/syntax error → logs to hook.log, returns empty array, does not throw
621
+ - [x] Test: hooks file with transitive local import → transitive module resolved and loaded correctly
622
+ - [x] Test: temp `.mjs` files are cleaned up after load (success and error paths)
623
+
624
+ ---
625
+
626
+ ### 15. Unit tests — CLI and manager
627
+
628
+ File: `__tests__/hooks/manager.test.ts`
629
+ - [x] Test: `--custom-hooks <path>` saves resolved absolute path to `customHooksPath` in config
630
+ - [x] Test: `--remove-custom-hooks` clears `customHooksPath` from config
631
+ - [x] Test: `--list-hooks` output includes param summary for configured policies
632
+ - [x] Test: `--list-hooks` warns on unknown `policyParams` keys
633
+ - [x] Test: `--list-hooks` shows "Custom Hooks" section when `customHooksPath` is set
634
+ - [x] Test: `--list-hooks` shows error row when hooks file fails to load
635
+
636
+ ---
637
+
638
+ ### 16. Documentation — `README.md`
639
+ - [x] Add `policyParams` section explaining the three-scope config and precedence rules
640
+ - [x] Add a table or subsection for each parameterized policy: param name, type, default, example
641
+ - [x] Add `--custom-hooks <path>` to the CLI reference section
642
+ - [x] Add `--remove-custom-hooks` to the CLI reference section
643
+ - [x] Add a "Custom Hooks" authoring guide with:
644
+ - [x] Installation step (`claudeye --install-hooks --custom-hooks ./my-hooks.js`)
645
+ - [x] Full working example file using `customHooks.add()` with `allow()`, `deny()`, `instruct()`
646
+ - [x] Description of each decision helper: `allow()`, `deny(message)`, `instruct(message)` — what each does, when to use it, what the message becomes in Claude's context
647
+ - [x] Note that `deny(message)` is prefixed with `"Blocked by claudeye:"` in the output
648
+ - [x] Description of `ctx` fields available (`eventType`, `toolName`, `toolInput`, `session`, `payload`)
649
+ - [x] Note on transitive imports being supported
650
+ - [x] Note on fail-open behavior and the hook.log location
651
+ - [x] Export `CustomHook`, `PolicyContext`, `PolicyResult` types in the Types section of the README
652
+
653
+ ---
654
+
655
+ ### 17. Changelog — `CHANGELOG.md`
656
+ - [x] Add `## [1.0.8-beta.0]` heading at the top
657
+ - [x] Document Part 1: policy params — mention `policyParams` config key, list all parameterized policies and their param names
658
+ - [x] Document Part 2: custom JS hooks — mention `--custom-hooks <path>`, `customHooks.add()` API, loader capabilities (transitive imports, ESM compat)
659
+ - [x] Reference the design doc (`design-docs/custom-hooks.md`) for full design rationale
660
+
661
+ ---
662
+
663
+ ### 18. Version bump
664
+ - [x] `package.json` → `"version": "1.0.8-beta.0"`
665
+ - [x] `packages/darwin-arm64/package.json` → `"version": "1.0.8-beta.0"`
666
+ - [x] `packages/darwin-x64/package.json` → `"version": "1.0.8-beta.0"`
667
+ - [x] `packages/linux-arm64/package.json` → `"version": "1.0.8-beta.0"`
668
+ - [x] `packages/linux-x64/package.json` → `"version": "1.0.8-beta.0"`
669
+ - [x] `packages/win32-x64/package.json` → `"version": "1.0.8-beta.0"`
670
+ - [x] `packages/wrapper/package.json` → `"version": "1.0.8-beta.0"`
671
+ - [x] Verify all version strings are consistent (`grep -r "1.0.7" package.json packages/`)
672
+
673
+ ---
674
+
675
+ ### 19. Final verification
676
+ - [x] `npm run build` (or equivalent) passes with zero errors
677
+ - [x] Full test suite passes (`npm test` or equivalent) with zero failures
678
+ - [x] `claudeye --list-hooks` runs without error on a clean install
679
+ - [x] `claudeye --install-hooks --custom-hooks <path>` correctly saves the path and loads hooks on next event
680
+ - [x] A manually authored `my-hooks.js` using `customHooks.add()` with a transitive import loads and evaluates correctly end-to-end
681
+ - [x] No `console.log` debug statements left in production code paths
682
+ - [x] No new `any` types introduced without a comment explaining why
683
+
684
+ ---
685
+
686
+ ### 20. Pull request
687
+ - [x] Stage all changes: confirm `git status` shows only intentional files (no `.env`, no build artifacts, no temp files)
688
+ - [x] Commit with a descriptive message referencing both features, e.g. `feat: policy params + custom JS hooks (v1.0.8-beta.0)`
689
+ - [x] Push the branch: `git push -u origin feat/custom-hooks`
690
+ - [x] Open a PR against `main` using `gh pr create` with:
691
+ - Title: `feat: policy params and custom JS hooks (v1.0.8-beta.0)`
692
+ - Body covering:
693
+ - [x] Summary of Part 1 (policy params — what changed, which policies, config shape)
694
+ - [x] Summary of Part 2 (custom hooks — API, loader, `--custom-hooks` flag)
695
+ - [x] Link to `design-docs/custom-hooks.md` for full design rationale
696
+ - [x] Test plan: what was tested manually and what is covered by unit tests
697
+ - [x] Note on backwards compatibility (no-params users are unaffected)
698
+ - [x] Confirm the PR URL is accessible and the description renders correctly
699
+
700
+ ---
701
+
702
+ ### 21. CI monitoring and fixes
703
+ - [x] Watch the CI run: `gh run watch` or `gh pr checks <pr-number> --watch`
704
+ - [x] Wait for all checks to complete — do not assume green until every job has finished
705
+ - [x] If any check fails:
706
+ - [x] Fetch the failure logs: `gh run view <run-id> --log-failed`
707
+ - [x] Read the full error output before attempting a fix — do not guess
708
+ - [x] Fix the root cause (do not skip or suppress failing checks with `--no-verify` or similar)
709
+ - [x] Push the fix as a new commit on the same branch
710
+ - [x] Re-watch CI until all checks pass
711
+ - [x] Repeat the fix cycle until every CI check is green
712
+ - [x] Once all checks pass, mark this section complete and notify the user that the PR is ready for review
713
+
714
+ ---
715
+
716
+ ## Open Items
717
+
718
+ - **#154** — Fail-open vs fail-closed semantics for enforcement hooks
719
+ - **Per-custom-hook params** — letting `policyParams` configure custom hooks via `ctx.params`
720
+ (deferred, design in a separate doc when ready)
721
+ - **`allowPatterns` matching safety** — implementation must parse commands into argv tokens,
722
+ not match raw strings, to prevent shell operator injection bypass