runwork 0.15.1 → 0.15.2

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 (403) hide show
  1. package/dist/index.js +19272 -116
  2. package/package.json +4 -4
  3. package/dist/__tests__/curl-parser.test.d.ts +0 -1
  4. package/dist/__tests__/curl-parser.test.js +0 -250
  5. package/dist/__tests__/install-scripts.test.d.ts +0 -1
  6. package/dist/__tests__/install-scripts.test.js +0 -280
  7. package/dist/__tests__/types-manager.test.d.ts +0 -1
  8. package/dist/__tests__/types-manager.test.js +0 -89
  9. package/dist/agents/__tests__/chatgpt-registry.test.d.ts +0 -1
  10. package/dist/agents/__tests__/chatgpt-registry.test.js +0 -61
  11. package/dist/agents/__tests__/claude-code-managed-block.test.d.ts +0 -1
  12. package/dist/agents/__tests__/claude-code-managed-block.test.js +0 -105
  13. package/dist/agents/__tests__/claude-code-plugin.test.d.ts +0 -1
  14. package/dist/agents/__tests__/claude-code-plugin.test.js +0 -47
  15. package/dist/agents/__tests__/claude-code-stats.test.d.ts +0 -1
  16. package/dist/agents/__tests__/claude-code-stats.test.js +0 -390
  17. package/dist/agents/__tests__/claude-desktop-memory.test.d.ts +0 -1
  18. package/dist/agents/__tests__/claude-desktop-memory.test.js +0 -154
  19. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.d.ts +0 -1
  20. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.js +0 -161
  21. package/dist/agents/__tests__/claude-desktop-plugin.test.d.ts +0 -1
  22. package/dist/agents/__tests__/claude-desktop-plugin.test.js +0 -117
  23. package/dist/agents/__tests__/claude-desktop-rpm.test.d.ts +0 -1
  24. package/dist/agents/__tests__/claude-desktop-rpm.test.js +0 -126
  25. package/dist/agents/__tests__/claude-desktop-stats.test.d.ts +0 -1
  26. package/dist/agents/__tests__/claude-desktop-stats.test.js +0 -280
  27. package/dist/agents/__tests__/codex-instructions.test.d.ts +0 -1
  28. package/dist/agents/__tests__/codex-instructions.test.js +0 -57
  29. package/dist/agents/__tests__/codex-minimum-permissions.test.d.ts +0 -1
  30. package/dist/agents/__tests__/codex-minimum-permissions.test.js +0 -82
  31. package/dist/agents/__tests__/codex-stats.test.d.ts +0 -1
  32. package/dist/agents/__tests__/codex-stats.test.js +0 -370
  33. package/dist/agents/__tests__/cursor-merge.test.d.ts +0 -1
  34. package/dist/agents/__tests__/cursor-merge.test.js +0 -66
  35. package/dist/agents/__tests__/cursor-stats.test.d.ts +0 -1
  36. package/dist/agents/__tests__/cursor-stats.test.js +0 -183
  37. package/dist/agents/__tests__/defaults-merge.test.d.ts +0 -1
  38. package/dist/agents/__tests__/defaults-merge.test.js +0 -268
  39. package/dist/agents/__tests__/detection.test.d.ts +0 -1
  40. package/dist/agents/__tests__/detection.test.js +0 -89
  41. package/dist/agents/__tests__/graceful-degradation.test.d.ts +0 -1
  42. package/dist/agents/__tests__/graceful-degradation.test.js +0 -129
  43. package/dist/agents/__tests__/instruction-hint.test.d.ts +0 -1
  44. package/dist/agents/__tests__/instruction-hint.test.js +0 -69
  45. package/dist/agents/__tests__/intro-skill.test.d.ts +0 -1
  46. package/dist/agents/__tests__/intro-skill.test.js +0 -193
  47. package/dist/agents/__tests__/schema-validation.test.d.ts +0 -1
  48. package/dist/agents/__tests__/schema-validation.test.js +0 -212
  49. package/dist/agents/__tests__/skill-slug.test.d.ts +0 -1
  50. package/dist/agents/__tests__/skill-slug.test.js +0 -77
  51. package/dist/agents/claude-code.d.ts +0 -59
  52. package/dist/agents/claude-code.js +0 -753
  53. package/dist/agents/claude-desktop-plugin-tree.d.ts +0 -59
  54. package/dist/agents/claude-desktop-plugin-tree.js +0 -143
  55. package/dist/agents/claude-desktop.d.ts +0 -47
  56. package/dist/agents/claude-desktop.js +0 -684
  57. package/dist/agents/cline.d.ts +0 -15
  58. package/dist/agents/cline.js +0 -130
  59. package/dist/agents/codex.d.ts +0 -44
  60. package/dist/agents/codex.js +0 -453
  61. package/dist/agents/conversation-skills.d.ts +0 -18
  62. package/dist/agents/conversation-skills.js +0 -229
  63. package/dist/agents/cursor.d.ts +0 -35
  64. package/dist/agents/cursor.js +0 -294
  65. package/dist/agents/default-config.d.ts +0 -30
  66. package/dist/agents/default-config.js +0 -67
  67. package/dist/agents/defaults-merge.d.ts +0 -87
  68. package/dist/agents/defaults-merge.js +0 -150
  69. package/dist/agents/detect.d.ts +0 -4
  70. package/dist/agents/detect.js +0 -67
  71. package/dist/agents/detection.d.ts +0 -18
  72. package/dist/agents/detection.js +0 -94
  73. package/dist/agents/gemini.d.ts +0 -15
  74. package/dist/agents/gemini.js +0 -122
  75. package/dist/agents/generic-adapter.d.ts +0 -25
  76. package/dist/agents/generic-adapter.js +0 -151
  77. package/dist/agents/intro-skill.d.ts +0 -45
  78. package/dist/agents/intro-skill.js +0 -447
  79. package/dist/agents/registry-data.d.ts +0 -192
  80. package/dist/agents/registry-data.js +0 -669
  81. package/dist/agents/registry.d.ts +0 -13
  82. package/dist/agents/registry.js +0 -36
  83. package/dist/agents/runtime-detection.d.ts +0 -82
  84. package/dist/agents/runtime-detection.js +0 -271
  85. package/dist/agents/session-start-hook.d.ts +0 -37
  86. package/dist/agents/session-start-hook.js +0 -159
  87. package/dist/agents/types.d.ts +0 -171
  88. package/dist/agents/types.js +0 -75
  89. package/dist/agents/utils/instruction-hint.d.ts +0 -21
  90. package/dist/agents/utils/instruction-hint.js +0 -108
  91. package/dist/agents/utils/json-config.d.ts +0 -19
  92. package/dist/agents/utils/json-config.js +0 -69
  93. package/dist/agents/utils/toml-config.d.ts +0 -8
  94. package/dist/agents/utils/toml-config.js +0 -27
  95. package/dist/agents/windsurf.d.ts +0 -14
  96. package/dist/agents/windsurf.js +0 -102
  97. package/dist/api/__tests__/client.test.d.ts +0 -1
  98. package/dist/api/__tests__/client.test.js +0 -272
  99. package/dist/api/client.d.ts +0 -326
  100. package/dist/api/client.js +0 -427
  101. package/dist/auth/__tests__/login-flow.test.d.ts +0 -1
  102. package/dist/auth/__tests__/login-flow.test.js +0 -101
  103. package/dist/auth/__tests__/store.test.d.ts +0 -1
  104. package/dist/auth/__tests__/store.test.js +0 -132
  105. package/dist/auth/login-flow.d.ts +0 -26
  106. package/dist/auth/login-flow.js +0 -137
  107. package/dist/auth/store.d.ts +0 -5
  108. package/dist/auth/store.js +0 -62
  109. package/dist/commands/__tests__/clone-args.test.d.ts +0 -1
  110. package/dist/commands/__tests__/clone-args.test.js +0 -51
  111. package/dist/commands/__tests__/clone-source-result.test.d.ts +0 -1
  112. package/dist/commands/__tests__/clone-source-result.test.js +0 -45
  113. package/dist/commands/__tests__/info-merge.test.d.ts +0 -1
  114. package/dist/commands/__tests__/info-merge.test.js +0 -55
  115. package/dist/commands/__tests__/mcp-entries.test.d.ts +0 -1
  116. package/dist/commands/__tests__/mcp-entries.test.js +0 -48
  117. package/dist/commands/__tests__/setup-persona.test.d.ts +0 -1
  118. package/dist/commands/__tests__/setup-persona.test.js +0 -31
  119. package/dist/commands/__tests__/setup.test.d.ts +0 -1
  120. package/dist/commands/__tests__/setup.test.js +0 -81
  121. package/dist/commands/__tests__/sync-redetect.test.d.ts +0 -1
  122. package/dist/commands/__tests__/sync-redetect.test.js +0 -96
  123. package/dist/commands/__tests__/sync-telemetry.test.d.ts +0 -1
  124. package/dist/commands/__tests__/sync-telemetry.test.js +0 -281
  125. package/dist/commands/__tests__/upgrade.test.d.ts +0 -1
  126. package/dist/commands/__tests__/upgrade.test.js +0 -157
  127. package/dist/commands/agents.d.ts +0 -2
  128. package/dist/commands/agents.js +0 -160
  129. package/dist/commands/api-keys.d.ts +0 -2
  130. package/dist/commands/api-keys.js +0 -95
  131. package/dist/commands/apps.d.ts +0 -2
  132. package/dist/commands/apps.js +0 -82
  133. package/dist/commands/build-plugin.d.ts +0 -2
  134. package/dist/commands/build-plugin.js +0 -135
  135. package/dist/commands/clone.d.ts +0 -60
  136. package/dist/commands/clone.js +0 -271
  137. package/dist/commands/components.d.ts +0 -2
  138. package/dist/commands/components.js +0 -43
  139. package/dist/commands/deploy.d.ts +0 -2
  140. package/dist/commands/deploy.js +0 -279
  141. package/dist/commands/dev.d.ts +0 -11
  142. package/dist/commands/dev.js +0 -1011
  143. package/dist/commands/doctor.d.ts +0 -2
  144. package/dist/commands/doctor.js +0 -230
  145. package/dist/commands/endpoints.d.ts +0 -2
  146. package/dist/commands/endpoints.js +0 -189
  147. package/dist/commands/entities.d.ts +0 -2
  148. package/dist/commands/entities.js +0 -198
  149. package/dist/commands/files.d.ts +0 -2
  150. package/dist/commands/files.js +0 -193
  151. package/dist/commands/inbox.d.ts +0 -11
  152. package/dist/commands/inbox.js +0 -60
  153. package/dist/commands/info.d.ts +0 -178
  154. package/dist/commands/info.js +0 -455
  155. package/dist/commands/init.d.ts +0 -21
  156. package/dist/commands/init.js +0 -185
  157. package/dist/commands/integrations.d.ts +0 -2
  158. package/dist/commands/integrations.js +0 -233
  159. package/dist/commands/login.d.ts +0 -2
  160. package/dist/commands/login.js +0 -44
  161. package/dist/commands/logout.d.ts +0 -2
  162. package/dist/commands/logout.js +0 -13
  163. package/dist/commands/logs.d.ts +0 -2
  164. package/dist/commands/logs.js +0 -232
  165. package/dist/commands/mcp-entries.d.ts +0 -13
  166. package/dist/commands/mcp-entries.js +0 -26
  167. package/dist/commands/mcp.d.ts +0 -2
  168. package/dist/commands/mcp.js +0 -245
  169. package/dist/commands/open.d.ts +0 -2
  170. package/dist/commands/open.js +0 -53
  171. package/dist/commands/resume.d.ts +0 -2
  172. package/dist/commands/resume.js +0 -289
  173. package/dist/commands/save-convo.d.ts +0 -8
  174. package/dist/commands/save-convo.js +0 -20
  175. package/dist/commands/schedules.d.ts +0 -2
  176. package/dist/commands/schedules.js +0 -221
  177. package/dist/commands/setup.d.ts +0 -27
  178. package/dist/commands/setup.js +0 -177
  179. package/dist/commands/share-convo.d.ts +0 -24
  180. package/dist/commands/share-convo.js +0 -167
  181. package/dist/commands/skills.d.ts +0 -2
  182. package/dist/commands/skills.js +0 -352
  183. package/dist/commands/sync-telemetry.d.ts +0 -33
  184. package/dist/commands/sync-telemetry.js +0 -186
  185. package/dist/commands/sync.d.ts +0 -37
  186. package/dist/commands/sync.js +0 -702
  187. package/dist/commands/uninstall.d.ts +0 -2
  188. package/dist/commands/uninstall.js +0 -145
  189. package/dist/commands/upgrade.d.ts +0 -14
  190. package/dist/commands/upgrade.js +0 -217
  191. package/dist/commands/validate.d.ts +0 -2
  192. package/dist/commands/validate.js +0 -89
  193. package/dist/commands/welcome.d.ts +0 -1
  194. package/dist/commands/welcome.js +0 -86
  195. package/dist/commands/workflows.d.ts +0 -2
  196. package/dist/commands/workflows.js +0 -187
  197. package/dist/deploy/__tests__/deploy-state.test.d.ts +0 -1
  198. package/dist/deploy/__tests__/deploy-state.test.js +0 -80
  199. package/dist/deploy/__tests__/deploy-status.test.d.ts +0 -1
  200. package/dist/deploy/__tests__/deploy-status.test.js +0 -41
  201. package/dist/deploy/__tests__/detach-args.test.d.ts +0 -1
  202. package/dist/deploy/__tests__/detach-args.test.js +0 -30
  203. package/dist/deploy/deploy-state.d.ts +0 -36
  204. package/dist/deploy/deploy-state.js +0 -63
  205. package/dist/deploy/deploy-status.d.ts +0 -21
  206. package/dist/deploy/deploy-status.js +0 -36
  207. package/dist/deploy/detach.d.ts +0 -32
  208. package/dist/deploy/detach.js +0 -71
  209. package/dist/dev/__tests__/attach.test.d.ts +0 -1
  210. package/dist/dev/__tests__/attach.test.js +0 -296
  211. package/dist/dev/__tests__/detach.test.d.ts +0 -1
  212. package/dist/dev/__tests__/detach.test.js +0 -404
  213. package/dist/dev/__tests__/preview-url-poller.test.d.ts +0 -1
  214. package/dist/dev/__tests__/preview-url-poller.test.js +0 -149
  215. package/dist/dev/__tests__/session.test.d.ts +0 -1
  216. package/dist/dev/__tests__/session.test.js +0 -446
  217. package/dist/dev/__tests__/startup-sync.test.d.ts +0 -1
  218. package/dist/dev/__tests__/startup-sync.test.js +0 -32
  219. package/dist/dev/__tests__/stop.test.d.ts +0 -1
  220. package/dist/dev/__tests__/stop.test.js +0 -172
  221. package/dist/dev/attach.d.ts +0 -120
  222. package/dist/dev/attach.js +0 -269
  223. package/dist/dev/detach.d.ts +0 -187
  224. package/dist/dev/detach.js +0 -292
  225. package/dist/dev/preview-url-poller.d.ts +0 -35
  226. package/dist/dev/preview-url-poller.js +0 -50
  227. package/dist/dev/session.d.ts +0 -175
  228. package/dist/dev/session.js +0 -258
  229. package/dist/dev/startup-sync.d.ts +0 -23
  230. package/dist/dev/startup-sync.js +0 -14
  231. package/dist/dev/stop.d.ts +0 -52
  232. package/dist/dev/stop.js +0 -101
  233. package/dist/devtools/registry-data.d.ts +0 -46
  234. package/dist/devtools/registry-data.js +0 -40
  235. package/dist/generated/bundled-types.d.ts +0 -1
  236. package/dist/generated/bundled-types.js +0 -46
  237. package/dist/generated/version.d.ts +0 -1
  238. package/dist/generated/version.js +0 -2
  239. package/dist/git/__tests__/auto-commit.test.d.ts +0 -1
  240. package/dist/git/__tests__/auto-commit.test.js +0 -431
  241. package/dist/git/__tests__/classify-sync-error.test.d.ts +0 -1
  242. package/dist/git/__tests__/classify-sync-error.test.js +0 -57
  243. package/dist/git/__tests__/credential-helper-e2e.test.d.ts +0 -21
  244. package/dist/git/__tests__/credential-helper-e2e.test.js +0 -195
  245. package/dist/git/__tests__/credentials.test.d.ts +0 -1
  246. package/dist/git/__tests__/credentials.test.js +0 -141
  247. package/dist/git/__tests__/deploy-guard.test.d.ts +0 -1
  248. package/dist/git/__tests__/deploy-guard.test.js +0 -61
  249. package/dist/git/__tests__/ensure-git-credential-helper.test.d.ts +0 -1
  250. package/dist/git/__tests__/ensure-git-credential-helper.test.js +0 -133
  251. package/dist/git/__tests__/ensure-runwork-remote.test.d.ts +0 -1
  252. package/dist/git/__tests__/ensure-runwork-remote.test.js +0 -109
  253. package/dist/git/__tests__/identity.test.d.ts +0 -1
  254. package/dist/git/__tests__/identity.test.js +0 -146
  255. package/dist/git/__tests__/manifest.test.d.ts +0 -1
  256. package/dist/git/__tests__/manifest.test.js +0 -446
  257. package/dist/git/__tests__/preflight-resolution.test.d.ts +0 -1
  258. package/dist/git/__tests__/preflight-resolution.test.js +0 -366
  259. package/dist/git/__tests__/preflight.test.d.ts +0 -1
  260. package/dist/git/__tests__/preflight.test.js +0 -36
  261. package/dist/git/__tests__/repo-config.test.d.ts +0 -1
  262. package/dist/git/__tests__/repo-config.test.js +0 -26
  263. package/dist/git/__tests__/sync.test.d.ts +0 -1
  264. package/dist/git/__tests__/sync.test.js +0 -405
  265. package/dist/git/auto-commit.d.ts +0 -35
  266. package/dist/git/auto-commit.js +0 -293
  267. package/dist/git/classify-sync-error.d.ts +0 -21
  268. package/dist/git/classify-sync-error.js +0 -111
  269. package/dist/git/credentials.d.ts +0 -75
  270. package/dist/git/credentials.js +0 -164
  271. package/dist/git/critical-files.d.ts +0 -20
  272. package/dist/git/critical-files.js +0 -68
  273. package/dist/git/deploy-guard.d.ts +0 -53
  274. package/dist/git/deploy-guard.js +0 -78
  275. package/dist/git/identity.d.ts +0 -44
  276. package/dist/git/identity.js +0 -133
  277. package/dist/git/preflight.d.ts +0 -57
  278. package/dist/git/preflight.js +0 -276
  279. package/dist/git/remote.d.ts +0 -37
  280. package/dist/git/remote.js +0 -75
  281. package/dist/git/repo-config.d.ts +0 -8
  282. package/dist/git/repo-config.js +0 -29
  283. package/dist/git/sync.d.ts +0 -15
  284. package/dist/git/sync.js +0 -159
  285. package/dist/health/__tests__/checks.test.d.ts +0 -1
  286. package/dist/health/__tests__/checks.test.js +0 -357
  287. package/dist/health/__tests__/cli-distribution-checks.test.d.ts +0 -1
  288. package/dist/health/__tests__/cli-distribution-checks.test.js +0 -196
  289. package/dist/health/__tests__/fix.test.d.ts +0 -1
  290. package/dist/health/__tests__/fix.test.js +0 -72
  291. package/dist/health/__tests__/runner-filter.test.d.ts +0 -1
  292. package/dist/health/__tests__/runner-filter.test.js +0 -61
  293. package/dist/health/checks.d.ts +0 -42
  294. package/dist/health/checks.js +0 -636
  295. package/dist/health/fix.d.ts +0 -22
  296. package/dist/health/fix.js +0 -62
  297. package/dist/health/runner.d.ts +0 -8
  298. package/dist/health/runner.js +0 -47
  299. package/dist/health/types.d.ts +0 -12
  300. package/dist/health/types.js +0 -1
  301. package/dist/index.d.ts +0 -1
  302. package/dist/logs/__tests__/tailer-format.test.d.ts +0 -1
  303. package/dist/logs/__tests__/tailer-format.test.js +0 -43
  304. package/dist/logs/tailer.d.ts +0 -17
  305. package/dist/logs/tailer.js +0 -217
  306. package/dist/sync/__tests__/change-detect.test.d.ts +0 -1
  307. package/dist/sync/__tests__/change-detect.test.js +0 -123
  308. package/dist/sync/__tests__/hash.test.d.ts +0 -1
  309. package/dist/sync/__tests__/hash.test.js +0 -18
  310. package/dist/sync/change-detect.d.ts +0 -19
  311. package/dist/sync/change-detect.js +0 -136
  312. package/dist/sync/conflict-ui.d.ts +0 -5
  313. package/dist/sync/conflict-ui.js +0 -78
  314. package/dist/sync/executor.d.ts +0 -23
  315. package/dist/sync/executor.js +0 -102
  316. package/dist/sync/hash.d.ts +0 -1
  317. package/dist/sync/hash.js +0 -4
  318. package/dist/sync/types.d.ts +0 -24
  319. package/dist/sync/types.js +0 -1
  320. package/dist/template/manifest.d.ts +0 -17
  321. package/dist/template/manifest.js +0 -145
  322. package/dist/tools/types.d.ts +0 -52
  323. package/dist/tools/types.js +0 -8
  324. package/dist/types-manager.d.ts +0 -1
  325. package/dist/types-manager.js +0 -35
  326. package/dist/types.d.ts +0 -349
  327. package/dist/types.js +0 -1
  328. package/dist/ui/__tests__/banner.test.d.ts +0 -1
  329. package/dist/ui/__tests__/banner.test.js +0 -98
  330. package/dist/ui/__tests__/colors.test.d.ts +0 -1
  331. package/dist/ui/__tests__/colors.test.js +0 -22
  332. package/dist/ui/__tests__/keyboard.test.d.ts +0 -1
  333. package/dist/ui/__tests__/keyboard.test.js +0 -34
  334. package/dist/ui/__tests__/status-line.test.d.ts +0 -1
  335. package/dist/ui/__tests__/status-line.test.js +0 -54
  336. package/dist/ui/banner.d.ts +0 -29
  337. package/dist/ui/banner.js +0 -153
  338. package/dist/ui/colors.d.ts +0 -4
  339. package/dist/ui/colors.js +0 -7
  340. package/dist/ui/keyboard.d.ts +0 -12
  341. package/dist/ui/keyboard.js +0 -61
  342. package/dist/ui/status-line.d.ts +0 -6
  343. package/dist/ui/status-line.js +0 -53
  344. package/dist/utils/__tests__/format-error.test.d.ts +0 -1
  345. package/dist/utils/__tests__/format-error.test.js +0 -43
  346. package/dist/utils/__tests__/help-json.test.d.ts +0 -1
  347. package/dist/utils/__tests__/help-json.test.js +0 -39
  348. package/dist/utils/__tests__/http.test.d.ts +0 -1
  349. package/dist/utils/__tests__/http.test.js +0 -381
  350. package/dist/utils/__tests__/ignore-matcher.test.d.ts +0 -1
  351. package/dist/utils/__tests__/ignore-matcher.test.js +0 -205
  352. package/dist/utils/__tests__/output.test.d.ts +0 -1
  353. package/dist/utils/__tests__/output.test.js +0 -38
  354. package/dist/utils/__tests__/prompt.test.d.ts +0 -1
  355. package/dist/utils/__tests__/prompt.test.js +0 -27
  356. package/dist/utils/__tests__/resolve.test.d.ts +0 -1
  357. package/dist/utils/__tests__/resolve.test.js +0 -95
  358. package/dist/utils/__tests__/sqlite.test.d.ts +0 -1
  359. package/dist/utils/__tests__/sqlite.test.js +0 -89
  360. package/dist/utils/agent-guidance.d.ts +0 -47
  361. package/dist/utils/agent-guidance.js +0 -128
  362. package/dist/utils/app-info.d.ts +0 -70
  363. package/dist/utils/app-info.js +0 -167
  364. package/dist/utils/curl-parser.d.ts +0 -12
  365. package/dist/utils/curl-parser.js +0 -162
  366. package/dist/utils/data-input.d.ts +0 -1
  367. package/dist/utils/data-input.js +0 -38
  368. package/dist/utils/format-error.d.ts +0 -10
  369. package/dist/utils/format-error.js +0 -38
  370. package/dist/utils/fs.d.ts +0 -5
  371. package/dist/utils/fs.js +0 -23
  372. package/dist/utils/help-json.d.ts +0 -70
  373. package/dist/utils/help-json.js +0 -88
  374. package/dist/utils/http.d.ts +0 -46
  375. package/dist/utils/http.js +0 -421
  376. package/dist/utils/ignore-matcher.d.ts +0 -47
  377. package/dist/utils/ignore-matcher.js +0 -132
  378. package/dist/utils/output.d.ts +0 -17
  379. package/dist/utils/output.js +0 -27
  380. package/dist/utils/prompt.d.ts +0 -5
  381. package/dist/utils/prompt.js +0 -42
  382. package/dist/utils/resolve.d.ts +0 -12
  383. package/dist/utils/resolve.js +0 -52
  384. package/dist/utils/setup-state.d.ts +0 -3
  385. package/dist/utils/setup-state.js +0 -19
  386. package/dist/utils/sqlite-adapter.d.ts +0 -48
  387. package/dist/utils/sqlite-adapter.js +0 -147
  388. package/dist/utils/sqlite.d.ts +0 -14
  389. package/dist/utils/sqlite.js +0 -14
  390. package/dist/utils/subprocess.d.ts +0 -19
  391. package/dist/utils/subprocess.js +0 -27
  392. package/dist/utils/which.d.ts +0 -14
  393. package/dist/utils/which.js +0 -47
  394. package/dist/utils/zip.d.ts +0 -7
  395. package/dist/utils/zip.js +0 -42
  396. package/dist/validate/__tests__/validate.test.d.ts +0 -1
  397. package/dist/validate/__tests__/validate.test.js +0 -42
  398. package/dist/validate/freshness.d.ts +0 -28
  399. package/dist/validate/freshness.js +0 -48
  400. package/dist/validate/preview.d.ts +0 -21
  401. package/dist/validate/preview.js +0 -39
  402. package/dist/workspace/resolve.d.ts +0 -19
  403. package/dist/workspace/resolve.js +0 -100
