runwork 0.15.1 → 0.16.0

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 (404) hide show
  1. package/bundled-types/task-delegation/task-delegation/types.d.ts +6 -0
  2. package/dist/index.js +20237 -116
  3. package/package.json +4 -4
  4. package/dist/__tests__/curl-parser.test.d.ts +0 -1
  5. package/dist/__tests__/curl-parser.test.js +0 -250
  6. package/dist/__tests__/install-scripts.test.d.ts +0 -1
  7. package/dist/__tests__/install-scripts.test.js +0 -280
  8. package/dist/__tests__/types-manager.test.d.ts +0 -1
  9. package/dist/__tests__/types-manager.test.js +0 -89
  10. package/dist/agents/__tests__/chatgpt-registry.test.d.ts +0 -1
  11. package/dist/agents/__tests__/chatgpt-registry.test.js +0 -61
  12. package/dist/agents/__tests__/claude-code-managed-block.test.d.ts +0 -1
  13. package/dist/agents/__tests__/claude-code-managed-block.test.js +0 -105
  14. package/dist/agents/__tests__/claude-code-plugin.test.d.ts +0 -1
  15. package/dist/agents/__tests__/claude-code-plugin.test.js +0 -47
  16. package/dist/agents/__tests__/claude-code-stats.test.d.ts +0 -1
  17. package/dist/agents/__tests__/claude-code-stats.test.js +0 -390
  18. package/dist/agents/__tests__/claude-desktop-memory.test.d.ts +0 -1
  19. package/dist/agents/__tests__/claude-desktop-memory.test.js +0 -154
  20. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.d.ts +0 -1
  21. package/dist/agents/__tests__/claude-desktop-plugin-tree.test.js +0 -161
  22. package/dist/agents/__tests__/claude-desktop-plugin.test.d.ts +0 -1
  23. package/dist/agents/__tests__/claude-desktop-plugin.test.js +0 -117
  24. package/dist/agents/__tests__/claude-desktop-rpm.test.d.ts +0 -1
  25. package/dist/agents/__tests__/claude-desktop-rpm.test.js +0 -126
  26. package/dist/agents/__tests__/claude-desktop-stats.test.d.ts +0 -1
  27. package/dist/agents/__tests__/claude-desktop-stats.test.js +0 -280
  28. package/dist/agents/__tests__/codex-instructions.test.d.ts +0 -1
  29. package/dist/agents/__tests__/codex-instructions.test.js +0 -57
  30. package/dist/agents/__tests__/codex-minimum-permissions.test.d.ts +0 -1
  31. package/dist/agents/__tests__/codex-minimum-permissions.test.js +0 -82
  32. package/dist/agents/__tests__/codex-stats.test.d.ts +0 -1
  33. package/dist/agents/__tests__/codex-stats.test.js +0 -370
  34. package/dist/agents/__tests__/cursor-merge.test.d.ts +0 -1
  35. package/dist/agents/__tests__/cursor-merge.test.js +0 -66
  36. package/dist/agents/__tests__/cursor-stats.test.d.ts +0 -1
  37. package/dist/agents/__tests__/cursor-stats.test.js +0 -183
  38. package/dist/agents/__tests__/defaults-merge.test.d.ts +0 -1
  39. package/dist/agents/__tests__/defaults-merge.test.js +0 -268
  40. package/dist/agents/__tests__/detection.test.d.ts +0 -1
  41. package/dist/agents/__tests__/detection.test.js +0 -89
  42. package/dist/agents/__tests__/graceful-degradation.test.d.ts +0 -1
  43. package/dist/agents/__tests__/graceful-degradation.test.js +0 -129
  44. package/dist/agents/__tests__/instruction-hint.test.d.ts +0 -1
  45. package/dist/agents/__tests__/instruction-hint.test.js +0 -69
  46. package/dist/agents/__tests__/intro-skill.test.d.ts +0 -1
  47. package/dist/agents/__tests__/intro-skill.test.js +0 -193
  48. package/dist/agents/__tests__/schema-validation.test.d.ts +0 -1
  49. package/dist/agents/__tests__/schema-validation.test.js +0 -212
  50. package/dist/agents/__tests__/skill-slug.test.d.ts +0 -1
  51. package/dist/agents/__tests__/skill-slug.test.js +0 -77
  52. package/dist/agents/claude-code.d.ts +0 -59
  53. package/dist/agents/claude-code.js +0 -753
  54. package/dist/agents/claude-desktop-plugin-tree.d.ts +0 -59
  55. package/dist/agents/claude-desktop-plugin-tree.js +0 -143
  56. package/dist/agents/claude-desktop.d.ts +0 -47
  57. package/dist/agents/claude-desktop.js +0 -684
  58. package/dist/agents/cline.d.ts +0 -15
  59. package/dist/agents/cline.js +0 -130
  60. package/dist/agents/codex.d.ts +0 -44
  61. package/dist/agents/codex.js +0 -453
  62. package/dist/agents/conversation-skills.d.ts +0 -18
  63. package/dist/agents/conversation-skills.js +0 -229
  64. package/dist/agents/cursor.d.ts +0 -35
  65. package/dist/agents/cursor.js +0 -294
  66. package/dist/agents/default-config.d.ts +0 -30
  67. package/dist/agents/default-config.js +0 -67
  68. package/dist/agents/defaults-merge.d.ts +0 -87
  69. package/dist/agents/defaults-merge.js +0 -150
  70. package/dist/agents/detect.d.ts +0 -4
  71. package/dist/agents/detect.js +0 -67
  72. package/dist/agents/detection.d.ts +0 -18
  73. package/dist/agents/detection.js +0 -94
  74. package/dist/agents/gemini.d.ts +0 -15
  75. package/dist/agents/gemini.js +0 -122
  76. package/dist/agents/generic-adapter.d.ts +0 -25
  77. package/dist/agents/generic-adapter.js +0 -151
  78. package/dist/agents/intro-skill.d.ts +0 -45
  79. package/dist/agents/intro-skill.js +0 -447
  80. package/dist/agents/registry-data.d.ts +0 -192
  81. package/dist/agents/registry-data.js +0 -669
  82. package/dist/agents/registry.d.ts +0 -13
  83. package/dist/agents/registry.js +0 -36
  84. package/dist/agents/runtime-detection.d.ts +0 -82
  85. package/dist/agents/runtime-detection.js +0 -271
  86. package/dist/agents/session-start-hook.d.ts +0 -37
  87. package/dist/agents/session-start-hook.js +0 -159
  88. package/dist/agents/types.d.ts +0 -171
  89. package/dist/agents/types.js +0 -75
  90. package/dist/agents/utils/instruction-hint.d.ts +0 -21
  91. package/dist/agents/utils/instruction-hint.js +0 -108
  92. package/dist/agents/utils/json-config.d.ts +0 -19
  93. package/dist/agents/utils/json-config.js +0 -69
  94. package/dist/agents/utils/toml-config.d.ts +0 -8
  95. package/dist/agents/utils/toml-config.js +0 -27
  96. package/dist/agents/windsurf.d.ts +0 -14
  97. package/dist/agents/windsurf.js +0 -102
  98. package/dist/api/__tests__/client.test.d.ts +0 -1
  99. package/dist/api/__tests__/client.test.js +0 -272
  100. package/dist/api/client.d.ts +0 -326
  101. package/dist/api/client.js +0 -427
  102. package/dist/auth/__tests__/login-flow.test.d.ts +0 -1
  103. package/dist/auth/__tests__/login-flow.test.js +0 -101
  104. package/dist/auth/__tests__/store.test.d.ts +0 -1
  105. package/dist/auth/__tests__/store.test.js +0 -132
  106. package/dist/auth/login-flow.d.ts +0 -26
  107. package/dist/auth/login-flow.js +0 -137
  108. package/dist/auth/store.d.ts +0 -5
  109. package/dist/auth/store.js +0 -62
  110. package/dist/commands/__tests__/clone-args.test.d.ts +0 -1
  111. package/dist/commands/__tests__/clone-args.test.js +0 -51
  112. package/dist/commands/__tests__/clone-source-result.test.d.ts +0 -1
  113. package/dist/commands/__tests__/clone-source-result.test.js +0 -45
  114. package/dist/commands/__tests__/info-merge.test.d.ts +0 -1
  115. package/dist/commands/__tests__/info-merge.test.js +0 -55
  116. package/dist/commands/__tests__/mcp-entries.test.d.ts +0 -1
  117. package/dist/commands/__tests__/mcp-entries.test.js +0 -48
  118. package/dist/commands/__tests__/setup-persona.test.d.ts +0 -1
  119. package/dist/commands/__tests__/setup-persona.test.js +0 -31
  120. package/dist/commands/__tests__/setup.test.d.ts +0 -1
  121. package/dist/commands/__tests__/setup.test.js +0 -81
  122. package/dist/commands/__tests__/sync-redetect.test.d.ts +0 -1
  123. package/dist/commands/__tests__/sync-redetect.test.js +0 -96
  124. package/dist/commands/__tests__/sync-telemetry.test.d.ts +0 -1
  125. package/dist/commands/__tests__/sync-telemetry.test.js +0 -281
  126. package/dist/commands/__tests__/upgrade.test.d.ts +0 -1
  127. package/dist/commands/__tests__/upgrade.test.js +0 -157
  128. package/dist/commands/agents.d.ts +0 -2
  129. package/dist/commands/agents.js +0 -160
  130. package/dist/commands/api-keys.d.ts +0 -2
  131. package/dist/commands/api-keys.js +0 -95
  132. package/dist/commands/apps.d.ts +0 -2
  133. package/dist/commands/apps.js +0 -82
  134. package/dist/commands/build-plugin.d.ts +0 -2
  135. package/dist/commands/build-plugin.js +0 -135
  136. package/dist/commands/clone.d.ts +0 -60
  137. package/dist/commands/clone.js +0 -271
  138. package/dist/commands/components.d.ts +0 -2
  139. package/dist/commands/components.js +0 -43
  140. package/dist/commands/deploy.d.ts +0 -2
  141. package/dist/commands/deploy.js +0 -279
  142. package/dist/commands/dev.d.ts +0 -11
  143. package/dist/commands/dev.js +0 -1011
  144. package/dist/commands/doctor.d.ts +0 -2
  145. package/dist/commands/doctor.js +0 -230
  146. package/dist/commands/endpoints.d.ts +0 -2
  147. package/dist/commands/endpoints.js +0 -189
  148. package/dist/commands/entities.d.ts +0 -2
  149. package/dist/commands/entities.js +0 -198
  150. package/dist/commands/files.d.ts +0 -2
  151. package/dist/commands/files.js +0 -193
  152. package/dist/commands/inbox.d.ts +0 -11
  153. package/dist/commands/inbox.js +0 -60
  154. package/dist/commands/info.d.ts +0 -178
  155. package/dist/commands/info.js +0 -455
  156. package/dist/commands/init.d.ts +0 -21
  157. package/dist/commands/init.js +0 -185
  158. package/dist/commands/integrations.d.ts +0 -2
  159. package/dist/commands/integrations.js +0 -233
  160. package/dist/commands/login.d.ts +0 -2
  161. package/dist/commands/login.js +0 -44
  162. package/dist/commands/logout.d.ts +0 -2
  163. package/dist/commands/logout.js +0 -13
  164. package/dist/commands/logs.d.ts +0 -2
  165. package/dist/commands/logs.js +0 -232
  166. package/dist/commands/mcp-entries.d.ts +0 -13
  167. package/dist/commands/mcp-entries.js +0 -26
  168. package/dist/commands/mcp.d.ts +0 -2
  169. package/dist/commands/mcp.js +0 -245
  170. package/dist/commands/open.d.ts +0 -2
  171. package/dist/commands/open.js +0 -53
  172. package/dist/commands/resume.d.ts +0 -2
  173. package/dist/commands/resume.js +0 -289
  174. package/dist/commands/save-convo.d.ts +0 -8
  175. package/dist/commands/save-convo.js +0 -20
  176. package/dist/commands/schedules.d.ts +0 -2
  177. package/dist/commands/schedules.js +0 -221
  178. package/dist/commands/setup.d.ts +0 -27
  179. package/dist/commands/setup.js +0 -177
  180. package/dist/commands/share-convo.d.ts +0 -24
  181. package/dist/commands/share-convo.js +0 -167
  182. package/dist/commands/skills.d.ts +0 -2
  183. package/dist/commands/skills.js +0 -352
  184. package/dist/commands/sync-telemetry.d.ts +0 -33
  185. package/dist/commands/sync-telemetry.js +0 -186
  186. package/dist/commands/sync.d.ts +0 -37
  187. package/dist/commands/sync.js +0 -702
  188. package/dist/commands/uninstall.d.ts +0 -2
  189. package/dist/commands/uninstall.js +0 -145
  190. package/dist/commands/upgrade.d.ts +0 -14
  191. package/dist/commands/upgrade.js +0 -217
  192. package/dist/commands/validate.d.ts +0 -2
  193. package/dist/commands/validate.js +0 -89
  194. package/dist/commands/welcome.d.ts +0 -1
  195. package/dist/commands/welcome.js +0 -86
  196. package/dist/commands/workflows.d.ts +0 -2
  197. package/dist/commands/workflows.js +0 -187
  198. package/dist/deploy/__tests__/deploy-state.test.d.ts +0 -1
  199. package/dist/deploy/__tests__/deploy-state.test.js +0 -80
  200. package/dist/deploy/__tests__/deploy-status.test.d.ts +0 -1
  201. package/dist/deploy/__tests__/deploy-status.test.js +0 -41
  202. package/dist/deploy/__tests__/detach-args.test.d.ts +0 -1
  203. package/dist/deploy/__tests__/detach-args.test.js +0 -30
  204. package/dist/deploy/deploy-state.d.ts +0 -36
  205. package/dist/deploy/deploy-state.js +0 -63
  206. package/dist/deploy/deploy-status.d.ts +0 -21
  207. package/dist/deploy/deploy-status.js +0 -36
  208. package/dist/deploy/detach.d.ts +0 -32
  209. package/dist/deploy/detach.js +0 -71
  210. package/dist/dev/__tests__/attach.test.d.ts +0 -1
  211. package/dist/dev/__tests__/attach.test.js +0 -296
  212. package/dist/dev/__tests__/detach.test.d.ts +0 -1
  213. package/dist/dev/__tests__/detach.test.js +0 -404
  214. package/dist/dev/__tests__/preview-url-poller.test.d.ts +0 -1
  215. package/dist/dev/__tests__/preview-url-poller.test.js +0 -149
  216. package/dist/dev/__tests__/session.test.d.ts +0 -1
  217. package/dist/dev/__tests__/session.test.js +0 -446
  218. package/dist/dev/__tests__/startup-sync.test.d.ts +0 -1
  219. package/dist/dev/__tests__/startup-sync.test.js +0 -32
  220. package/dist/dev/__tests__/stop.test.d.ts +0 -1
  221. package/dist/dev/__tests__/stop.test.js +0 -172
  222. package/dist/dev/attach.d.ts +0 -120
  223. package/dist/dev/attach.js +0 -269
  224. package/dist/dev/detach.d.ts +0 -187
  225. package/dist/dev/detach.js +0 -292
  226. package/dist/dev/preview-url-poller.d.ts +0 -35
  227. package/dist/dev/preview-url-poller.js +0 -50
  228. package/dist/dev/session.d.ts +0 -175
  229. package/dist/dev/session.js +0 -258
  230. package/dist/dev/startup-sync.d.ts +0 -23
  231. package/dist/dev/startup-sync.js +0 -14
  232. package/dist/dev/stop.d.ts +0 -52
  233. package/dist/dev/stop.js +0 -101
  234. package/dist/devtools/registry-data.d.ts +0 -46
  235. package/dist/devtools/registry-data.js +0 -40
  236. package/dist/generated/bundled-types.d.ts +0 -1
  237. package/dist/generated/bundled-types.js +0 -46
  238. package/dist/generated/version.d.ts +0 -1
  239. package/dist/generated/version.js +0 -2
  240. package/dist/git/__tests__/auto-commit.test.d.ts +0 -1
  241. package/dist/git/__tests__/auto-commit.test.js +0 -431
  242. package/dist/git/__tests__/classify-sync-error.test.d.ts +0 -1
  243. package/dist/git/__tests__/classify-sync-error.test.js +0 -57
  244. package/dist/git/__tests__/credential-helper-e2e.test.d.ts +0 -21
  245. package/dist/git/__tests__/credential-helper-e2e.test.js +0 -195
  246. package/dist/git/__tests__/credentials.test.d.ts +0 -1
  247. package/dist/git/__tests__/credentials.test.js +0 -141
  248. package/dist/git/__tests__/deploy-guard.test.d.ts +0 -1
  249. package/dist/git/__tests__/deploy-guard.test.js +0 -61
  250. package/dist/git/__tests__/ensure-git-credential-helper.test.d.ts +0 -1
  251. package/dist/git/__tests__/ensure-git-credential-helper.test.js +0 -133
  252. package/dist/git/__tests__/ensure-runwork-remote.test.d.ts +0 -1
  253. package/dist/git/__tests__/ensure-runwork-remote.test.js +0 -109
  254. package/dist/git/__tests__/identity.test.d.ts +0 -1
  255. package/dist/git/__tests__/identity.test.js +0 -146
  256. package/dist/git/__tests__/manifest.test.d.ts +0 -1
  257. package/dist/git/__tests__/manifest.test.js +0 -446
  258. package/dist/git/__tests__/preflight-resolution.test.d.ts +0 -1
  259. package/dist/git/__tests__/preflight-resolution.test.js +0 -366
  260. package/dist/git/__tests__/preflight.test.d.ts +0 -1
  261. package/dist/git/__tests__/preflight.test.js +0 -36
  262. package/dist/git/__tests__/repo-config.test.d.ts +0 -1
  263. package/dist/git/__tests__/repo-config.test.js +0 -26
  264. package/dist/git/__tests__/sync.test.d.ts +0 -1
  265. package/dist/git/__tests__/sync.test.js +0 -405
  266. package/dist/git/auto-commit.d.ts +0 -35
  267. package/dist/git/auto-commit.js +0 -293
  268. package/dist/git/classify-sync-error.d.ts +0 -21
  269. package/dist/git/classify-sync-error.js +0 -111
  270. package/dist/git/credentials.d.ts +0 -75
  271. package/dist/git/credentials.js +0 -164
  272. package/dist/git/critical-files.d.ts +0 -20
  273. package/dist/git/critical-files.js +0 -68
  274. package/dist/git/deploy-guard.d.ts +0 -53
  275. package/dist/git/deploy-guard.js +0 -78
  276. package/dist/git/identity.d.ts +0 -44
  277. package/dist/git/identity.js +0 -133
  278. package/dist/git/preflight.d.ts +0 -57
  279. package/dist/git/preflight.js +0 -276
  280. package/dist/git/remote.d.ts +0 -37
  281. package/dist/git/remote.js +0 -75
  282. package/dist/git/repo-config.d.ts +0 -8
  283. package/dist/git/repo-config.js +0 -29
  284. package/dist/git/sync.d.ts +0 -15
  285. package/dist/git/sync.js +0 -159
  286. package/dist/health/__tests__/checks.test.d.ts +0 -1
  287. package/dist/health/__tests__/checks.test.js +0 -357
  288. package/dist/health/__tests__/cli-distribution-checks.test.d.ts +0 -1
  289. package/dist/health/__tests__/cli-distribution-checks.test.js +0 -196
  290. package/dist/health/__tests__/fix.test.d.ts +0 -1
  291. package/dist/health/__tests__/fix.test.js +0 -72
  292. package/dist/health/__tests__/runner-filter.test.d.ts +0 -1
  293. package/dist/health/__tests__/runner-filter.test.js +0 -61
  294. package/dist/health/checks.d.ts +0 -42
  295. package/dist/health/checks.js +0 -636
  296. package/dist/health/fix.d.ts +0 -22
  297. package/dist/health/fix.js +0 -62
  298. package/dist/health/runner.d.ts +0 -8
  299. package/dist/health/runner.js +0 -47
  300. package/dist/health/types.d.ts +0 -12
  301. package/dist/health/types.js +0 -1
  302. package/dist/index.d.ts +0 -1
  303. package/dist/logs/__tests__/tailer-format.test.d.ts +0 -1
  304. package/dist/logs/__tests__/tailer-format.test.js +0 -43
  305. package/dist/logs/tailer.d.ts +0 -17
  306. package/dist/logs/tailer.js +0 -217
  307. package/dist/sync/__tests__/change-detect.test.d.ts +0 -1
  308. package/dist/sync/__tests__/change-detect.test.js +0 -123
  309. package/dist/sync/__tests__/hash.test.d.ts +0 -1
  310. package/dist/sync/__tests__/hash.test.js +0 -18
  311. package/dist/sync/change-detect.d.ts +0 -19
  312. package/dist/sync/change-detect.js +0 -136
  313. package/dist/sync/conflict-ui.d.ts +0 -5
  314. package/dist/sync/conflict-ui.js +0 -78
  315. package/dist/sync/executor.d.ts +0 -23
  316. package/dist/sync/executor.js +0 -102
  317. package/dist/sync/hash.d.ts +0 -1
  318. package/dist/sync/hash.js +0 -4
  319. package/dist/sync/types.d.ts +0 -24
  320. package/dist/sync/types.js +0 -1
  321. package/dist/template/manifest.d.ts +0 -17
  322. package/dist/template/manifest.js +0 -145
  323. package/dist/tools/types.d.ts +0 -52
  324. package/dist/tools/types.js +0 -8
  325. package/dist/types-manager.d.ts +0 -1
  326. package/dist/types-manager.js +0 -35
  327. package/dist/types.d.ts +0 -349
  328. package/dist/types.js +0 -1
  329. package/dist/ui/__tests__/banner.test.d.ts +0 -1
  330. package/dist/ui/__tests__/banner.test.js +0 -98
  331. package/dist/ui/__tests__/colors.test.d.ts +0 -1
  332. package/dist/ui/__tests__/colors.test.js +0 -22
  333. package/dist/ui/__tests__/keyboard.test.d.ts +0 -1
  334. package/dist/ui/__tests__/keyboard.test.js +0 -34
  335. package/dist/ui/__tests__/status-line.test.d.ts +0 -1
  336. package/dist/ui/__tests__/status-line.test.js +0 -54
  337. package/dist/ui/banner.d.ts +0 -29
  338. package/dist/ui/banner.js +0 -153
  339. package/dist/ui/colors.d.ts +0 -4
  340. package/dist/ui/colors.js +0 -7
  341. package/dist/ui/keyboard.d.ts +0 -12
  342. package/dist/ui/keyboard.js +0 -61
  343. package/dist/ui/status-line.d.ts +0 -6
  344. package/dist/ui/status-line.js +0 -53
  345. package/dist/utils/__tests__/format-error.test.d.ts +0 -1
  346. package/dist/utils/__tests__/format-error.test.js +0 -43
  347. package/dist/utils/__tests__/help-json.test.d.ts +0 -1
  348. package/dist/utils/__tests__/help-json.test.js +0 -39
  349. package/dist/utils/__tests__/http.test.d.ts +0 -1
  350. package/dist/utils/__tests__/http.test.js +0 -381
  351. package/dist/utils/__tests__/ignore-matcher.test.d.ts +0 -1
  352. package/dist/utils/__tests__/ignore-matcher.test.js +0 -205
  353. package/dist/utils/__tests__/output.test.d.ts +0 -1
  354. package/dist/utils/__tests__/output.test.js +0 -38
  355. package/dist/utils/__tests__/prompt.test.d.ts +0 -1
  356. package/dist/utils/__tests__/prompt.test.js +0 -27
  357. package/dist/utils/__tests__/resolve.test.d.ts +0 -1
  358. package/dist/utils/__tests__/resolve.test.js +0 -95
  359. package/dist/utils/__tests__/sqlite.test.d.ts +0 -1
  360. package/dist/utils/__tests__/sqlite.test.js +0 -89
  361. package/dist/utils/agent-guidance.d.ts +0 -47
  362. package/dist/utils/agent-guidance.js +0 -128
  363. package/dist/utils/app-info.d.ts +0 -70
  364. package/dist/utils/app-info.js +0 -167
  365. package/dist/utils/curl-parser.d.ts +0 -12
  366. package/dist/utils/curl-parser.js +0 -162
  367. package/dist/utils/data-input.d.ts +0 -1
  368. package/dist/utils/data-input.js +0 -38
  369. package/dist/utils/format-error.d.ts +0 -10
  370. package/dist/utils/format-error.js +0 -38
  371. package/dist/utils/fs.d.ts +0 -5
  372. package/dist/utils/fs.js +0 -23
  373. package/dist/utils/help-json.d.ts +0 -70
  374. package/dist/utils/help-json.js +0 -88
  375. package/dist/utils/http.d.ts +0 -46
  376. package/dist/utils/http.js +0 -421
  377. package/dist/utils/ignore-matcher.d.ts +0 -47
  378. package/dist/utils/ignore-matcher.js +0 -132
  379. package/dist/utils/output.d.ts +0 -17
  380. package/dist/utils/output.js +0 -27
  381. package/dist/utils/prompt.d.ts +0 -5
  382. package/dist/utils/prompt.js +0 -42
  383. package/dist/utils/resolve.d.ts +0 -12
  384. package/dist/utils/resolve.js +0 -52
  385. package/dist/utils/setup-state.d.ts +0 -3
  386. package/dist/utils/setup-state.js +0 -19
  387. package/dist/utils/sqlite-adapter.d.ts +0 -48
  388. package/dist/utils/sqlite-adapter.js +0 -147
  389. package/dist/utils/sqlite.d.ts +0 -14
  390. package/dist/utils/sqlite.js +0 -14
  391. package/dist/utils/subprocess.d.ts +0 -19
  392. package/dist/utils/subprocess.js +0 -27
  393. package/dist/utils/which.d.ts +0 -14
  394. package/dist/utils/which.js +0 -47
  395. package/dist/utils/zip.d.ts +0 -7
  396. package/dist/utils/zip.js +0 -42
  397. package/dist/validate/__tests__/validate.test.d.ts +0 -1
  398. package/dist/validate/__tests__/validate.test.js +0 -42
  399. package/dist/validate/freshness.d.ts +0 -28
  400. package/dist/validate/freshness.js +0 -48
  401. package/dist/validate/preview.d.ts +0 -21
  402. package/dist/validate/preview.js +0 -39
  403. package/dist/workspace/resolve.d.ts +0 -19
  404. 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
- }