@phnx-labs/agents-cli 1.12.0 → 1.14.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 (496) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README.md +308 -297
  3. package/dist/commands/alias.d.ts +11 -0
  4. package/dist/commands/alias.js +117 -0
  5. package/dist/commands/beta.d.ts +2 -0
  6. package/dist/commands/beta.js +53 -0
  7. package/dist/commands/cloud.d.ts +10 -0
  8. package/dist/commands/cloud.js +408 -0
  9. package/dist/commands/commands.d.ts +9 -1
  10. package/dist/commands/commands.js +24 -172
  11. package/dist/commands/daemon.d.ts +8 -1
  12. package/dist/commands/daemon.js +13 -5
  13. package/dist/commands/doctor.d.ts +15 -0
  14. package/dist/commands/doctor.js +132 -0
  15. package/dist/commands/drive.d.ts +8 -1
  16. package/dist/commands/drive.js +20 -3
  17. package/dist/commands/exec.d.ts +8 -1
  18. package/dist/commands/exec.js +207 -20
  19. package/dist/commands/factory.d.ts +19 -0
  20. package/dist/commands/factory.js +71 -0
  21. package/dist/commands/fork.d.ts +8 -1
  22. package/dist/commands/fork.js +11 -4
  23. package/dist/commands/hooks.d.ts +9 -1
  24. package/dist/commands/hooks.js +30 -182
  25. package/dist/commands/init.d.ts +15 -1
  26. package/dist/commands/init.js +168 -74
  27. package/dist/commands/mcp.d.ts +9 -1
  28. package/dist/commands/mcp.js +11 -7
  29. package/dist/commands/models.d.ts +8 -1
  30. package/dist/commands/models.js +45 -6
  31. package/dist/commands/packages.d.ts +8 -1
  32. package/dist/commands/packages.js +13 -7
  33. package/dist/commands/permissions.d.ts +9 -1
  34. package/dist/commands/permissions.js +3 -3
  35. package/dist/commands/plugins.d.ts +8 -1
  36. package/dist/commands/plugins.js +13 -2
  37. package/dist/commands/profiles.d.ts +11 -0
  38. package/dist/commands/profiles.js +291 -0
  39. package/dist/commands/prune.d.ts +22 -0
  40. package/dist/commands/prune.js +191 -0
  41. package/dist/commands/pty.d.ts +1 -1
  42. package/dist/commands/pty.js +2 -1
  43. package/dist/commands/pull.d.ts +8 -1
  44. package/dist/commands/pull.js +93 -129
  45. package/dist/commands/refresh-memory.d.ts +7 -1
  46. package/dist/commands/refresh-memory.js +7 -1
  47. package/dist/commands/repo.d.ts +15 -0
  48. package/dist/commands/repo.js +570 -0
  49. package/dist/commands/resource-view.d.ts +10 -3
  50. package/dist/commands/resource-view.js +18 -5
  51. package/dist/commands/routines.d.ts +8 -1
  52. package/dist/commands/routines.js +17 -4
  53. package/dist/commands/rules.d.ts +9 -1
  54. package/dist/commands/rules.js +16 -11
  55. package/dist/commands/secrets.d.ts +10 -0
  56. package/dist/commands/secrets.js +518 -0
  57. package/dist/commands/sessions-picker.d.ts +2 -1
  58. package/dist/commands/sessions-picker.js +88 -11
  59. package/dist/commands/sessions-tail.d.ts +19 -0
  60. package/dist/commands/sessions-tail.js +235 -0
  61. package/dist/commands/sessions.d.ts +2 -1
  62. package/dist/commands/sessions.js +288 -7
  63. package/dist/commands/skills.d.ts +9 -1
  64. package/dist/commands/skills.js +28 -178
  65. package/dist/commands/status.d.ts +7 -1
  66. package/dist/commands/status.js +7 -1
  67. package/dist/commands/subagents.d.ts +8 -1
  68. package/dist/commands/subagents.js +11 -1
  69. package/dist/commands/sync.d.ts +8 -1
  70. package/dist/commands/sync.js +8 -1
  71. package/dist/commands/teams-picker.d.ts +4 -1
  72. package/dist/commands/teams-picker.js +55 -3
  73. package/dist/commands/teams.d.ts +15 -1
  74. package/dist/commands/teams.js +323 -69
  75. package/dist/commands/usage.d.ts +11 -0
  76. package/dist/commands/usage.js +60 -0
  77. package/dist/commands/utils.d.ts +6 -1
  78. package/dist/commands/utils.js +6 -1
  79. package/dist/commands/versions.d.ts +8 -1
  80. package/dist/commands/versions.js +4 -3
  81. package/dist/commands/view.d.ts +47 -2
  82. package/dist/commands/view.js +353 -20
  83. package/dist/index.d.ts +7 -2
  84. package/dist/index.js +205 -38
  85. package/dist/lib/acp/client.d.ts +31 -0
  86. package/dist/lib/acp/client.js +117 -0
  87. package/dist/lib/acp/harnesses.d.ts +26 -0
  88. package/dist/lib/acp/harnesses.js +65 -0
  89. package/dist/lib/acp/run.d.ts +18 -0
  90. package/dist/lib/acp/run.js +39 -0
  91. package/dist/lib/agents.d.ts +74 -2
  92. package/dist/lib/agents.js +207 -23
  93. package/dist/lib/artifact-actions.d.ts +8 -4
  94. package/dist/lib/artifact-actions.js +8 -6
  95. package/dist/lib/auto-pull-worker.d.ts +11 -0
  96. package/dist/lib/auto-pull-worker.js +121 -0
  97. package/dist/lib/auto-pull.d.ts +31 -0
  98. package/dist/lib/auto-pull.js +97 -0
  99. package/dist/lib/beta.d.ts +23 -0
  100. package/dist/lib/beta.js +90 -0
  101. package/dist/lib/capabilities.d.ts +29 -0
  102. package/dist/lib/capabilities.js +74 -0
  103. package/dist/lib/cloud/codex.d.ts +25 -0
  104. package/dist/lib/cloud/codex.js +250 -0
  105. package/dist/lib/cloud/factory.d.ts +31 -0
  106. package/dist/lib/cloud/factory.js +53 -0
  107. package/dist/lib/cloud/registry.d.ts +15 -0
  108. package/dist/lib/cloud/registry.js +67 -0
  109. package/dist/lib/cloud/rush.d.ts +75 -0
  110. package/dist/lib/cloud/rush.js +438 -0
  111. package/dist/lib/cloud/store.d.ts +22 -0
  112. package/dist/lib/cloud/store.js +115 -0
  113. package/dist/lib/cloud/stream.d.ts +23 -0
  114. package/dist/lib/cloud/stream.js +194 -0
  115. package/dist/lib/cloud/types.d.ts +205 -0
  116. package/dist/lib/cloud/types.js +34 -0
  117. package/dist/lib/command-skills.d.ts +20 -0
  118. package/dist/lib/command-skills.js +142 -0
  119. package/dist/lib/commands.d.ts +22 -2
  120. package/dist/lib/commands.js +51 -11
  121. package/dist/lib/convert.d.ts +10 -1
  122. package/dist/lib/convert.js +9 -1
  123. package/dist/lib/daemon.d.ts +21 -1
  124. package/dist/lib/daemon.js +97 -4
  125. package/dist/lib/drive-sync.d.ts +18 -1
  126. package/dist/lib/drive-sync.js +57 -15
  127. package/dist/lib/exec.d.ts +25 -5
  128. package/dist/lib/exec.js +72 -27
  129. package/dist/lib/fs-walk.d.ts +2 -0
  130. package/dist/lib/fs-walk.js +40 -0
  131. package/dist/lib/fuzzy.d.ts +53 -0
  132. package/dist/lib/fuzzy.js +72 -0
  133. package/dist/lib/gemini-settings.d.ts +4 -0
  134. package/dist/lib/gemini-settings.js +33 -0
  135. package/dist/lib/git.d.ts +12 -2
  136. package/dist/lib/git.js +17 -6
  137. package/dist/lib/help.d.ts +20 -1
  138. package/dist/lib/help.js +45 -6
  139. package/dist/lib/hooks/match.d.ts +32 -0
  140. package/dist/lib/hooks/match.js +120 -0
  141. package/dist/lib/hooks.d.ts +17 -4
  142. package/dist/lib/hooks.js +191 -21
  143. package/dist/lib/manifest.d.ts +6 -1
  144. package/dist/lib/manifest.js +15 -4
  145. package/dist/lib/markdown.d.ts +0 -1
  146. package/dist/lib/markdown.js +6 -1
  147. package/dist/lib/mcp.d.ts +0 -1
  148. package/dist/lib/mcp.js +29 -33
  149. package/dist/lib/memory-compile.d.ts +13 -3
  150. package/dist/lib/memory-compile.js +31 -9
  151. package/dist/lib/memory.d.ts +14 -7
  152. package/dist/lib/memory.js +67 -38
  153. package/dist/lib/migrate.d.ts +8 -0
  154. package/dist/lib/migrate.js +85 -0
  155. package/dist/lib/models.d.ts +25 -11
  156. package/dist/lib/models.js +405 -16
  157. package/dist/lib/onepassword.d.ts +63 -0
  158. package/dist/lib/onepassword.js +186 -0
  159. package/dist/lib/paths.d.ts +8 -0
  160. package/dist/lib/paths.js +20 -0
  161. package/dist/lib/permissions.d.ts +24 -2
  162. package/dist/lib/permissions.js +117 -48
  163. package/dist/lib/picker.d.ts +10 -1
  164. package/dist/lib/picker.js +15 -1
  165. package/dist/lib/plugins.d.ts +7 -1
  166. package/dist/lib/plugins.js +10 -1
  167. package/dist/lib/profiles-presets.d.ts +24 -0
  168. package/dist/lib/profiles-presets.js +103 -0
  169. package/dist/lib/profiles.d.ts +69 -0
  170. package/dist/lib/profiles.js +144 -0
  171. package/dist/lib/pty-client.d.ts +1 -1
  172. package/dist/lib/pty-client.js +0 -1
  173. package/dist/lib/pty-server.d.ts +16 -2
  174. package/dist/lib/pty-server.js +92 -3
  175. package/dist/lib/registry.d.ts +23 -3
  176. package/dist/lib/registry.js +153 -8
  177. package/dist/lib/resources.d.ts +28 -1
  178. package/dist/lib/resources.js +79 -1
  179. package/dist/lib/rotate.d.ts +89 -0
  180. package/dist/lib/rotate.js +327 -0
  181. package/dist/lib/routines.d.ts +29 -1
  182. package/dist/lib/routines.js +32 -5
  183. package/dist/lib/runner.d.ts +14 -1
  184. package/dist/lib/runner.js +22 -3
  185. package/dist/lib/sandbox.d.ts +16 -1
  186. package/dist/lib/sandbox.js +39 -16
  187. package/dist/lib/scheduler.d.ts +8 -1
  188. package/dist/lib/scheduler.js +8 -1
  189. package/dist/lib/secrets/AgentsKeychain.app/Contents/CodeResources +0 -0
  190. package/dist/lib/secrets/AgentsKeychain.app/Contents/Info.plist +22 -0
  191. package/dist/lib/secrets/AgentsKeychain.app/Contents/MacOS/AgentsKeychain +0 -0
  192. package/dist/lib/secrets/AgentsKeychain.app/Contents/_CodeSignature/CodeResources +123 -0
  193. package/dist/lib/secrets/AgentsKeychain.app/Contents/embedded.provisionprofile +0 -0
  194. package/dist/lib/secrets/bundles.d.ts +39 -0
  195. package/dist/lib/secrets/bundles.js +189 -0
  196. package/dist/lib/secrets/index.d.ts +55 -0
  197. package/dist/lib/secrets/index.js +211 -0
  198. package/dist/lib/secrets/profiles.d.ts +10 -0
  199. package/dist/lib/secrets/profiles.js +13 -0
  200. package/dist/lib/session/active.d.ts +43 -0
  201. package/dist/lib/session/active.js +392 -0
  202. package/dist/lib/session/artifacts.d.ts +16 -0
  203. package/dist/lib/session/artifacts.js +95 -0
  204. package/dist/lib/session/cloud.d.ts +30 -0
  205. package/dist/lib/session/cloud.js +121 -0
  206. package/dist/lib/session/db.d.ts +23 -2
  207. package/dist/lib/session/db.js +76 -12
  208. package/dist/lib/session/discover.d.ts +19 -4
  209. package/dist/lib/session/discover.js +344 -48
  210. package/dist/lib/session/parse.d.ts +28 -1
  211. package/dist/lib/session/parse.js +267 -9
  212. package/dist/lib/session/prompt.d.ts +9 -1
  213. package/dist/lib/session/prompt.js +17 -3
  214. package/dist/lib/session/render.d.ts +13 -1
  215. package/dist/lib/session/render.js +20 -1
  216. package/dist/lib/session/team-filter.d.ts +9 -1
  217. package/dist/lib/session/team-filter.js +11 -2
  218. package/dist/lib/session/types.d.ts +24 -2
  219. package/dist/lib/session/types.js +10 -2
  220. package/dist/lib/shims.d.ts +93 -5
  221. package/dist/lib/shims.js +380 -67
  222. package/dist/lib/skills.d.ts +27 -2
  223. package/dist/lib/skills.js +127 -65
  224. package/dist/lib/sqlite.d.ts +43 -0
  225. package/dist/lib/sqlite.js +94 -0
  226. package/dist/lib/state.d.ts +114 -22
  227. package/dist/lib/state.js +323 -138
  228. package/dist/lib/subagents.d.ts +9 -1
  229. package/dist/lib/subagents.js +70 -63
  230. package/dist/lib/sync-manifest.d.ts +81 -0
  231. package/dist/lib/sync-manifest.js +450 -0
  232. package/dist/lib/teams/agents.d.ts +103 -5
  233. package/dist/lib/teams/agents.js +414 -91
  234. package/dist/lib/teams/api.d.ts +26 -3
  235. package/dist/lib/teams/api.js +63 -3
  236. package/dist/lib/teams/debug.d.ts +6 -1
  237. package/dist/lib/teams/debug.js +6 -1
  238. package/dist/lib/teams/file_ops.d.ts +7 -1
  239. package/dist/lib/teams/file_ops.js +7 -1
  240. package/dist/lib/teams/index.d.ts +15 -0
  241. package/dist/lib/teams/index.js +14 -0
  242. package/dist/lib/teams/parsers.d.ts +4 -1
  243. package/dist/lib/teams/parsers.js +11 -1
  244. package/dist/lib/teams/persistence.d.ts +15 -1
  245. package/dist/lib/teams/persistence.js +102 -20
  246. package/dist/lib/teams/registry.d.ts +12 -1
  247. package/dist/lib/teams/registry.js +116 -33
  248. package/dist/lib/teams/summarizer.d.ts +15 -1
  249. package/dist/lib/teams/summarizer.js +14 -1
  250. package/dist/lib/teams/supervisor.d.ts +48 -0
  251. package/dist/lib/teams/supervisor.js +73 -0
  252. package/dist/lib/template.d.ts +8 -6
  253. package/dist/lib/template.js +8 -6
  254. package/dist/lib/types.d.ts +147 -8
  255. package/dist/lib/types.js +26 -3
  256. package/dist/lib/usage.d.ts +48 -1
  257. package/dist/lib/usage.js +97 -16
  258. package/dist/lib/version-duplicates.d.ts +21 -0
  259. package/dist/lib/version-duplicates.js +90 -0
  260. package/dist/lib/versions.d.ts +39 -4
  261. package/dist/lib/versions.js +401 -111
  262. package/package.json +33 -18
  263. package/scripts/postinstall.js +126 -30
  264. package/dist/commands/__tests__/sessions.test.d.ts +0 -2
  265. package/dist/commands/__tests__/sessions.test.d.ts.map +0 -1
  266. package/dist/commands/__tests__/sessions.test.js +0 -636
  267. package/dist/commands/__tests__/sessions.test.js.map +0 -1
  268. package/dist/commands/commands.d.ts.map +0 -1
  269. package/dist/commands/commands.js.map +0 -1
  270. package/dist/commands/daemon.d.ts.map +0 -1
  271. package/dist/commands/daemon.js.map +0 -1
  272. package/dist/commands/drive.d.ts.map +0 -1
  273. package/dist/commands/drive.js.map +0 -1
  274. package/dist/commands/exec.d.ts.map +0 -1
  275. package/dist/commands/exec.js.map +0 -1
  276. package/dist/commands/fork.d.ts.map +0 -1
  277. package/dist/commands/fork.js.map +0 -1
  278. package/dist/commands/hooks.d.ts.map +0 -1
  279. package/dist/commands/hooks.js.map +0 -1
  280. package/dist/commands/init.d.ts.map +0 -1
  281. package/dist/commands/init.js.map +0 -1
  282. package/dist/commands/mcp.d.ts.map +0 -1
  283. package/dist/commands/mcp.js.map +0 -1
  284. package/dist/commands/models.d.ts.map +0 -1
  285. package/dist/commands/models.js.map +0 -1
  286. package/dist/commands/packages.d.ts.map +0 -1
  287. package/dist/commands/packages.js.map +0 -1
  288. package/dist/commands/permissions.d.ts.map +0 -1
  289. package/dist/commands/permissions.js.map +0 -1
  290. package/dist/commands/plugins.d.ts.map +0 -1
  291. package/dist/commands/plugins.js.map +0 -1
  292. package/dist/commands/pty.d.ts.map +0 -1
  293. package/dist/commands/pty.js.map +0 -1
  294. package/dist/commands/pull.d.ts.map +0 -1
  295. package/dist/commands/pull.js.map +0 -1
  296. package/dist/commands/push.d.ts +0 -3
  297. package/dist/commands/push.d.ts.map +0 -1
  298. package/dist/commands/push.js +0 -180
  299. package/dist/commands/push.js.map +0 -1
  300. package/dist/commands/refresh-memory.d.ts.map +0 -1
  301. package/dist/commands/refresh-memory.js.map +0 -1
  302. package/dist/commands/resource-view.d.ts.map +0 -1
  303. package/dist/commands/resource-view.js.map +0 -1
  304. package/dist/commands/routines.d.ts.map +0 -1
  305. package/dist/commands/routines.js.map +0 -1
  306. package/dist/commands/rules.d.ts.map +0 -1
  307. package/dist/commands/rules.js.map +0 -1
  308. package/dist/commands/sessions-picker.d.ts.map +0 -1
  309. package/dist/commands/sessions-picker.js.map +0 -1
  310. package/dist/commands/sessions.d.ts.map +0 -1
  311. package/dist/commands/sessions.js.map +0 -1
  312. package/dist/commands/skills.d.ts.map +0 -1
  313. package/dist/commands/skills.js.map +0 -1
  314. package/dist/commands/status.d.ts.map +0 -1
  315. package/dist/commands/status.js.map +0 -1
  316. package/dist/commands/subagents.d.ts.map +0 -1
  317. package/dist/commands/subagents.js.map +0 -1
  318. package/dist/commands/sync.d.ts.map +0 -1
  319. package/dist/commands/sync.js.map +0 -1
  320. package/dist/commands/teams-picker.d.ts.map +0 -1
  321. package/dist/commands/teams-picker.js.map +0 -1
  322. package/dist/commands/teams.d.ts.map +0 -1
  323. package/dist/commands/teams.js.map +0 -1
  324. package/dist/commands/utils.d.ts.map +0 -1
  325. package/dist/commands/utils.js.map +0 -1
  326. package/dist/commands/versions.d.ts.map +0 -1
  327. package/dist/commands/versions.js.map +0 -1
  328. package/dist/commands/view.d.ts.map +0 -1
  329. package/dist/commands/view.js.map +0 -1
  330. package/dist/index.d.ts.map +0 -1
  331. package/dist/index.js.map +0 -1
  332. package/dist/lib/__tests__/bugfixes.test.d.ts +0 -2
  333. package/dist/lib/__tests__/bugfixes.test.d.ts.map +0 -1
  334. package/dist/lib/__tests__/bugfixes.test.js +0 -192
  335. package/dist/lib/__tests__/bugfixes.test.js.map +0 -1
  336. package/dist/lib/__tests__/exec.test.d.ts +0 -2
  337. package/dist/lib/__tests__/exec.test.d.ts.map +0 -1
  338. package/dist/lib/__tests__/exec.test.js +0 -446
  339. package/dist/lib/__tests__/exec.test.js.map +0 -1
  340. package/dist/lib/__tests__/git-sync.test.d.ts +0 -2
  341. package/dist/lib/__tests__/git-sync.test.d.ts.map +0 -1
  342. package/dist/lib/__tests__/git-sync.test.js +0 -138
  343. package/dist/lib/__tests__/git-sync.test.js.map +0 -1
  344. package/dist/lib/__tests__/hooks.test.d.ts +0 -2
  345. package/dist/lib/__tests__/hooks.test.d.ts.map +0 -1
  346. package/dist/lib/__tests__/hooks.test.js +0 -203
  347. package/dist/lib/__tests__/hooks.test.js.map +0 -1
  348. package/dist/lib/__tests__/memory-compile.test.d.ts +0 -2
  349. package/dist/lib/__tests__/memory-compile.test.d.ts.map +0 -1
  350. package/dist/lib/__tests__/memory-compile.test.js +0 -95
  351. package/dist/lib/__tests__/memory-compile.test.js.map +0 -1
  352. package/dist/lib/__tests__/models.test.d.ts +0 -2
  353. package/dist/lib/__tests__/models.test.d.ts.map +0 -1
  354. package/dist/lib/__tests__/models.test.js +0 -184
  355. package/dist/lib/__tests__/models.test.js.map +0 -1
  356. package/dist/lib/__tests__/usage.test.d.ts +0 -2
  357. package/dist/lib/__tests__/usage.test.d.ts.map +0 -1
  358. package/dist/lib/__tests__/usage.test.js +0 -218
  359. package/dist/lib/__tests__/usage.test.js.map +0 -1
  360. package/dist/lib/agents.d.ts.map +0 -1
  361. package/dist/lib/agents.js.map +0 -1
  362. package/dist/lib/artifact-actions.d.ts.map +0 -1
  363. package/dist/lib/artifact-actions.js.map +0 -1
  364. package/dist/lib/commands.d.ts.map +0 -1
  365. package/dist/lib/commands.js.map +0 -1
  366. package/dist/lib/convert.d.ts.map +0 -1
  367. package/dist/lib/convert.js.map +0 -1
  368. package/dist/lib/daemon.d.ts.map +0 -1
  369. package/dist/lib/daemon.js.map +0 -1
  370. package/dist/lib/drive-sync.d.ts.map +0 -1
  371. package/dist/lib/drive-sync.js.map +0 -1
  372. package/dist/lib/exec.d.ts.map +0 -1
  373. package/dist/lib/exec.js.map +0 -1
  374. package/dist/lib/factory.d.ts +0 -57
  375. package/dist/lib/factory.d.ts.map +0 -1
  376. package/dist/lib/factory.js +0 -110
  377. package/dist/lib/factory.js.map +0 -1
  378. package/dist/lib/git.d.ts.map +0 -1
  379. package/dist/lib/git.js.map +0 -1
  380. package/dist/lib/help.d.ts.map +0 -1
  381. package/dist/lib/help.js.map +0 -1
  382. package/dist/lib/hooks.d.ts.map +0 -1
  383. package/dist/lib/hooks.js.map +0 -1
  384. package/dist/lib/manifest.d.ts.map +0 -1
  385. package/dist/lib/manifest.js.map +0 -1
  386. package/dist/lib/markdown.d.ts.map +0 -1
  387. package/dist/lib/markdown.js.map +0 -1
  388. package/dist/lib/mcp.d.ts.map +0 -1
  389. package/dist/lib/mcp.js.map +0 -1
  390. package/dist/lib/memory-compile.d.ts.map +0 -1
  391. package/dist/lib/memory-compile.js.map +0 -1
  392. package/dist/lib/memory.d.ts.map +0 -1
  393. package/dist/lib/memory.js.map +0 -1
  394. package/dist/lib/models.d.ts.map +0 -1
  395. package/dist/lib/models.js.map +0 -1
  396. package/dist/lib/permissions.d.ts.map +0 -1
  397. package/dist/lib/permissions.js.map +0 -1
  398. package/dist/lib/picker.d.ts.map +0 -1
  399. package/dist/lib/picker.js.map +0 -1
  400. package/dist/lib/plugins.d.ts.map +0 -1
  401. package/dist/lib/plugins.js.map +0 -1
  402. package/dist/lib/pty-client.d.ts.map +0 -1
  403. package/dist/lib/pty-client.js.map +0 -1
  404. package/dist/lib/pty-server.d.ts.map +0 -1
  405. package/dist/lib/pty-server.js.map +0 -1
  406. package/dist/lib/registry.d.ts.map +0 -1
  407. package/dist/lib/registry.js.map +0 -1
  408. package/dist/lib/resources.d.ts.map +0 -1
  409. package/dist/lib/resources.js.map +0 -1
  410. package/dist/lib/routines.d.ts.map +0 -1
  411. package/dist/lib/routines.js.map +0 -1
  412. package/dist/lib/runner.d.ts.map +0 -1
  413. package/dist/lib/runner.js.map +0 -1
  414. package/dist/lib/sandbox.d.ts.map +0 -1
  415. package/dist/lib/sandbox.js.map +0 -1
  416. package/dist/lib/scheduler.d.ts.map +0 -1
  417. package/dist/lib/scheduler.js.map +0 -1
  418. package/dist/lib/session/__tests__/db.test.d.ts +0 -2
  419. package/dist/lib/session/__tests__/db.test.d.ts.map +0 -1
  420. package/dist/lib/session/__tests__/db.test.js +0 -54
  421. package/dist/lib/session/__tests__/db.test.js.map +0 -1
  422. package/dist/lib/session/__tests__/discover.test.d.ts +0 -2
  423. package/dist/lib/session/__tests__/discover.test.d.ts.map +0 -1
  424. package/dist/lib/session/__tests__/discover.test.js +0 -63
  425. package/dist/lib/session/__tests__/discover.test.js.map +0 -1
  426. package/dist/lib/session/__tests__/prompt.test.d.ts +0 -2
  427. package/dist/lib/session/__tests__/prompt.test.d.ts.map +0 -1
  428. package/dist/lib/session/__tests__/prompt.test.js +0 -44
  429. package/dist/lib/session/__tests__/prompt.test.js.map +0 -1
  430. package/dist/lib/session/__tests__/render.test.d.ts +0 -2
  431. package/dist/lib/session/__tests__/render.test.d.ts.map +0 -1
  432. package/dist/lib/session/__tests__/render.test.js +0 -602
  433. package/dist/lib/session/__tests__/render.test.js.map +0 -1
  434. package/dist/lib/session/db.d.ts.map +0 -1
  435. package/dist/lib/session/db.js.map +0 -1
  436. package/dist/lib/session/discover.d.ts.map +0 -1
  437. package/dist/lib/session/discover.js.map +0 -1
  438. package/dist/lib/session/parse.d.ts.map +0 -1
  439. package/dist/lib/session/parse.js.map +0 -1
  440. package/dist/lib/session/prompt.d.ts.map +0 -1
  441. package/dist/lib/session/prompt.js.map +0 -1
  442. package/dist/lib/session/prompt.test.d.ts +0 -2
  443. package/dist/lib/session/prompt.test.d.ts.map +0 -1
  444. package/dist/lib/session/prompt.test.js +0 -57
  445. package/dist/lib/session/prompt.test.js.map +0 -1
  446. package/dist/lib/session/render.d.ts.map +0 -1
  447. package/dist/lib/session/render.js.map +0 -1
  448. package/dist/lib/session/team-filter.d.ts.map +0 -1
  449. package/dist/lib/session/team-filter.js.map +0 -1
  450. package/dist/lib/session/team-filter.test.d.ts +0 -2
  451. package/dist/lib/session/team-filter.test.d.ts.map +0 -1
  452. package/dist/lib/session/team-filter.test.js +0 -157
  453. package/dist/lib/session/team-filter.test.js.map +0 -1
  454. package/dist/lib/session/types.d.ts.map +0 -1
  455. package/dist/lib/session/types.js.map +0 -1
  456. package/dist/lib/shims.d.ts.map +0 -1
  457. package/dist/lib/shims.js.map +0 -1
  458. package/dist/lib/skills.d.ts.map +0 -1
  459. package/dist/lib/skills.js.map +0 -1
  460. package/dist/lib/state.d.ts.map +0 -1
  461. package/dist/lib/state.js.map +0 -1
  462. package/dist/lib/subagents.d.ts.map +0 -1
  463. package/dist/lib/subagents.js.map +0 -1
  464. package/dist/lib/teams/agents.d.ts.map +0 -1
  465. package/dist/lib/teams/agents.js.map +0 -1
  466. package/dist/lib/teams/api.d.ts.map +0 -1
  467. package/dist/lib/teams/api.js.map +0 -1
  468. package/dist/lib/teams/cloud.d.ts +0 -11
  469. package/dist/lib/teams/cloud.d.ts.map +0 -1
  470. package/dist/lib/teams/cloud.js +0 -169
  471. package/dist/lib/teams/cloud.js.map +0 -1
  472. package/dist/lib/teams/debug.d.ts.map +0 -1
  473. package/dist/lib/teams/debug.js.map +0 -1
  474. package/dist/lib/teams/file_ops.d.ts.map +0 -1
  475. package/dist/lib/teams/file_ops.js.map +0 -1
  476. package/dist/lib/teams/parsers.d.ts.map +0 -1
  477. package/dist/lib/teams/parsers.js.map +0 -1
  478. package/dist/lib/teams/persistence.d.ts.map +0 -1
  479. package/dist/lib/teams/persistence.js.map +0 -1
  480. package/dist/lib/teams/ralph.d.ts +0 -8
  481. package/dist/lib/teams/ralph.d.ts.map +0 -1
  482. package/dist/lib/teams/ralph.js +0 -59
  483. package/dist/lib/teams/ralph.js.map +0 -1
  484. package/dist/lib/teams/registry.d.ts.map +0 -1
  485. package/dist/lib/teams/registry.js.map +0 -1
  486. package/dist/lib/teams/summarizer.d.ts.map +0 -1
  487. package/dist/lib/teams/summarizer.js.map +0 -1
  488. package/dist/lib/template.d.ts.map +0 -1
  489. package/dist/lib/template.js.map +0 -1
  490. package/dist/lib/types.d.ts.map +0 -1
  491. package/dist/lib/types.js.map +0 -1
  492. package/dist/lib/usage.d.ts.map +0 -1
  493. package/dist/lib/usage.js.map +0 -1
  494. package/dist/lib/versions.d.ts.map +0 -1
  495. package/dist/lib/versions.js.map +0 -1
  496. package/scripts/rebuild-sqlite.sh +0 -46
