@dylanpiercey/work 0.0.47 → 0.0.48

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 (265) hide show
  1. package/bin/work.mjs +77 -47
  2. package/dist/{_DM_oFS_v.js → _CO83dVER.js} +446 -34
  3. package/dist/_DjrRGy4k.js +2 -0
  4. package/dist/{_o0dwm0Ww.js → _Hz_qlZE1.js} +59 -59
  5. package/dist/{_Dm4BVuln.js → _m3ryV1w6.js} +23 -22
  6. package/dist/index.mjs +2027 -662
  7. package/dist/public/assets/{_9CHuxVRu.js → _1cz-l3Ka.js} +1 -1
  8. package/dist/public/assets/_1cz-l3Ka.js.br +0 -0
  9. package/dist/public/assets/{_By0S6RFm2.js → _1oYv4fmY2.js} +1 -1
  10. package/dist/public/assets/_1oYv4fmY2.js.br +0 -0
  11. package/dist/public/assets/{_CfyASWBT2.js → _3i592Qvz2.js} +1 -1
  12. package/dist/public/assets/_3i592Qvz2.js.br +0 -0
  13. package/dist/public/assets/{_6fdNa05X2.js → _8nx9Raqx2.js} +1 -1
  14. package/dist/public/assets/_8nx9Raqx2.js.br +0 -0
  15. package/dist/public/assets/{_DJYs9cGt2.js → _9yP8iK4t2.js} +1 -1
  16. package/dist/public/assets/_9yP8iK4t2.js.br +0 -0
  17. package/dist/public/assets/{_zkaPdW0C2.js → _B-MMW3nb2.js} +1 -1
  18. package/dist/public/assets/_B-MMW3nb2.js.br +0 -0
  19. package/dist/public/assets/{_D1Ecsx8-2.js → _B2fn4I8S2.js} +1 -1
  20. package/dist/public/assets/_B2fn4I8S2.js.br +0 -0
  21. package/dist/public/assets/{_CrvHv7e4.js → _B49r6O_E.js} +1 -1
  22. package/dist/public/assets/_B49r6O_E.js.br +0 -0
  23. package/dist/public/assets/{_FZ5aDFyS.js → _BBW7mJhZ.js} +1 -1
  24. package/dist/public/assets/_BBW7mJhZ.js.br +0 -0
  25. package/dist/public/assets/{_fkktwOR8.js → _BC2FBUbj.js} +1 -1
  26. package/dist/public/assets/_BC2FBUbj.js.br +0 -0
  27. package/dist/public/assets/{_2_8X99jw.js → _BFt-jSq-.js} +1 -1
  28. package/dist/public/assets/_BFt-jSq-.js.br +0 -0
  29. package/dist/public/assets/{_BmH7JUGb2.js → _BGyMoPGj2.js} +1 -1
  30. package/dist/public/assets/_BGyMoPGj2.js.br +0 -0
  31. package/dist/public/assets/{_B8PQyubX.js → _BLjOZLxk.js} +1 -1
  32. package/dist/public/assets/_BLjOZLxk.js.br +0 -0
  33. package/dist/public/assets/{_BPq9uIVf.js → _BPFJiBiE.js} +1 -1
  34. package/dist/public/assets/_BPFJiBiE.js.br +0 -0
  35. package/dist/public/assets/{_DFC22iAc.js → _BPLnh5S4.js} +1 -1
  36. package/dist/public/assets/_BPLnh5S4.js.br +0 -0
  37. package/dist/public/assets/{_CMIAElmF.js → _BRzL7uNP.js} +1 -1
  38. package/dist/public/assets/_BRzL7uNP.js.br +0 -0
  39. package/dist/public/assets/{_DZExUZ7A.js → _BV-nVD9L2.js} +1 -1
  40. package/dist/public/assets/_BV-nVD9L2.js.br +0 -0
  41. package/dist/public/assets/{_DbkqHev42.js → _BbMkV19p2.js} +1 -1
  42. package/dist/public/assets/_BbMkV19p2.js.br +0 -0
  43. package/dist/public/assets/{_QZ7jIJEp.js → _BbW3-3ve.js} +1 -1
  44. package/dist/public/assets/_BbW3-3ve.js.br +0 -0
  45. package/dist/public/assets/{_BRHBgjBP2.js → _BdbnwCKs2.js} +1 -1
  46. package/dist/public/assets/_BdbnwCKs2.js.br +0 -0
  47. package/dist/public/assets/_BeSgyXoy2.js +1 -0
  48. package/dist/public/assets/_BeSgyXoy2.js.br +0 -0
  49. package/dist/public/assets/{_CRF3psRH.js → _Bg9mkw0u.js} +1 -1
  50. package/dist/public/assets/_Bg9mkw0u.js.br +0 -0
  51. package/dist/public/assets/{_BHjsQD4C.js → _BhUM9ZCP.js} +1 -1
  52. package/dist/public/assets/_BhUM9ZCP.js.br +0 -0
  53. package/dist/public/assets/{_C9YvMapn.js → _Bhnzfac_.js} +1 -1
  54. package/dist/public/assets/_Bhnzfac_.js.br +0 -0
  55. package/dist/public/assets/{_BPiDffSK.js → _BiEWaww7.js} +1 -1
  56. package/dist/public/assets/_BiEWaww7.js.br +0 -0
  57. package/dist/public/assets/{_B3rIZBik.js → _Bm-lmvlM.js} +1 -1
  58. package/dist/public/assets/_Bm-lmvlM.js.br +0 -0
  59. package/dist/public/assets/{_Cu3f85ax2.js → _Bpdzs0h4.js} +1 -1
  60. package/dist/public/assets/_Bpdzs0h4.js.br +0 -0
  61. package/dist/public/assets/{_BzuTzxB9.js → _BqeAAcor.js} +1 -1
  62. package/dist/public/assets/_BqeAAcor.js.br +0 -0
  63. package/dist/public/assets/{_5pEZdV75.js → _Bvwr3uff.js} +1 -1
  64. package/dist/public/assets/_Bvwr3uff.js.br +0 -0
  65. package/dist/public/assets/{_CRpvVy-g.js → _ByiODT9w.js} +1 -1
  66. package/dist/public/assets/_ByiODT9w.js.br +0 -0
  67. package/dist/public/assets/{_nqBpAHq9.js → _C4NK2Cq5.js} +1 -1
  68. package/dist/public/assets/_C4NK2Cq5.js.br +0 -0
  69. package/dist/public/assets/{_B2pxLNBO.js → _CASsRCtt.js} +1 -1
  70. package/dist/public/assets/_CASsRCtt.js.br +0 -0
  71. package/dist/public/assets/{_DPW4NADy2.js → _CH4P29Yf2.js} +1 -1
  72. package/dist/public/assets/_CH4P29Yf2.js.br +0 -0
  73. package/dist/public/assets/{_COmscE442.js → _CHqTBuzz2.js} +1 -1
  74. package/dist/public/assets/_CHqTBuzz2.js.br +0 -0
  75. package/dist/public/assets/{_DvqRc7vA2.js → _CIeZtXbg2.js} +1 -1
  76. package/dist/public/assets/_CIeZtXbg2.js.br +0 -0
  77. package/dist/public/assets/{_DU0F-fSc.js → _CObQoJCq.js} +1 -1
  78. package/dist/public/assets/_CObQoJCq.js.br +0 -0
  79. package/dist/public/assets/{_BxuGlOMJ.js → _CQDBqJkT.js} +1 -1
  80. package/dist/public/assets/_CQDBqJkT.js.br +0 -0
  81. package/dist/public/assets/{_DZyW50O5.js → _CUqlR7rP.js} +1 -1
  82. package/dist/public/assets/_CUqlR7rP.js.br +0 -0
  83. package/dist/public/assets/{_BDIKDRj8.js → _CUwAZxRw.js} +1 -1
  84. package/dist/public/assets/_CUwAZxRw.js.br +0 -0
  85. package/dist/public/assets/{_DeCqhciO.js → _CbMNS899.js} +1 -1
  86. package/dist/public/assets/_CbMNS899.js.br +0 -0
  87. package/dist/public/assets/{_BIP7B1g62.js → _Ced5468N2.js} +1 -1
  88. package/dist/public/assets/{_Cawlufow.js → _Cf0wSsqE.js} +1 -1
  89. package/dist/public/assets/_Cf0wSsqE.js.br +0 -0
  90. package/dist/public/assets/{_BMWhe7UA2.js → _ClEKr0Tm2.js} +1 -1
  91. package/dist/public/assets/_ClEKr0Tm2.js.br +0 -0
  92. package/dist/public/assets/{_ChIGZgCK2.js → _CsNJf4g52.js} +1 -1
  93. package/dist/public/assets/_CsNJf4g52.js.br +0 -0
  94. package/dist/public/assets/{_Dj0FqIsq2.js → _CtErcdf92.js} +1 -1
  95. package/dist/public/assets/_CtErcdf92.js.br +0 -0
  96. package/dist/public/assets/{_Btx74Q-k.js → _DAfu0wMa.js} +1 -1
  97. package/dist/public/assets/_DAfu0wMa.js.br +0 -0
  98. package/dist/public/assets/{_DgucIXC9.js → _DBN8F3s1.js} +1 -1
  99. package/dist/public/assets/_DBN8F3s1.js.br +0 -0
  100. package/dist/public/assets/{_DPc97sYv2.js → _DBn74psf2.js} +1 -1
  101. package/dist/public/assets/{_lTcPBjyz2.js → _DFOnuGNp.js} +1 -1
  102. package/dist/public/assets/_DFOnuGNp.js.br +0 -0
  103. package/dist/public/assets/{_CYb-TtX12.js → _DHvVwuPu2.js} +1 -1
  104. package/dist/public/assets/_DHvVwuPu2.js.br +0 -0
  105. package/dist/public/assets/{_AG00U05V.js → _DKnLFVdw.js} +1 -1
  106. package/dist/public/assets/_DKnLFVdw.js.br +0 -0
  107. package/dist/public/assets/{_D5DIKC5J2.js → _DLFnXIrG2.js} +1 -1
  108. package/dist/public/assets/_DLFnXIrG2.js.br +0 -0
  109. package/dist/public/assets/{_Dvsdxjs1.js → _DLK0WouR.js} +1 -1
  110. package/dist/public/assets/_DLK0WouR.js.br +0 -0
  111. package/dist/public/assets/_DLLEkkcM.js +1531 -0
  112. package/dist/public/assets/_DLLEkkcM.js.br +0 -0
  113. package/dist/public/assets/{_ClduJgR5.js → _DOpT45mO.js} +1 -1
  114. package/dist/public/assets/_DOpT45mO.js.br +0 -0
  115. package/dist/public/assets/{_ByQc1pkS.js → _DT9Qs1il.js} +1 -1
  116. package/dist/public/assets/_DT9Qs1il.js.br +0 -0
  117. package/dist/public/assets/{_C3QGlxhv2.js → _DVPPxo4e2.js} +1 -1
  118. package/dist/public/assets/_DVPPxo4e2.js.br +0 -0
  119. package/dist/public/assets/{_CpxRirGf.js → _De7fhQUT.js} +1 -1
  120. package/dist/public/assets/_De7fhQUT.js.br +0 -0
  121. package/dist/public/assets/{_BmtVFK052.js → _DgmBuYFG2.js} +1 -1
  122. package/dist/public/assets/_DgmBuYFG2.js.br +0 -0
  123. package/dist/public/assets/{_BLvHtG5b.js → _DjLQQUoq.js} +1 -1
  124. package/dist/public/assets/_DjLQQUoq.js.br +0 -0
  125. package/dist/public/assets/{_CBF2sJFl.js → _Dn4wMX5v.js} +1 -1
  126. package/dist/public/assets/_Dn4wMX5v.js.br +0 -0
  127. package/dist/public/assets/{_tKPNE6U52.js → _DsJkMBKU2.js} +1 -1
  128. package/dist/public/assets/_DsJkMBKU2.js.br +0 -0
  129. package/dist/public/assets/{_CYLr_2iE.js → _Ez06j6Qv.js} +1 -1
  130. package/dist/public/assets/_Ez06j6Qv.js.br +0 -0
  131. package/dist/public/assets/{_CyDJr5hJ.js → _FCV34uHN.js} +1 -1
  132. package/dist/public/assets/_FCV34uHN.js.br +0 -0
  133. package/dist/public/assets/{_BgDRYHYE.js → _I6H6F0ME.js} +1 -1
  134. package/dist/public/assets/_I6H6F0ME.js.br +0 -0
  135. package/dist/public/assets/{_ji5qc8J4.js → _K6PNL3j4.js} +1 -1
  136. package/dist/public/assets/_K6PNL3j4.js.br +0 -0
  137. package/dist/public/assets/{_CCXyJU0G.js → _KVpYyL9A.js} +1 -1
  138. package/dist/public/assets/_KVpYyL9A.js.br +0 -0
  139. package/dist/public/assets/{_BEEHMSv_.js → _KjztUkjx.js} +1 -1
  140. package/dist/public/assets/_KjztUkjx.js.br +0 -0
  141. package/dist/public/assets/{_BGFm3dJ4.js → _Q6y5EfU1.js} +1 -1
  142. package/dist/public/assets/_Q6y5EfU1.js.br +0 -0
  143. package/dist/public/assets/{_C7kYFLNM.js → _cRLLpjIg.js} +1 -1
  144. package/dist/public/assets/_cRLLpjIg.js.br +0 -0
  145. package/dist/public/assets/{_CXsVxa93.js → _h8qSl3Me.js} +1 -1
  146. package/dist/public/assets/{_BxlHpe2T.js → _kv39JOeM.js} +1 -1
  147. package/dist/public/assets/_kv39JOeM.js.br +0 -0
  148. package/dist/public/assets/{_DTXvrAdN.js → _o1of2_lP.js} +1 -1
  149. package/dist/public/assets/_o1of2_lP.js.br +0 -0
  150. package/dist/public/assets/{_T_hWiFRO.js → _qoSWRJiT.js} +1 -1
  151. package/dist/public/assets/_qoSWRJiT.js.br +0 -0
  152. package/dist/public/assets/{_BZe4BZ4G.js → _yQJK428k.js} +1 -1
  153. package/dist/public/assets/_yQJK428k.js.br +0 -0
  154. package/dist/public/assets/diff-view-CQX-Ovnt.css +1 -0
  155. package/dist/public/assets/diff-view-CQX-Ovnt.css.br +0 -0
  156. package/dist/public/assets/index-DR0Bvd6u.css +1 -0
  157. package/dist/public/assets/index-DR0Bvd6u.css.br +0 -0
  158. package/dist/public/assets/index-fCEONff1.js +85 -0
  159. package/dist/public/assets/index-fCEONff1.js.br +0 -0
  160. package/lib/setup/catalog.d.mts +22 -0
  161. package/lib/setup/catalog.mjs +72 -0
  162. package/lib/setup/doctor.d.mts +49 -0
  163. package/lib/setup/doctor.mjs +203 -0
  164. package/lib/setup/install.d.mts +14 -0
  165. package/lib/setup/install.mjs +135 -0
  166. package/package.json +2 -1
  167. package/dist/_CV5G1-Sr.js +0 -2
  168. package/dist/public/assets/_2_8X99jw.js.br +0 -0
  169. package/dist/public/assets/_5pEZdV75.js.br +0 -0
  170. package/dist/public/assets/_6fdNa05X2.js.br +0 -0
  171. package/dist/public/assets/_9CHuxVRu.js.br +0 -0
  172. package/dist/public/assets/_AG00U05V.js.br +0 -0
  173. package/dist/public/assets/_B2pxLNBO.js.br +0 -0
  174. package/dist/public/assets/_B3rIZBik.js.br +0 -0
  175. package/dist/public/assets/_B8PQyubX.js.br +0 -0
  176. package/dist/public/assets/_BDIKDRj8.js.br +0 -0
  177. package/dist/public/assets/_BEEHMSv_.js.br +0 -0
  178. package/dist/public/assets/_BGFm3dJ4.js.br +0 -0
  179. package/dist/public/assets/_BHjsQD4C.js.br +0 -0
  180. package/dist/public/assets/_BLibugcj.js +0 -1531
  181. package/dist/public/assets/_BLibugcj.js.br +0 -0
  182. package/dist/public/assets/_BLvHtG5b.js.br +0 -0
  183. package/dist/public/assets/_BMWhe7UA2.js.br +0 -0
  184. package/dist/public/assets/_BPiDffSK.js.br +0 -0
  185. package/dist/public/assets/_BPq9uIVf.js.br +0 -0
  186. package/dist/public/assets/_BRHBgjBP2.js.br +0 -0
  187. package/dist/public/assets/_BZe4BZ4G.js.br +0 -0
  188. package/dist/public/assets/_BgDRYHYE.js.br +0 -0
  189. package/dist/public/assets/_BmH7JUGb2.js.br +0 -0
  190. package/dist/public/assets/_BmtVFK052.js.br +0 -0
  191. package/dist/public/assets/_Btx74Q-k.js.br +0 -0
  192. package/dist/public/assets/_BxlHpe2T.js.br +0 -0
  193. package/dist/public/assets/_BxuGlOMJ.js.br +0 -0
  194. package/dist/public/assets/_By0S6RFm2.js.br +0 -0
  195. package/dist/public/assets/_ByQc1pkS.js.br +0 -0
  196. package/dist/public/assets/_BzuTzxB9.js.br +0 -0
  197. package/dist/public/assets/_C3QGlxhv2.js.br +0 -0
  198. package/dist/public/assets/_C7kYFLNM.js.br +0 -0
  199. package/dist/public/assets/_C9YvMapn.js.br +0 -0
  200. package/dist/public/assets/_CBF2sJFl.js.br +0 -0
  201. package/dist/public/assets/_CCXyJU0G.js.br +0 -0
  202. package/dist/public/assets/_CMIAElmF.js.br +0 -0
  203. package/dist/public/assets/_COmscE442.js.br +0 -0
  204. package/dist/public/assets/_CRF3psRH.js.br +0 -0
  205. package/dist/public/assets/_CRpvVy-g.js.br +0 -0
  206. package/dist/public/assets/_CYLr_2iE.js.br +0 -0
  207. package/dist/public/assets/_CYb-TtX12.js.br +0 -0
  208. package/dist/public/assets/_Cawlufow.js.br +0 -0
  209. package/dist/public/assets/_CfyASWBT2.js.br +0 -0
  210. package/dist/public/assets/_ChIGZgCK2.js.br +0 -0
  211. package/dist/public/assets/_ClduJgR5.js.br +0 -0
  212. package/dist/public/assets/_Cp2bkjzT2.js +0 -1
  213. package/dist/public/assets/_Cp2bkjzT2.js.br +0 -0
  214. package/dist/public/assets/_CpxRirGf.js.br +0 -0
  215. package/dist/public/assets/_CrvHv7e4.js.br +0 -0
  216. package/dist/public/assets/_Cu3f85ax2.js.br +0 -0
  217. package/dist/public/assets/_CyDJr5hJ.js.br +0 -0
  218. package/dist/public/assets/_D1Ecsx8-2.js.br +0 -0
  219. package/dist/public/assets/_D2tmOnaH.js +0 -1
  220. package/dist/public/assets/_D2tmOnaH.js.br +0 -0
  221. package/dist/public/assets/_D5DIKC5J2.js.br +0 -0
  222. package/dist/public/assets/_DFC22iAc.js.br +0 -0
  223. package/dist/public/assets/_DJYs9cGt2.js.br +0 -0
  224. package/dist/public/assets/_DPW4NADy2.js.br +0 -0
  225. package/dist/public/assets/_DTXvrAdN.js.br +0 -0
  226. package/dist/public/assets/_DU0F-fSc.js.br +0 -0
  227. package/dist/public/assets/_DZExUZ7A.js.br +0 -0
  228. package/dist/public/assets/_DZyW50O5.js.br +0 -0
  229. package/dist/public/assets/_DbkqHev42.js.br +0 -0
  230. package/dist/public/assets/_DeCqhciO.js.br +0 -0
  231. package/dist/public/assets/_DgucIXC9.js.br +0 -0
  232. package/dist/public/assets/_Dj0FqIsq2.js.br +0 -0
  233. package/dist/public/assets/_DvqRc7vA2.js.br +0 -0
  234. package/dist/public/assets/_Dvsdxjs1.js.br +0 -0
  235. package/dist/public/assets/_FZ5aDFyS.js.br +0 -0
  236. package/dist/public/assets/_QZ7jIJEp.js.br +0 -0
  237. package/dist/public/assets/_T_hWiFRO.js.br +0 -0
  238. package/dist/public/assets/_fkktwOR8.js.br +0 -0
  239. package/dist/public/assets/_ji5qc8J4.js.br +0 -0
  240. package/dist/public/assets/_lTcPBjyz2.js.br +0 -0
  241. package/dist/public/assets/_nqBpAHq9.js.br +0 -0
  242. package/dist/public/assets/_tKPNE6U52.js.br +0 -0
  243. package/dist/public/assets/_zkaPdW0C2.js.br +0 -0
  244. package/dist/public/assets/diff-view-AJeZtePd.css +0 -1
  245. package/dist/public/assets/diff-view-AJeZtePd.css.br +0 -0
  246. package/dist/public/assets/index-BG3uLJV6.js +0 -85
  247. package/dist/public/assets/index-BG3uLJV6.js.br +0 -0
  248. package/dist/public/assets/index-_5MkiydM.css +0 -1
  249. package/dist/public/assets/index-_5MkiydM.css.br +0 -0
  250. package/dist/public/assets/preload-helper-C1JvlFma.css +0 -1
  251. package/dist/public/assets/preload-helper-C1JvlFma.css.br +0 -0
  252. /package/dist/public/assets/{_B5W6OYN72.js → _B5W6OYN7.js} +0 -0
  253. /package/dist/public/assets/{_B5W6OYN72.js.br → _B5W6OYN7.js.br} +0 -0
  254. /package/dist/public/assets/{_DMoTqEGO2.js → _DMoTqEGO.js} +0 -0
  255. /package/dist/public/assets/{_DMoTqEGO2.js.br → _DMoTqEGO.js.br} +0 -0
  256. /package/dist/public/assets/{_DmIc4jLQ2.js → _DmIc4jLQ.js} +0 -0
  257. /package/dist/public/assets/{_DmIc4jLQ2.js.br → _DmIc4jLQ.js.br} +0 -0
  258. /package/dist/public/assets/{_DsUTQ-LC.js → _DsUTQ-LC2.js} +0 -0
  259. /package/dist/public/assets/{_DsUTQ-LC.js.br → _DsUTQ-LC2.js.br} +0 -0
  260. /package/dist/public/assets/{_VbXTXTou.js → _VbXTXTou2.js} +0 -0
  261. /package/dist/public/assets/{_VbXTXTou.js.br → _VbXTXTou2.js.br} +0 -0
  262. /package/dist/public/assets/{_iXnhIJG7.js → _iXnhIJG72.js} +0 -0
  263. /package/dist/public/assets/{_iXnhIJG7.js.br → _iXnhIJG72.js.br} +0 -0
  264. /package/dist/public/assets/{_vGVdxbeo.js → _vGVdxbeo2.js} +0 -0
  265. /package/dist/public/assets/{_vGVdxbeo.js.br → _vGVdxbeo2.js.br} +0 -0