@@ -1,753 +0,0 @@
1
- import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'fs';
2
- import { join } from 'path';
3
- import { homedir, platform } from 'os';
4
- import { execFileSync } from '../utils/subprocess.js';
5
- import { whichBinary } from '../utils/which.js';
6
- import { buildSkillMd } from './types.js';
7
- import { mergeJsonMcpServers, readJsonConfig, writeJsonConfig, removeRunworkMcpServers } from './utils/json-config.js';
8
- import { writeHintToFile, writeTeamInstructionsToFile, removeHintFromFile, removeTeamInstructionsFromFile } from './utils/instruction-hint.js';
9
- import { SESSION_START_HOOK_SCRIPT } from './session-start-hook.js';
10
- import { mergeMarkerless } from './defaults-merge.js';
11
- const PLUGIN_NAME = 'runwork';
12
- const PLUGIN_VERSION = '1.0.0';
13
- /**
14
- * Legacy in-array sentinel that older CLI versions injected at the head of the
15
- * managed permission block. Claude Code >= 2.1.x validates every allow/deny
16
- * entry as a tool rule and rejects this with "matches no known tool" on
17
- * startup, so the adapter is now markerless and actively strips this marker
18
- * from any existing user's settings on their next sync.
19
- */
20
- const LEGACY_MANAGED_MARKER = '# runwork-managed';
21
- function getPluginJson() {
22
- return {
23
- name: PLUGIN_NAME,
24
- version: PLUGIN_VERSION,
25
- description: 'Skills and tools from your Runwork workspace',
26
- author: { name: 'Runwork' },
27
- homepage: 'https://www.runwork.ai',
28
- };
29
- }
30
- function getMarketplaceJson() {
31
- return {
32
- name: 'runwork',
33
- owner: { name: 'Runwork' },
34
- plugins: [
35
- {
36
- name: PLUGIN_NAME,
37
- source: `./plugins/${PLUGIN_NAME}`,
38
- description: 'Skills and tools from your Runwork workspace',
39
- },
40
- ],
41
- };
42
- }
43
- export class ClaudeCodeAdapter {
44
- name = 'Claude Code';
45
- slug = 'claude-code';
46
- mcpProvidesSkills = true;
47
- async detect() {
48
- if (whichBinary('claude'))
49
- return true;
50
- // Fallback: check app bundle on macOS
51
- if (platform() === 'darwin')
52
- return existsSync('/Applications/Claude.app');
53
- return false;
54
- }
55
- supportsMcpScope(_scope) {
56
- return true;
57
- }
58
- supportsSkills() {
59
- return true;
60
- }
61
- async writeMcpServers(servers, scope) {
62
- if (scope === 'project') {
63
- // Project scope: write to .mcp.json (standard Claude Code location)
64
- const filePath = join(process.cwd(), '.mcp.json');
65
- const entries = {};
66
- for (const s of servers) {
67
- entries[s.name] = {
68
- type: 'http',
69
- url: s.url,
70
- ...(s.headers ? { headers: s.headers } : {}),
71
- ...(s.description ? { description: s.description } : {}),
72
- };
73
- }
74
- mergeJsonMcpServers(filePath, entries, 'mcpServers');
75
- }
76
- else {
77
- // User scope: write MCP config both in global settings and inside the plugin
78
- const settingsPath = join(homedir(), '.claude', 'settings.json');
79
- const entries = {};
80
- for (const s of servers) {
81
- entries[s.name] = {
82
- type: 'http',
83
- url: s.url,
84
- ...(s.headers ? { headers: s.headers } : {}),
85
- ...(s.description ? { description: s.description } : {}),
86
- };
87
- }
88
- mergeJsonMcpServers(settingsPath, entries, 'mcpServers');
89
- // Also write .mcp.json in the plugin directory
90
- const pluginDir = this.getPluginDir();
91
- mkdirSync(pluginDir, { recursive: true });
92
- const pluginMcpPath = join(pluginDir, '.mcp.json');
93
- const marketDir = this.getMarketplaceDir();
94
- mkdirSync(marketDir, { recursive: true });
95
- const marketplaceMcpPath = join(marketDir, '.mcp.json');
96
- const pluginEntries = {};
97
- for (const s of servers) {
98
- pluginEntries[s.name] = {
99
- type: 'http',
100
- url: s.url,
101
- ...(s.headers ? { headers: s.headers } : {}),
102
- ...(s.description ? { description: s.description } : {}),
103
- };
104
- }
105
- writeJsonConfig(pluginMcpPath, pluginEntries);
106
- writeJsonConfig(marketplaceMcpPath, pluginEntries);
107
- }
108
- }
109
- /**
110
- * Install the Runwork SessionStart hook into the plugin tree (user scope).
111
- * The hook writes ~/.runwork/sessions/<sessionId>.json with the active
112
- * conversation's transcript path + metadata, used by `runwork share-convo`
113
- * for high-fidelity capture and by `runwork resume` for placement.
114
- *
115
- * Called as part of user-scope writeSkills() to keep sync flow consistent.
116
- * Emits a one-line confirmation matching the format other adapter steps
117
- * use (` [Claude Code] Installed ... (user)`) so `runwork sync` output
118
- * shows whether the hook actually landed.
119
- */
120
- installSessionStartHook(pluginDir, label) {
121
- const hooksDir = join(pluginDir, 'hooks');
122
- mkdirSync(hooksDir, { recursive: true });
123
- const scriptPath = join(hooksDir, 'on-session-start.sh');
124
- writeFileSync(scriptPath, SESSION_START_HOOK_SCRIPT);
125
- try {
126
- // Best-effort executable bit; chmod is a no-op on Windows.
127
- chmodSync(scriptPath, 0o755);
128
- }
129
- catch {
130
- /* not fatal */
131
- }
132
- const hooksManifest = {
133
- SessionStart: [
134
- { command: '${CLAUDE_PLUGIN_ROOT}/hooks/on-session-start.sh' },
135
- ],
136
- };
137
- writeFileSync(join(hooksDir, 'hooks.json'), JSON.stringify(hooksManifest, null, 2));
138
- console.log(` [Claude Code] Installed SessionStart hook (${label}) -> ${scriptPath}`);
139
- }
140
- async writeSkills(skills, scope) {
141
- // Always write to the standard skills directory (guaranteed to work)
142
- const baseDir = scope === 'project'
143
- ? join(process.cwd(), '.claude', 'skills')
144
- : join(homedir(), '.claude', 'skills');
145
- for (const skill of skills) {
146
- const skillDir = join(baseDir, skill.filename);
147
- cleanupOldSkillDir(baseDir, skill);
148
- mkdirSync(skillDir, { recursive: true });
149
- writeFileSync(join(skillDir, 'SKILL.md'), buildSkillMd(skill));
150
- }
151
- // User scope: also write as a plugin for native plugin UI support
152
- if (scope === 'user') {
153
- const pluginDir = this.getPluginDir();
154
- // Create plugin.json
155
- const pluginJsonDir = join(pluginDir, '.claude-plugin');
156
- mkdirSync(pluginJsonDir, { recursive: true });
157
- writeFileSync(join(pluginJsonDir, 'plugin.json'), JSON.stringify(getPluginJson(), null, 2));
158
- // Write skill files inside the plugin
159
- for (const skill of skills) {
160
- const skillDir = join(pluginDir, 'skills', skill.filename);
161
- cleanupOldSkillDir(join(pluginDir, 'skills'), skill);
162
- mkdirSync(skillDir, { recursive: true });
163
- writeFileSync(join(skillDir, 'SKILL.md'), buildSkillMd(skill));
164
- }
165
- // Also write to the marketplace directory
166
- const marketDir = this.getMarketplaceDir();
167
- const marketPluginJsonDir = join(marketDir, '.claude-plugin');
168
- mkdirSync(marketPluginJsonDir, { recursive: true });
169
- writeFileSync(join(marketPluginJsonDir, 'plugin.json'), JSON.stringify(getPluginJson(), null, 2));
170
- for (const skill of skills) {
171
- const skillDir = join(marketDir, 'skills', skill.filename);
172
- cleanupOldSkillDir(join(marketDir, 'skills'), skill);
173
- mkdirSync(skillDir, { recursive: true });
174
- writeFileSync(join(skillDir, 'SKILL.md'), buildSkillMd(skill));
175
- }
176
- // Register in installed_plugins.json
177
- this.registerPlugin(pluginDir);
178
- }
179
- }
180
- /**
181
- * Install the runwork SessionStart hook for Claude Code (user scope only).
182
- * Called once per sync by the main sync loop AFTER writeSkills has
183
- * populated the plugin directories. Kept separate from writeSkills because
184
- * writeSkills is also invoked per-skill by the diff executor during
185
- * push/pull, and the hook install + log line must not repeat for every
186
- * skill change.
187
- */
188
- async writeBuiltInHooks(scope) {
189
- if (scope !== 'user')
190
- return;
191
- const pluginDir = this.getPluginDir();
192
- const marketDir = this.getMarketplaceDir();
193
- if (existsSync(pluginDir)) {
194
- this.installSessionStartHook(pluginDir, 'plugin cache');
195
- }
196
- if (existsSync(marketDir)) {
197
- this.installSessionStartHook(marketDir, 'marketplace');
198
- }
199
- }
200
- async writeInstructionHint(hint, scope) {
201
- const filePath = scope === 'project'
202
- ? join(process.cwd(), '.claude', 'CLAUDE.md')
203
- : join(homedir(), '.claude', 'CLAUDE.md');
204
- writeHintToFile(filePath, hint);
205
- }
206
- async writeTeamInstructions(instructions, scope) {
207
- // Write to CLAUDE.md via markers (direct instruction file approach)
208
- const filePath = scope === 'project'
209
- ? join(process.cwd(), '.claude', 'CLAUDE.md')
210
- : join(homedir(), '.claude', 'CLAUDE.md');
211
- writeTeamInstructionsToFile(filePath, instructions);
212
- // Also write as a plugin skill (same mechanism as Claude Desktop)
213
- if (scope === 'user') {
214
- const skillContent = `---\nname: runwork-team-instructions\ndescription: Team instructions from your Runwork workspace. Always follow these guidelines.\n---\n\n${instructions}`;
215
- const pluginDir = this.getPluginDir();
216
- const marketDir = this.getMarketplaceDir();
217
- for (const dir of [
218
- join(pluginDir, 'skills', 'runwork-team-instructions'),
219
- join(marketDir, 'skills', 'runwork-team-instructions'),
220
- ]) {
221
- mkdirSync(dir, { recursive: true });
222
- writeFileSync(join(dir, 'SKILL.md'), skillContent);
223
- }
224
- }
225
- }
226
- // ── Agent config (model, permissions) ──────────────────────────────
227
- async writeAgentConfig(config, scope, baseline) {
228
- const settingsPath = scope === 'project'
229
- ? join(process.cwd(), '.claude', 'settings.json')
230
- : join(homedir(), '.claude', 'settings.json');
231
- const hadFile = existsSync(settingsPath);
232
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
233
- let settings = {};
234
- if (hadFile) {
235
- try {
236
- settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
237
- }
238
- catch { /* start fresh */ }
239
- }
240
- // Retro-fix migration: strip the legacy in-array sentinel from any existing
241
- // settings, regardless of whether we inject new rules this sync. This is
242
- // what removes the broken "# runwork-managed" entry that makes Claude Code
243
- // >= 2.1.x print "matches no known tool" on startup.
244
- if (settings.permissions && typeof settings.permissions === 'object') {
245
- for (const key of ['allow', 'deny']) {
246
- const arr = settings.permissions[key];
247
- if (Array.isArray(arr)) {
248
- settings.permissions[key] = arr.filter((x) => x !== LEGACY_MANAGED_MARKER);
249
- }
250
- }
251
- }
252
- if (config.modelPreference) {
253
- settings.model = config.modelPreference;
254
- }
255
- if (config.permissionRules) {
256
- if (!settings.permissions)
257
- settings.permissions = {};
258
- const perms = settings.permissions;
259
- // Markerless merge: subtract our previous contribution (baseline) to leave
260
- // the user's own entries intact, then append the freshly resolved set.
261
- if (config.permissionRules.allow) {
262
- perms.allow = mergeMarkerless(Array.isArray(perms.allow) ? perms.allow : [], baseline?.allow ?? [], config.permissionRules.allow);
263
- }
264
- if (config.permissionRules.deny) {
265
- perms.deny = mergeMarkerless(Array.isArray(perms.deny) ? perms.deny : [], baseline?.deny ?? [], config.permissionRules.deny);
266
- }
267
- if (config.permissionRules.defaultMode) {
268
- perms.defaultMode = config.permissionRules.defaultMode;
269
- }
270
- }
271
- // Nothing to persist and no file to clean up: avoid creating an empty file.
272
- if (!hadFile && !config.modelPreference && !config.permissionRules)
273
- return;
274
- mkdirSync(join(settingsPath, '..'), { recursive: true });
275
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
276
- }
277
- /**
278
- * Markerless adapter: removal detection relies on the `baseline`
279
- * (state.lastInjected) passed to writeAgentConfig, exactly like Cursor, since
280
- * the adapter no longer writes an on-disk sentinel to delimit its entries.
281
- * Returning undefined tells the sync loop to skip on-disk removal detection.
282
- */
283
- async readManagedBlock(_scope) {
284
- return undefined;
285
- }
286
- // ── Cleanup (uninstall) ────────────────────────────────────────────
287
- async cleanup(scope, manifest) {
288
- // 1. Remove MCP server entries
289
- if (scope === 'project') {
290
- removeRunworkMcpServers(join(process.cwd(), '.mcp.json'), 'mcpServers');
291
- }
292
- else {
293
- removeRunworkMcpServers(join(homedir(), '.claude', 'settings.json'), 'mcpServers');
294
- }
295
- // 2. Remove only skill directories that we synced (listed in manifest)
296
- const skillsDir = scope === 'project'
297
- ? join(process.cwd(), '.claude', 'skills')
298
- : join(homedir(), '.claude', 'skills');
299
- if (existsSync(skillsDir) && manifest?.skillFilenames.length) {
300
- const allowed = new Set(manifest.skillFilenames);
301
- for (const entry of readdirSync(skillsDir)) {
302
- if (!allowed.has(entry))
303
- continue;
304
- try {
305
- rmSync(join(skillsDir, entry), { recursive: true, force: true });
306
- }
307
- catch { /* best-effort */ }
308
- }
309
- }
310
- // 3. Remove instruction hints and team instructions
311
- const instructionFile = scope === 'project'
312
- ? join(process.cwd(), '.claude', 'CLAUDE.md')
313
- : join(homedir(), '.claude', 'CLAUDE.md');
314
- removeHintFromFile(instructionFile);
315
- removeTeamInstructionsFromFile(instructionFile);
316
- // 4. Remove agent config overrides (managed permission entries, model, enabledPlugins)
317
- if (scope === 'user') {
318
- const settingsPath = join(homedir(), '.claude', 'settings.json');
319
- if (existsSync(settingsPath)) {
320
- try {
321
- const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
322
- // Remove managed permission entries. Legacy installs carry the
323
- // in-array marker, so everything from the marker onward is ours.
324
- // Always also drop any stray marker so uninstall never leaves the
325
- // entry that breaks Claude Code startup.
326
- if (settings.permissions) {
327
- for (const key of ['allow', 'deny']) {
328
- const arr = settings.permissions[key];
329
- if (!Array.isArray(arr))
330
- continue;
331
- const idx = arr.indexOf(LEGACY_MANAGED_MARKER);
332
- settings.permissions[key] = (idx >= 0 ? arr.slice(0, idx) : arr)
333
- .filter((x) => x !== LEGACY_MANAGED_MARKER);
334
- }
335
- }
336
- // Remove plugin enablement
337
- if (settings.enabledPlugins) {
338
- delete settings.enabledPlugins[`${PLUGIN_NAME}@runwork`];
339
- }
340
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
341
- }
342
- catch { /* best-effort */ }
343
- }
344
- // 5. Remove plugin directories
345
- const pluginDir = this.getPluginDir();
346
- const marketRoot = this.getMarketplaceRoot();
347
- for (const dir of [pluginDir, marketRoot]) {
348
- if (existsSync(dir)) {
349
- try {
350
- rmSync(dir, { recursive: true, force: true });
351
- }
352
- catch { /* best-effort */ }
353
- }
354
- }
355
- // 6. Remove from installed_plugins.json
356
- const pluginsBase = this.getPluginsBaseDir();
357
- const installedPath = join(pluginsBase, 'installed_plugins.json');
358
- if (existsSync(installedPath)) {
359
- try {
360
- const installed = readJsonConfig(installedPath);
361
- if (installed.plugins) {
362
- delete installed.plugins[`${PLUGIN_NAME}@runwork`];
363
- writeJsonConfig(installedPath, installed);
364
- }
365
- }
366
- catch { /* best-effort */ }
367
- }
368
- // 7. Remove from known_marketplaces.json
369
- const marketplacesPath = join(pluginsBase, 'known_marketplaces.json');
370
- if (existsSync(marketplacesPath)) {
371
- try {
372
- const marketplaces = readJsonConfig(marketplacesPath);
373
- delete marketplaces['runwork'];
374
- writeJsonConfig(marketplacesPath, marketplaces);
375
- }
376
- catch { /* best-effort */ }
377
- }
378
- }
379
- }
380
- // ── Usage stats (passive, best-effort) ─────────────────────────────
381
- async readUsageStats(lastSyncAt) {
382
- // Source of truth: ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl
383
- // Each line is one user/assistant/system entry. The file grows continuously
384
- // during a live session, so mtime + per-entry timestamp give an accurate
385
- // post-sync activity picture. (stats-cache.json was abandoned upstream and
386
- // session-env/ only records session-start hooks.)
387
- try {
388
- const claudeDir = join(homedir(), '.claude');
389
- if (!existsSync(claudeDir))
390
- return null;
391
- const projectsDir = join(claudeDir, 'projects');
392
- if (!existsSync(projectsDir))
393
- return null;
394
- const sinceMs = lastSyncAt ? new Date(lastSyncAt).getTime() : 0;
395
- let sessionCount = 0;
396
- let messageCount = 0;
397
- let toolCallCount = 0;
398
- let inputTokens = 0;
399
- let outputTokens = 0;
400
- let cacheReadTokens = 0;
401
- let latestActivityMs = 0;
402
- // Dedup: ccusage uses ${message.id}:${requestId} to drop retransmissions.
403
- // Entries without both fields pass through undeduped (same behavior).
404
- const seenEntries = new Set();
405
- let cwdEntries;
406
- try {
407
- cwdEntries = readdirSync(projectsDir);
408
- }
409
- catch {
410
- return null;
411
- }
412
- for (const cwd of cwdEntries) {
413
- const cwdPath = join(projectsDir, cwd);
414
- let files;
415
- try {
416
- files = readdirSync(cwdPath);
417
- }
418
- catch {
419
- continue;
420
- }
421
- for (const file of files) {
422
- if (!file.endsWith('.jsonl'))
423
- continue;
424
- const filePath = join(cwdPath, file);
425
- let stat;
426
- try {
427
- stat = statSync(filePath);
428
- }
429
- catch {
430
- continue;
431
- }
432
- if (stat.mtimeMs <= sinceMs)
433
- continue;
434
- let content;
435
- try {
436
- content = readFileSync(filePath, 'utf-8');
437
- }
438
- catch {
439
- continue;
440
- }
441
- let sessionHadActivity = false;
442
- for (const line of content.split('\n')) {
443
- if (!line)
444
- continue;
445
- let entry;
446
- try {
447
- entry = JSON.parse(line);
448
- }
449
- catch {
450
- continue;
451
- }
452
- const tsRaw = entry.timestamp;
453
- if (typeof tsRaw !== 'string')
454
- continue;
455
- const ts = Date.parse(tsRaw);
456
- if (!Number.isFinite(ts) || ts <= sinceMs)
457
- continue;
458
- sessionHadActivity = true;
459
- if (ts > latestActivityMs)
460
- latestActivityMs = ts;
461
- const type = entry.type;
462
- if (type === 'user' || type === 'assistant') {
463
- // Dedup by message.id + requestId (same approach as ccusage)
464
- const msg = entry.message;
465
- const msgId = msg && typeof msg === 'object' ? msg.id : undefined;
466
- const reqId = entry.requestId;
467
- if (typeof msgId === 'string' && typeof reqId === 'string') {
468
- const dedupKey = `${msgId}:${reqId}`;
469
- if (seenEntries.has(dedupKey))
470
- continue;
471
- seenEntries.add(dedupKey);
472
- }
473
- messageCount++;
474
- }
475
- if (type === 'assistant') {
476
- const msg = entry.message;
477
- if (msg && typeof msg === 'object') {
478
- const msgRecord = msg;
479
- const blocks = Array.isArray(msgRecord.content) ? msgRecord.content : [];
480
- for (const block of blocks) {
481
- if (block && typeof block === 'object'
482
- && block.type === 'tool_use') {
483
- toolCallCount++;
484
- }
485
- }
486
- const usage = msgRecord.usage;
487
- if (usage && typeof usage === 'object') {
488
- const u = usage;
489
- if (typeof u.input_tokens === 'number')
490
- inputTokens += u.input_tokens;
491
- if (typeof u.output_tokens === 'number')
492
- outputTokens += u.output_tokens;
493
- if (typeof u.cache_read_input_tokens === 'number') {
494
- cacheReadTokens += u.cache_read_input_tokens;
495
- }
496
- }
497
- }
498
- }
499
- }
500
- if (sessionHadActivity)
501
- sessionCount++;
502
- }
503
- }
504
- if (sessionCount === 0)
505
- return null;
506
- return {
507
- hasNewActivity: true,
508
- sessionCount,
509
- messageCount,
510
- toolCallCount,
511
- tokensUsed: inputTokens + outputTokens,
512
- aiLinesAdded: 0,
513
- aiLinesRemoved: 0,
514
- lastActiveAt: latestActivityMs > 0 ? new Date(latestActivityMs).toISOString() : null,
515
- extra: { inputTokens, outputTokens, cacheReadTokens },
516
- };
517
- }
518
- catch {
519
- return null;
520
- }
521
- }
522
- async readSkillUsage(lastSyncAt) {
523
- // Walk the same JSONL files as readUsageStats and detect actual skill
524
- // invocations. Two verified paths exist in the data:
525
- //
526
- // Path A (model-initiated): assistant message contains a tool_use block
527
- // with name === "Skill" and input.skill === "<skill-name>".
528
- //
529
- // Path B (user-initiated slash command): user message contains
530
- // <command-name>/xxx</command-name>, and the NEXT user message starts
531
- // with "Base directory for this skill:" (confirming the harness treated
532
- // it as a skill, not a built-in command).
533
- //
534
- // MCP skill tools (mcp__*__skill_*) are listed in deferred-tool blocks
535
- // but are never actually invoked in any observed JSONL data.
536
- try {
537
- const projectsDir = join(homedir(), '.claude', 'projects');
538
- if (!existsSync(projectsDir))
539
- return null;
540
- const sinceMs = lastSyncAt ? new Date(lastSyncAt).getTime() : 0;
541
- const skillCounts = new Map();
542
- const recordSkill = (name, ts) => {
543
- const existing = skillCounts.get(name);
544
- if (existing) {
545
- existing.count++;
546
- if (ts > existing.lastTs)
547
- existing.lastTs = ts;
548
- }
549
- else {
550
- skillCounts.set(name, { count: 1, lastTs: ts });
551
- }
552
- };
553
- let cwdEntries;
554
- try {
555
- cwdEntries = readdirSync(projectsDir);
556
- }
557
- catch {
558
- return null;
559
- }
560
- for (const cwd of cwdEntries) {
561
- const cwdPath = join(projectsDir, cwd);
562
- let files;
563
- try {
564
- files = readdirSync(cwdPath);
565
- }
566
- catch {
567
- continue;
568
- }
569
- for (const file of files) {
570
- if (!file.endsWith('.jsonl'))
571
- continue;
572
- const filePath = join(cwdPath, file);
573
- let fileStat;
574
- try {
575
- fileStat = statSync(filePath);
576
- }
577
- catch {
578
- continue;
579
- }
580
- if (fileStat.mtimeMs <= sinceMs)
581
- continue;
582
- let content;
583
- try {
584
- content = readFileSync(filePath, 'utf-8');
585
- }
586
- catch {
587
- continue;
588
- }
589
- // Track pending slash command for Path B lookahead
590
- let pendingCommand = null;
591
- for (const line of content.split('\n')) {
592
- if (!line)
593
- continue;
594
- let entry;
595
- try {
596
- entry = JSON.parse(line);
597
- }
598
- catch {
599
- continue;
600
- }
601
- const tsRaw = entry.timestamp;
602
- if (typeof tsRaw !== 'string')
603
- continue;
604
- const ts = Date.parse(tsRaw);
605
- if (!Number.isFinite(ts) || ts <= sinceMs)
606
- continue;
607
- const type = entry.type;
608
- // Path A: Skill tool calls in assistant messages
609
- if (type === 'assistant') {
610
- const msg = entry.message;
611
- if (msg && typeof msg === 'object') {
612
- const blocks = Array.isArray(msg.content)
613
- ? msg.content
614
- : [];
615
- for (const block of blocks) {
616
- if (block && block.type === 'tool_use' && block.name === 'Skill') {
617
- const input = block.input;
618
- if (input && typeof input.skill === 'string') {
619
- recordSkill(input.skill, ts);
620
- }
621
- }
622
- }
623
- }
624
- }
625
- // Path B: slash command -> skill content injection
626
- if (type === 'user') {
627
- const msg = entry.message;
628
- const msgContent = msg?.content;
629
- const text = typeof msgContent === 'string' ? msgContent : '';
630
- // Check if this is a skill content injection following a slash command
631
- if (pendingCommand && text.startsWith('Base directory for this skill:')) {
632
- recordSkill(pendingCommand.name, pendingCommand.ts);
633
- pendingCommand = null;
634
- continue;
635
- }
636
- // Reset pending on any user message that isn't skill content
637
- if (pendingCommand && type === 'user') {
638
- pendingCommand = null;
639
- }
640
- // Check for slash command pattern
641
- const match = text.match(/<command-name>\/?([^<]+)<\/command-name>/);
642
- if (match) {
643
- const cmdName = match[1].replace(/^\//, '');
644
- pendingCommand = { name: cmdName, ts };
645
- }
646
- }
647
- }
648
- }
649
- }
650
- if (skillCounts.size === 0)
651
- return null;
652
- const results = [];
653
- for (const [skillName, { count, lastTs }] of skillCounts) {
654
- results.push({
655
- skillName,
656
- count,
657
- lastUsedAt: new Date(lastTs).toISOString(),
658
- });
659
- }
660
- return results;
661
- }
662
- catch {
663
- return null;
664
- }
665
- }
666
- async readVersion() {
667
- try {
668
- const output = execFileSync('claude', ['--version'], { stdio: 'pipe' }).toString().trim();
669
- return output;
670
- }
671
- catch {
672
- return null;
673
- }
674
- }
675
- // ── Plugin helpers ─────────────────────────────────────────────────
676
- getPluginsBaseDir() {
677
- return join(homedir(), '.claude', 'plugins');
678
- }
679
- getPluginDir() {
680
- return join(this.getPluginsBaseDir(), 'cache', 'runwork', PLUGIN_NAME, PLUGIN_VERSION);
681
- }
682
- /** The marketplace root (contains marketplace.json and plugins/) */
683
- getMarketplaceRoot() {
684
- return join(this.getPluginsBaseDir(), 'marketplaces', 'runwork');
685
- }
686
- /** The plugin directory within the marketplace */
687
- getMarketplaceDir() {
688
- return join(this.getMarketplaceRoot(), 'plugins', PLUGIN_NAME);
689
- }
690
- registerPlugin(pluginDir) {
691
- const pluginsBase = this.getPluginsBaseDir();
692
- mkdirSync(pluginsBase, { recursive: true });
693
- // Register in installed_plugins.json
694
- const installedPath = join(pluginsBase, 'installed_plugins.json');
695
- const installed = readJsonConfig(installedPath);
696
- if (!installed.version)
697
- installed.version = 2;
698
- if (!installed.plugins)
699
- installed.plugins = {};
700
- const pluginKey = `${PLUGIN_NAME}@runwork`;
701
- const wasRegistered = !!installed.plugins[pluginKey];
702
- installed.plugins[pluginKey] = [{
703
- scope: 'user',
704
- installPath: pluginDir,
705
- version: PLUGIN_VERSION,
706
- installedAt: new Date().toISOString(),
707
- lastUpdated: new Date().toISOString(),
708
- }];
709
- writeJsonConfig(installedPath, installed);
710
- // Write marketplace.json catalog
711
- const marketRoot = this.getMarketplaceRoot();
712
- const marketCatalogDir = join(marketRoot, '.claude-plugin');
713
- mkdirSync(marketCatalogDir, { recursive: true });
714
- writeFileSync(join(marketCatalogDir, 'marketplace.json'), JSON.stringify(getMarketplaceJson(), null, 2));
715
- // Register in known_marketplaces.json
716
- const marketplacesPath = join(pluginsBase, 'known_marketplaces.json');
717
- const marketplaces = readJsonConfig(marketplacesPath);
718
- marketplaces['runwork'] = {
719
- source: { source: 'directory', path: marketRoot },
720
- installLocation: marketRoot,
721
- lastUpdated: new Date().toISOString(),
722
- };
723
- writeJsonConfig(marketplacesPath, marketplaces);
724
- console.log(` [Claude Code] ${wasRegistered ? 'Refreshed' : 'Registered'} plugin ` +
725
- `${pluginKey} v${PLUGIN_VERSION} -> ${installedPath}`);
726
- // Enable the plugin in settings.json
727
- const settingsPath = join(homedir(), '.claude', 'settings.json');
728
- const settings = readJsonConfig(settingsPath);
729
- if (!settings['enabledPlugins']) {
730
- settings['enabledPlugins'] = {};
731
- }
732
- const enabled = settings['enabledPlugins'];
733
- if (!enabled[`${PLUGIN_NAME}@runwork`]) {
734
- enabled[`${PLUGIN_NAME}@runwork`] = true;
735
- writeJsonConfig(settingsPath, settings);
736
- }
737
- }
738
- }
739
- /**
740
- * Remove old skill directory that used the display name (with spaces) if it
741
- * differs from the new slug-based directory name.
742
- */
743
- function cleanupOldSkillDir(baseDir, skill) {
744
- if (skill.name === skill.filename)
745
- return;
746
- const oldDir = join(baseDir, skill.name);
747
- if (existsSync(oldDir)) {
748
- try {
749
- rmSync(oldDir, { recursive: true, force: true });
750
- }
751
- catch { /* best-effort */ }
752
- }
753
- }