@@ -1,10 +1,20 @@
1
+ /**
2
+ * Slash command management -- discovery, installation, and syncing.
3
+ *
4
+ * Commands are markdown files in ~/.agents/commands/ exposed as `/command-name`
5
+ * shortcuts by agents. This module discovers them, converts between formats
6
+ * (markdown for Claude/Codex, TOML for Gemini), and installs them into
7
+ * agent version homes.
8
+ */
1
9
  import * as fs from 'fs';
2
10
  import * as path from 'path';
3
11
  import * as yaml from 'yaml';
4
12
  import { AGENTS, COMMANDS_CAPABLE_AGENTS, ensureCommandsDir } from './agents.js';
5
13
  import { markdownToToml } from './convert.js';
6
- import { getCommandsDir, getProjectAgentsDir } from './state.js';
14
+ import { getCommandsDir, getUserCommandsDir, getEnabledExtraRepos, getProjectAgentsDir, getSkillsDir } from './state.js';
7
15
  import { getEffectiveHome, getVersionHomePath, listInstalledVersions } from './versions.js';
16
+ import { commandSkillMatches, installCommandSkillToVersion, listCommandSkillsInVersion, removeCommandSkillFromVersion, shouldInstallCommandAsSkill, } from './command-skills.js';
17
+ /** Parse command metadata (name, description) from YAML frontmatter or TOML headers. */
8
18
  export function parseCommandMetadata(filePath) {
9
19
  if (!fs.existsSync(filePath)) {
10
20
  return null;
@@ -40,6 +50,7 @@ export function parseCommandMetadata(filePath) {
40
50
  return null;
41
51
  }
42
52
  }
53
+ /** Validate command metadata, returning errors and warnings. */
43
54
  export function validateCommandMetadata(metadata, commandName) {
44
55
  const errors = [];
45
56
  const warnings = [];
@@ -61,6 +72,7 @@ export function validateCommandMetadata(metadata, commandName) {
61
72
  }
62
73
  return { valid: errors.length === 0, errors, warnings };
63
74
  }
75
+ /** Discover all command markdown files in a repository's commands/ directory. */
64
76
  export function discoverCommands(repoPath) {
65
77
  const commands = [];
66
78
  const commandsDir = path.join(repoPath, 'commands');
@@ -93,6 +105,7 @@ function extractDescription(content) {
93
105
  const firstLine = content.split('\n').find((l) => l.trim() && !l.startsWith('---'));
94
106
  return firstLine?.slice(0, 80) || '';
95
107
  }
108
+ /** Find the source path for a command in a repository. */
96
109
  export function resolveCommandSource(repoPath, commandName) {
97
110
  const commandPath = path.join(repoPath, 'commands', `${commandName}.md`);
98
111
  if (fs.existsSync(commandPath)) {
@@ -100,6 +113,7 @@ export function resolveCommandSource(repoPath, commandName) {
100
113
  }
101
114
  return null;
102
115
  }
116
+ /** Install a command into an agent's config directory, with optional format conversion. */
103
117
  export function installCommand(sourcePath, agentId, commandName, method = 'symlink') {
104
118
  // Validate command metadata before installation
105
119
  const metadata = parseCommandMetadata(sourcePath);
@@ -149,6 +163,11 @@ export function getVersionCommandsDir(agent, version) {
149
163
  * List command names (without extension) installed in a specific version home.
150
164
  */
151
165
  export function listCommandsInVersionHome(agent, version) {
166
+ const versionHome = getVersionHomePath(agent, version);
167
+ const agentDir = path.join(versionHome, `.${agent}`);
168
+ if (shouldInstallCommandAsSkill(agent, version)) {
169
+ return listCommandSkillsInVersion(agentDir);
170
+ }
152
171
  const dir = getVersionCommandsDir(agent, version);
153
172
  if (!fs.existsSync(dir))
154
173
  return [];
@@ -166,6 +185,11 @@ function versionCommandMatches(agent, version, commandName) {
166
185
  const sourcePath = path.join(getCommandsDir(), `${commandName}.md`);
167
186
  if (!fs.existsSync(sourcePath))
168
187
  return false;
188
+ const versionHome = getVersionHomePath(agent, version);
189
+ const agentDir = path.join(versionHome, `.${agent}`);
190
+ if (shouldInstallCommandAsSkill(agent, version)) {
191
+ return commandSkillMatches(agentDir, commandName, sourcePath);
192
+ }
169
193
  const agentConfig = AGENTS[agent];
170
194
  const ext = agentConfig.format === 'toml' ? '.toml' : '.md';
171
195
  const installedPath = path.join(getVersionCommandsDir(agent, version), `${commandName}${ext}`);
@@ -220,6 +244,14 @@ export function installCommandToVersion(agent, version, commandName, method = 'c
220
244
  if (!fs.existsSync(sourcePath)) {
221
245
  return { success: false, error: `Command '${commandName}' not found in central` };
222
246
  }
247
+ const versionHome = getVersionHomePath(agent, version);
248
+ const agentDir = path.join(versionHome, `.${agent}`);
249
+ if (shouldInstallCommandAsSkill(agent, version)) {
250
+ return installCommandSkillToVersion(agentDir, commandName, sourcePath, [
251
+ getSkillsDir(),
252
+ ...getEnabledExtraRepos().map((repo) => path.join(repo.dir, 'skills')),
253
+ ]);
254
+ }
223
255
  const agentConfig = AGENTS[agent];
224
256
  const commandsDir = getVersionCommandsDir(agent, version);
225
257
  fs.mkdirSync(commandsDir, { recursive: true });
@@ -249,6 +281,11 @@ export function installCommandToVersion(agent, version, commandName, method = 'c
249
281
  * Remove a single command from a specific version home.
250
282
  */
251
283
  export function removeCommandFromVersion(agent, version, commandName) {
284
+ const versionHome = getVersionHomePath(agent, version);
285
+ const agentDir = path.join(versionHome, `.${agent}`);
286
+ if (shouldInstallCommandAsSkill(agent, version)) {
287
+ return removeCommandSkillFromVersion(agentDir, commandName);
288
+ }
252
289
  const ext = AGENTS[agent].format === 'toml' ? '.toml' : '.md';
253
290
  const targetPath = path.join(getVersionCommandsDir(agent, version), `${commandName}${ext}`);
254
291
  if (!fs.existsSync(targetPath) && !fs.lstatSync(targetPath, { throwIfNoEntry: false })) {
@@ -281,6 +318,7 @@ export function iterCommandsCapableVersions(filter) {
281
318
  }
282
319
  return pairs;
283
320
  }
321
+ /** Remove a command from an agent's config directory. */
284
322
  export function uninstallCommand(agentId, commandName) {
285
323
  const agent = AGENTS[agentId];
286
324
  const home = getEffectiveHome(agentId);
@@ -293,6 +331,7 @@ export function uninstallCommand(agentId, commandName) {
293
331
  }
294
332
  return false;
295
333
  }
334
+ /** List command names installed for an agent in the active version home. */
296
335
  export function listInstalledCommands(agentId) {
297
336
  const agent = AGENTS[agentId];
298
337
  const home = getEffectiveHome(agentId);
@@ -448,7 +487,7 @@ export function installCommandCentrally(sourcePath, commandName) {
448
487
  warnings: validation.warnings,
449
488
  };
450
489
  }
451
- const centralDir = getCommandsDir();
490
+ const centralDir = getUserCommandsDir();
452
491
  if (!fs.existsSync(centralDir)) {
453
492
  fs.mkdirSync(centralDir, { recursive: true });
454
493
  }
@@ -466,17 +505,19 @@ export function installCommandCentrally(sourcePath, commandName) {
466
505
  }
467
506
  }
468
507
  /**
469
- * List commands from central ~/.agents/commands/ directory.
508
+ * List commands from user (~/.agents/commands/) and system (~/.agents-system/commands/) dirs.
509
+ * User dir takes priority; deduplication preserves first occurrence.
470
510
  */
471
511
  export function listCentralCommands() {
472
- const centralDir = getCommandsDir();
473
- if (!fs.existsSync(centralDir)) {
474
- return [];
512
+ const seen = new Set();
513
+ for (const dir of [getUserCommandsDir(), getCommandsDir()]) {
514
+ if (!fs.existsSync(dir))
515
+ continue;
516
+ for (const f of fs.readdirSync(dir).filter((f) => f.endsWith('.md'))) {
517
+ seen.add(f.replace('.md', ''));
518
+ }
475
519
  }
476
- return fs
477
- .readdirSync(centralDir)
478
- .filter((f) => f.endsWith('.md'))
479
- .map((f) => f.replace('.md', ''));
520
+ return Array.from(seen);
480
521
  }
481
522
  /**
482
523
  * Get detailed info about a command from central storage.
@@ -496,4 +537,3 @@ export function getCommandInfo(name) {
496
537
  content,
497
538
  };
498
539
  }
499
- //# sourceMappingURL=commands.js.map
@@ -1,11 +1,20 @@
1
+ /**
2
+ * Format conversion between Markdown (Claude/Codex) and TOML (Gemini) command files.
3
+ *
4
+ * Handles frontmatter parsing and bidirectional translation so that slash commands
5
+ * authored in one format can be synced to agents that expect the other.
6
+ */
7
+ /** Parsed YAML frontmatter from a Markdown command file. */
1
8
  export interface MarkdownFrontmatter {
2
9
  description?: string;
3
10
  [key: string]: unknown;
4
11
  }
12
+ /** Extract YAML frontmatter and body from a Markdown string. Returns empty frontmatter if none found. */
5
13
  export declare function parseMarkdownFrontmatter(content: string): {
6
14
  frontmatter: MarkdownFrontmatter;
7
15
  body: string;
8
16
  };
17
+ /** Convert a Markdown command file to Gemini's TOML format, translating $ARGUMENTS to {{args}}. */
9
18
  export declare function markdownToToml(skillName: string, markdown: string): string;
19
+ /** Convert a Gemini TOML command file back to Markdown format, translating {{args}} to $ARGUMENTS. */
10
20
  export declare function tomlToMarkdown(toml: string): string;
11
- //# sourceMappingURL=convert.d.ts.map
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Format conversion between Markdown (Claude/Codex) and TOML (Gemini) command files.
3
+ *
4
+ * Handles frontmatter parsing and bidirectional translation so that slash commands
5
+ * authored in one format can be synced to agents that expect the other.
6
+ */
7
+ /** Extract YAML frontmatter and body from a Markdown string. Returns empty frontmatter if none found. */
1
8
  export function parseMarkdownFrontmatter(content) {
2
9
  const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
3
10
  if (!match) {
@@ -16,6 +23,7 @@ export function parseMarkdownFrontmatter(content) {
16
23
  }
17
24
  return { frontmatter, body };
18
25
  }
26
+ /** Convert a Markdown command file to Gemini's TOML format, translating $ARGUMENTS to {{args}}. */
19
27
  export function markdownToToml(skillName, markdown) {
20
28
  const { frontmatter, body } = parseMarkdownFrontmatter(markdown);
21
29
  const description = frontmatter.description || `Run ${skillName} command`;
@@ -32,6 +40,7 @@ export function markdownToToml(skillName, markdown) {
32
40
  ];
33
41
  return lines.join('\n');
34
42
  }
43
+ /** Convert a Gemini TOML command file back to Markdown format, translating {{args}} to $ARGUMENTS. */
35
44
  export function tomlToMarkdown(toml) {
36
45
  const nameMatch = toml.match(/name\s*=\s*"([^"]+)"/);
37
46
  const descMatch = toml.match(/description\s*=\s*"([^"]+)"/);
@@ -42,4 +51,3 @@ export function tomlToMarkdown(toml) {
42
51
  const lines = ['---', `description: ${description}`, '---', '', prompt, ''];
43
52
  return lines.join('\n');
44
53
  }
45
- //# sourceMappingURL=convert.js.map
@@ -1,22 +1,42 @@
1
+ /**
2
+ * Daemon lifecycle management for the routines scheduler.
3
+ *
4
+ * The daemon is a long-running process that holds a JobScheduler and
5
+ * triggers jobs on their cron schedules. It can be managed via launchd
6
+ * (macOS), systemd (Linux), or as a plain detached process. PID tracking,
7
+ * log output, reload (SIGHUP), and graceful shutdown are handled here.
8
+ */
9
+ /** Read the stored daemon PID from disk. Returns null if not present or invalid. */
1
10
  export declare function readDaemonPid(): number | null;
11
+ /** Write the daemon PID to the pid file. */
2
12
  export declare function writeDaemonPid(pid: number): void;
13
+ /** Remove the daemon PID file. */
3
14
  export declare function removeDaemonPid(): void;
15
+ /** Check if the daemon process is alive by sending signal 0 to the stored PID. */
4
16
  export declare function isDaemonRunning(): boolean;
17
+ /** Append a timestamped log line to the daemon log file (owner-only permissions). */
5
18
  export declare function log(level: string, message: string): void;
19
+ /** Main daemon loop: load jobs, schedule crons, monitor runs, and handle signals. */
6
20
  export declare function runDaemon(): Promise<void>;
21
+ /** Generate a macOS launchd plist for auto-starting the daemon. */
7
22
  export declare function generateLaunchdPlist(): string;
23
+ /** Generate a Linux systemd user unit for auto-starting the daemon. */
8
24
  export declare function generateSystemdUnit(): string;
25
+ /** Start the daemon via launchd, systemd, or as a detached process. */
9
26
  export declare function startDaemon(): {
10
27
  pid: number | null;
11
28
  method: string;
12
29
  };
30
+ /** Stop the daemon, unloading it from launchd/systemd if applicable. */
13
31
  export declare function stopDaemon(): boolean;
32
+ /** Get current daemon status including running state, PID, and enabled job count. */
14
33
  export declare function getDaemonStatus(): {
15
34
  running: boolean;
16
35
  pid: number | null;
17
36
  jobCount: number;
18
37
  logPath: string;
19
38
  };
39
+ /** Read the daemon log, optionally limited to the last N lines. */
20
40
  export declare function readDaemonLog(lines?: number): string;
41
+ /** Send SIGHUP to the daemon to trigger a job reload. */
21
42
  export declare function signalDaemonReload(): boolean;
22
- //# sourceMappingURL=daemon.d.ts.map
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Daemon lifecycle management for the routines scheduler.
3
+ *
4
+ * The daemon is a long-running process that holds a JobScheduler and
5
+ * triggers jobs on their cron schedules. It can be managed via launchd
6
+ * (macOS), systemd (Linux), or as a plain detached process. PID tracking,
7
+ * log output, reload (SIGHUP), and graceful shutdown are handled here.
8
+ */
1
9
  import { spawn, execSync } from 'child_process';
2
10
  import * as fs from 'fs';
3
11
  import * as path from 'path';
@@ -7,12 +15,57 @@ import { listJobs as listAllJobs } from './routines.js';
7
15
  import { JobScheduler } from './scheduler.js';
8
16
  import { executeJobDetached, monitorRunningJobs } from './runner.js';
9
17
  const PID_FILE = 'daemon.pid';
18
+ const LOCK_FILE = 'daemon.lock';
10
19
  const LOG_FILE = 'daemon.log';
11
- const PLIST_NAME = 'co.swarmify.agents-daemon';
20
+ const PLIST_NAME = 'com.phnx-labs.agents-daemon';
12
21
  const SYSTEMD_UNIT = 'agents-daemon.service';
13
22
  function getPidPath() {
14
23
  return path.join(getAgentsDir(), PID_FILE);
15
24
  }
25
+ function getLockPath() {
26
+ return path.join(getAgentsDir(), LOCK_FILE);
27
+ }
28
+ /**
29
+ * Acquire an exclusive start lock. Returns a release function on success,
30
+ * or null if another process already holds the lock. Uses O_EXCL to
31
+ * atomically create the file — no TOCTOU window.
32
+ */
33
+ function acquireStartLock() {
34
+ const lockPath = getLockPath();
35
+ try {
36
+ const fd = fs.openSync(lockPath, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY);
37
+ fs.writeSync(fd, String(process.pid));
38
+ fs.closeSync(fd);
39
+ return () => {
40
+ try {
41
+ fs.unlinkSync(lockPath);
42
+ }
43
+ catch { /* already removed */ }
44
+ };
45
+ }
46
+ catch (err) {
47
+ if (err.code === 'EEXIST') {
48
+ // Lock file exists — check if the holder is still alive (stale lock recovery)
49
+ try {
50
+ const holderPid = parseInt(fs.readFileSync(lockPath, 'utf-8').trim(), 10);
51
+ if (!isNaN(holderPid)) {
52
+ try {
53
+ process.kill(holderPid, 0);
54
+ return null; // holder is alive, lock is valid
55
+ }
56
+ catch {
57
+ // holder is dead, remove stale lock and retry once
58
+ fs.unlinkSync(lockPath);
59
+ return acquireStartLock();
60
+ }
61
+ }
62
+ }
63
+ catch { /* can't read lock file — treat as held */ }
64
+ return null;
65
+ }
66
+ throw err;
67
+ }
68
+ }
16
69
  function getLogPath() {
17
70
  return path.join(getAgentsDir(), LOG_FILE);
18
71
  }
@@ -22,6 +75,7 @@ function getLaunchdPlistPath() {
22
75
  function getSystemdUnitPath() {
23
76
  return path.join(os.homedir(), '.config', 'systemd', 'user', `${SYSTEMD_UNIT}`);
24
77
  }
78
+ /** Read the stored daemon PID from disk. Returns null if not present or invalid. */
25
79
  export function readDaemonPid() {
26
80
  const pidPath = getPidPath();
27
81
  if (!fs.existsSync(pidPath))
@@ -34,15 +88,18 @@ export function readDaemonPid() {
34
88
  return null;
35
89
  }
36
90
  }
91
+ /** Write the daemon PID to the pid file. */
37
92
  export function writeDaemonPid(pid) {
38
93
  fs.writeFileSync(getPidPath(), String(pid), 'utf-8');
39
94
  }
95
+ /** Remove the daemon PID file. */
40
96
  export function removeDaemonPid() {
41
97
  const pidPath = getPidPath();
42
98
  if (fs.existsSync(pidPath)) {
43
99
  fs.unlinkSync(pidPath);
44
100
  }
45
101
  }
102
+ /** Check if the daemon process is alive by sending signal 0 to the stored PID. */
46
103
  export function isDaemonRunning() {
47
104
  const pid = readDaemonPid();
48
105
  if (!pid)
@@ -56,11 +113,27 @@ export function isDaemonRunning() {
56
113
  return false;
57
114
  }
58
115
  }
116
+ /** Redact values that look like tokens or credentials in a log message. */
117
+ function redactSecrets(message) {
118
+ let safe = message;
119
+ safe = safe.replace(/eyJ[A-Za-z0-9_-]{20,}/g, '[REDACTED_TOKEN]');
120
+ safe = safe.replace(/Bearer\s+\S+/gi, 'Bearer [REDACTED]');
121
+ safe = safe.replace(/(sk-[a-zA-Z0-9]{20,})/g, '[REDACTED_KEY]');
122
+ safe = safe.replace(/(ANTHROPIC_API_KEY|OPENAI_API_KEY|API_KEY|SECRET|TOKEN|PASSWORD)=\S+/gi, '$1=[REDACTED]');
123
+ return safe;
124
+ }
125
+ /** Append a timestamped log line to the daemon log file (owner-only permissions). */
59
126
  export function log(level, message) {
60
127
  const timestamp = new Date().toISOString();
61
- const line = `[${timestamp}] [${level.toUpperCase()}] ${message}\n`;
62
- fs.appendFileSync(getLogPath(), line, 'utf-8');
128
+ const line = `[${timestamp}] [${level.toUpperCase()}] ${redactSecrets(message)}\n`;
129
+ const logPath = getLogPath();
130
+ fs.appendFileSync(logPath, line, 'utf-8');
131
+ try {
132
+ fs.chmodSync(logPath, 0o600);
133
+ }
134
+ catch { /* best effort */ }
63
135
  }
136
+ /** Main daemon loop: load jobs, schedule crons, monitor runs, and handle signals. */
64
137
  export async function runDaemon() {
65
138
  writeDaemonPid(process.pid);
66
139
  log('INFO', `Daemon started (PID: ${process.pid})`);
@@ -101,6 +174,7 @@ export async function runDaemon() {
101
174
  process.on('SIGINT', handleShutdown);
102
175
  await new Promise(() => { });
103
176
  }
177
+ /** Generate a macOS launchd plist for auto-starting the daemon. */
104
178
  export function generateLaunchdPlist() {
105
179
  const agentsBin = getAgentsBinPath();
106
180
  const logPath = getLogPath();
@@ -132,6 +206,7 @@ export function generateLaunchdPlist() {
132
206
  </dict>
133
207
  </plist>`;
134
208
  }
209
+ /** Generate a Linux systemd user unit for auto-starting the daemon. */
135
210
  export function generateSystemdUnit() {
136
211
  const agentsBin = getAgentsBinPath();
137
212
  return `[Unit]
@@ -156,11 +231,26 @@ function getAgentsBinPath() {
156
231
  return 'agents';
157
232
  }
158
233
  }
234
+ /** Start the daemon via launchd, systemd, or as a detached process. */
159
235
  export function startDaemon() {
160
236
  if (isDaemonRunning()) {
161
237
  const pid = readDaemonPid();
162
238
  return { pid, method: 'already-running' };
163
239
  }
240
+ const releaseLock = acquireStartLock();
241
+ if (!releaseLock) {
242
+ // Another process is already starting the daemon
243
+ const pid = waitForPid(3000);
244
+ return { pid, method: 'already-starting' };
245
+ }
246
+ try {
247
+ return startDaemonLocked();
248
+ }
249
+ finally {
250
+ releaseLock();
251
+ }
252
+ }
253
+ function startDaemonLocked() {
164
254
  const platform = os.platform();
165
255
  if (platform === 'darwin') {
166
256
  try {
@@ -225,6 +315,7 @@ function waitForPid(timeoutMs) {
225
315
  }
226
316
  return readDaemonPid();
227
317
  }
318
+ /** Stop the daemon, unloading it from launchd/systemd if applicable. */
228
319
  export function stopDaemon() {
229
320
  const platform = os.platform();
230
321
  if (platform === 'darwin') {
@@ -276,6 +367,7 @@ export function stopDaemon() {
276
367
  removeDaemonPid();
277
368
  return true;
278
369
  }
370
+ /** Get current daemon status including running state, PID, and enabled job count. */
279
371
  export function getDaemonStatus() {
280
372
  const running = isDaemonRunning();
281
373
  const pid = readDaemonPid();
@@ -286,6 +378,7 @@ export function getDaemonStatus() {
286
378
  catch { /* job listing failed */ }
287
379
  return { running, pid, jobCount, logPath: getLogPath() };
288
380
  }
381
+ /** Read the daemon log, optionally limited to the last N lines. */
289
382
  export function readDaemonLog(lines) {
290
383
  const logPath = getLogPath();
291
384
  if (!fs.existsSync(logPath))
@@ -296,6 +389,7 @@ export function readDaemonLog(lines) {
296
389
  const allLines = content.split('\n');
297
390
  return allLines.slice(-lines).join('\n');
298
391
  }
392
+ /** Send SIGHUP to the daemon to trigger a job reload. */
299
393
  export function signalDaemonReload() {
300
394
  const pid = readDaemonPid();
301
395
  if (!pid)
@@ -308,4 +402,3 @@ export function signalDaemonReload() {
308
402
  return false;
309
403
  }
310
404
  }
311
- //# sourceMappingURL=daemon.js.map
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Remote drive sync for agent sessions and config.
3
+ *
4
+ * Provides rsync-based push/pull between the local ~/.agents/drive/
5
+ * directory and a remote host, plus attach/detach to swap the active
6
+ * agent's config directory symlink to the drive directory (for working
7
+ * with a remote machine's session data locally).
8
+ */
9
+ /** Persisted drive configuration stored at ~/.agents/drive/config.json. */
1
10
  export interface DriveConfig {
2
11
  remote: string | null;
3
12
  attached: boolean;
@@ -8,13 +17,21 @@ export interface DriveConfig {
8
17
  lastPull: string | null;
9
18
  lastPush: string | null;
10
19
  }
20
+ /** Read drive config from disk, returning defaults if missing. */
11
21
  export declare function readDriveConfig(): DriveConfig;
22
+ /** Write drive config to disk. */
12
23
  export declare function writeDriveConfig(config: DriveConfig): void;
24
+ /** Set the remote target (user@host) for rsync operations. */
13
25
  export declare function setRemote(target: string): void;
26
+ /** Pull drive data from the remote host via rsync. */
14
27
  export declare function pull(): Promise<void>;
28
+ /** Push local drive data to the remote host via rsync. */
15
29
  export declare function push(): Promise<void>;
30
+ /** Attach drive by swapping the agent's config directory symlink to the drive directory. */
16
31
  export declare function attach(): void;
32
+ /** Detach drive by restoring the agent's config directory to its previous symlink target. */
17
33
  export declare function detach(): void;
34
+ /** Current drive state for display purposes. */
18
35
  export interface DriveStatus {
19
36
  remote: string | null;
20
37
  attached: boolean;
@@ -24,5 +41,5 @@ export interface DriveStatus {
24
41
  configDirTarget: string | null;
25
42
  homeFileTargets: Record<string, string | null>;
26
43
  }
44
+ /** Gather current drive status by inspecting config, symlinks, and timestamps. */
27
45
  export declare function getDriveStatus(): DriveStatus;
28
- //# sourceMappingURL=drive-sync.d.ts.map
@@ -1,27 +1,61 @@
1
+ /**
2
+ * Remote drive sync for agent sessions and config.
3
+ *
4
+ * Provides rsync-based push/pull between the local ~/.agents/drive/
5
+ * directory and a remote host, plus attach/detach to swap the active
6
+ * agent's config directory symlink to the drive directory (for working
7
+ * with a remote machine's session data locally).
8
+ */
1
9
  import * as fs from 'fs';
2
10
  import * as path from 'path';
3
11
  import * as os from 'os';
4
- import { exec } from 'child_process';
12
+ import { execFile } from 'child_process';
5
13
  import { promisify } from 'util';
6
14
  import { getDriveDir } from './state.js';
7
15
  import { AGENTS } from './agents.js';
8
- const execAsync = promisify(exec);
16
+ const execFileAsync = promisify(execFile);
17
+ // `remote` flows from disk into rsync/ssh argv. Use a strict regex so a
18
+ // tampered ~/.agents/drive/config.json can't sneak shell metacharacters or
19
+ // argv flags (leading -) past the boundary.
20
+ const REMOTE_RE = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+$/;
21
+ function assertValidRemote(remote) {
22
+ if (!REMOTE_RE.test(remote)) {
23
+ throw new Error(`Invalid drive remote: ${JSON.stringify(remote)}. Expected: user@host`);
24
+ }
25
+ }
9
26
  const AGENT = 'claude';
10
27
  function configPath() {
11
28
  return path.join(getDriveDir(), 'config.json');
12
29
  }
30
+ /** Read drive config from disk, returning defaults if missing. */
13
31
  export function readDriveConfig() {
14
32
  const p = configPath();
15
33
  if (fs.existsSync(p)) {
16
34
  try {
17
- return JSON.parse(fs.readFileSync(p, 'utf-8'));
35
+ const parsed = JSON.parse(fs.readFileSync(p, 'utf-8'));
36
+ // Re-validate `remote` on every read. setRemote validates on write, but
37
+ // the file can be tampered with out-of-band (a malicious skill, a synced
38
+ // config from a hostile repo, etc.) and pull/push shell out with the value.
39
+ if (parsed.remote != null) {
40
+ assertValidRemote(parsed.remote);
41
+ }
42
+ return parsed;
18
43
  }
19
- catch {
20
- // Fall through to default
44
+ catch (err) {
45
+ // If the config is malformed or has a tainted remote, fail closed rather
46
+ // than silently fall back to defaults — a tainted remote that fell back
47
+ // to null would mask the attack.
48
+ if (err instanceof SyntaxError) {
49
+ // Bad JSON: fall through to defaults.
50
+ }
51
+ else {
52
+ throw err;
53
+ }
21
54
  }
22
55
  }
23
56
  return { remote: null, attached: false, previousTargets: null, lastPull: null, lastPush: null };
24
57
  }
58
+ /** Write drive config to disk. */
25
59
  export function writeDriveConfig(config) {
26
60
  const dir = getDriveDir();
27
61
  if (!fs.existsSync(dir)) {
@@ -29,36 +63,43 @@ export function writeDriveConfig(config) {
29
63
  }
30
64
  fs.writeFileSync(configPath(), JSON.stringify(config, null, 2));
31
65
  }
66
+ /** Set the remote target (user@host) for rsync operations. */
32
67
  export function setRemote(target) {
33
- if (!target.match(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+$/)) {
34
- throw new Error(`Invalid remote: ${target}. Expected: user@host`);
35
- }
68
+ assertValidRemote(target);
36
69
  const config = readDriveConfig();
37
70
  config.remote = target;
38
71
  writeDriveConfig(config);
39
72
  }
73
+ /** Pull drive data from the remote host via rsync. */
40
74
  export async function pull() {
41
75
  const config = readDriveConfig();
42
76
  if (!config.remote)
43
77
  throw new Error('No remote configured. Run: agents drive remote <user@host>');
78
+ assertValidRemote(config.remote);
44
79
  const localDir = getDriveDir() + '/';
45
- const remote = `${config.remote}:~/.agents/drive/`;
46
- await execAsync(`rsync -az --exclude='config.json' ${remote} ${localDir}`);
80
+ const remoteSpec = `${config.remote}:~/.agents/drive/`;
81
+ // Argv form: no shell, no interpolation — even a tainted `config.remote` that
82
+ // somehow got past the regex cannot escape into command syntax.
83
+ await execFileAsync('rsync', ['-az', '--exclude=config.json', remoteSpec, localDir]);
47
84
  config.lastPull = new Date().toISOString();
48
85
  writeDriveConfig(config);
49
86
  }
87
+ /** Push local drive data to the remote host via rsync. */
50
88
  export async function push() {
51
89
  const config = readDriveConfig();
52
90
  if (!config.remote)
53
91
  throw new Error('No remote configured. Run: agents drive remote <user@host>');
92
+ assertValidRemote(config.remote);
54
93
  const localDir = getDriveDir() + '/';
55
- const remote = `${config.remote}:~/.agents/drive/`;
56
- // Ensure remote directory exists
57
- await execAsync(`ssh ${config.remote} 'mkdir -p ~/.agents/drive'`);
58
- await execAsync(`rsync -az --exclude='config.json' ${localDir} ${remote}`);
94
+ const remoteSpec = `${config.remote}:~/.agents/drive/`;
95
+ // Ensure remote directory exists. ssh's command argument is one positional
96
+ // string; we hand it as a single argv element so no local shell sees it.
97
+ await execFileAsync('ssh', [config.remote, 'mkdir -p ~/.agents/drive']);
98
+ await execFileAsync('rsync', ['-az', '--exclude=config.json', localDir, remoteSpec]);
59
99
  config.lastPush = new Date().toISOString();
60
100
  writeDriveConfig(config);
61
101
  }
102
+ /** Attach drive by swapping the agent's config directory symlink to the drive directory. */
62
103
  export function attach() {
63
104
  const config = readDriveConfig();
64
105
  if (config.attached)
@@ -123,6 +164,7 @@ export function attach() {
123
164
  config.attached = true;
124
165
  writeDriveConfig(config);
125
166
  }
167
+ /** Detach drive by restoring the agent's config directory to its previous symlink target. */
126
168
  export function detach() {
127
169
  const config = readDriveConfig();
128
170
  if (!config.attached)
@@ -151,6 +193,7 @@ export function detach() {
151
193
  config.previousTargets = null;
152
194
  writeDriveConfig(config);
153
195
  }
196
+ /** Gather current drive status by inspecting config, symlinks, and timestamps. */
154
197
  export function getDriveStatus() {
155
198
  const config = readDriveConfig();
156
199
  const home = os.homedir();
@@ -190,4 +233,3 @@ export function getDriveStatus() {
190
233
  homeFileTargets,
191
234
  };
192
235
  }
193
- //# sourceMappingURL=drive-sync.js.map