package/bin/work.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  // work CLI — ships with the npm package (no dependencies; plain node).
3
3
  //
4
- // work setup install/refresh the background service (+ optional tunnel)
4
+ // work setup install missing tools, sign in, install/refresh the background service
5
+ // work doctor report machine readiness (--json, --fix to install what's missing)
5
6
  // work start run the server in the foreground
6
7
  // work update upgrade the npm package and refresh the service
7
8
  // work usage print agent plan/quota usage
@@ -12,6 +13,9 @@ import os from "node:os";
12
13
  import path from "node:path";
13
14
  import { fileURLToPath } from "node:url";
14
15
  import { createRequire } from "node:module";
16
+ import readline from "node:readline/promises";
17
+ import { doctor, formatDoctor } from "../lib/setup/doctor.mjs";
18
+ import { authGithub, installAgent, installTool } from "../lib/setup/install.mjs";
15
19
 
16
20
  const pkgRoot = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
17
21
  const pkg = JSON.parse(fs.readFileSync(path.join(pkgRoot, "package.json"), "utf8"));
@@ -41,6 +45,9 @@ switch (command) {
41
45
  case "setup":
42
46
  await setup();
43
47
  break;
48
+ case "doctor":
49
+ await doctorCmd();
50
+ break;
44
51
  case "update":
45
52
  await update();
46
53
  break;
@@ -54,7 +61,7 @@ switch (command) {
54
61
  break;
55
62
  default:
56
63
  console.log(
57
- `work ${pkg.version}\n\nusage: work <setup|start|update|usage|version>`,
64
+ `work ${pkg.version}\n\nusage: work <setup|doctor|start|update|usage|version>`,
58
65
  );
59
66
  }
60
67
 
@@ -136,51 +143,7 @@ function short(ms) {
136
143
  }
137
144
 
138
145
  async function setup() {
139
- // Runtime tools. The curl installer normally provides these; a plain
140
- // `npm i -g` user may be missing them.
141
- for (const tool of ["git", "tmux"]) {
142
- if (!have(tool)) die(`${tool} not found — install it and re-run (the curl installer does this automatically)`);
143
- }
144
-
145
- // Default toolset (mirrors DylanPiercey/start): gh for PR features plus
146
- // the utilities agents reach for constantly. Static binaries via mise,
147
- // each non-fatal, skipped when already on PATH.
148
- if (have("mise")) {
149
- const tools = [
150
- "gh",
151
- "ripgrep", // rg
152
- "fd",
153
- "jq",
154
- "delta",
155
- "ast-grep",
156
- "hyperfine",
157
- "fzf",
158
- "bottom",
159
- "pnpm",
160
- ];
161
- // Note: ast-grep's short alias `sg` collides with the coreutils
162
- // setgroups command — check the long binary name.
163
- const binOf = { ripgrep: "rg", bottom: "btm" };
164
- for (const tool of tools) {
165
- if (have(binOf[tool] || tool)) continue;
166
- log(`installing ${tool} via mise`);
167
- if (spawnSync("mise", ["use", "-g", "-y", `${tool}@latest`], { stdio: "inherit" }).status !== 0) {
168
- warn(`${tool} install failed (non-fatal)`);
169
- }
170
- }
171
- } else if (!have("gh")) {
172
- warn("gh not found and mise unavailable — PR features need gh; install it and re-run");
173
- }
174
- if (have("gh") && spawnSync("gh", ["auth", "status"], { stdio: "ignore" }).status !== 0) {
175
- if (process.env.GH_TOKEN || process.env.GITHUB_TOKEN) {
176
- log("gh will use GH_TOKEN from the environment");
177
- } else if (yes) {
178
- warn("gh is not authenticated — run `gh auth login` later");
179
- } else {
180
- log("authenticating gh (GitHub PRs/clones)");
181
- sh("gh", ["auth", "login"]);
182
- }
183
- }
146
+ await fix(await doctor(), { agents: yes ? "skip" : "prompt" });
184
147
 
185
148
  // One-shot cleanups between versions. Run them against the settings the
186
149
  // service actually uses: migrate.mjs exits quietly when it finds no db, so
@@ -206,6 +169,73 @@ async function update() {
206
169
  sh("work", ["setup", ...(yes ? ["--yes"] : [])]);
207
170
  }
208
171
 
172
+ /** Machine readiness from lib/setup — the same probe the Settings page runs. */
173
+ async function doctorCmd() {
174
+ let d = await doctor();
175
+ if (args.includes("--fix")) {
176
+ await fix(d, { agents: yes ? "skip" : "prompt" });
177
+ d = await doctor();
178
+ }
179
+ if (args.includes("--json")) return console.log(JSON.stringify(d, null, 2));
180
+ console.log(formatDoctor(d));
181
+ if (!d.ready) process.exit(1);
182
+ }
183
+
184
+ /**
185
+ * Bring the machine to "ready": required tools, then optional ones (each
186
+ * non-fatal), then gh sign-in, then agent CLIs. `--yes` never prompts —
187
+ * sign-in and agents are deferred with a hint. Re-runs are idempotent
188
+ * because everything is keyed off what doctor() found missing.
189
+ */
190
+ async function fix(d, { agents = "prompt" } = {}) {
191
+ for (const tool of d.tools.filter((t) => !t.installed)) {
192
+ if (!tool.installable) {
193
+ if (tool.required) die(`${tool.label} not found — install it and re-run (the curl installer does this automatically)`);
194
+ continue;
195
+ }
196
+ log(`installing ${tool.label} via mise`);
197
+ try {
198
+ await installTool(tool.id, { log: (l) => console.log(` ${l}`) });
199
+ } catch (err) {
200
+ if (tool.required) die(`${tool.label} install failed: ${err.message}`);
201
+ warn(`${tool.label} install failed (non-fatal)`);
202
+ }
203
+ }
204
+ const authed = d.github.some((h) => h.authed);
205
+ if (!authed && have("gh")) {
206
+ if (process.env.GH_TOKEN || process.env.GITHUB_TOKEN) {
207
+ log("gh will use GH_TOKEN from the environment");
208
+ } else if (yes) {
209
+ warn("gh is not authenticated — run `gh auth login` later");
210
+ } else {
211
+ log("signing in to GitHub (PRs/clones)");
212
+ await authGithub("github.com", { interactive: true }).catch((err) => warn(err.message));
213
+ }
214
+ }
215
+ const missingAgents = d.agents.filter((a) => !a.installed);
216
+ if (missingAgents.length && agents !== "skip") {
217
+ const names = missingAgents.map((a) => a.label).join(", ");
218
+ let go = agents === "all";
219
+ if (!go) {
220
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
221
+ const ans = await rl.question(`Install coding agent CLIs (${names})? [y/N] `).catch(() => "");
222
+ rl.close();
223
+ go = /^y/i.test(ans.trim());
224
+ }
225
+ if (go) {
226
+ for (const a of missingAgents) {
227
+ try {
228
+ await installAgent(a.id, { log: (l) => console.log(` ${l}`) });
229
+ } catch (err) {
230
+ warn(`${a.label} install failed (non-fatal): ${err.message}`);
231
+ }
232
+ }
233
+ }
234
+ } else if (!d.agents.some((a) => a.installed)) {
235
+ warn(`no coding agent CLI found — install one later from Settings or: work doctor --fix`);
236
+ }
237
+ }
238
+
209
239
  /** PATH baked into the service — it runs without a login shell. */
210
240
  function servicePath() {
211
241
  const home = os.homedir();