@jacques-ai/cli 0.0.7-alpha.1

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 (508) hide show
  1. package/dist/assets/mascot-ansi.d.ts +8 -0
  2. package/dist/assets/mascot-ansi.d.ts.map +1 -0
  3. package/dist/assets/mascot-ansi.js +15 -0
  4. package/dist/assets/mascot-ansi.js.map +1 -0
  5. package/dist/cli.d.ts +15 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +53 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/client-helper.d.ts +14 -0
  10. package/dist/commands/client-helper.d.ts.map +1 -0
  11. package/dist/commands/client-helper.js +38 -0
  12. package/dist/commands/client-helper.js.map +1 -0
  13. package/dist/commands/dashboard.d.ts +8 -0
  14. package/dist/commands/dashboard.d.ts.map +1 -0
  15. package/dist/commands/dashboard.js +159 -0
  16. package/dist/commands/dashboard.js.map +1 -0
  17. package/dist/commands/index.d.ts +6 -0
  18. package/dist/commands/index.d.ts.map +1 -0
  19. package/dist/commands/index.js +6 -0
  20. package/dist/commands/index.js.map +1 -0
  21. package/dist/commands/list.d.ts +5 -0
  22. package/dist/commands/list.d.ts.map +1 -0
  23. package/dist/commands/list.js +13 -0
  24. package/dist/commands/list.js.map +1 -0
  25. package/dist/commands/search.d.ts +13 -0
  26. package/dist/commands/search.d.ts.map +1 -0
  27. package/dist/commands/search.js +79 -0
  28. package/dist/commands/search.js.map +1 -0
  29. package/dist/commands/setup.d.ts +8 -0
  30. package/dist/commands/setup.d.ts.map +1 -0
  31. package/dist/commands/setup.js +32 -0
  32. package/dist/commands/setup.js.map +1 -0
  33. package/dist/commands/status.d.ts +5 -0
  34. package/dist/commands/status.d.ts.map +1 -0
  35. package/dist/commands/status.js +27 -0
  36. package/dist/commands/status.js.map +1 -0
  37. package/dist/components/ActiveSessionsView.d.ts +18 -0
  38. package/dist/components/ActiveSessionsView.d.ts.map +1 -0
  39. package/dist/components/ActiveSessionsView.js +68 -0
  40. package/dist/components/ActiveSessionsView.js.map +1 -0
  41. package/dist/components/AddContextConfirmView.d.ts +21 -0
  42. package/dist/components/AddContextConfirmView.d.ts.map +1 -0
  43. package/dist/components/AddContextConfirmView.js +44 -0
  44. package/dist/components/AddContextConfirmView.js.map +1 -0
  45. package/dist/components/App.d.ts +11 -0
  46. package/dist/components/App.d.ts.map +1 -0
  47. package/dist/components/App.js +292 -0
  48. package/dist/components/App.js.map +1 -0
  49. package/dist/components/ArchiveBrowserView.d.ts +40 -0
  50. package/dist/components/ArchiveBrowserView.d.ts.map +1 -0
  51. package/dist/components/ArchiveBrowserView.js +161 -0
  52. package/dist/components/ArchiveBrowserView.js.map +1 -0
  53. package/dist/components/ArchiveInitProgressView.d.ts +16 -0
  54. package/dist/components/ArchiveInitProgressView.d.ts.map +1 -0
  55. package/dist/components/ArchiveInitProgressView.js +72 -0
  56. package/dist/components/ArchiveInitProgressView.js.map +1 -0
  57. package/dist/components/AutoCompactToggle.d.ts +16 -0
  58. package/dist/components/AutoCompactToggle.d.ts.map +1 -0
  59. package/dist/components/AutoCompactToggle.js +12 -0
  60. package/dist/components/AutoCompactToggle.js.map +1 -0
  61. package/dist/components/BottomControls.d.ts +12 -0
  62. package/dist/components/BottomControls.d.ts.map +1 -0
  63. package/dist/components/BottomControls.js +11 -0
  64. package/dist/components/BottomControls.js.map +1 -0
  65. package/dist/components/CompactHeader.d.ts +21 -0
  66. package/dist/components/CompactHeader.d.ts.map +1 -0
  67. package/dist/components/CompactHeader.js +63 -0
  68. package/dist/components/CompactHeader.js.map +1 -0
  69. package/dist/components/CompactPanel.d.ts +22 -0
  70. package/dist/components/CompactPanel.d.ts.map +1 -0
  71. package/dist/components/CompactPanel.js +31 -0
  72. package/dist/components/CompactPanel.js.map +1 -0
  73. package/dist/components/ContentBox.d.ts +14 -0
  74. package/dist/components/ContentBox.d.ts.map +1 -0
  75. package/dist/components/ContentBox.js +24 -0
  76. package/dist/components/ContentBox.js.map +1 -0
  77. package/dist/components/ContextProgress.d.ts +14 -0
  78. package/dist/components/ContextProgress.d.ts.map +1 -0
  79. package/dist/components/ContextProgress.js +36 -0
  80. package/dist/components/ContextProgress.js.map +1 -0
  81. package/dist/components/Dashboard.d.ts +46 -0
  82. package/dist/components/Dashboard.d.ts.map +1 -0
  83. package/dist/components/Dashboard.js +67 -0
  84. package/dist/components/Dashboard.js.map +1 -0
  85. package/dist/components/FilterSelectionView.d.ts +15 -0
  86. package/dist/components/FilterSelectionView.d.ts.map +1 -0
  87. package/dist/components/FilterSelectionView.js +27 -0
  88. package/dist/components/FilterSelectionView.js.map +1 -0
  89. package/dist/components/GoogleDocsBrowserView.d.ts +20 -0
  90. package/dist/components/GoogleDocsBrowserView.d.ts.map +1 -0
  91. package/dist/components/GoogleDocsBrowserView.js +72 -0
  92. package/dist/components/GoogleDocsBrowserView.js.map +1 -0
  93. package/dist/components/HandoffBrowserView.d.ts +20 -0
  94. package/dist/components/HandoffBrowserView.d.ts.map +1 -0
  95. package/dist/components/HandoffBrowserView.js +66 -0
  96. package/dist/components/HandoffBrowserView.js.map +1 -0
  97. package/dist/components/Header.d.ts +14 -0
  98. package/dist/components/Header.d.ts.map +1 -0
  99. package/dist/components/Header.js +16 -0
  100. package/dist/components/Header.js.map +1 -0
  101. package/dist/components/HorizontalMenu.d.ts +24 -0
  102. package/dist/components/HorizontalMenu.d.ts.map +1 -0
  103. package/dist/components/HorizontalMenu.js +20 -0
  104. package/dist/components/HorizontalMenu.js.map +1 -0
  105. package/dist/components/ImageMascot.d.ts +8 -0
  106. package/dist/components/ImageMascot.d.ts.map +1 -0
  107. package/dist/components/ImageMascot.js +7 -0
  108. package/dist/components/ImageMascot.js.map +1 -0
  109. package/dist/components/LLMWorkingView.d.ts +19 -0
  110. package/dist/components/LLMWorkingView.d.ts.map +1 -0
  111. package/dist/components/LLMWorkingView.js +72 -0
  112. package/dist/components/LLMWorkingView.js.map +1 -0
  113. package/dist/components/LoadContextView.d.ts +22 -0
  114. package/dist/components/LoadContextView.d.ts.map +1 -0
  115. package/dist/components/LoadContextView.js +83 -0
  116. package/dist/components/LoadContextView.js.map +1 -0
  117. package/dist/components/MainMenuView.d.ts +20 -0
  118. package/dist/components/MainMenuView.d.ts.map +1 -0
  119. package/dist/components/MainMenuView.js +49 -0
  120. package/dist/components/MainMenuView.js.map +1 -0
  121. package/dist/components/Mascot.d.ts +24 -0
  122. package/dist/components/Mascot.d.ts.map +1 -0
  123. package/dist/components/Mascot.js +32 -0
  124. package/dist/components/Mascot.js.map +1 -0
  125. package/dist/components/Menu.d.ts +22 -0
  126. package/dist/components/Menu.d.ts.map +1 -0
  127. package/dist/components/Menu.js +28 -0
  128. package/dist/components/Menu.js.map +1 -0
  129. package/dist/components/NotionBrowserView.d.ts +21 -0
  130. package/dist/components/NotionBrowserView.d.ts.map +1 -0
  131. package/dist/components/NotionBrowserView.js +75 -0
  132. package/dist/components/NotionBrowserView.js.map +1 -0
  133. package/dist/components/ObsidianBrowserView.d.ts +21 -0
  134. package/dist/components/ObsidianBrowserView.d.ts.map +1 -0
  135. package/dist/components/ObsidianBrowserView.js +74 -0
  136. package/dist/components/ObsidianBrowserView.js.map +1 -0
  137. package/dist/components/ObsidianConfigView.d.ts +19 -0
  138. package/dist/components/ObsidianConfigView.d.ts.map +1 -0
  139. package/dist/components/ObsidianConfigView.js +45 -0
  140. package/dist/components/ObsidianConfigView.js.map +1 -0
  141. package/dist/components/PlaceholderView.d.ts +15 -0
  142. package/dist/components/PlaceholderView.d.ts.map +1 -0
  143. package/dist/components/PlaceholderView.js +20 -0
  144. package/dist/components/PlaceholderView.js.map +1 -0
  145. package/dist/components/PlanViewerView.d.ts +26 -0
  146. package/dist/components/PlanViewerView.d.ts.map +1 -0
  147. package/dist/components/PlanViewerView.js +170 -0
  148. package/dist/components/PlanViewerView.js.map +1 -0
  149. package/dist/components/ProgressBar.d.ts +24 -0
  150. package/dist/components/ProgressBar.d.ts.map +1 -0
  151. package/dist/components/ProgressBar.js +23 -0
  152. package/dist/components/ProgressBar.js.map +1 -0
  153. package/dist/components/ProjectDashboardView.d.ts +38 -0
  154. package/dist/components/ProjectDashboardView.d.ts.map +1 -0
  155. package/dist/components/ProjectDashboardView.js +129 -0
  156. package/dist/components/ProjectDashboardView.js.map +1 -0
  157. package/dist/components/SaveContextView.d.ts +32 -0
  158. package/dist/components/SaveContextView.d.ts.map +1 -0
  159. package/dist/components/SaveContextView.js +41 -0
  160. package/dist/components/SaveContextView.js.map +1 -0
  161. package/dist/components/SessionDetails.d.ts +14 -0
  162. package/dist/components/SessionDetails.d.ts.map +1 -0
  163. package/dist/components/SessionDetails.js +87 -0
  164. package/dist/components/SessionDetails.js.map +1 -0
  165. package/dist/components/SessionsExperimentView.d.ts +35 -0
  166. package/dist/components/SessionsExperimentView.d.ts.map +1 -0
  167. package/dist/components/SessionsExperimentView.js +347 -0
  168. package/dist/components/SessionsExperimentView.js.map +1 -0
  169. package/dist/components/SessionsList.d.ts +20 -0
  170. package/dist/components/SessionsList.d.ts.map +1 -0
  171. package/dist/components/SessionsList.js +75 -0
  172. package/dist/components/SessionsList.js.map +1 -0
  173. package/dist/components/SettingsView.d.ts +48 -0
  174. package/dist/components/SettingsView.d.ts.map +1 -0
  175. package/dist/components/SettingsView.js +156 -0
  176. package/dist/components/SettingsView.js.map +1 -0
  177. package/dist/components/SourceSelectionView.d.ts +26 -0
  178. package/dist/components/SourceSelectionView.d.ts.map +1 -0
  179. package/dist/components/SourceSelectionView.js +109 -0
  180. package/dist/components/SourceSelectionView.js.map +1 -0
  181. package/dist/components/VerticalMenu.d.ts +18 -0
  182. package/dist/components/VerticalMenu.d.ts.map +1 -0
  183. package/dist/components/VerticalMenu.js +15 -0
  184. package/dist/components/VerticalMenu.js.map +1 -0
  185. package/dist/components/ascii-art/index.d.ts +6 -0
  186. package/dist/components/ascii-art/index.d.ts.map +1 -0
  187. package/dist/components/ascii-art/index.js +6 -0
  188. package/dist/components/ascii-art/index.js.map +1 -0
  189. package/dist/components/ascii-art/progress.d.ts +53 -0
  190. package/dist/components/ascii-art/progress.d.ts.map +1 -0
  191. package/dist/components/ascii-art/progress.js +102 -0
  192. package/dist/components/ascii-art/progress.js.map +1 -0
  193. package/dist/components/ascii-art/scene.d.ts +34 -0
  194. package/dist/components/ascii-art/scene.d.ts.map +1 -0
  195. package/dist/components/ascii-art/scene.js +72 -0
  196. package/dist/components/ascii-art/scene.js.map +1 -0
  197. package/dist/components/index.d.ts +27 -0
  198. package/dist/components/index.d.ts.map +1 -0
  199. package/dist/components/index.js +25 -0
  200. package/dist/components/index.js.map +1 -0
  201. package/dist/components/layout/HorizontalLayout.d.ts +19 -0
  202. package/dist/components/layout/HorizontalLayout.d.ts.map +1 -0
  203. package/dist/components/layout/HorizontalLayout.js +62 -0
  204. package/dist/components/layout/HorizontalLayout.js.map +1 -0
  205. package/dist/components/layout/VerticalLayout.d.ts +16 -0
  206. package/dist/components/layout/VerticalLayout.d.ts.map +1 -0
  207. package/dist/components/layout/VerticalLayout.js +32 -0
  208. package/dist/components/layout/VerticalLayout.js.map +1 -0
  209. package/dist/components/layout/index.d.ts +6 -0
  210. package/dist/components/layout/index.d.ts.map +1 -0
  211. package/dist/components/layout/index.js +4 -0
  212. package/dist/components/layout/index.js.map +1 -0
  213. package/dist/components/layout/theme.d.ts +20 -0
  214. package/dist/components/layout/theme.d.ts.map +1 -0
  215. package/dist/components/layout/theme.js +23 -0
  216. package/dist/components/layout/theme.js.map +1 -0
  217. package/dist/components/setup/DoneStep.d.ts +7 -0
  218. package/dist/components/setup/DoneStep.d.ts.map +1 -0
  219. package/dist/components/setup/DoneStep.js +31 -0
  220. package/dist/components/setup/DoneStep.js.map +1 -0
  221. package/dist/components/setup/InstallingStep.d.ts +11 -0
  222. package/dist/components/setup/InstallingStep.d.ts.map +1 -0
  223. package/dist/components/setup/InstallingStep.js +27 -0
  224. package/dist/components/setup/InstallingStep.js.map +1 -0
  225. package/dist/components/setup/OptionsStep.d.ts +9 -0
  226. package/dist/components/setup/OptionsStep.d.ts.map +1 -0
  227. package/dist/components/setup/OptionsStep.js +39 -0
  228. package/dist/components/setup/OptionsStep.js.map +1 -0
  229. package/dist/components/setup/PrerequisitesStep.d.ts +7 -0
  230. package/dist/components/setup/PrerequisitesStep.d.ts.map +1 -0
  231. package/dist/components/setup/PrerequisitesStep.js +31 -0
  232. package/dist/components/setup/PrerequisitesStep.js.map +1 -0
  233. package/dist/components/setup/SetupFrame.d.ts +17 -0
  234. package/dist/components/setup/SetupFrame.d.ts.map +1 -0
  235. package/dist/components/setup/SetupFrame.js +33 -0
  236. package/dist/components/setup/SetupFrame.js.map +1 -0
  237. package/dist/components/setup/SetupWizard.d.ts +9 -0
  238. package/dist/components/setup/SetupWizard.d.ts.map +1 -0
  239. package/dist/components/setup/SetupWizard.js +149 -0
  240. package/dist/components/setup/SetupWizard.js.map +1 -0
  241. package/dist/components/setup/Spinner.d.ts +10 -0
  242. package/dist/components/setup/Spinner.d.ts.map +1 -0
  243. package/dist/components/setup/Spinner.js +20 -0
  244. package/dist/components/setup/Spinner.js.map +1 -0
  245. package/dist/components/setup/SyncStep.d.ts +11 -0
  246. package/dist/components/setup/SyncStep.d.ts.map +1 -0
  247. package/dist/components/setup/SyncStep.js +47 -0
  248. package/dist/components/setup/SyncStep.js.map +1 -0
  249. package/dist/components/setup/VerificationStep.d.ts +7 -0
  250. package/dist/components/setup/VerificationStep.d.ts.map +1 -0
  251. package/dist/components/setup/VerificationStep.js +27 -0
  252. package/dist/components/setup/VerificationStep.js.map +1 -0
  253. package/dist/components/setup/WelcomeStep.d.ts +6 -0
  254. package/dist/components/setup/WelcomeStep.d.ts.map +1 -0
  255. package/dist/components/setup/WelcomeStep.js +17 -0
  256. package/dist/components/setup/WelcomeStep.js.map +1 -0
  257. package/dist/components/shared/ProgressLine.d.ts +10 -0
  258. package/dist/components/shared/ProgressLine.d.ts.map +1 -0
  259. package/dist/components/shared/ProgressLine.js +18 -0
  260. package/dist/components/shared/ProgressLine.js.map +1 -0
  261. package/dist/components/shared/ProjectLine.d.ts +10 -0
  262. package/dist/components/shared/ProjectLine.d.ts.map +1 -0
  263. package/dist/components/shared/ProjectLine.js +19 -0
  264. package/dist/components/shared/ProjectLine.js.map +1 -0
  265. package/dist/components/shared/ScanningIndicator.d.ts +9 -0
  266. package/dist/components/shared/ScanningIndicator.d.ts.map +1 -0
  267. package/dist/components/shared/ScanningIndicator.js +22 -0
  268. package/dist/components/shared/ScanningIndicator.js.map +1 -0
  269. package/dist/components/shared/StatusLine.d.ts +13 -0
  270. package/dist/components/shared/StatusLine.d.ts.map +1 -0
  271. package/dist/components/shared/StatusLine.js +24 -0
  272. package/dist/components/shared/StatusLine.js.map +1 -0
  273. package/dist/components/shared/StatusLine.test.d.ts +8 -0
  274. package/dist/components/shared/StatusLine.test.d.ts.map +1 -0
  275. package/dist/components/shared/StatusLine.test.js +50 -0
  276. package/dist/components/shared/StatusLine.test.js.map +1 -0
  277. package/dist/components/shared/index.d.ts +4 -0
  278. package/dist/components/shared/index.d.ts.map +1 -0
  279. package/dist/components/shared/index.js +4 -0
  280. package/dist/components/shared/index.js.map +1 -0
  281. package/dist/handoff/catalog.test.d.ts +5 -0
  282. package/dist/handoff/catalog.test.d.ts.map +1 -0
  283. package/dist/handoff/catalog.test.js +172 -0
  284. package/dist/handoff/catalog.test.js.map +1 -0
  285. package/dist/handoff/subagents.test.d.ts +8 -0
  286. package/dist/handoff/subagents.test.d.ts.map +1 -0
  287. package/dist/handoff/subagents.test.js +139 -0
  288. package/dist/handoff/subagents.test.js.map +1 -0
  289. package/dist/hooks/useAddContextFlow.d.ts +29 -0
  290. package/dist/hooks/useAddContextFlow.d.ts.map +1 -0
  291. package/dist/hooks/useAddContextFlow.js +83 -0
  292. package/dist/hooks/useAddContextFlow.js.map +1 -0
  293. package/dist/hooks/useArchiveBrowser.d.ts +37 -0
  294. package/dist/hooks/useArchiveBrowser.d.ts.map +1 -0
  295. package/dist/hooks/useArchiveBrowser.js +175 -0
  296. package/dist/hooks/useArchiveBrowser.js.map +1 -0
  297. package/dist/hooks/useClaudeToken.d.ts +29 -0
  298. package/dist/hooks/useClaudeToken.d.ts.map +1 -0
  299. package/dist/hooks/useClaudeToken.js +166 -0
  300. package/dist/hooks/useClaudeToken.js.map +1 -0
  301. package/dist/hooks/useGoogleDocsBrowser.d.ts +29 -0
  302. package/dist/hooks/useGoogleDocsBrowser.d.ts.map +1 -0
  303. package/dist/hooks/useGoogleDocsBrowser.js +146 -0
  304. package/dist/hooks/useGoogleDocsBrowser.js.map +1 -0
  305. package/dist/hooks/useHandoffBrowser.d.ts +27 -0
  306. package/dist/hooks/useHandoffBrowser.d.ts.map +1 -0
  307. package/dist/hooks/useHandoffBrowser.js +92 -0
  308. package/dist/hooks/useHandoffBrowser.js.map +1 -0
  309. package/dist/hooks/useJacquesClient.d.ts +69 -0
  310. package/dist/hooks/useJacquesClient.d.ts.map +1 -0
  311. package/dist/hooks/useJacquesClient.js +248 -0
  312. package/dist/hooks/useJacquesClient.js.map +1 -0
  313. package/dist/hooks/useLlmWorking.d.ts +30 -0
  314. package/dist/hooks/useLlmWorking.d.ts.map +1 -0
  315. package/dist/hooks/useLlmWorking.js +127 -0
  316. package/dist/hooks/useLlmWorking.js.map +1 -0
  317. package/dist/hooks/useLoadContext.d.ts +27 -0
  318. package/dist/hooks/useLoadContext.d.ts.map +1 -0
  319. package/dist/hooks/useLoadContext.js +102 -0
  320. package/dist/hooks/useLoadContext.js.map +1 -0
  321. package/dist/hooks/useNotification.d.ts +36 -0
  322. package/dist/hooks/useNotification.d.ts.map +1 -0
  323. package/dist/hooks/useNotification.js +89 -0
  324. package/dist/hooks/useNotification.js.map +1 -0
  325. package/dist/hooks/useNotification.test.d.ts +9 -0
  326. package/dist/hooks/useNotification.test.d.ts.map +1 -0
  327. package/dist/hooks/useNotification.test.js +144 -0
  328. package/dist/hooks/useNotification.test.js.map +1 -0
  329. package/dist/hooks/useNotionBrowser.d.ts +30 -0
  330. package/dist/hooks/useNotionBrowser.d.ts.map +1 -0
  331. package/dist/hooks/useNotionBrowser.js +154 -0
  332. package/dist/hooks/useNotionBrowser.js.map +1 -0
  333. package/dist/hooks/useObsidianBrowser.d.ts +42 -0
  334. package/dist/hooks/useObsidianBrowser.d.ts.map +1 -0
  335. package/dist/hooks/useObsidianBrowser.js +63 -0
  336. package/dist/hooks/useObsidianBrowser.js.map +1 -0
  337. package/dist/hooks/useObsidianConfig.d.ts +28 -0
  338. package/dist/hooks/useObsidianConfig.d.ts.map +1 -0
  339. package/dist/hooks/useObsidianConfig.js +119 -0
  340. package/dist/hooks/useObsidianConfig.js.map +1 -0
  341. package/dist/hooks/useObsidianFileBrowser.d.ts +29 -0
  342. package/dist/hooks/useObsidianFileBrowser.d.ts.map +1 -0
  343. package/dist/hooks/useObsidianFileBrowser.js +114 -0
  344. package/dist/hooks/useObsidianFileBrowser.js.map +1 -0
  345. package/dist/hooks/useProjectDashboard.d.ts +38 -0
  346. package/dist/hooks/useProjectDashboard.d.ts.map +1 -0
  347. package/dist/hooks/useProjectDashboard.js +224 -0
  348. package/dist/hooks/useProjectDashboard.js.map +1 -0
  349. package/dist/hooks/useProjectSelector.d.ts +17 -0
  350. package/dist/hooks/useProjectSelector.d.ts.map +1 -0
  351. package/dist/hooks/useProjectSelector.js +43 -0
  352. package/dist/hooks/useProjectSelector.js.map +1 -0
  353. package/dist/hooks/useProjectSelector.test.d.ts +7 -0
  354. package/dist/hooks/useProjectSelector.test.d.ts.map +1 -0
  355. package/dist/hooks/useProjectSelector.test.js +117 -0
  356. package/dist/hooks/useProjectSelector.test.js.map +1 -0
  357. package/dist/hooks/useSaveFlow.d.ts +30 -0
  358. package/dist/hooks/useSaveFlow.d.ts.map +1 -0
  359. package/dist/hooks/useSaveFlow.js +195 -0
  360. package/dist/hooks/useSaveFlow.js.map +1 -0
  361. package/dist/hooks/useSessions.test.d.ts +7 -0
  362. package/dist/hooks/useSessions.test.d.ts.map +1 -0
  363. package/dist/hooks/useSessions.test.js +153 -0
  364. package/dist/hooks/useSessions.test.js.map +1 -0
  365. package/dist/hooks/useSessionsExperiment.d.ts +97 -0
  366. package/dist/hooks/useSessionsExperiment.d.ts.map +1 -0
  367. package/dist/hooks/useSessionsExperiment.js +321 -0
  368. package/dist/hooks/useSessionsExperiment.js.map +1 -0
  369. package/dist/hooks/useSettings.d.ts +47 -0
  370. package/dist/hooks/useSettings.d.ts.map +1 -0
  371. package/dist/hooks/useSettings.js +245 -0
  372. package/dist/hooks/useSettings.js.map +1 -0
  373. package/dist/hooks/useSetupWizard.d.ts +35 -0
  374. package/dist/hooks/useSetupWizard.d.ts.map +1 -0
  375. package/dist/hooks/useSetupWizard.js +438 -0
  376. package/dist/hooks/useSetupWizard.js.map +1 -0
  377. package/dist/hooks/useUsageLimits.d.ts +24 -0
  378. package/dist/hooks/useUsageLimits.d.ts.map +1 -0
  379. package/dist/hooks/useUsageLimits.js +58 -0
  380. package/dist/hooks/useUsageLimits.js.map +1 -0
  381. package/dist/hooks/useUsageLimits.test.d.ts +7 -0
  382. package/dist/hooks/useUsageLimits.test.d.ts.map +1 -0
  383. package/dist/hooks/useUsageLimits.test.js +136 -0
  384. package/dist/hooks/useUsageLimits.test.js.map +1 -0
  385. package/dist/hooks/useWorktrees.d.ts +28 -0
  386. package/dist/hooks/useWorktrees.d.ts.map +1 -0
  387. package/dist/hooks/useWorktrees.js +57 -0
  388. package/dist/hooks/useWorktrees.js.map +1 -0
  389. package/dist/hooks/useWorktrees.test.d.ts +7 -0
  390. package/dist/hooks/useWorktrees.test.d.ts.map +1 -0
  391. package/dist/hooks/useWorktrees.test.js +119 -0
  392. package/dist/hooks/useWorktrees.test.js.map +1 -0
  393. package/dist/templates/compact-prompt.d.ts +16 -0
  394. package/dist/templates/compact-prompt.d.ts.map +1 -0
  395. package/dist/templates/compact-prompt.js +47 -0
  396. package/dist/templates/compact-prompt.js.map +1 -0
  397. package/dist/templates/context-skill.d.ts +8 -0
  398. package/dist/templates/context-skill.d.ts.map +1 -0
  399. package/dist/templates/context-skill.js +42 -0
  400. package/dist/templates/context-skill.js.map +1 -0
  401. package/dist/types.d.ts +127 -0
  402. package/dist/types.d.ts.map +1 -0
  403. package/dist/types.js +8 -0
  404. package/dist/types.js.map +1 -0
  405. package/dist/utils/activity.d.ts +17 -0
  406. package/dist/utils/activity.d.ts.map +1 -0
  407. package/dist/utils/activity.js +78 -0
  408. package/dist/utils/activity.js.map +1 -0
  409. package/dist/utils/bottom-controls.d.ts +24 -0
  410. package/dist/utils/bottom-controls.d.ts.map +1 -0
  411. package/dist/utils/bottom-controls.js +29 -0
  412. package/dist/utils/bottom-controls.js.map +1 -0
  413. package/dist/utils/clipboard.d.ts +2 -0
  414. package/dist/utils/clipboard.d.ts.map +1 -0
  415. package/dist/utils/clipboard.js +20 -0
  416. package/dist/utils/clipboard.js.map +1 -0
  417. package/dist/utils/constants.d.ts +6 -0
  418. package/dist/utils/constants.d.ts.map +1 -0
  419. package/dist/utils/constants.js +6 -0
  420. package/dist/utils/constants.js.map +1 -0
  421. package/dist/utils/format.d.ts +17 -0
  422. package/dist/utils/format.d.ts.map +1 -0
  423. package/dist/utils/format.js +31 -0
  424. package/dist/utils/format.js.map +1 -0
  425. package/dist/utils/session-mode.d.ts +14 -0
  426. package/dist/utils/session-mode.d.ts.map +1 -0
  427. package/dist/utils/session-mode.js +29 -0
  428. package/dist/utils/session-mode.js.map +1 -0
  429. package/dist/utils/session-mode.test.d.ts +7 -0
  430. package/dist/utils/session-mode.test.d.ts.map +1 -0
  431. package/dist/utils/session-mode.test.js +102 -0
  432. package/dist/utils/session-mode.test.js.map +1 -0
  433. package/dist/utils/sessions-items-builder.d.ts +29 -0
  434. package/dist/utils/sessions-items-builder.d.ts.map +1 -0
  435. package/dist/utils/sessions-items-builder.js +394 -0
  436. package/dist/utils/sessions-items-builder.js.map +1 -0
  437. package/dist/utils/settings.d.ts +100 -0
  438. package/dist/utils/settings.d.ts.map +1 -0
  439. package/dist/utils/settings.js +206 -0
  440. package/dist/utils/settings.js.map +1 -0
  441. package/dist/websocket-client.d.ts +70 -0
  442. package/dist/websocket-client.d.ts.map +1 -0
  443. package/dist/websocket-client.js +188 -0
  444. package/dist/websocket-client.js.map +1 -0
  445. package/hooks/adapters/__init__.py +17 -0
  446. package/hooks/adapters/__pycache__/__init__.cpython-311.pyc +0 -0
  447. package/hooks/adapters/__pycache__/__init__.cpython-313.pyc +0 -0
  448. package/hooks/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  449. package/hooks/adapters/__pycache__/base.cpython-311.pyc +0 -0
  450. package/hooks/adapters/__pycache__/base.cpython-313.pyc +0 -0
  451. package/hooks/adapters/__pycache__/base.cpython-314.pyc +0 -0
  452. package/hooks/adapters/__pycache__/calibration.cpython-311.pyc +0 -0
  453. package/hooks/adapters/__pycache__/calibration.cpython-313.pyc +0 -0
  454. package/hooks/adapters/__pycache__/calibration.cpython-314.pyc +0 -0
  455. package/hooks/adapters/__pycache__/claude_code.cpython-311.pyc +0 -0
  456. package/hooks/adapters/__pycache__/claude_code.cpython-313.pyc +0 -0
  457. package/hooks/adapters/__pycache__/claude_code.cpython-314.pyc +0 -0
  458. package/hooks/adapters/__pycache__/cursor.cpython-311.pyc +0 -0
  459. package/hooks/adapters/__pycache__/cursor.cpython-313.pyc +0 -0
  460. package/hooks/adapters/__pycache__/cursor.cpython-314.pyc +0 -0
  461. package/hooks/adapters/__pycache__/skills.cpython-311.pyc +0 -0
  462. package/hooks/adapters/__pycache__/skills.cpython-313.pyc +0 -0
  463. package/hooks/adapters/__pycache__/skills.cpython-314.pyc +0 -0
  464. package/hooks/adapters/__pycache__/test_adapters.cpython-311-pytest-9.0.2.pyc +0 -0
  465. package/hooks/adapters/__pycache__/test_adapters.cpython-313.pyc +0 -0
  466. package/hooks/adapters/__pycache__/test_calibration.cpython-311-pytest-9.0.2.pyc +0 -0
  467. package/hooks/adapters/__pycache__/test_skills.cpython-311-pytest-9.0.2.pyc +0 -0
  468. package/hooks/adapters/__pycache__/test_tokenizer.cpython-311-pytest-9.0.2.pyc +0 -0
  469. package/hooks/adapters/__pycache__/tokenizer.cpython-311.pyc +0 -0
  470. package/hooks/adapters/__pycache__/tokenizer.cpython-313.pyc +0 -0
  471. package/hooks/adapters/__pycache__/tokenizer.cpython-314.pyc +0 -0
  472. package/hooks/adapters/base.py +459 -0
  473. package/hooks/adapters/calibration.py +236 -0
  474. package/hooks/adapters/claude_code.py +316 -0
  475. package/hooks/adapters/context_parser.py +288 -0
  476. package/hooks/adapters/cursor.py +258 -0
  477. package/hooks/adapters/skills.py +160 -0
  478. package/hooks/adapters/template.py +281 -0
  479. package/hooks/adapters/test_adapters.py +516 -0
  480. package/hooks/adapters/test_calibration.py +235 -0
  481. package/hooks/adapters/test_skills.py +162 -0
  482. package/hooks/adapters/test_tokenizer.py +158 -0
  483. package/hooks/adapters/tokenizer.py +192 -0
  484. package/hooks/claude-code/pre-tool-use.py +36 -0
  485. package/hooks/claude-code/register-session.py +35 -0
  486. package/hooks/claude-code/report-activity.py +32 -0
  487. package/hooks/claude-code/session-idle.py +32 -0
  488. package/hooks/claude-code/statusline.sh +91 -0
  489. package/hooks/claude-code/unregister-session.py +32 -0
  490. package/hooks/cursor/README.md +61 -0
  491. package/hooks/cursor/after-agent-response.py +97 -0
  492. package/hooks/cursor/hooks.json.template +30 -0
  493. package/hooks/cursor/post-tool-use.py +32 -0
  494. package/hooks/cursor/pre-compact.py +61 -0
  495. package/hooks/cursor/session-end.py +32 -0
  496. package/hooks/cursor/session-start.py +66 -0
  497. package/hooks/git-detect.sh +47 -0
  498. package/hooks/install.py +441 -0
  499. package/hooks/jacques-register-session.py +286 -0
  500. package/hooks/jacques-report-activity.py +145 -0
  501. package/hooks/jacques-session-idle.py +57 -0
  502. package/hooks/jacques-unregister-session.py +57 -0
  503. package/hooks/requirements.txt +9 -0
  504. package/hooks/statusline.py +457 -0
  505. package/hooks/statusline.sh +212 -0
  506. package/package.json +63 -0
  507. package/skills/jacques-continue/SKILL.md +87 -0
  508. package/skills/jacques-handoff/SKILL.md +147 -0
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ pre-compact.py - Receive Cursor context metrics and calibrate estimates
4
+
5
+ Called on Cursor's preCompact hook.
6
+ This is the KEY hook that provides context usage metrics for Cursor!
7
+
8
+ The preCompact event fires when Cursor is about to compact the context,
9
+ and contains valuable information about current context window usage.
10
+
11
+ Additionally, this hook calibrates token estimation by comparing
12
+ actual metrics with previous estimates.
13
+ """
14
+ import sys
15
+ from pathlib import Path
16
+
17
+ # Add parent directory to path for adapter imports
18
+ sys.path.insert(0, str(Path(__file__).parent.parent))
19
+
20
+ from adapters.cursor import CursorAdapter
21
+ from adapters import calibration
22
+
23
+
24
+ def main():
25
+ adapter = CursorAdapter()
26
+
27
+ # Parse input from stdin
28
+ input_data = adapter.parse_input()
29
+ if not input_data:
30
+ sys.exit(0)
31
+
32
+ # Debug logging (important for understanding Cursor's data format)
33
+ adapter.log_debug(input_data, 'preCompact')
34
+
35
+ # Get session ID and actual token count for calibration
36
+ session_id = input_data.get('conversation_id')
37
+ actual_tokens = input_data.get('context_tokens', 0)
38
+
39
+ if session_id and actual_tokens > 0:
40
+ # Calibrate: compare actual vs estimated
41
+ factor = calibration.calibrate_from_actual(session_id, actual_tokens)
42
+
43
+ if factor:
44
+ # Log calibration for debugging
45
+ try:
46
+ with open('/tmp/jacques-hook-debug.log', 'a') as f:
47
+ f.write(f"[calibration] session={session_id[:8]}... ")
48
+ f.write(f"actual={actual_tokens} factor={factor:.2f}\n")
49
+ except:
50
+ pass
51
+
52
+ # Build and send context_update payload (with actual values)
53
+ payload = adapter.build_pre_compact_payload(input_data)
54
+ if payload:
55
+ # Mark this as actual (not estimate) by ensuring is_estimate is False/absent
56
+ payload['is_estimate'] = False
57
+ adapter.send_event(payload, use_fallback=False)
58
+
59
+
60
+ if __name__ == '__main__':
61
+ main()
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ session-end.py - Unregister Cursor session from Jacques
4
+
5
+ Called on Cursor's sessionEnd hook.
6
+ Removes Cursor session from Jacques server.
7
+ """
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ # Add parent directory to path for adapter imports
12
+ sys.path.insert(0, str(Path(__file__).parent.parent))
13
+
14
+ from adapters.cursor import CursorAdapter
15
+
16
+
17
+ def main():
18
+ adapter = CursorAdapter()
19
+
20
+ # Parse input from stdin
21
+ input_data = adapter.parse_input()
22
+ if not input_data:
23
+ sys.exit(0)
24
+
25
+ # Build and send session_end payload
26
+ payload = adapter.build_session_end_payload(input_data)
27
+ if payload:
28
+ adapter.send_event(payload, use_fallback=False)
29
+
30
+
31
+ if __name__ == '__main__':
32
+ main()
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ session-start.py - Register Cursor session with Jacques
4
+
5
+ Called on Cursor's sessionStart hook.
6
+ Registers new Cursor Native AI session with the Jacques server.
7
+
8
+ Also sends initial context estimate based on installed skills.
9
+ Cursor injects all agent_skills into every chat context, so we estimate
10
+ that overhead to show a realistic starting percentage instead of 0%.
11
+
12
+ Typical overhead:
13
+ - 21 skills ≈ 34,000 tokens
14
+ - On 200k context (Claude): ~17% used by skills alone
15
+ """
16
+ import sys
17
+ from pathlib import Path
18
+
19
+ # Add parent directory to path for adapter imports
20
+ sys.path.insert(0, str(Path(__file__).parent.parent))
21
+
22
+ from adapters.cursor import CursorAdapter
23
+ from adapters import skills
24
+
25
+
26
+ def main():
27
+ adapter = CursorAdapter()
28
+
29
+ # Parse input from stdin
30
+ input_data = adapter.parse_input()
31
+ if not input_data:
32
+ sys.exit(0)
33
+
34
+ # Debug logging
35
+ adapter.log_debug(input_data, 'sessionStart')
36
+
37
+ # Build and send session_start payload
38
+ payload = adapter.build_session_start_payload(input_data)
39
+ if payload:
40
+ adapter.send_event(payload, use_fallback=True)
41
+
42
+ # Estimate initial context from installed skills
43
+ # Cursor injects all skills into context, so this is more accurate than 0%
44
+ model = adapter.get_model(input_data)
45
+ initial_estimate = skills.get_initial_context_estimate(model)
46
+
47
+ # Log skill overhead for debugging
48
+ try:
49
+ with open('/tmp/jacques-hook-debug.log', 'a') as f:
50
+ f.write(f"[session-start] Initial estimate: {skills.get_skills_summary()}\n")
51
+ f.write(f"[session-start] Starting at {initial_estimate['used_percentage']}%\n")
52
+ except:
53
+ pass
54
+
55
+ # Send initial context estimate (skills + system prompt overhead)
56
+ context_payload = adapter.build_context_estimate_payload(
57
+ input_data,
58
+ estimated_tokens=initial_estimate['total_initial_tokens'],
59
+ model=model,
60
+ )
61
+ if context_payload:
62
+ adapter.send_event(context_payload, use_fallback=False)
63
+
64
+
65
+ if __name__ == '__main__':
66
+ main()
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # git-detect.sh - Single source of truth for git detection
4
+ #
5
+ # Usage: git-detect.sh <project_dir>
6
+ # Outputs 3 lines:
7
+ # 1. git_branch - current branch name (empty if not git)
8
+ # 2. git_worktree - worktree basename (empty if main repo)
9
+ # 3. git_repo_root - main worktree root path (empty if not git)
10
+ #
11
+ # Detection algorithm:
12
+ # git rev-parse --abbrev-ref HEAD -> branch name
13
+ # git rev-parse --git-common-dir -> shared .git path
14
+ # Returns ".git" (relative) -> normal repo -> repo_root = project_dir
15
+ # Returns absolute path -> worktree -> repo_root = dirname(path)
16
+
17
+ project_dir="$1"
18
+
19
+ if [ -z "$project_dir" ] || [ ! -d "$project_dir" ]; then
20
+ printf '\n\n\n'
21
+ exit 0
22
+ fi
23
+
24
+ # Single git command to get both branch and common-dir
25
+ git_output=$(git -C "$project_dir" rev-parse --abbrev-ref HEAD --git-common-dir 2>/dev/null)
26
+
27
+ if [ -z "$git_output" ]; then
28
+ printf '\n\n\n'
29
+ exit 0
30
+ fi
31
+
32
+ branch=$(echo "$git_output" | sed -n '1p')
33
+ common=$(echo "$git_output" | sed -n '2p')
34
+
35
+ worktree=""
36
+ repo_root=""
37
+
38
+ if [ "$common" = ".git" ]; then
39
+ # Normal repo (not a worktree) - resolve to absolute path
40
+ repo_root=$(cd "$project_dir" && pwd)
41
+ elif [ -n "$common" ]; then
42
+ # Worktree - common dir is absolute path to shared .git
43
+ repo_root=$(dirname "$common")
44
+ worktree=$(basename "$project_dir")
45
+ fi
46
+
47
+ printf '%s\n%s\n%s\n' "$branch" "$worktree" "$repo_root"
@@ -0,0 +1,441 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ install.py - Unified installer for Jacques hooks
4
+
5
+ Installs hooks for various AI tools:
6
+ - Claude Code CLI: ~/.claude/settings.json
7
+ - Cursor Native: .cursor/hooks.json (per-project)
8
+
9
+ Usage:
10
+ python3 install.py --source claude_code # Install Claude Code hooks
11
+ python3 install.py --source cursor # Install Cursor hooks
12
+ python3 install.py --all # Install all sources
13
+ python3 install.py --list # Show available sources
14
+ python3 install.py --status # Show installation status
15
+ """
16
+ import argparse
17
+ import json
18
+ import os
19
+ import shutil
20
+ import sys
21
+ from datetime import datetime
22
+ from pathlib import Path
23
+ from typing import Optional, List, Dict, Any
24
+
25
+
26
+ # ============================================================================
27
+ # Configuration
28
+ # ============================================================================
29
+
30
+ JACQUES_HOME = Path.home() / '.jacques'
31
+ HOOKS_DIR = JACQUES_HOME / 'hooks'
32
+ SCRIPT_DIR = Path(__file__).parent
33
+
34
+ SOURCES = {
35
+ 'claude_code': {
36
+ 'name': 'Claude Code CLI',
37
+ 'description': 'Claude Code CLI (standalone or in Cursor terminal)',
38
+ 'config_path': Path.home() / '.claude' / 'settings.json',
39
+ 'hooks_subdir': 'claude-code',
40
+ 'hooks': {
41
+ 'SessionStart': 'register-session.py',
42
+ 'PreToolUse': 'pre-tool-use.py',
43
+ 'PostToolUse': 'report-activity.py',
44
+ 'Stop': 'session-idle.py',
45
+ 'SessionEnd': 'unregister-session.py',
46
+ },
47
+ 'statusline': 'statusline.sh',
48
+ },
49
+ 'cursor': {
50
+ 'name': 'Cursor Native',
51
+ 'description': 'Cursor Native AI (sidebar chat)',
52
+ 'config_template': SCRIPT_DIR / 'cursor' / 'hooks.json.template',
53
+ 'hooks_subdir': 'cursor',
54
+ 'hooks': {
55
+ 'sessionStart': 'session-start.py',
56
+ 'sessionEnd': 'session-end.py',
57
+ 'postToolUse': 'post-tool-use.py',
58
+ 'preCompact': 'pre-compact.py',
59
+ },
60
+ },
61
+ }
62
+
63
+
64
+ # ============================================================================
65
+ # Utility Functions
66
+ # ============================================================================
67
+
68
+ def log(message: str, level: str = 'info') -> None:
69
+ """Print a log message with color."""
70
+ colors = {
71
+ 'info': '\033[0m', # Default
72
+ 'success': '\033[92m', # Green
73
+ 'warning': '\033[93m', # Yellow
74
+ 'error': '\033[91m', # Red
75
+ }
76
+ reset = '\033[0m'
77
+ color = colors.get(level, colors['info'])
78
+ prefix = {
79
+ 'info': ' ',
80
+ 'success': '✓ ',
81
+ 'warning': '⚠ ',
82
+ 'error': '✗ ',
83
+ }.get(level, ' ')
84
+ print(f"{color}{prefix}{message}{reset}")
85
+
86
+
87
+ def backup_file(path: Path) -> Optional[Path]:
88
+ """Create a backup of a file. Returns backup path or None if file doesn't exist."""
89
+ if not path.exists():
90
+ return None
91
+
92
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
93
+ backup_path = path.parent / f"{path.name}.backup_{timestamp}"
94
+ shutil.copy2(path, backup_path)
95
+ log(f"Backed up {path} → {backup_path}", 'info')
96
+ return backup_path
97
+
98
+
99
+ def ensure_directory(path: Path) -> None:
100
+ """Create directory if it doesn't exist."""
101
+ path.mkdir(parents=True, exist_ok=True)
102
+
103
+
104
+ # ============================================================================
105
+ # Installation Functions
106
+ # ============================================================================
107
+
108
+ def install_hook_files(source: str) -> bool:
109
+ """
110
+ Install hook files to ~/.jacques/hooks/{source}/
111
+
112
+ Returns True if successful.
113
+ """
114
+ config = SOURCES[source]
115
+ hooks_subdir = config['hooks_subdir']
116
+
117
+ # Source and destination directories
118
+ src_dir = SCRIPT_DIR / hooks_subdir
119
+ dst_dir = HOOKS_DIR / hooks_subdir
120
+ adapters_src = SCRIPT_DIR / 'adapters'
121
+ adapters_dst = HOOKS_DIR / 'adapters'
122
+
123
+ if not src_dir.exists():
124
+ log(f"Source directory not found: {src_dir}", 'error')
125
+ return False
126
+
127
+ # Create destination directories
128
+ ensure_directory(dst_dir)
129
+ ensure_directory(adapters_dst)
130
+
131
+ # Copy adapters
132
+ log(f"Installing adapters to {adapters_dst}", 'info')
133
+ for file in adapters_src.glob('*.py'):
134
+ dst_file = adapters_dst / file.name
135
+ # Skip if source and dest are the same file (e.g., symlinks)
136
+ try:
137
+ if file.resolve() == dst_file.resolve():
138
+ log(f" Skipped {file.name} (same file)", 'info')
139
+ continue
140
+ except:
141
+ pass
142
+ shutil.copy2(file, dst_file)
143
+ log(f" Copied {file.name}", 'info')
144
+
145
+ # Copy hook files
146
+ log(f"Installing {config['name']} hooks to {dst_dir}", 'info')
147
+ for hook_name, filename in config['hooks'].items():
148
+ src_file = src_dir / filename
149
+ if src_file.exists():
150
+ dst_file = dst_dir / filename
151
+ # Skip if source and dest are the same file
152
+ try:
153
+ if src_file.resolve() == dst_file.resolve():
154
+ log(f" {hook_name} → {filename} (already linked)", 'success')
155
+ continue
156
+ except:
157
+ pass
158
+ shutil.copy2(src_file, dst_file)
159
+ # Make executable
160
+ os.chmod(dst_file, 0o755)
161
+ log(f" {hook_name} → {filename}", 'success')
162
+ else:
163
+ log(f" Missing: {filename}", 'warning')
164
+
165
+ # Copy statusline script if exists
166
+ if 'statusline' in config:
167
+ statusline_src = src_dir / config['statusline']
168
+ if statusline_src.exists():
169
+ statusline_dst = dst_dir / config['statusline']
170
+ # Skip if source and dest are the same file
171
+ try:
172
+ if statusline_src.resolve() == statusline_dst.resolve():
173
+ log(f" statusLine → {config['statusline']} (already linked)", 'success')
174
+ else:
175
+ shutil.copy2(statusline_src, statusline_dst)
176
+ os.chmod(statusline_dst, 0o755)
177
+ log(f" statusLine → {config['statusline']}", 'success')
178
+ except:
179
+ shutil.copy2(statusline_src, statusline_dst)
180
+ os.chmod(statusline_dst, 0o755)
181
+ log(f" statusLine → {config['statusline']}", 'success')
182
+
183
+ return True
184
+
185
+
186
+ def install_claude_code() -> bool:
187
+ """
188
+ Install Claude Code hooks by updating ~/.claude/settings.json
189
+
190
+ Returns True if successful.
191
+ """
192
+ # First, install hook files
193
+ if not install_hook_files('claude_code'):
194
+ return False
195
+
196
+ config = SOURCES['claude_code']
197
+ settings_path = config['config_path']
198
+
199
+ # Load or create settings
200
+ settings: Dict[str, Any] = {}
201
+ if settings_path.exists():
202
+ backup_file(settings_path)
203
+ try:
204
+ with open(settings_path, 'r') as f:
205
+ settings = json.load(f)
206
+ except json.JSONDecodeError:
207
+ log(f"Invalid JSON in {settings_path}, creating new", 'warning')
208
+ settings = {}
209
+
210
+ # Build hooks configuration
211
+ hooks_base = str(HOOKS_DIR / config['hooks_subdir'])
212
+
213
+ hooks_config = {
214
+ 'SessionStart': [f"python3 {hooks_base}/register-session.py"],
215
+ 'PreToolUse': [f"python3 {hooks_base}/pre-tool-use.py"],
216
+ 'PostToolUse': [f"python3 {hooks_base}/report-activity.py"],
217
+ 'Stop': [f"python3 {hooks_base}/session-idle.py"],
218
+ 'SessionEnd': [f"python3 {hooks_base}/unregister-session.py"],
219
+ }
220
+
221
+ # Build statusLine configuration
222
+ statusline_path = f"{hooks_base}/statusline.sh"
223
+
224
+ # Update settings
225
+ settings['hooks'] = hooks_config
226
+ settings['statusLine'] = statusline_path
227
+
228
+ # Write settings
229
+ ensure_directory(settings_path.parent)
230
+ with open(settings_path, 'w') as f:
231
+ json.dump(settings, f, indent=2)
232
+
233
+ log(f"Updated {settings_path}", 'success')
234
+ log("Claude Code hooks installed successfully!", 'success')
235
+
236
+ return True
237
+
238
+
239
+ def install_cursor(project_path: Optional[Path] = None) -> bool:
240
+ """
241
+ Install Cursor hooks by copying hooks.json template.
242
+
243
+ Args:
244
+ project_path: Optional project directory. If not provided, installs globally.
245
+
246
+ Returns True if successful.
247
+ """
248
+ # First, install hook files
249
+ if not install_hook_files('cursor'):
250
+ return False
251
+
252
+ config = SOURCES['cursor']
253
+ template_path = config['config_template']
254
+
255
+ if not template_path.exists():
256
+ log(f"Template not found: {template_path}", 'error')
257
+ return False
258
+
259
+ # Determine destination
260
+ if project_path:
261
+ dest_path = project_path / '.cursor' / 'hooks.json'
262
+ else:
263
+ # Print instructions for manual installation
264
+ log("Cursor hooks installed to ~/.jacques/hooks/cursor/", 'success')
265
+ log("", 'info')
266
+ log("To enable for a project, copy the template:", 'info')
267
+ log(f" cp {template_path} /path/to/project/.cursor/hooks.json", 'info')
268
+ log("", 'info')
269
+ log("Or copy to current directory:", 'info')
270
+ log(f" mkdir -p .cursor && cp {template_path} .cursor/hooks.json", 'info')
271
+ return True
272
+
273
+ # Copy template
274
+ ensure_directory(dest_path.parent)
275
+ if dest_path.exists():
276
+ backup_file(dest_path)
277
+
278
+ shutil.copy2(template_path, dest_path)
279
+ log(f"Installed hooks to {dest_path}", 'success')
280
+ log("Cursor hooks installed successfully!", 'success')
281
+
282
+ return True
283
+
284
+
285
+ def install_source(source: str, project_path: Optional[Path] = None) -> bool:
286
+ """Install hooks for a specific source."""
287
+ if source not in SOURCES:
288
+ log(f"Unknown source: {source}", 'error')
289
+ log(f"Available sources: {', '.join(SOURCES.keys())}", 'info')
290
+ return False
291
+
292
+ log(f"Installing {SOURCES[source]['name']} hooks...", 'info')
293
+
294
+ if source == 'claude_code':
295
+ return install_claude_code()
296
+ elif source == 'cursor':
297
+ return install_cursor(project_path)
298
+
299
+ return False
300
+
301
+
302
+ def install_all() -> bool:
303
+ """Install all available sources."""
304
+ success = True
305
+ for source in SOURCES:
306
+ log(f"\n--- {SOURCES[source]['name']} ---", 'info')
307
+ if not install_source(source):
308
+ success = False
309
+ return success
310
+
311
+
312
+ # ============================================================================
313
+ # Status Functions
314
+ # ============================================================================
315
+
316
+ def check_status() -> None:
317
+ """Check installation status for all sources."""
318
+ log("Jacques Hook Installation Status", 'info')
319
+ log("=" * 40, 'info')
320
+
321
+ # Check ~/.jacques directory
322
+ if JACQUES_HOME.exists():
323
+ log(f"Jacques home: {JACQUES_HOME}", 'success')
324
+ else:
325
+ log(f"Jacques home not found: {JACQUES_HOME}", 'warning')
326
+
327
+ # Check adapters
328
+ adapters_dir = HOOKS_DIR / 'adapters'
329
+ if adapters_dir.exists() and (adapters_dir / 'base.py').exists():
330
+ log(f"Adapters: Installed", 'success')
331
+ else:
332
+ log(f"Adapters: Not installed", 'warning')
333
+
334
+ log("", 'info')
335
+
336
+ # Check each source
337
+ for source, config in SOURCES.items():
338
+ log(f"{config['name']}:", 'info')
339
+
340
+ # Check hooks directory
341
+ hooks_dir = HOOKS_DIR / config['hooks_subdir']
342
+ if hooks_dir.exists():
343
+ hook_count = len(list(hooks_dir.glob('*.py')))
344
+ log(f" Hooks directory: {hooks_dir} ({hook_count} files)", 'success')
345
+ else:
346
+ log(f" Hooks directory: Not found", 'warning')
347
+
348
+ # Check config file
349
+ if source == 'claude_code':
350
+ settings_path = config['config_path']
351
+ if settings_path.exists():
352
+ try:
353
+ with open(settings_path, 'r') as f:
354
+ settings = json.load(f)
355
+ if 'hooks' in settings:
356
+ log(f" Config: {settings_path} (hooks configured)", 'success')
357
+ else:
358
+ log(f" Config: {settings_path} (no hooks)", 'warning')
359
+ except:
360
+ log(f" Config: {settings_path} (invalid JSON)", 'error')
361
+ else:
362
+ log(f" Config: Not found", 'warning')
363
+
364
+ log("", 'info')
365
+
366
+
367
+ def list_sources() -> None:
368
+ """List available sources."""
369
+ log("Available Sources:", 'info')
370
+ log("=" * 40, 'info')
371
+ for source, config in SOURCES.items():
372
+ log(f" {source}: {config['description']}", 'info')
373
+
374
+
375
+ # ============================================================================
376
+ # Main
377
+ # ============================================================================
378
+
379
+ def main():
380
+ parser = argparse.ArgumentParser(
381
+ description='Install Jacques hooks for AI tools',
382
+ formatter_class=argparse.RawDescriptionHelpFormatter,
383
+ epilog="""
384
+ Examples:
385
+ python3 install.py --source claude_code Install Claude Code hooks
386
+ python3 install.py --source cursor Install Cursor hooks
387
+ python3 install.py --all Install all sources
388
+ python3 install.py --list List available sources
389
+ python3 install.py --status Show installation status
390
+ """
391
+ )
392
+
393
+ parser.add_argument(
394
+ '--source', '-s',
395
+ help='Source to install (claude_code, cursor)',
396
+ choices=list(SOURCES.keys()),
397
+ )
398
+ parser.add_argument(
399
+ '--all', '-a',
400
+ action='store_true',
401
+ help='Install all available sources',
402
+ )
403
+ parser.add_argument(
404
+ '--list', '-l',
405
+ action='store_true',
406
+ help='List available sources',
407
+ )
408
+ parser.add_argument(
409
+ '--status',
410
+ action='store_true',
411
+ help='Show installation status',
412
+ )
413
+ parser.add_argument(
414
+ '--project', '-p',
415
+ type=Path,
416
+ help='Project directory for Cursor hooks',
417
+ )
418
+
419
+ args = parser.parse_args()
420
+
421
+ if args.list:
422
+ list_sources()
423
+ return 0
424
+
425
+ if args.status:
426
+ check_status()
427
+ return 0
428
+
429
+ if args.all:
430
+ return 0 if install_all() else 1
431
+
432
+ if args.source:
433
+ return 0 if install_source(args.source, args.project) else 1
434
+
435
+ # No arguments - show help
436
+ parser.print_help()
437
+ return 0
438
+
439
+
440
+ if __name__ == '__main__':
441
+ sys.exit(main())