@paradigma-inc/flywheel 0.1.115 → 0.1.134

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 (623) hide show
  1. package/README.md +67 -10
  2. package/package.json +14 -6
  3. package/skills/flywheel/SKILL.md +9 -6
  4. package/skills/flywheel/example-workflows/organizing-exploring-and-iterating-on-a-research-topic.md +38 -46
  5. package/skills/flywheel/example-workflows/reproducing-papers-on-a-budget.md +34 -36
  6. package/skills/flywheel/getting-started/flywheel-quickstart.md +2 -5
  7. package/skills/flywheel/references/INTERFACES.md +2 -2
  8. package/skills/flywheel/references/experiment-design-protocol.md +32 -25
  9. package/skills/flywheel/references/flywheel-cli-tool-map.md +120 -76
  10. package/skills/flywheel/references/flywheel-mcp-tool-map.md +42 -32
  11. package/skills/flywheel/setting-up-flywheel/claude-code-cli-installation.md +1 -1
  12. package/skills/flywheel/setting-up-flywheel/codex-cli-installation.md +1 -1
  13. package/skills/flywheel/setting-up-flywheel/installation-overview.md +2 -6
  14. package/skills/flywheel/setting-up-flywheel/other-hosts-installation.md +45 -25
  15. package/skills/flywheel/setting-up-flywheel/updating-flywheel-mcp.md +34 -11
  16. package/skills/flywheel-auto/SKILL.md +40 -23
  17. package/skills/flywheel-auto/evals/evals.json +1 -1
  18. package/skills/flywheel-auto/references/INTERFACES.md +2 -2
  19. package/skills/flywheel-auto/references/experiment-design-protocol.md +31 -23
  20. package/skills/flywheel-auto/references/flywheel-cli-tool-map.md +172 -127
  21. package/skills/flywheel-auto/references/flywheel-mcp-tool-map.md +22 -24
  22. package/skills/flywheel-lookahead/SKILL.md +47 -28
  23. package/skills/flywheel-lookahead/agents/openai.yaml +1 -1
  24. package/skills/flywheel-lookahead/evals/evals.json +6 -6
  25. package/skills/flywheel-lookahead/references/INTERFACES.md +2 -2
  26. package/skills/flywheel-lookahead/references/flywheel-cli-tool-map.md +172 -127
  27. package/skills/flywheel-lookahead/references/flywheel-mcp-tool-map.md +22 -24
  28. package/skills/flywheel-prove/SKILL.md +2 -2
  29. package/skills/flywheel-prove/references/workflow.md +21 -2
  30. package/skills/flywheel-reproduce/SKILL.md +39 -19
  31. package/skills/flywheel-reproduce/evals/evals.json +1 -1
  32. package/skills/flywheel-reproduce/references/INTERFACES.md +2 -2
  33. package/skills/flywheel-reproduce/references/experiment-design-protocol.md +31 -23
  34. package/skills/flywheel-reproduce/references/flywheel-cli-tool-map.md +172 -127
  35. package/skills/flywheel-reproduce/references/flywheel-mcp-tool-map.md +22 -24
  36. package/skills/flywheel-to-graph/SKILL.md +37 -17
  37. package/skills/flywheel-to-graph/references/INTERFACES.md +2 -2
  38. package/skills/flywheel-to-graph/references/flywheel-cli-tool-map.md +172 -127
  39. package/skills/flywheel-to-graph/references/flywheel-mcp-tool-map.md +22 -24
  40. package/skills/flywheel-tree/references/workflow.md +6 -37
  41. package/src/cli.mjs +1145 -1141
  42. package/src/mcp-writer.mjs +413 -435
  43. package/src/public-command-metadata.mjs +28 -5
  44. package/src/runtime/delegate.mjs +2 -19
  45. package/src/runtime/required-runtime-commands.json +80 -28
  46. package/src/runtime/runtime-config.mjs +39 -60
  47. package/src/runtime/vendor/flywheel-cli-dist/auth/credentials.js +330 -0
  48. package/src/runtime/vendor/flywheel-cli-dist/auth/credentials.js.map +1 -0
  49. package/src/runtime/vendor/flywheel-cli-dist/auth/login.js +90 -139
  50. package/src/runtime/vendor/flywheel-cli-dist/auth/login.js.map +1 -1
  51. package/src/runtime/vendor/flywheel-cli-dist/auth/profiles.js +1 -1
  52. package/src/runtime/vendor/flywheel-cli-dist/auth/profiles.js.map +1 -1
  53. package/src/runtime/vendor/flywheel-cli-dist/auth/secure-write.js +116 -0
  54. package/src/runtime/vendor/flywheel-cli-dist/auth/secure-write.js.map +1 -0
  55. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-test-users-create.js +248 -1
  56. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-test-users-create.js.map +1 -1
  57. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-test-users-login.js +65 -1
  58. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-test-users-login.js.map +1 -1
  59. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-test-users-revoke-api-key.js +17 -0
  60. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-test-users-revoke-api-key.js.map +1 -0
  61. package/src/runtime/vendor/flywheel-cli-dist/commands/aliases.js +3 -7
  62. package/src/runtime/vendor/flywheel-cli-dist/commands/aliases.js.map +1 -1
  63. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-credentials-clear.js +12 -0
  64. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-credentials-clear.js.map +1 -0
  65. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-credentials-set.js +29 -0
  66. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-credentials-set.js.map +1 -0
  67. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-login.js +12 -0
  68. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-login.js.map +1 -1
  69. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-status.js +46 -10
  70. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-status.js.map +1 -1
  71. package/src/runtime/vendor/flywheel-cli-dist/commands/env.js +17 -40
  72. package/src/runtime/vendor/flywheel-cli-dist/commands/env.js.map +1 -1
  73. package/src/runtime/vendor/flywheel-cli-dist/commands/graph-operation-resources.js +305 -0
  74. package/src/runtime/vendor/flywheel-cli-dist/commands/graph-operation-resources.js.map +1 -0
  75. package/src/runtime/vendor/flywheel-cli-dist/commands/graph-operation-support.js +72 -0
  76. package/src/runtime/vendor/flywheel-cli-dist/commands/graph-operation-support.js.map +1 -0
  77. package/src/runtime/vendor/flywheel-cli-dist/commands/graph-operation.js +286 -0
  78. package/src/runtime/vendor/flywheel-cli-dist/commands/graph-operation.js.map +1 -0
  79. package/src/runtime/vendor/flywheel-cli-dist/commands/help-metadata.js +30 -5
  80. package/src/runtime/vendor/flywheel-cli-dist/commands/help-metadata.js.map +1 -1
  81. package/src/runtime/vendor/flywheel-cli-dist/commands/help.js +27 -12
  82. package/src/runtime/vendor/flywheel-cli-dist/commands/help.js.map +1 -1
  83. package/src/runtime/vendor/flywheel-cli-dist/commands/hosted-commit-replay.js +284 -0
  84. package/src/runtime/vendor/flywheel-cli-dist/commands/hosted-commit-replay.js.map +1 -0
  85. package/src/runtime/vendor/flywheel-cli-dist/commands/hosted-graph.js +169 -0
  86. package/src/runtime/vendor/flywheel-cli-dist/commands/hosted-graph.js.map +1 -0
  87. package/src/runtime/vendor/flywheel-cli-dist/commands/hosted-lineage-list.js +13 -0
  88. package/src/runtime/vendor/flywheel-cli-dist/commands/hosted-lineage-list.js.map +1 -0
  89. package/src/runtime/vendor/flywheel-cli-dist/commands/hosted-repository-snapshot.js +227 -0
  90. package/src/runtime/vendor/flywheel-cli-dist/commands/hosted-repository-snapshot.js.map +1 -0
  91. package/src/runtime/vendor/flywheel-cli-dist/commands/index.js +21 -51
  92. package/src/runtime/vendor/flywheel-cli-dist/commands/index.js.map +1 -1
  93. package/src/runtime/vendor/flywheel-cli-dist/commands/node-create-schema.js +25 -0
  94. package/src/runtime/vendor/flywheel-cli-dist/commands/node-create-schema.js.map +1 -0
  95. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-list.js +11 -9
  96. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-list.js.map +1 -1
  97. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-set.js +38 -45
  98. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-set.js.map +1 -1
  99. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-show.js +14 -17
  100. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-show.js.map +1 -1
  101. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-unset.js +13 -8
  102. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-unset.js.map +1 -1
  103. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/admin.js +34 -3
  104. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/admin.js.map +1 -1
  105. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/auth.js +9 -9
  106. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/auth.js.map +1 -1
  107. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/hosted.js +76 -0
  108. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/hosted.js.map +1 -0
  109. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/lifecycle.js +4 -138
  110. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/lifecycle.js.map +1 -1
  111. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/profile.js +8 -13
  112. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/profile.js.map +1 -1
  113. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/repository.js +362 -0
  114. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/repository.js.map +1 -0
  115. package/src/runtime/vendor/flywheel-cli-dist/commands/registry.js +45 -183
  116. package/src/runtime/vendor/flywheel-cli-dist/commands/registry.js.map +1 -1
  117. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-edit.js +47 -0
  118. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-edit.js.map +1 -0
  119. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-operation.js +181 -0
  120. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-operation.js.map +1 -0
  121. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-output.js +163 -0
  122. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-output.js.map +1 -0
  123. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-projection.js +79 -0
  124. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-projection.js.map +1 -0
  125. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-selection.js +80 -0
  126. package/src/runtime/vendor/flywheel-cli-dist/commands/repository-selection.js.map +1 -0
  127. package/src/runtime/vendor/flywheel-cli-dist/commands/retired-command-names.js +78 -0
  128. package/src/runtime/vendor/flywheel-cli-dist/commands/retired-command-names.js.map +1 -0
  129. package/src/runtime/vendor/flywheel-cli-dist/commands/types.js.map +1 -1
  130. package/src/runtime/vendor/flywheel-cli-dist/commands/usage-spec.js +3 -2
  131. package/src/runtime/vendor/flywheel-cli-dist/commands/usage-spec.js.map +1 -1
  132. package/src/runtime/vendor/flywheel-cli-dist/config/index.js +5 -0
  133. package/src/runtime/vendor/flywheel-cli-dist/config/index.js.map +1 -0
  134. package/src/runtime/vendor/flywheel-cli-dist/config/io.js +139 -0
  135. package/src/runtime/vendor/flywheel-cli-dist/config/io.js.map +1 -0
  136. package/src/runtime/vendor/flywheel-cli-dist/config/migration.js +299 -0
  137. package/src/runtime/vendor/flywheel-cli-dist/config/migration.js.map +1 -0
  138. package/src/runtime/vendor/flywheel-cli-dist/config/model.js +214 -0
  139. package/src/runtime/vendor/flywheel-cli-dist/config/model.js.map +1 -0
  140. package/src/runtime/vendor/flywheel-cli-dist/config/path.js +30 -0
  141. package/src/runtime/vendor/flywheel-cli-dist/config/path.js.map +1 -0
  142. package/src/runtime/vendor/flywheel-cli-dist/credential-output.js +29 -0
  143. package/src/runtime/vendor/flywheel-cli-dist/credential-output.js.map +1 -0
  144. package/src/runtime/vendor/flywheel-cli-dist/errors.js +1 -16
  145. package/src/runtime/vendor/flywheel-cli-dist/errors.js.map +1 -1
  146. package/src/runtime/vendor/flywheel-cli-dist/generatedProductTelemetryContract.js +3 -3
  147. package/src/runtime/vendor/flywheel-cli-dist/generatedProductTelemetryContract.js.map +1 -1
  148. package/src/runtime/vendor/flywheel-cli-dist/grammar/globals.js +19 -9
  149. package/src/runtime/vendor/flywheel-cli-dist/grammar/globals.js.map +1 -1
  150. package/src/runtime/vendor/flywheel-cli-dist/grammar/parse.js +33 -4
  151. package/src/runtime/vendor/flywheel-cli-dist/grammar/parse.js.map +1 -1
  152. package/src/runtime/vendor/flywheel-cli-dist/http/client.js +322 -304
  153. package/src/runtime/vendor/flywheel-cli-dist/http/client.js.map +1 -1
  154. package/src/runtime/vendor/flywheel-cli-dist/http/debug.js +1 -21
  155. package/src/runtime/vendor/flywheel-cli-dist/http/debug.js.map +1 -1
  156. package/src/runtime/vendor/flywheel-cli-dist/http/retry.js +1 -0
  157. package/src/runtime/vendor/flywheel-cli-dist/http/retry.js.map +1 -1
  158. package/src/runtime/vendor/flywheel-cli-dist/local/adapter.js +244 -0
  159. package/src/runtime/vendor/flywheel-cli-dist/local/adapter.js.map +1 -0
  160. package/src/runtime/vendor/flywheel-cli-dist/local/domain/errors.js +7 -0
  161. package/src/runtime/vendor/flywheel-cli-dist/local/domain/errors.js.map +1 -0
  162. package/src/runtime/vendor/flywheel-cli-dist/local/domain/history.js +35 -0
  163. package/src/runtime/vendor/flywheel-cli-dist/local/domain/history.js.map +1 -0
  164. package/src/runtime/vendor/flywheel-cli-dist/local/domain/invariants.js +42 -0
  165. package/src/runtime/vendor/flywheel-cli-dist/local/domain/invariants.js.map +1 -0
  166. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/artifact-properties.js +179 -0
  167. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/artifact-properties.js.map +1 -0
  168. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/commits.js +152 -0
  169. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/commits.js.map +1 -0
  170. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/constants.js +71 -0
  171. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/constants.js.map +1 -0
  172. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/encoding.js +73 -0
  173. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/encoding.js.map +1 -0
  174. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/imported-artifact-properties.js +82 -0
  175. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/imported-artifact-properties.js.map +1 -0
  176. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/operations.js +345 -0
  177. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/operations.js.map +1 -0
  178. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/tags.js +57 -0
  179. package/src/runtime/vendor/flywheel-cli-dist/local/domain/models/tags.js.map +1 -0
  180. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/conflicts.js +149 -0
  181. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/conflicts.js.map +1 -0
  182. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/context.js +115 -0
  183. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/context.js.map +1 -0
  184. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/keys.js +44 -0
  185. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/keys.js.map +1 -0
  186. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/pull.js +159 -0
  187. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/pull.js.map +1 -0
  188. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/replay.js +346 -0
  189. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/replay.js.map +1 -0
  190. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/resolve.js +37 -0
  191. package/src/runtime/vendor/flywheel-cli-dist/local/domain/rebase/resolve.js.map +1 -0
  192. package/src/runtime/vendor/flywheel-cli-dist/local/domain/revert/inverses.js +203 -0
  193. package/src/runtime/vendor/flywheel-cli-dist/local/domain/revert/inverses.js.map +1 -0
  194. package/src/runtime/vendor/flywheel-cli-dist/local/domain/revert/plan.js +207 -0
  195. package/src/runtime/vendor/flywheel-cli-dist/local/domain/revert/plan.js.map +1 -0
  196. package/src/runtime/vendor/flywheel-cli-dist/local/domain/revert/tag-inverses.js +109 -0
  197. package/src/runtime/vendor/flywheel-cli-dist/local/domain/revert/tag-inverses.js.map +1 -0
  198. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/commit.js +61 -0
  199. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/commit.js.map +1 -0
  200. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/projection.js +46 -0
  201. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/projection.js.map +1 -0
  202. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/revert.js +203 -0
  203. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/revert.js.map +1 -0
  204. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/staging.js +44 -0
  205. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/staging.js.map +1 -0
  206. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/writes.js +188 -0
  207. package/src/runtime/vendor/flywheel-cli-dist/local/domain/service/writes.js.map +1 -0
  208. package/src/runtime/vendor/flywheel-cli-dist/local/domain/sync/cursors.js +54 -0
  209. package/src/runtime/vendor/flywheel-cli-dist/local/domain/sync/cursors.js.map +1 -0
  210. package/src/runtime/vendor/flywheel-cli-dist/local/domain/sync/local-pull.js +25 -0
  211. package/src/runtime/vendor/flywheel-cli-dist/local/domain/sync/local-pull.js.map +1 -0
  212. package/src/runtime/vendor/flywheel-cli-dist/local/domain/sync-models.js +2 -0
  213. package/src/runtime/vendor/flywheel-cli-dist/local/domain/sync-models.js.map +1 -0
  214. package/src/runtime/vendor/flywheel-cli-dist/local/fs/native.js +7 -0
  215. package/src/runtime/vendor/flywheel-cli-dist/local/fs/native.js.map +1 -0
  216. package/src/runtime/vendor/flywheel-cli-dist/local/fs/state.js +129 -0
  217. package/src/runtime/vendor/flywheel-cli-dist/local/fs/state.js.map +1 -0
  218. package/src/runtime/vendor/flywheel-cli-dist/local/fs/writer-lock.js +277 -0
  219. package/src/runtime/vendor/flywheel-cli-dist/local/fs/writer-lock.js.map +1 -0
  220. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/bootstrap.js +183 -0
  221. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/bootstrap.js.map +1 -0
  222. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/context.js +2 -0
  223. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/context.js.map +1 -0
  224. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/dispatch.js +121 -0
  225. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/dispatch.js.map +1 -0
  226. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/doctor.js +16 -0
  227. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/doctor.js.map +1 -0
  228. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/identity.js +72 -0
  229. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/identity.js.map +1 -0
  230. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/conflicts.js +59 -0
  231. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/conflicts.js.map +1 -0
  232. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/core.js +125 -0
  233. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/core.js.map +1 -0
  234. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/history.js +129 -0
  235. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/history.js.map +1 -0
  236. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/index.js +31 -0
  237. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/index.js.map +1 -0
  238. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/maintenance.js +49 -0
  239. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/maintenance.js.map +1 -0
  240. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/projections.js +30 -0
  241. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/projections.js.map +1 -0
  242. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/shared.js +12 -0
  243. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/operations/shared.js.map +1 -0
  244. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/platform.js +18 -0
  245. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/platform.js.map +1 -0
  246. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/projection.js +125 -0
  247. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/projection.js.map +1 -0
  248. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/clone.js +37 -0
  249. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/clone.js.map +1 -0
  250. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/pull.js +44 -0
  251. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/pull.js.map +1 -0
  252. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/purge.js +58 -0
  253. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/purge.js.map +1 -0
  254. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/push.js +118 -0
  255. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/push.js.map +1 -0
  256. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/transport.js +277 -0
  257. package/src/runtime/vendor/flywheel-cli-dist/local/runtime/remote/transport.js.map +1 -0
  258. package/src/runtime/vendor/flywheel-cli-dist/local/store/apply.js +132 -0
  259. package/src/runtime/vendor/flywheel-cli-dist/local/store/apply.js.map +1 -0
  260. package/src/runtime/vendor/flywheel-cli-dist/local/store/backup/archive.js +372 -0
  261. package/src/runtime/vendor/flywheel-cli-dist/local/store/backup/archive.js.map +1 -0
  262. package/src/runtime/vendor/flywheel-cli-dist/local/store/backup/backup.js +210 -0
  263. package/src/runtime/vendor/flywheel-cli-dist/local/store/backup/backup.js.map +1 -0
  264. package/src/runtime/vendor/flywheel-cli-dist/local/store/backup/restore.js +278 -0
  265. package/src/runtime/vendor/flywheel-cli-dist/local/store/backup/restore.js.map +1 -0
  266. package/src/runtime/vendor/flywheel-cli-dist/local/store/backup/retained-directory.js +192 -0
  267. package/src/runtime/vendor/flywheel-cli-dist/local/store/backup/retained-directory.js.map +1 -0
  268. package/src/runtime/vendor/flywheel-cli-dist/local/store/commits.js +114 -0
  269. package/src/runtime/vendor/flywheel-cli-dist/local/store/commits.js.map +1 -0
  270. package/src/runtime/vendor/flywheel-cli-dist/local/store/contract.js +65 -0
  271. package/src/runtime/vendor/flywheel-cli-dist/local/store/contract.js.map +1 -0
  272. package/src/runtime/vendor/flywheel-cli-dist/local/store/diagnostics-worker.js +145 -0
  273. package/src/runtime/vendor/flywheel-cli-dist/local/store/diagnostics-worker.js.map +1 -0
  274. package/src/runtime/vendor/flywheel-cli-dist/local/store/diagnostics.js +218 -0
  275. package/src/runtime/vendor/flywheel-cli-dist/local/store/diagnostics.js.map +1 -0
  276. package/src/runtime/vendor/flywheel-cli-dist/local/store/gc.js +71 -0
  277. package/src/runtime/vendor/flywheel-cli-dist/local/store/gc.js.map +1 -0
  278. package/src/runtime/vendor/flywheel-cli-dist/local/store/history-validation.js +298 -0
  279. package/src/runtime/vendor/flywheel-cli-dist/local/store/history-validation.js.map +1 -0
  280. package/src/runtime/vendor/flywheel-cli-dist/local/store/latest-values.js +121 -0
  281. package/src/runtime/vendor/flywheel-cli-dist/local/store/latest-values.js.map +1 -0
  282. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrate.js +69 -0
  283. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrate.js.map +1 -0
  284. package/src/runtime/vendor/flywheel-cli-dist/local/store/migration/provenance.js +49 -0
  285. package/src/runtime/vendor/flywheel-cli-dist/local/store/migration/provenance.js.map +1 -0
  286. package/src/runtime/vendor/flywheel-cli-dist/local/store/migration/steps.js +424 -0
  287. package/src/runtime/vendor/flywheel-cli-dist/local/store/migration/steps.js.map +1 -0
  288. package/src/runtime/vendor/flywheel-cli-dist/local/store/migration/versions.js +10 -0
  289. package/src/runtime/vendor/flywheel-cli-dist/local/store/migration/versions.js.map +1 -0
  290. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrations/001_initial.sql +319 -0
  291. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrations/002_staged_latest_values.sql +8 -0
  292. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrations/003_remove_cli_editing_lease.sql +21 -0
  293. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrations/004_hosted_association.sql +7 -0
  294. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrations/005_artifact_properties.sql +68 -0
  295. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrations.js +12 -0
  296. package/src/runtime/vendor/flywheel-cli-dist/local/store/migrations.js.map +1 -0
  297. package/src/runtime/vendor/flywheel-cli-dist/local/store/objects.js +410 -0
  298. package/src/runtime/vendor/flywheel-cli-dist/local/store/objects.js.map +1 -0
  299. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/apply.js +77 -0
  300. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/apply.js.map +1 -0
  301. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/artifacts.js +240 -0
  302. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/artifacts.js.map +1 -0
  303. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/nodes.js +127 -0
  304. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/nodes.js.map +1 -0
  305. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/relations.js +107 -0
  306. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/relations.js.map +1 -0
  307. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/rules.js +80 -0
  308. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/rules.js.map +1 -0
  309. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/tags.js +219 -0
  310. package/src/runtime/vendor/flywheel-cli-dist/local/store/projection/tags.js.map +1 -0
  311. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/hosted.js +164 -0
  312. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/hosted.js.map +1 -0
  313. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/read.js +20 -0
  314. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/read.js.map +1 -0
  315. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/replace.js +41 -0
  316. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/replace.js.map +1 -0
  317. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/schema.js +22 -0
  318. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/schema.js.map +1 -0
  319. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/validate.js +188 -0
  320. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot/validate.js.map +1 -0
  321. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot.js +5 -0
  322. package/src/runtime/vendor/flywheel-cli-dist/local/store/snapshot.js.map +1 -0
  323. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/connection.js +214 -0
  324. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/connection.js.map +1 -0
  325. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/errors.js +4 -0
  326. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/errors.js.map +1 -0
  327. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/rows.js +44 -0
  328. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/rows.js.map +1 -0
  329. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/schema.js +38 -0
  330. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/schema.js.map +1 -0
  331. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/store.js +284 -0
  332. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/store.js.map +1 -0
  333. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/verify.js +133 -0
  334. package/src/runtime/vendor/flywheel-cli-dist/local/store/sqlite/verify.js.map +1 -0
  335. package/src/runtime/vendor/flywheel-cli-dist/local/store/sync-commits.js +98 -0
  336. package/src/runtime/vendor/flywheel-cli-dist/local/store/sync-commits.js.map +1 -0
  337. package/src/runtime/vendor/flywheel-cli-dist/local/store/sync.js +161 -0
  338. package/src/runtime/vendor/flywheel-cli-dist/local/store/sync.js.map +1 -0
  339. package/src/runtime/vendor/flywheel-cli-dist/local/store/workspace-state.js +97 -0
  340. package/src/runtime/vendor/flywheel-cli-dist/local/store/workspace-state.js.map +1 -0
  341. package/src/runtime/vendor/flywheel-cli-dist/local/store/workspace.js +69 -0
  342. package/src/runtime/vendor/flywheel-cli-dist/local/store/workspace.js.map +1 -0
  343. package/src/runtime/vendor/flywheel-cli-dist/main.js +651 -376
  344. package/src/runtime/vendor/flywheel-cli-dist/main.js.map +1 -1
  345. package/src/runtime/vendor/flywheel-cli-dist/output/format.js +18 -11
  346. package/src/runtime/vendor/flywheel-cli-dist/output/format.js.map +1 -1
  347. package/src/runtime/vendor/flywheel-cli-dist/prebuilds/darwin-arm64/node.napi.node +0 -0
  348. package/src/runtime/vendor/flywheel-cli-dist/prebuilds/darwin-x64/node.napi.node +0 -0
  349. package/src/runtime/vendor/flywheel-cli-dist/prebuilds/linux-arm64/node.napi.glibc.node +0 -0
  350. package/src/runtime/vendor/flywheel-cli-dist/prebuilds/linux-arm64/node.napi.musl.node +0 -0
  351. package/src/runtime/vendor/flywheel-cli-dist/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  352. package/src/runtime/vendor/flywheel-cli-dist/prebuilds/linux-x64/node.napi.musl.node +0 -0
  353. package/src/runtime/vendor/manifest.json +246 -257
  354. package/src/setup/command.mjs +5 -0
  355. package/src/setup/io/patchers/json.mjs +1 -1
  356. package/src/setup/io/patchers/toml.mjs +3 -1
  357. package/src/setup/io/patchers/yaml.mjs +1 -1
  358. package/src/setup/modes/cli.mjs +76 -7
  359. package/src/setup/modes/mcp-command.mjs +802 -793
  360. package/src/setup/modes/mcp.mjs +7 -3
  361. package/src/setup/shared/prior-mode-detect.mjs +18 -21
  362. package/src/setup/test-seams.mjs +25 -0
  363. package/src/setup-auth.mjs +76 -10
  364. package/src/toml-lines.mjs +52 -0
  365. package/src/unified-cli.mjs +31 -16
  366. package/skills/flywheel-llm-proof-paper/scripts/__pycache__/check_paper.cpython-312.pyc +0 -0
  367. package/src/runtime/vendor/flywheel-cli-dist/auth/active-key-id.d.ts +0 -1
  368. package/src/runtime/vendor/flywheel-cli-dist/auth/baseurl.d.ts +0 -35
  369. package/src/runtime/vendor/flywheel-cli-dist/auth/config.d.ts +0 -34
  370. package/src/runtime/vendor/flywheel-cli-dist/auth/config.js +0 -92
  371. package/src/runtime/vendor/flywheel-cli-dist/auth/config.js.map +0 -1
  372. package/src/runtime/vendor/flywheel-cli-dist/auth/fingerprint.d.ts +0 -5
  373. package/src/runtime/vendor/flywheel-cli-dist/auth/keychain.d.ts +0 -4
  374. package/src/runtime/vendor/flywheel-cli-dist/auth/keychain.js +0 -31
  375. package/src/runtime/vendor/flywheel-cli-dist/auth/keychain.js.map +0 -1
  376. package/src/runtime/vendor/flywheel-cli-dist/auth/login.d.ts +0 -24
  377. package/src/runtime/vendor/flywheel-cli-dist/auth/profile.d.ts +0 -15
  378. package/src/runtime/vendor/flywheel-cli-dist/auth/profile.js +0 -150
  379. package/src/runtime/vendor/flywheel-cli-dist/auth/profile.js.map +0 -1
  380. package/src/runtime/vendor/flywheel-cli-dist/auth/profiles.d.ts +0 -27
  381. package/src/runtime/vendor/flywheel-cli-dist/commands/_admin-auth.d.ts +0 -27
  382. package/src/runtime/vendor/flywheel-cli-dist/commands/_artifacts-upload-helpers.d.ts +0 -32
  383. package/src/runtime/vendor/flywheel-cli-dist/commands/_artifacts-upload-helpers.js +0 -213
  384. package/src/runtime/vendor/flywheel-cli-dist/commands/_artifacts-upload-helpers.js.map +0 -1
  385. package/src/runtime/vendor/flywheel-cli-dist/commands/_browser-handoff.d.ts +0 -35
  386. package/src/runtime/vendor/flywheel-cli-dist/commands/_open-url.d.ts +0 -2
  387. package/src/runtime/vendor/flywheel-cli-dist/commands/_secret-param.d.ts +0 -7
  388. package/src/runtime/vendor/flywheel-cli-dist/commands/_stream-file-out.d.ts +0 -39
  389. package/src/runtime/vendor/flywheel-cli-dist/commands/_stream-writer.d.ts +0 -34
  390. package/src/runtime/vendor/flywheel-cli-dist/commands/_wait-polling.d.ts +0 -50
  391. package/src/runtime/vendor/flywheel-cli-dist/commands/account-detach.d.ts +0 -2
  392. package/src/runtime/vendor/flywheel-cli-dist/commands/account-emails-add.d.ts +0 -2
  393. package/src/runtime/vendor/flywheel-cli-dist/commands/account-emails-remove.d.ts +0 -2
  394. package/src/runtime/vendor/flywheel-cli-dist/commands/account-emails-set-primary.d.ts +0 -2
  395. package/src/runtime/vendor/flywheel-cli-dist/commands/account-get.d.ts +0 -2
  396. package/src/runtime/vendor/flywheel-cli-dist/commands/account-merge-preview.d.ts +0 -2
  397. package/src/runtime/vendor/flywheel-cli-dist/commands/account-merge-proof.d.ts +0 -2
  398. package/src/runtime/vendor/flywheel-cli-dist/commands/account-merge.d.ts +0 -2
  399. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-compute-policy-get.d.ts +0 -2
  400. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-compute-policy-set.d.ts +0 -2
  401. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-export-stream.d.ts +0 -2
  402. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-export.d.ts +0 -2
  403. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-graphs-list.d.ts +0 -4
  404. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-nodes-audit-list.d.ts +0 -2
  405. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-test-users-create.d.ts +0 -2
  406. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-test-users-delete.d.ts +0 -2
  407. package/src/runtime/vendor/flywheel-cli-dist/commands/admin-test-users-login.d.ts +0 -2
  408. package/src/runtime/vendor/flywheel-cli-dist/commands/aliases.d.ts +0 -13
  409. package/src/runtime/vendor/flywheel-cli-dist/commands/api-keys-create.d.ts +0 -2
  410. package/src/runtime/vendor/flywheel-cli-dist/commands/api-keys-delete.d.ts +0 -2
  411. package/src/runtime/vendor/flywheel-cli-dist/commands/api-keys-list.d.ts +0 -18
  412. package/src/runtime/vendor/flywheel-cli-dist/commands/api-keys-rotate.d.ts +0 -2
  413. package/src/runtime/vendor/flywheel-cli-dist/commands/approval-sessions-expire.d.ts +0 -2
  414. package/src/runtime/vendor/flywheel-cli-dist/commands/approval-sessions-heartbeat.d.ts +0 -2
  415. package/src/runtime/vendor/flywheel-cli-dist/commands/approval-sessions-list.d.ts +0 -2
  416. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-delete-bulk.d.ts +0 -2
  417. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-delete-bulk.js +0 -22
  418. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-delete-bulk.js.map +0 -1
  419. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-delete.d.ts +0 -2
  420. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-delete.js +0 -8
  421. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-delete.js.map +0 -1
  422. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-get.d.ts +0 -2
  423. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-list.d.ts +0 -2
  424. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-note-set.d.ts +0 -2
  425. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-note-set.js +0 -9
  426. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-note-set.js.map +0 -1
  427. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-upload-finalize.d.ts +0 -2
  428. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-upload-finalize.js +0 -7
  429. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-upload-finalize.js.map +0 -1
  430. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-upload-prepare.d.ts +0 -2
  431. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-upload-prepare.js +0 -15
  432. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-upload-prepare.js.map +0 -1
  433. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-upload.d.ts +0 -2
  434. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-upload.js +0 -5
  435. package/src/runtime/vendor/flywheel-cli-dist/commands/artifacts-upload.js.map +0 -1
  436. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-keychain-clear.d.ts +0 -2
  437. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-keychain-clear.js +0 -8
  438. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-keychain-clear.js.map +0 -1
  439. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-keychain-set.d.ts +0 -2
  440. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-keychain-set.js +0 -30
  441. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-keychain-set.js.map +0 -1
  442. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-login.d.ts +0 -2
  443. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-mode.d.ts +0 -4
  444. package/src/runtime/vendor/flywheel-cli-dist/commands/auth-status.d.ts +0 -2
  445. package/src/runtime/vendor/flywheel-cli-dist/commands/blobs-get.d.ts +0 -2
  446. package/src/runtime/vendor/flywheel-cli-dist/commands/campaign-budgets-create.d.ts +0 -2
  447. package/src/runtime/vendor/flywheel-cli-dist/commands/campaign-budgets-list.d.ts +0 -1
  448. package/src/runtime/vendor/flywheel-cli-dist/commands/campaign-budgets-revoke.d.ts +0 -1
  449. package/src/runtime/vendor/flywheel-cli-dist/commands/campaign-budgets-update.d.ts +0 -2
  450. package/src/runtime/vendor/flywheel-cli-dist/commands/campaign-snapshot.d.ts +0 -1
  451. package/src/runtime/vendor/flywheel-cli-dist/commands/compute-acquire.d.ts +0 -2
  452. package/src/runtime/vendor/flywheel-cli-dist/commands/compute-budgets.d.ts +0 -2
  453. package/src/runtime/vendor/flywheel-cli-dist/commands/compute-connection.d.ts +0 -2
  454. package/src/runtime/vendor/flywheel-cli-dist/commands/compute-funding.d.ts +0 -2
  455. package/src/runtime/vendor/flywheel-cli-dist/commands/compute-grants-list.d.ts +0 -2
  456. package/src/runtime/vendor/flywheel-cli-dist/commands/compute-grants-request-approval.d.ts +0 -2
  457. package/src/runtime/vendor/flywheel-cli-dist/commands/compute-options.d.ts +0 -2
  458. package/src/runtime/vendor/flywheel-cli-dist/commands/compute-release-all.d.ts +0 -2
  459. package/src/runtime/vendor/flywheel-cli-dist/commands/compute-release.d.ts +0 -2
  460. package/src/runtime/vendor/flywheel-cli-dist/commands/compute-status.d.ts +0 -2
  461. package/src/runtime/vendor/flywheel-cli-dist/commands/credits-balance.d.ts +0 -1
  462. package/src/runtime/vendor/flywheel-cli-dist/commands/credits-billing-portal.d.ts +0 -2
  463. package/src/runtime/vendor/flywheel-cli-dist/commands/credits-purchase.d.ts +0 -2
  464. package/src/runtime/vendor/flywheel-cli-dist/commands/credits-referral-claim.d.ts +0 -2
  465. package/src/runtime/vendor/flywheel-cli-dist/commands/credits-referral.d.ts +0 -1
  466. package/src/runtime/vendor/flywheel-cli-dist/commands/credits-subscribe.d.ts +0 -2
  467. package/src/runtime/vendor/flywheel-cli-dist/commands/credits-subscription.d.ts +0 -1
  468. package/src/runtime/vendor/flywheel-cli-dist/commands/credits-transactions.d.ts +0 -2
  469. package/src/runtime/vendor/flywheel-cli-dist/commands/credits-usage.d.ts +0 -2
  470. package/src/runtime/vendor/flywheel-cli-dist/commands/destructive-confirmation.d.ts +0 -2
  471. package/src/runtime/vendor/flywheel-cli-dist/commands/enums.d.ts +0 -22
  472. package/src/runtime/vendor/flywheel-cli-dist/commands/env.d.ts +0 -8
  473. package/src/runtime/vendor/flywheel-cli-dist/commands/executions-launch.d.ts +0 -2
  474. package/src/runtime/vendor/flywheel-cli-dist/commands/executions-list.d.ts +0 -1
  475. package/src/runtime/vendor/flywheel-cli-dist/commands/executions-terminate.d.ts +0 -2
  476. package/src/runtime/vendor/flywheel-cli-dist/commands/export-history.d.ts +0 -2
  477. package/src/runtime/vendor/flywheel-cli-dist/commands/export-subgraph.d.ts +0 -2
  478. package/src/runtime/vendor/flywheel-cli-dist/commands/export-summary-pdf.d.ts +0 -2
  479. package/src/runtime/vendor/flywheel-cli-dist/commands/export-summary-render-pdf.d.ts +0 -2
  480. package/src/runtime/vendor/flywheel-cli-dist/commands/export-summary-stream.d.ts +0 -2
  481. package/src/runtime/vendor/flywheel-cli-dist/commands/export-summary.d.ts +0 -2
  482. package/src/runtime/vendor/flywheel-cli-dist/commands/feedback-create.d.ts +0 -2
  483. package/src/runtime/vendor/flywheel-cli-dist/commands/files-list.d.ts +0 -2
  484. package/src/runtime/vendor/flywheel-cli-dist/commands/github-disconnect.d.ts +0 -1
  485. package/src/runtime/vendor/flywheel-cli-dist/commands/github-link.d.ts +0 -2
  486. package/src/runtime/vendor/flywheel-cli-dist/commands/github-refresh-repos.d.ts +0 -1
  487. package/src/runtime/vendor/flywheel-cli-dist/commands/github-status.d.ts +0 -1
  488. package/src/runtime/vendor/flywheel-cli-dist/commands/graph-get.d.ts +0 -2
  489. package/src/runtime/vendor/flywheel-cli-dist/commands/handler-factory.d.ts +0 -22
  490. package/src/runtime/vendor/flywheel-cli-dist/commands/help-format.d.ts +0 -31
  491. package/src/runtime/vendor/flywheel-cli-dist/commands/help-metadata.d.ts +0 -36
  492. package/src/runtime/vendor/flywheel-cli-dist/commands/help.d.ts +0 -17
  493. package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-create.d.ts +0 -2
  494. package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-delete.d.ts +0 -1
  495. package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-list.d.ts +0 -2
  496. package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-runs-list.d.ts +0 -2
  497. package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-create.d.ts +0 -2
  498. package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-delete.d.ts +0 -1
  499. package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-list.d.ts +0 -1
  500. package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-secrets-update.d.ts +0 -2
  501. package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-set-enabled.d.ts +0 -2
  502. package/src/runtime/vendor/flywheel-cli-dist/commands/hooks-update.d.ts +0 -2
  503. package/src/runtime/vendor/flywheel-cli-dist/commands/import-subgraph.d.ts +0 -2
  504. package/src/runtime/vendor/flywheel-cli-dist/commands/index.d.ts +0 -23
  505. package/src/runtime/vendor/flywheel-cli-dist/commands/integrations-huggingface-remove.d.ts +0 -1
  506. package/src/runtime/vendor/flywheel-cli-dist/commands/integrations-huggingface-set.d.ts +0 -2
  507. package/src/runtime/vendor/flywheel-cli-dist/commands/integrations-status.d.ts +0 -1
  508. package/src/runtime/vendor/flywheel-cli-dist/commands/integrations-wandb-remove.d.ts +0 -1
  509. package/src/runtime/vendor/flywheel-cli-dist/commands/integrations-wandb-set.d.ts +0 -2
  510. package/src/runtime/vendor/flywheel-cli-dist/commands/machines-list.d.ts +0 -1
  511. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-add-parent.d.ts +0 -2
  512. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-add-parent.js +0 -15
  513. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-add-parent.js.map +0 -1
  514. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-branch.d.ts +0 -2
  515. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-branch.js +0 -10
  516. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-branch.js.map +0 -1
  517. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-children.d.ts +0 -2
  518. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-children.js +0 -8
  519. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-children.js.map +0 -1
  520. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-commit-new.d.ts +0 -2
  521. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-commit-new.js +0 -6
  522. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-commit-new.js.map +0 -1
  523. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-commit.d.ts +0 -2
  524. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-commit.js +0 -7
  525. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-commit.js.map +0 -1
  526. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-create.d.ts +0 -2
  527. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-create.js +0 -6
  528. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-create.js.map +0 -1
  529. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-delete-bulk.d.ts +0 -2
  530. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-delete-bulk.js +0 -16
  531. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-delete-bulk.js.map +0 -1
  532. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-delete.d.ts +0 -2
  533. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-delete.js +0 -11
  534. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-delete.js.map +0 -1
  535. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-files.d.ts +0 -1
  536. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-get.d.ts +0 -2
  537. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-list.d.ts +0 -2
  538. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-merge.d.ts +0 -2
  539. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-merge.js +0 -33
  540. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-merge.js.map +0 -1
  541. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-parents.d.ts +0 -2
  542. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-parents.js +0 -8
  543. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-parents.js.map +0 -1
  544. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-remove-parent.d.ts +0 -2
  545. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-remove-parent.js +0 -15
  546. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-remove-parent.js.map +0 -1
  547. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-render-ancestry.d.ts +0 -2
  548. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-render-summary.d.ts +0 -2
  549. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-render-tree.d.ts +0 -2
  550. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-resolve-slug.d.ts +0 -2
  551. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-sharing-get.d.ts +0 -1
  552. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-sharing-set-bulk.d.ts +0 -2
  553. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-sharing-set.d.ts +0 -2
  554. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-sharing-summaries.d.ts +0 -2
  555. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-stage-lease-acquire.d.ts +0 -2
  556. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-stage-lease-heartbeat.d.ts +0 -2
  557. package/src/runtime/vendor/flywheel-cli-dist/commands/nodes-stage-lease-release.d.ts +0 -2
  558. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-list.d.ts +0 -2
  559. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-set.d.ts +0 -2
  560. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-show.d.ts +0 -2
  561. package/src/runtime/vendor/flywheel-cli-dist/commands/profile-unset.d.ts +0 -2
  562. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/account.d.ts +0 -2
  563. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/admin.d.ts +0 -8
  564. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/api-keys.d.ts +0 -2
  565. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/approval.d.ts +0 -2
  566. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/artifacts.d.ts +0 -2
  567. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/artifacts.js +0 -140
  568. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/artifacts.js.map +0 -1
  569. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/auth.d.ts +0 -2
  570. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/budgets.d.ts +0 -2
  571. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/compute.d.ts +0 -2
  572. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/credits.d.ts +0 -2
  573. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/env.d.ts +0 -2
  574. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/executions.d.ts +0 -2
  575. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/export.d.ts +0 -2
  576. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/github.d.ts +0 -2
  577. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/graph.d.ts +0 -2
  578. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/hooks.d.ts +0 -2
  579. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/integrations.d.ts +0 -2
  580. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/lifecycle.d.ts +0 -2
  581. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/profile.d.ts +0 -2
  582. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/resources.d.ts +0 -2
  583. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/sharing.d.ts +0 -2
  584. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/tagging.d.ts +0 -2
  585. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/tagging.js +0 -98
  586. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/tagging.js.map +0 -1
  587. package/src/runtime/vendor/flywheel-cli-dist/commands/registry/updates.d.ts +0 -2
  588. package/src/runtime/vendor/flywheel-cli-dist/commands/registry.d.ts +0 -27
  589. package/src/runtime/vendor/flywheel-cli-dist/commands/remote-artifacts-refresh.d.ts +0 -2
  590. package/src/runtime/vendor/flywheel-cli-dist/commands/remote-artifacts-resolve.d.ts +0 -2
  591. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-assign.d.ts +0 -2
  592. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-assign.js +0 -25
  593. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-assign.js.map +0 -1
  594. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-create.d.ts +0 -2
  595. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-create.js +0 -25
  596. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-create.js.map +0 -1
  597. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-delete.d.ts +0 -2
  598. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-delete.js +0 -11
  599. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-delete.js.map +0 -1
  600. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-update.d.ts +0 -2
  601. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-update.js +0 -28
  602. package/src/runtime/vendor/flywheel-cli-dist/commands/tags-update.js.map +0 -1
  603. package/src/runtime/vendor/flywheel-cli-dist/commands/types.d.ts +0 -30
  604. package/src/runtime/vendor/flywheel-cli-dist/commands/updates-hide-all-active.d.ts +0 -1
  605. package/src/runtime/vendor/flywheel-cli-dist/commands/updates-hide.d.ts +0 -2
  606. package/src/runtime/vendor/flywheel-cli-dist/commands/updates-list.d.ts +0 -2
  607. package/src/runtime/vendor/flywheel-cli-dist/commands/usage-spec.d.ts +0 -6
  608. package/src/runtime/vendor/flywheel-cli-dist/commands/utils.d.ts +0 -11
  609. package/src/runtime/vendor/flywheel-cli-dist/errors.d.ts +0 -86
  610. package/src/runtime/vendor/flywheel-cli-dist/exit-codes.d.ts +0 -8
  611. package/src/runtime/vendor/flywheel-cli-dist/generatedFeedbackContract.d.ts +0 -41
  612. package/src/runtime/vendor/flywheel-cli-dist/generatedProductTelemetryContract.d.ts +0 -13
  613. package/src/runtime/vendor/flywheel-cli-dist/grammar/globals.d.ts +0 -26
  614. package/src/runtime/vendor/flywheel-cli-dist/grammar/parse.d.ts +0 -17
  615. package/src/runtime/vendor/flywheel-cli-dist/http/client.d.ts +0 -91
  616. package/src/runtime/vendor/flywheel-cli-dist/http/debug.d.ts +0 -5
  617. package/src/runtime/vendor/flywheel-cli-dist/http/poll.d.ts +0 -18
  618. package/src/runtime/vendor/flywheel-cli-dist/http/retry.d.ts +0 -30
  619. package/src/runtime/vendor/flywheel-cli-dist/main.d.ts +0 -33
  620. package/src/runtime/vendor/flywheel-cli-dist/output/format.d.ts +0 -9
  621. package/src/runtime/vendor/flywheel-cli-dist/runtime-entry.d.ts +0 -1
  622. package/src/runtime/vendor/flywheel-cli-dist/version.d.ts +0 -3
  623. package/src/secure-write.mjs +0 -43
package/src/cli.mjs CHANGED
@@ -4,42 +4,43 @@ import ora from "ora";
4
4
  import pc from "picocolors";
5
5
  import { access, readFile, rm } from "node:fs/promises";
6
6
  import path from "node:path";
7
+ import { isatty } from "node:tty";
7
8
 
8
9
  import {
9
- ALL_HOST_NAMES,
10
- SERVER_NAME,
11
- SETUP_HOST_NAMES,
12
- SKILL_ONLY_HOST_NAMES,
13
- detectHosts,
14
- getHost,
15
- isSkillOnlyHost,
16
- normalizeHosts,
10
+ ALL_HOST_NAMES,
11
+ SERVER_NAME,
12
+ SETUP_HOST_NAMES,
13
+ SKILL_ONLY_HOST_NAMES,
14
+ detectHosts,
15
+ getHost,
16
+ isSkillOnlyHost,
17
+ normalizeHosts,
17
18
  } from "./agents.mjs";
18
19
  import { generateCompletionScript } from "./completion.mjs";
19
20
  import {
20
- installCompletion,
21
- uninstallCompletion,
21
+ installCompletion,
22
+ uninstallCompletion,
22
23
  } from "./completion-install.mjs";
23
24
  import {
24
- readEntryServerUrl,
25
- readNamedConfigEntry,
26
- readJsonConfig,
27
- readTomlServerEntry,
28
- readYamlConfig,
29
- removeCodexTomlServer,
30
- removeJsonServerEntry,
31
- resolveMcpPath,
32
- writeJsonConfig,
33
- writeYamlConfig,
25
+ readEntryServerUrl,
26
+ readNamedConfigEntry,
27
+ readJsonConfig,
28
+ readTomlServerEntry,
29
+ readYamlConfig,
30
+ removeCodexTomlServer,
31
+ removeJsonServerEntry,
32
+ resolveMcpPath,
33
+ writeJsonConfig,
34
+ writeYamlConfig,
34
35
  } from "./mcp-writer.mjs";
35
36
  import {
36
- listBundledSkills,
37
- partitionInstallSkillHosts,
38
- removeInstalledSkillsForHosts,
39
- resolveInstalledSkillDir,
40
- resolveFlywheelInstalledMarkerPath,
41
- SUPPORTED_INSTALL_SKILL_HOSTS,
42
- resolvePackageRoot,
37
+ listBundledSkills,
38
+ partitionInstallSkillHosts,
39
+ removeInstalledSkillsForHosts,
40
+ resolveInstalledSkillDir,
41
+ resolveFlywheelInstalledMarkerPath,
42
+ SUPPORTED_INSTALL_SKILL_HOSTS,
43
+ resolvePackageRoot,
43
44
  } from "./skill-installer.mjs";
44
45
  import { normalizeSetupAuthMode } from "./setup-auth.mjs";
45
46
  import { resolveSetupBaseUrl } from "./setup/base-url.mjs";
@@ -47,292 +48,292 @@ import { runSetupRouter } from "./setup/command.mjs";
47
48
  import { SetupModeUsageError } from "./setup/mode.mjs";
48
49
  import { runCliSetupMode } from "./setup/modes/cli.mjs";
49
50
  import {
50
- buildGuidedSkillInstallPrompt,
51
- runMcpModeCommand,
51
+ buildGuidedSkillInstallPrompt,
52
+ runMcpModeCommand,
52
53
  } from "./setup/modes/mcp-command.mjs";
53
54
  import { COMPLETION_SHELL_CHOICES } from "./public-command-metadata.mjs";
54
55
  import { findFlywheelMcpEntryNames } from "./setup/shared/prior-mode-detect.mjs";
55
56
  import { renderSetupSummary } from "./setup/shared/summary.mjs";
56
57
 
57
58
  async function pathExists(targetPath) {
58
- try {
59
- await access(targetPath);
60
- return true;
61
- } catch {
62
- return false;
63
- }
59
+ try {
60
+ await access(targetPath);
61
+ return true;
62
+ } catch {
63
+ return false;
64
+ }
64
65
  }
65
66
 
66
67
  export { buildGuidedSkillInstallPrompt };
67
68
 
68
69
  const log = {
69
- info: (message) => console.log(pc.cyan(message)),
70
- warn: (message) => console.log(pc.yellow(`⚠ ${message}`)),
71
- error: (message) => console.log(pc.red(`✖ ${message}`)),
72
- plain: (message) => console.log(message),
73
- blank: () => console.log(""),
70
+ info: (message) => console.log(pc.cyan(message)),
71
+ warn: (message) => console.log(pc.yellow(`⚠ ${message}`)),
72
+ error: (message) => console.log(pc.red(`✖ ${message}`)),
73
+ plain: (message) => console.log(message),
74
+ blank: () => console.log(""),
74
75
  };
75
76
 
76
77
  const CHECKBOX_THEME = {
77
- style: {
78
- highlight: (text) => pc.green(text),
79
- disabledChoice: (text) => ` ${pc.dim("◯")} ${pc.dim(text)}`,
80
- },
78
+ style: {
79
+ highlight: (text) => pc.green(text),
80
+ disabledChoice: (text) => ` ${pc.dim("◯")} ${pc.dim(text)}`,
81
+ },
81
82
  };
82
83
 
83
84
  function hostChoiceDescription({ detected = false, configured = false } = {}) {
84
- if (configured) return "Already has a Flywheel entry for this scope.";
85
- if (detected) return "Detected on this machine.";
86
- return "Supported host; select it if you use it here.";
85
+ if (configured) return "Already has a Flywheel entry for this scope.";
86
+ if (detected) return "Detected on this machine.";
87
+ return "Supported host; select it if you use it here.";
87
88
  }
88
89
 
89
90
  function normalizeBaseUrl(value) {
90
- const normalized = String(value || "").trim();
91
- let parsedUrl;
92
- try {
93
- parsedUrl = new URL(normalized);
94
- } catch {
95
- throw new Error("Base URL must be a valid absolute URL.");
96
- }
97
-
98
- if (parsedUrl.pathname !== "/" || parsedUrl.search || parsedUrl.hash) {
99
- throw new Error(
100
- "Base URL must be a public Flywheel origin without a path, query, or hash.",
101
- );
102
- }
91
+ const normalized = String(value || "").trim();
92
+ let parsedUrl;
93
+ try {
94
+ parsedUrl = new URL(normalized);
95
+ } catch {
96
+ throw new Error("Base URL must be a valid absolute URL.");
97
+ }
98
+
99
+ if (parsedUrl.pathname !== "/" || parsedUrl.search || parsedUrl.hash) {
100
+ throw new Error(
101
+ "Base URL must be a public Flywheel origin without a path, query, or hash.",
102
+ );
103
+ }
103
104
 
104
- return parsedUrl.origin;
105
+ return parsedUrl.origin;
105
106
  }
106
107
 
107
108
  function normalizeServerName(value) {
108
- const normalized = String(value || "").trim();
109
- if (!normalized) {
110
- throw new Error("Server name cannot be empty.");
111
- }
112
- return normalized;
109
+ const normalized = String(value || "").trim();
110
+ if (!normalized) {
111
+ throw new Error("Server name cannot be empty.");
112
+ }
113
+ return normalized;
113
114
  }
114
115
 
115
116
  function normalizeAuthMode(value) {
116
- return normalizeSetupAuthMode(value);
117
+ return normalizeSetupAuthMode(value);
117
118
  }
118
119
 
119
120
  function selectedHostsFromOptions(options) {
120
- const hosts = [];
121
- if (options.claude) hosts.push("claude");
122
- if (options.cursor) hosts.push("cursor");
123
- if (options.universal) hosts.push("universal");
124
- if (options.antigravity) hosts.push("antigravity");
125
- if (options.opencode) hosts.push("opencode");
126
- if (options.codex) hosts.push("codex");
127
- if (options.gemini) hosts.push("gemini");
128
- if (options.piMono) hosts.push("pi-mono");
129
- if (options.hermesAgent) hosts.push("hermes-agent");
130
- if (options.openclaw) hosts.push("openclaw");
131
- return hosts;
121
+ const hosts = [];
122
+ if (options.claude) hosts.push("claude");
123
+ if (options.cursor) hosts.push("cursor");
124
+ if (options.universal) hosts.push("universal");
125
+ if (options.antigravity) hosts.push("antigravity");
126
+ if (options.opencode) hosts.push("opencode");
127
+ if (options.codex) hosts.push("codex");
128
+ if (options.gemini) hosts.push("gemini");
129
+ if (options.piMono) hosts.push("pi-mono");
130
+ if (options.hermesAgent) hosts.push("hermes-agent");
131
+ if (options.openclaw) hosts.push("openclaw");
132
+ return hosts;
132
133
  }
133
134
 
134
135
  const UNINSTALL_OPTION_KEY_BY_HOST = Object.freeze({
135
- claude: "claude",
136
- codex: "codex",
137
- opencode: "opencode",
138
- cursor: "cursor",
139
- gemini: "gemini",
140
- universal: "universal",
141
- antigravity: "antigravity",
142
- "pi-mono": "piMono",
143
- "hermes-agent": "hermesAgent",
144
- openclaw: "openclaw",
136
+ claude: "claude",
137
+ codex: "codex",
138
+ opencode: "opencode",
139
+ cursor: "cursor",
140
+ gemini: "gemini",
141
+ universal: "universal",
142
+ antigravity: "antigravity",
143
+ "pi-mono": "piMono",
144
+ "hermes-agent": "hermesAgent",
145
+ openclaw: "openclaw",
145
146
  });
146
147
 
147
148
  function buildUninstallOptionsForHosts({
148
- hostNames = [],
149
- scope = "project",
150
- serverName = SERVER_NAME,
149
+ hostNames = [],
150
+ scope = "project",
151
+ serverName = SERVER_NAME,
151
152
  } = {}) {
152
- const options = {
153
- yes: true,
154
- scope,
155
- name: serverName,
156
- };
153
+ const options = {
154
+ yes: true,
155
+ scope,
156
+ name: serverName,
157
+ };
157
158
 
158
- for (const hostName of hostNames) {
159
- const optionKey = UNINSTALL_OPTION_KEY_BY_HOST[hostName];
160
- if (optionKey) {
161
- options[optionKey] = true;
162
- }
159
+ for (const hostName of hostNames) {
160
+ const optionKey = UNINSTALL_OPTION_KEY_BY_HOST[hostName];
161
+ if (optionKey) {
162
+ options[optionKey] = true;
163
163
  }
164
+ }
164
165
 
165
- return options;
166
+ return options;
166
167
  }
167
168
 
168
169
  function parseHostsList(value) {
169
- if (!value) return [];
170
- return normalizeHosts(
171
- String(value)
172
- .split(",")
173
- .map((item) => item.trim())
174
- .filter(Boolean),
175
- );
170
+ if (!value) return [];
171
+ return normalizeHosts(
172
+ String(value)
173
+ .split(",")
174
+ .map((item) => item.trim())
175
+ .filter(Boolean),
176
+ );
176
177
  }
177
178
 
178
179
  function collectModeValues(value, previousValues = []) {
179
- return [...previousValues, value];
180
+ return [...previousValues, value];
180
181
  }
181
182
 
182
183
  function mcpCandidatesForScope(host, scope) {
183
- if (scope === "global") return host.mcp.globalPaths;
184
- return host.mcp.projectPaths.map((candidate) =>
185
- path.join(process.cwd(), candidate),
186
- );
184
+ if (scope === "global") return host.mcp.globalPaths;
185
+ return host.mcp.projectPaths.map((candidate) =>
186
+ path.join(process.cwd(), candidate),
187
+ );
187
188
  }
188
189
 
189
190
  async function isAlreadyConfigured(hostName, scope, serverName) {
190
- const existingState = await readExistingServerState(
191
- hostName,
192
- scope,
193
- serverName,
194
- );
195
- return existingState.exists;
191
+ const existingState = await readExistingServerState(
192
+ hostName,
193
+ scope,
194
+ serverName,
195
+ );
196
+ return existingState.exists;
196
197
  }
197
198
 
198
199
  async function readExistingServerState(hostName, scope, serverName) {
199
- const host = getHost(hostName);
200
- if (isSkillOnlyHost(host)) {
201
- return { exists: false, url: null, mcpPath: null };
202
- }
203
- const mcpPath = await resolveMcpPath(mcpCandidatesForScope(host, scope));
204
-
205
- if (host.mcp.configType === "toml") {
206
- const { exists, url } = await readTomlServerEntry(mcpPath, serverName);
207
- return { exists, url, mcpPath };
208
- }
209
-
210
- const existing =
211
- host.mcp.configType === "yaml"
212
- ? await readYamlConfig(mcpPath)
213
- : await readJsonConfig(mcpPath);
214
- const entry = readNamedConfigEntry(existing, host.mcp.configKey, serverName);
215
- return {
216
- exists: entry !== null,
217
- url: readEntryServerUrl(entry),
218
- mcpPath,
219
- };
200
+ const host = getHost(hostName);
201
+ if (isSkillOnlyHost(host)) {
202
+ return { exists: false, url: null, mcpPath: null };
203
+ }
204
+ const mcpPath = await resolveMcpPath(mcpCandidatesForScope(host, scope));
205
+
206
+ if (host.mcp.configType === "toml") {
207
+ const { exists, url } = await readTomlServerEntry(mcpPath, serverName);
208
+ return { exists, url, mcpPath };
209
+ }
210
+
211
+ const existing =
212
+ host.mcp.configType === "yaml"
213
+ ? await readYamlConfig(mcpPath)
214
+ : await readJsonConfig(mcpPath);
215
+ const entry = readNamedConfigEntry(existing, host.mcp.configKey, serverName);
216
+ return {
217
+ exists: entry !== null,
218
+ url: readEntryServerUrl(entry),
219
+ mcpPath,
220
+ };
220
221
  }
221
222
 
222
223
  async function promptHosts(
223
- scope,
224
- detected,
225
- serverName,
226
- { disableAlreadyConfigured = true } = {},
224
+ scope,
225
+ detected,
226
+ serverName,
227
+ { disableAlreadyConfigured = true } = {},
227
228
  ) {
228
- const choices = await Promise.all(
229
- ALL_HOST_NAMES.map(async (hostName) => {
230
- const configured = await isAlreadyConfigured(
231
- hostName,
232
- scope,
233
- serverName,
234
- ).catch(() => false);
235
- return {
236
- name: SETUP_HOST_NAMES[hostName],
237
- value: hostName,
238
- short: SETUP_HOST_NAMES[hostName],
239
- description: hostChoiceDescription({
240
- detected: detected.includes(hostName),
241
- configured,
242
- }),
243
- checked: detected.includes(hostName),
244
- disabled:
245
- disableAlreadyConfigured && configured
246
- ? "(already configured)"
247
- : false,
248
- };
229
+ const choices = await Promise.all(
230
+ ALL_HOST_NAMES.map(async (hostName) => {
231
+ const configured = await isAlreadyConfigured(
232
+ hostName,
233
+ scope,
234
+ serverName,
235
+ ).catch(() => false);
236
+ return {
237
+ name: SETUP_HOST_NAMES[hostName],
238
+ value: hostName,
239
+ short: SETUP_HOST_NAMES[hostName],
240
+ description: hostChoiceDescription({
241
+ detected: detected.includes(hostName),
242
+ configured,
249
243
  }),
250
- );
251
-
252
- if (
253
- disableAlreadyConfigured &&
254
- choices.every((choice) => Boolean(choice.disabled))
255
- ) {
256
- log.info("Flywheel is already configured for all detected hosts.");
257
- return null;
258
- }
259
-
260
- try {
261
- return await checkbox({
262
- message: "Which hosts do you want to set up?",
263
- choices,
264
- loop: false,
265
- theme: CHECKBOX_THEME,
266
- validate: (selected) =>
267
- selected.length > 0 || "Select at least one host.",
268
- });
269
- } catch {
270
- return null;
271
- }
244
+ checked: detected.includes(hostName),
245
+ disabled:
246
+ disableAlreadyConfigured && configured
247
+ ? "(already configured)"
248
+ : false,
249
+ };
250
+ }),
251
+ );
252
+
253
+ if (
254
+ disableAlreadyConfigured &&
255
+ choices.every((choice) => Boolean(choice.disabled))
256
+ ) {
257
+ log.info("Flywheel is already configured for all detected hosts.");
258
+ return null;
259
+ }
260
+
261
+ try {
262
+ return await checkbox({
263
+ message: "Which hosts do you want to set up?",
264
+ choices,
265
+ loop: false,
266
+ theme: CHECKBOX_THEME,
267
+ validate: (selected) =>
268
+ selected.length > 0 || "Select at least one host.",
269
+ });
270
+ } catch {
271
+ return null;
272
+ }
272
273
  }
273
274
 
274
275
  async function resolveHosts(
275
- options,
276
- scope,
277
- serverName,
278
- { allowPrompt = true, disableAlreadyConfigured = true } = {},
276
+ options,
277
+ scope,
278
+ serverName,
279
+ { allowPrompt = true, disableAlreadyConfigured = true } = {},
279
280
  ) {
280
- const explicit = selectedHostsFromOptions(options);
281
- if (explicit.length > 0) return explicit;
282
-
283
- const detected = await detectHosts(scope);
284
- const promptDisabled =
285
- options.yes || process.stdout.isTTY !== true || !allowPrompt;
286
- if (detected.length > 0 && promptDisabled) {
287
- return detected;
288
- }
289
-
290
- if (promptDisabled) {
291
- log.warn(
292
- "No hosts were detected for prompt-free setup. Pass explicit host flags such as --codex.",
293
- );
294
- return [];
295
- }
296
-
297
- log.blank();
298
- const selected = await promptHosts(scope, detected, serverName, {
299
- disableAlreadyConfigured,
300
- });
301
- if (!selected) {
302
- log.warn("Setup cancelled");
303
- return [];
304
- }
305
- return selected;
281
+ const explicit = selectedHostsFromOptions(options);
282
+ if (explicit.length > 0) return explicit;
283
+
284
+ const detected = await detectHosts(scope);
285
+ const promptDisabled =
286
+ options.yes || process.stdout.isTTY !== true || !allowPrompt;
287
+ if (detected.length > 0 && promptDisabled) {
288
+ return detected;
289
+ }
290
+
291
+ if (promptDisabled) {
292
+ log.warn(
293
+ "No hosts were detected for prompt-free setup. Pass explicit host flags such as --codex.",
294
+ );
295
+ return [];
296
+ }
297
+
298
+ log.blank();
299
+ const selected = await promptHosts(scope, detected, serverName, {
300
+ disableAlreadyConfigured,
301
+ });
302
+ if (!selected) {
303
+ log.warn("Setup cancelled");
304
+ return [];
305
+ }
306
+ return selected;
306
307
  }
307
308
 
308
309
  export function buildSetupModePromptConfig() {
309
- return {
310
- message: "How should your agent access Flywheel?",
311
- choices: [
312
- {
313
- name: "MCP + bundled skills",
314
- value: "mcp",
315
- short: "MCP + skills",
316
- description:
317
- "Configure MCP tools plus bundled skills for supported AI hosts.",
318
- },
319
- {
320
- name: "CLI + bundled skills",
321
- value: "cli",
322
- short: "CLI + skills",
323
- description:
324
- "Install bundled skills for agents that call the flywheel binary.",
325
- },
326
- ],
327
- default: "mcp",
328
- loop: false,
329
- pageSize: 4,
330
- theme: CHECKBOX_THEME,
331
- };
310
+ return {
311
+ message: "How should your agent access Flywheel?",
312
+ choices: [
313
+ {
314
+ name: "MCP + bundled skills",
315
+ value: "mcp",
316
+ short: "MCP + skills",
317
+ description:
318
+ "Configure MCP tools plus bundled skills for supported AI hosts.",
319
+ },
320
+ {
321
+ name: "CLI + bundled skills",
322
+ value: "cli",
323
+ short: "CLI + skills",
324
+ description:
325
+ "Install bundled skills for agents that call the flywheel binary.",
326
+ },
327
+ ],
328
+ default: "mcp",
329
+ loop: false,
330
+ pageSize: 4,
331
+ theme: CHECKBOX_THEME,
332
+ };
332
333
  }
333
334
 
334
335
  async function promptSetupMode() {
335
- return await select(buildSetupModePromptConfig());
336
+ return await select(buildSetupModePromptConfig());
336
337
  }
337
338
 
338
339
  /**
@@ -348,327 +349,329 @@ async function promptSetupMode() {
348
349
  * it up front with guidance toward the correct invocation.
349
350
  */
350
351
  function validateCliModeFlags(options) {
351
- if (options.installSkill && options.skipSkill) {
352
- throw new SetupModeUsageError(
353
- "--install-skill and --skip-skill cannot be used together.",
354
- );
355
- }
356
- // CLI mode is intentionally "skills only", so --skip-skill would contradict
357
- // the mode contract and silently surprising behavior should be rejected.
358
- if (options.skipSkill) {
359
- throw new SetupModeUsageError(
360
- "--skip-skill is not supported with --mode cli; use --mode mcp --skip-skill for MCP-only setup.",
361
- );
362
- }
363
- if (options.oauth === true) {
364
- throw new SetupModeUsageError(
365
- "--oauth is not supported with --mode cli. --oauth only affects the MCP config written by --mode mcp; re-run with --mode mcp --oauth, or drop --oauth for a CLI-mode setup.",
366
- );
367
- }
368
- }
369
-
370
- async function runCliModeCommand(options) {
371
- validateCliModeFlags(options);
372
- const scope = options.project ? "project" : "global";
373
- const baseUrl = normalizeBaseUrl(
374
- resolveSetupBaseUrl({ explicitBaseUrl: options.baseUrl }),
352
+ if (options.installSkill && options.skipSkill) {
353
+ throw new SetupModeUsageError(
354
+ "--install-skill and --skip-skill cannot be used together.",
375
355
  );
376
- const serverUrl = `${baseUrl}/mcp-server`;
377
- const serverName = normalizeServerName(options.name || SERVER_NAME);
378
- const hosts = await resolveHosts(options, scope, serverName, {
379
- allowPrompt: true,
380
- // CLI mode is a skills refresh/install path, so existing MCP wiring should
381
- // not make hosts ineligible for selection.
382
- disableAlreadyConfigured: false,
383
- });
384
- if (hosts.length === 0) {
385
- return { exitCode: 0 };
386
- }
387
-
388
- const result = await runCliSetupMode({
389
- selectedHosts: hosts,
390
- scope,
391
- cwd: process.cwd(),
392
- force: options.force === true,
393
- apiKey: options.apiKey,
394
- authMode: options.authMode,
395
- baseUrl,
396
- serverName,
397
- serverUrl,
398
- reconcilePriorMode: async ({ hostNames, serverNames }) => {
399
- // Uninstall each detected server name so renamed/drifted Flywheel MCP
400
- // entries are actually removed. When the detector found no explicit
401
- // names (prior CLI artifacts case), fall back to the current request's
402
- // --name so the skill cleanup path still runs.
403
- const targetNames =
404
- Array.isArray(serverNames) && serverNames.length > 0
405
- ? serverNames
406
- : [serverName];
407
- for (const targetName of targetNames) {
408
- // eslint-disable-next-line no-await-in-loop
409
- await runUninstallCommand(
410
- buildUninstallOptionsForHosts({
411
- hostNames,
412
- scope,
413
- serverName: targetName,
414
- }),
415
- );
416
- }
417
- },
418
- });
356
+ }
357
+ // CLI mode is intentionally "skills only", so --skip-skill would contradict
358
+ // the mode contract and silently surprising behavior should be rejected.
359
+ if (options.skipSkill) {
360
+ throw new SetupModeUsageError(
361
+ "--skip-skill is not supported with --mode cli; use --mode mcp --skip-skill for MCP-only setup.",
362
+ );
363
+ }
364
+ if (options.oauth === true) {
365
+ throw new SetupModeUsageError(
366
+ "--oauth is not supported with --mode cli. --oauth only affects the MCP config written by --mode mcp; re-run with --mode mcp --oauth, or drop --oauth for a CLI-mode setup.",
367
+ );
368
+ }
369
+ }
419
370
 
420
- const lines = renderSetupSummary(result);
421
- log.blank();
422
- for (const line of lines) {
423
- log.plain(` ${line}`);
424
- }
425
- log.blank();
426
-
427
- if (result.exitCode !== 0) {
428
- const failureDetails = result.agentResults
429
- .filter((agentResult) => agentResult.success !== true)
430
- .flatMap((agentResult) =>
431
- Array.isArray(agentResult.warnings) ? agentResult.warnings : [],
432
- )
433
- .join(" | ");
434
- const error = new Error(
435
- failureDetails.length > 0
436
- ? `CLI setup encountered host-level failures: ${failureDetails}`
437
- : "CLI setup encountered host-level failures.",
371
+ async function runCliModeCommand(options, readStdinAuth) {
372
+ validateCliModeFlags(options);
373
+ const scope = options.project ? "project" : "global";
374
+ const baseUrl = normalizeBaseUrl(
375
+ resolveSetupBaseUrl({ explicitBaseUrl: options.baseUrl }),
376
+ );
377
+ const serverUrl = `${baseUrl}/mcp-server`;
378
+ const serverName = normalizeServerName(options.name || SERVER_NAME);
379
+ const hosts = await resolveHosts(options, scope, serverName, {
380
+ allowPrompt: true,
381
+ // CLI mode is a skills refresh/install path, so existing MCP wiring should
382
+ // not make hosts ineligible for selection.
383
+ disableAlreadyConfigured: false,
384
+ });
385
+ if (hosts.length === 0 && readStdinAuth === undefined) {
386
+ return { exitCode: 0 };
387
+ }
388
+
389
+ const result = await runCliSetupMode({
390
+ selectedHosts: hosts,
391
+ scope,
392
+ cwd: process.cwd(),
393
+ force: options.force === true,
394
+ apiKey: options.apiKey,
395
+ authMode: options.authMode,
396
+ readStdinAuth,
397
+ baseUrl,
398
+ serverName,
399
+ serverUrl,
400
+ reconcilePriorMode: async ({ hostNames, serverNames }) => {
401
+ // Uninstall each detected server name so renamed/drifted Flywheel MCP
402
+ // entries are actually removed. When the detector found no explicit
403
+ // names (prior CLI artifacts case), fall back to the current request's
404
+ // --name so the skill cleanup path still runs.
405
+ const targetNames =
406
+ Array.isArray(serverNames) && serverNames.length > 0
407
+ ? serverNames
408
+ : [serverName];
409
+ for (const targetName of targetNames) {
410
+ // eslint-disable-next-line no-await-in-loop
411
+ await runUninstallCommand(
412
+ buildUninstallOptionsForHosts({
413
+ hostNames,
414
+ scope,
415
+ serverName: targetName,
416
+ }),
438
417
  );
439
- error.exitCode = result.exitCode;
440
- throw error;
441
- }
418
+ }
419
+ },
420
+ });
421
+
422
+ const lines = renderSetupSummary(result);
423
+ log.blank();
424
+ for (const line of lines) {
425
+ log.plain(` ${line}`);
426
+ }
427
+ log.blank();
428
+
429
+ if (result.exitCode !== 0) {
430
+ const failureDetails = result.agentResults
431
+ .filter((agentResult) => agentResult.success !== true)
432
+ .flatMap((agentResult) =>
433
+ Array.isArray(agentResult.warnings) ? agentResult.warnings : [],
434
+ )
435
+ .join(" | ");
436
+ const error = new Error(
437
+ failureDetails.length > 0
438
+ ? `CLI setup encountered host-level failures: ${failureDetails}`
439
+ : "CLI setup encountered host-level failures.",
440
+ );
441
+ error.exitCode = result.exitCode;
442
+ throw error;
443
+ }
442
444
 
443
- return result;
445
+ return result;
444
446
  }
445
447
 
446
448
  async function runSetupCommandViaRouter(options) {
447
- return await runSetupRouter(options, {
448
- isInteractive:
449
- process.stdin.isTTY === true && process.stdout.isTTY === true,
450
- promptMode: promptSetupMode,
451
- runMcpMode: async () =>
452
- await runMcpModeCommand(options, {
453
- force: options.force === true,
454
- reconcilePriorMode: async ({
455
- hostNames,
456
- serverNames,
457
- scope: reconcileScope,
458
- serverName: requestedServerName,
459
- }) => {
460
- // Prior CLI artifacts have no MCP entry name, so fall back to the
461
- // current request's --name for the skill uninstall path. Prior MCP
462
- // entries may carry drifted names; uninstall each detected name so
463
- // the reconcile actually removes what we detected.
464
- const targetNames =
465
- Array.isArray(serverNames) && serverNames.length > 0
466
- ? serverNames
467
- : [requestedServerName];
468
- for (const targetName of targetNames) {
469
- // eslint-disable-next-line no-await-in-loop
470
- await runUninstallCommand(
471
- buildUninstallOptionsForHosts({
472
- hostNames,
473
- scope: reconcileScope,
474
- serverName: targetName,
475
- }),
476
- );
477
- }
478
- },
479
- }),
480
- runCliMode: async () => await runCliModeCommand(options),
481
- });
449
+ return await runSetupRouter(options, {
450
+ isInteractive:
451
+ isatty(0) && process.stdout.isTTY === true,
452
+ promptMode: promptSetupMode,
453
+ runMcpMode: async ({ readStdinAuth }) =>
454
+ await runMcpModeCommand(options, {
455
+ readStdinAuth,
456
+ force: options.force === true,
457
+ reconcilePriorMode: async ({
458
+ hostNames,
459
+ serverNames,
460
+ scope: reconcileScope,
461
+ serverName: requestedServerName,
462
+ }) => {
463
+ // Prior CLI artifacts have no MCP entry name, so fall back to the
464
+ // current request's --name for the skill uninstall path. Prior MCP
465
+ // entries may carry drifted names; uninstall each detected name so
466
+ // the reconcile actually removes what we detected.
467
+ const targetNames =
468
+ Array.isArray(serverNames) && serverNames.length > 0
469
+ ? serverNames
470
+ : [requestedServerName];
471
+ for (const targetName of targetNames) {
472
+ // eslint-disable-next-line no-await-in-loop
473
+ await runUninstallCommand(
474
+ buildUninstallOptionsForHosts({
475
+ hostNames,
476
+ scope: reconcileScope,
477
+ serverName: targetName,
478
+ }),
479
+ );
480
+ }
481
+ },
482
+ }),
483
+ runCliMode: async ({ readStdinAuth }) => await runCliModeCommand(options, readStdinAuth),
484
+ });
482
485
  }
483
486
 
484
487
  async function runCompletionCommand(shell, options) {
485
- try {
486
- const script = await generateCompletionScript({
487
- shell,
488
- includeBashCompletionLib: options.includeBashCompletionLib === true,
489
- });
490
- process.stdout.write(script);
491
- } catch (error) {
492
- const message = error instanceof Error ? error.message : String(error);
493
- process.stderr.write(`${message}\n`);
494
- process.exitCode = 1;
495
- }
488
+ try {
489
+ const script = await generateCompletionScript({
490
+ shell,
491
+ includeBashCompletionLib: options.includeBashCompletionLib === true,
492
+ });
493
+ process.stdout.write(script);
494
+ } catch (error) {
495
+ const message = error instanceof Error ? error.message : String(error);
496
+ process.stderr.write(`${message}\n`);
497
+ process.exitCode = 1;
498
+ }
496
499
  }
497
500
 
498
501
  async function runCompletionInstallCommand(shell, options) {
499
- try {
500
- await installCompletion({
501
- shell,
502
- dir: options.dir,
503
- force: options.force === true,
504
- dryRun: options.dryRun === true,
505
- updateProfile: options.updateProfile === true,
506
- yes: options.yes === true,
507
- isInteractive:
508
- process.stdin.isTTY === true && process.stdout.isTTY === true,
509
- stdout: (chunk) => process.stdout.write(chunk),
510
- stderr: (chunk) => process.stderr.write(chunk),
511
- confirmProfileUpdate: async ({ message, default: defaultValue }) =>
512
- await confirm({ message, default: defaultValue }),
513
- generateCompletionScript,
514
- });
515
- } catch (error) {
516
- const message = error instanceof Error ? error.message : String(error);
517
- process.stderr.write(`${message}\n`);
518
- process.exitCode = 1;
519
- }
502
+ try {
503
+ await installCompletion({
504
+ shell,
505
+ dir: options.dir,
506
+ force: options.force === true,
507
+ dryRun: options.dryRun === true,
508
+ updateProfile: options.updateProfile === true,
509
+ yes: options.yes === true,
510
+ isInteractive:
511
+ process.stdin.isTTY === true && process.stdout.isTTY === true,
512
+ stdout: (chunk) => process.stdout.write(chunk),
513
+ stderr: (chunk) => process.stderr.write(chunk),
514
+ confirmProfileUpdate: async ({ message, default: defaultValue }) =>
515
+ await confirm({ message, default: defaultValue }),
516
+ generateCompletionScript,
517
+ });
518
+ } catch (error) {
519
+ const message = error instanceof Error ? error.message : String(error);
520
+ process.stderr.write(`${message}\n`);
521
+ process.exitCode = 1;
522
+ }
520
523
  }
521
524
 
522
525
  async function runCompletionUninstallCommand(shell, options) {
523
- try {
524
- await uninstallCompletion({
525
- shell,
526
- dir: options.dir,
527
- dryRun: options.dryRun === true,
528
- updateProfile: options.updateProfile === true,
529
- yes: options.yes === true,
530
- isInteractive:
531
- process.stdin.isTTY === true && process.stdout.isTTY === true,
532
- stdout: (chunk) => process.stdout.write(chunk),
533
- stderr: (chunk) => process.stderr.write(chunk),
534
- confirmProfileUpdate: async ({ message, default: defaultValue }) =>
535
- await confirm({ message, default: defaultValue }),
536
- });
537
- } catch (error) {
538
- const message = error instanceof Error ? error.message : String(error);
539
- process.stderr.write(`${message}\n`);
540
- process.exitCode = 1;
541
- }
526
+ try {
527
+ await uninstallCompletion({
528
+ shell,
529
+ dir: options.dir,
530
+ dryRun: options.dryRun === true,
531
+ updateProfile: options.updateProfile === true,
532
+ yes: options.yes === true,
533
+ isInteractive:
534
+ process.stdin.isTTY === true && process.stdout.isTTY === true,
535
+ stdout: (chunk) => process.stdout.write(chunk),
536
+ stderr: (chunk) => process.stderr.write(chunk),
537
+ confirmProfileUpdate: async ({ message, default: defaultValue }) =>
538
+ await confirm({ message, default: defaultValue }),
539
+ });
540
+ } catch (error) {
541
+ const message = error instanceof Error ? error.message : String(error);
542
+ process.stderr.write(`${message}\n`);
543
+ process.exitCode = 1;
544
+ }
542
545
  }
543
546
 
544
547
  function parseUninstallScope(value) {
545
- const normalized = String(value || "")
546
- .trim()
547
- .toLowerCase();
548
- if (
549
- normalized === "global" ||
550
- normalized === "project" ||
551
- normalized === "all"
552
- ) {
553
- return normalized;
554
- }
555
- return "all";
548
+ const normalized = String(value || "")
549
+ .trim()
550
+ .toLowerCase();
551
+ if (
552
+ normalized === "global" ||
553
+ normalized === "project" ||
554
+ normalized === "all"
555
+ ) {
556
+ return normalized;
557
+ }
558
+ return "all";
556
559
  }
557
560
 
558
561
  function scopesFromUninstallScope(scope) {
559
- return scope === "all" ? ["global", "project"] : [scope];
562
+ return scope === "all" ? ["global", "project"] : [scope];
560
563
  }
561
564
 
562
565
  function keyPath(configKey) {
563
- return Array.isArray(configKey) ? configKey : [configKey];
566
+ return Array.isArray(configKey) ? configKey : [configKey];
564
567
  }
565
568
 
566
569
  function readConfigSection(config, configKey) {
567
- const pathParts = keyPath(configKey);
568
- let current = config && typeof config === "object" ? config : {};
569
- for (const part of pathParts) {
570
- if (
571
- !current ||
572
- typeof current !== "object" ||
573
- Array.isArray(current) ||
574
- !(part in current)
575
- ) {
576
- return {};
577
- }
578
- const next = current[part];
579
- if (!next || typeof next !== "object" || Array.isArray(next)) {
580
- return {};
581
- }
582
- current = next;
570
+ const pathParts = keyPath(configKey);
571
+ let current = config && typeof config === "object" ? config : {};
572
+ for (const part of pathParts) {
573
+ if (
574
+ !current ||
575
+ typeof current !== "object" ||
576
+ Array.isArray(current) ||
577
+ !(part in current)
578
+ ) {
579
+ return {};
580
+ }
581
+ const next = current[part];
582
+ if (!next || typeof next !== "object" || Array.isArray(next)) {
583
+ return {};
583
584
  }
584
- return current;
585
+ current = next;
586
+ }
587
+ return current;
585
588
  }
586
589
 
587
590
  function parseTomlServerNames(tomlText) {
588
- const serverNames = new Set();
589
- for (const line of String(tomlText || "")
590
- .replace(/\r\n/g, "\n")
591
- .split("\n")) {
592
- const match = line
593
- .trim()
594
- .match(/^\[mcp_servers\.([A-Za-z0-9_-]+)\](?:\s*#.*)?$/);
595
- if (!match) {
596
- continue;
597
- }
598
- serverNames.add(match[1]);
591
+ const serverNames = new Set();
592
+ for (const line of String(tomlText || "")
593
+ .replace(/\r\n/g, "\n")
594
+ .split("\n")) {
595
+ const match = line
596
+ .trim()
597
+ .match(/^\[mcp_servers\.([A-Za-z0-9_-]+)\](?:\s*#.*)?$/);
598
+ if (!match) {
599
+ continue;
599
600
  }
600
- return [...serverNames].sort();
601
+ serverNames.add(match[1]);
602
+ }
603
+ return [...serverNames].sort();
601
604
  }
602
605
 
603
606
  function isLikelyFlywheelMcpUrl(url) {
604
- if (typeof url !== "string" || url.trim().length === 0) {
605
- return false;
606
- }
607
- try {
608
- const parsed = new URL(url);
609
- return parsed.pathname === "/mcp-server";
610
- } catch {
611
- return false;
612
- }
607
+ if (typeof url !== "string" || url.trim().length === 0) {
608
+ return false;
609
+ }
610
+ try {
611
+ const parsed = new URL(url);
612
+ return parsed.pathname === "/mcp-server";
613
+ } catch {
614
+ return false;
615
+ }
613
616
  }
614
617
 
615
618
  async function listHostMcpEntries(hostName, scope) {
616
- const host = getHost(hostName);
617
- if (isSkillOnlyHost(host)) {
618
- return [];
619
+ const host = getHost(hostName);
620
+ if (isSkillOnlyHost(host)) {
621
+ return [];
622
+ }
623
+ const filePath = await resolveMcpPath(mcpCandidatesForScope(host, scope));
624
+
625
+ if (host.mcp.configType === "toml") {
626
+ let raw = "";
627
+ try {
628
+ raw = await readFile(filePath, "utf8");
629
+ } catch {
630
+ return [];
619
631
  }
620
- const filePath = await resolveMcpPath(mcpCandidatesForScope(host, scope));
621
-
622
- if (host.mcp.configType === "toml") {
623
- let raw = "";
624
- try {
625
- raw = await readFile(filePath, "utf8");
626
- } catch {
627
- return [];
628
- }
629
- const entries = [];
630
- for (const serverName of parseTomlServerNames(raw)) {
631
- // eslint-disable-next-line no-await-in-loop
632
- const entry = await readTomlServerEntry(filePath, serverName);
633
- if (!entry.exists) {
634
- continue;
635
- }
636
- entries.push({
637
- serverName,
638
- url: typeof entry.url === "string" ? entry.url : null,
639
- });
640
- }
641
- return entries;
632
+ const entries = [];
633
+ for (const serverName of parseTomlServerNames(raw)) {
634
+ // eslint-disable-next-line no-await-in-loop
635
+ const entry = await readTomlServerEntry(filePath, serverName);
636
+ if (!entry.exists) {
637
+ continue;
638
+ }
639
+ entries.push({
640
+ serverName,
641
+ url: typeof entry.url === "string" ? entry.url : null,
642
+ });
642
643
  }
643
-
644
- const config =
645
- host.mcp.configType === "yaml"
646
- ? await readYamlConfig(filePath)
647
- : await readJsonConfig(filePath);
648
- const section = readConfigSection(config, host.mcp.configKey);
649
- return Object.entries(section)
650
- .filter(
651
- ([, entry]) =>
652
- entry && typeof entry === "object" && !Array.isArray(entry),
653
- )
654
- .map(([serverName, entry]) => ({
655
- serverName,
656
- url: readEntryServerUrl(entry),
657
- }));
644
+ return entries;
645
+ }
646
+
647
+ const config =
648
+ host.mcp.configType === "yaml"
649
+ ? await readYamlConfig(filePath)
650
+ : await readJsonConfig(filePath);
651
+ const section = readConfigSection(config, host.mcp.configKey);
652
+ return Object.entries(section)
653
+ .filter(
654
+ ([, entry]) =>
655
+ entry && typeof entry === "object" && !Array.isArray(entry),
656
+ )
657
+ .map(([serverName, entry]) => ({
658
+ serverName,
659
+ url: readEntryServerUrl(entry),
660
+ }));
658
661
  }
659
662
 
660
663
  async function resolveHostsWithRemainingFlywheelMcpEntries({ scope }) {
661
- const remainingHosts = [];
662
- for (const hostName of SUPPORTED_INSTALL_SKILL_HOSTS) {
663
- // eslint-disable-next-line no-await-in-loop
664
- const hostEntries = await listHostMcpEntries(hostName, scope).catch(
665
- () => [],
666
- );
667
- if (hostEntries.some((entry) => isLikelyFlywheelMcpUrl(entry.url))) {
668
- remainingHosts.push(hostName);
669
- }
664
+ const remainingHosts = [];
665
+ for (const hostName of SUPPORTED_INSTALL_SKILL_HOSTS) {
666
+ // eslint-disable-next-line no-await-in-loop
667
+ const hostEntries = await listHostMcpEntries(hostName, scope).catch(
668
+ () => [],
669
+ );
670
+ if (hostEntries.some((entry) => isLikelyFlywheelMcpUrl(entry.url))) {
671
+ remainingHosts.push(hostName);
670
672
  }
671
- return remainingHosts;
673
+ }
674
+ return remainingHosts;
672
675
  }
673
676
 
674
677
  /**
@@ -697,95 +700,95 @@ async function resolveHostsWithRemainingFlywheelMcpEntries({ scope }) {
697
700
  * they are excluded from retention here.
698
701
  */
699
702
  async function resolveSkillOnlyHostsRetainingArtifacts({
700
- scope,
701
- excludedHostNames = [],
703
+ scope,
704
+ excludedHostNames = [],
702
705
  }) {
703
- const excluded = new Set(excludedHostNames);
704
- const retained = [];
705
- for (const hostName of SUPPORTED_INSTALL_SKILL_HOSTS) {
706
- if (excluded.has(hostName)) continue;
707
- let markerPath;
708
- try {
709
- markerPath = resolveFlywheelInstalledMarkerPath(
710
- process.cwd(),
711
- hostName,
712
- scope,
713
- );
714
- } catch {
715
- // Host isn't registered with the flywheel skill installer; no marker
716
- // to consult, nothing to retain.
717
- continue;
718
- }
719
- // eslint-disable-next-line no-await-in-loop
720
- const markerExists = await pathExists(markerPath);
721
- if (markerExists) {
722
- retained.push(hostName);
723
- }
706
+ const excluded = new Set(excludedHostNames);
707
+ const retained = [];
708
+ for (const hostName of SUPPORTED_INSTALL_SKILL_HOSTS) {
709
+ if (excluded.has(hostName)) continue;
710
+ let markerPath;
711
+ try {
712
+ markerPath = resolveFlywheelInstalledMarkerPath(
713
+ process.cwd(),
714
+ hostName,
715
+ scope,
716
+ );
717
+ } catch {
718
+ // Host isn't registered with the flywheel skill installer; no marker
719
+ // to consult, nothing to retain.
720
+ continue;
721
+ }
722
+ // eslint-disable-next-line no-await-in-loop
723
+ const markerExists = await pathExists(markerPath);
724
+ if (markerExists) {
725
+ retained.push(hostName);
724
726
  }
725
- return retained;
727
+ }
728
+ return retained;
726
729
  }
727
730
 
728
731
  async function findFlywheelServerNamesOnHost(hostName, scope) {
729
- // Mirror setup's prior-mode detector: walk every MCP entry on the host and
730
- // keep those whose URL is Flywheel-identifying (hostname contains "flywheel"
731
- // or path === /mcp-server with a matching target origin). Uninstall must
732
- // catch renamed or drifted entries (e.g. a non-default TOML section name
733
- // under `[mcp_servers.*]`) that setup already detects; otherwise a user
734
- // whose host has a non-default entry name is stuck between setup ("already
735
- // installed") and uninstall ("not configured").
736
- return await findFlywheelMcpEntryNames({ hostName, scope }).catch(() => []);
732
+ // Mirror setup's prior-mode detector: walk every MCP entry on the host and
733
+ // keep those whose URL is Flywheel-identifying (hostname contains "flywheel"
734
+ // or path === /mcp-server with a matching target origin). Uninstall must
735
+ // catch renamed or drifted entries (e.g. a non-default TOML section name
736
+ // under `[mcp_servers.*]`) that setup already detects; otherwise a user
737
+ // whose host has a non-default entry name is stuck between setup ("already
738
+ // installed") and uninstall ("not configured").
739
+ return await findFlywheelMcpEntryNames({ hostName, scope }).catch(() => []);
737
740
  }
738
741
 
739
742
  async function resolveUninstallServerNamesForHost(
740
- hostName,
741
- scope,
742
- { explicitServerName },
743
+ hostName,
744
+ scope,
745
+ { explicitServerName },
743
746
  ) {
744
- if (explicitServerName) {
745
- const configured = await isAlreadyConfigured(
746
- hostName,
747
- scope,
748
- explicitServerName,
749
- ).catch(() => false);
750
- return configured ? [explicitServerName] : [];
751
- }
752
- return await findFlywheelServerNamesOnHost(hostName, scope);
747
+ if (explicitServerName) {
748
+ const configured = await isAlreadyConfigured(
749
+ hostName,
750
+ scope,
751
+ explicitServerName,
752
+ ).catch(() => false);
753
+ return configured ? [explicitServerName] : [];
754
+ }
755
+ return await findFlywheelServerNamesOnHost(hostName, scope);
753
756
  }
754
757
 
755
758
  async function isConfiguredForUninstallScope(
756
- hostName,
757
- scope,
758
- { explicitServerName },
759
+ hostName,
760
+ scope,
761
+ { explicitServerName },
759
762
  ) {
760
- const scopes = scopesFromUninstallScope(scope);
761
- for (const singleScope of scopes) {
762
- // eslint-disable-next-line no-await-in-loop
763
- const targets = await resolveUninstallServerNamesForHost(
764
- hostName,
765
- singleScope,
766
- { explicitServerName },
763
+ const scopes = scopesFromUninstallScope(scope);
764
+ for (const singleScope of scopes) {
765
+ // eslint-disable-next-line no-await-in-loop
766
+ const targets = await resolveUninstallServerNamesForHost(
767
+ hostName,
768
+ singleScope,
769
+ { explicitServerName },
770
+ );
771
+ if (targets.length > 0) return true;
772
+ // Skill-only hosts and CLI-mode MCP-capable hosts never write an MCP
773
+ // entry, so the sweep above finds nothing for them. Fall back to the
774
+ // install marker: if this host wrote its own ownership marker in the
775
+ // selected scope, it IS configured for the purposes of the uninstall
776
+ // prompt.
777
+ if (SUPPORTED_INSTALL_SKILL_HOSTS.includes(hostName)) {
778
+ try {
779
+ const markerPath = resolveFlywheelInstalledMarkerPath(
780
+ process.cwd(),
781
+ hostName,
782
+ singleScope,
767
783
  );
768
- if (targets.length > 0) return true;
769
- // Skill-only hosts and CLI-mode MCP-capable hosts never write an MCP
770
- // entry, so the sweep above finds nothing for them. Fall back to the
771
- // install marker: if this host wrote its own ownership marker in the
772
- // selected scope, it IS configured for the purposes of the uninstall
773
- // prompt.
774
- if (SUPPORTED_INSTALL_SKILL_HOSTS.includes(hostName)) {
775
- try {
776
- const markerPath = resolveFlywheelInstalledMarkerPath(
777
- process.cwd(),
778
- hostName,
779
- singleScope,
780
- );
781
- // eslint-disable-next-line no-await-in-loop
782
- if (await pathExists(markerPath)) return true;
783
- } catch {
784
- // Host isn't registered with the skill installer; nothing to check.
785
- }
786
- }
784
+ // eslint-disable-next-line no-await-in-loop
785
+ if (await pathExists(markerPath)) return true;
786
+ } catch {
787
+ // Host isn't registered with the skill installer; nothing to check.
788
+ }
787
789
  }
788
- return false;
790
+ }
791
+ return false;
789
792
  }
790
793
 
791
794
  /**
@@ -796,23 +799,23 @@ async function isConfiguredForUninstallScope(
796
799
  * prompt even though they write no MCP entry.
797
800
  */
798
801
  export async function isHostConfiguredForUninstall({
799
- hostName,
800
- scope = "project",
801
- serverName = SERVER_NAME,
802
+ hostName,
803
+ scope = "project",
804
+ serverName = SERVER_NAME,
802
805
  } = {}) {
803
- // Mirror `runUninstallCommand`'s derivation: only treat the caller's
804
- // `serverName` as "explicit" when it differs from the package default.
805
- // An explicit name short-circuits the Flywheel-identifying sweep in
806
- // `resolveUninstallServerNamesForHost`, which the default-named case
807
- // needs to run so drifted entries (and the marker fallback for
808
- // skill-only / CLI-mode hosts) are reachable.
809
- const explicitServerName =
810
- typeof serverName === "string" &&
811
- serverName.length > 0 &&
812
- serverName !== SERVER_NAME
813
- ? serverName
814
- : null;
815
- return isConfiguredForUninstallScope(hostName, scope, { explicitServerName });
806
+ // Mirror `runUninstallCommand`'s derivation: only treat the caller's
807
+ // `serverName` as "explicit" when it differs from the package default.
808
+ // An explicit name short-circuits the Flywheel-identifying sweep in
809
+ // `resolveUninstallServerNamesForHost`, which the default-named case
810
+ // needs to run so drifted entries (and the marker fallback for
811
+ // skill-only / CLI-mode hosts) are reachable.
812
+ const explicitServerName =
813
+ typeof serverName === "string" &&
814
+ serverName.length > 0 &&
815
+ serverName !== SERVER_NAME
816
+ ? serverName
817
+ : null;
818
+ return isConfiguredForUninstallScope(hostName, scope, { explicitServerName });
816
819
  }
817
820
 
818
821
  /**
@@ -830,380 +833,380 @@ export async function isHostConfiguredForUninstall({
830
833
  * without pre-filtering.
831
834
  */
832
835
  export async function cleanupHostInstallMarkers({
833
- cwd = process.cwd(),
834
- scopes = ["project"],
835
- hostNames = [],
836
+ cwd = process.cwd(),
837
+ scopes = ["project"],
838
+ hostNames = [],
836
839
  } = {}) {
837
- for (const singleScope of scopes) {
838
- for (const hostName of hostNames) {
839
- let markerPath;
840
- try {
841
- markerPath = resolveFlywheelInstalledMarkerPath(
842
- cwd,
843
- hostName,
844
- singleScope,
845
- );
846
- } catch {
847
- continue;
848
- }
849
- // eslint-disable-next-line no-await-in-loop
850
- await rm(markerPath, { force: true });
851
- }
840
+ for (const singleScope of scopes) {
841
+ for (const hostName of hostNames) {
842
+ let markerPath;
843
+ try {
844
+ markerPath = resolveFlywheelInstalledMarkerPath(
845
+ cwd,
846
+ hostName,
847
+ singleScope,
848
+ );
849
+ } catch {
850
+ continue;
851
+ }
852
+ // eslint-disable-next-line no-await-in-loop
853
+ await rm(markerPath, { force: true });
852
854
  }
855
+ }
853
856
  }
854
857
 
855
858
  async function promptUninstallScope(defaultScope) {
856
- try {
857
- return await select({
858
- message: "Which scope do you want to uninstall from?",
859
- choices: [
860
- { name: "All (global and project)", value: "all" },
861
- { name: "Global", value: "global" },
862
- { name: "Project", value: "project" },
863
- ],
864
- default: defaultScope,
865
- theme: CHECKBOX_THEME,
866
- });
867
- } catch {
868
- return null;
869
- }
859
+ try {
860
+ return await select({
861
+ message: "Which scope do you want to uninstall from?",
862
+ choices: [
863
+ { name: "All (global and project)", value: "all" },
864
+ { name: "Global", value: "global" },
865
+ { name: "Project", value: "project" },
866
+ ],
867
+ default: defaultScope,
868
+ theme: CHECKBOX_THEME,
869
+ });
870
+ } catch {
871
+ return null;
872
+ }
870
873
  }
871
874
 
872
875
  async function promptUninstallHosts(scope, { explicitServerName }) {
873
- const choices = await Promise.all(
874
- ALL_HOST_NAMES.map(async (hostName) => {
875
- const configured = await isConfiguredForUninstallScope(hostName, scope, {
876
- explicitServerName,
877
- });
878
- return {
879
- name: SETUP_HOST_NAMES[hostName],
880
- value: hostName,
881
- checked: configured,
882
- disabled: configured ? false : "(not configured)",
883
- };
884
- }),
885
- );
876
+ const choices = await Promise.all(
877
+ ALL_HOST_NAMES.map(async (hostName) => {
878
+ const configured = await isConfiguredForUninstallScope(hostName, scope, {
879
+ explicitServerName,
880
+ });
881
+ return {
882
+ name: SETUP_HOST_NAMES[hostName],
883
+ value: hostName,
884
+ checked: configured,
885
+ disabled: configured ? false : "(not configured)",
886
+ };
887
+ }),
888
+ );
889
+
890
+ if (choices.every((choice) => Boolean(choice.disabled))) {
891
+ log.info("Flywheel is not configured for the selected scope.");
892
+ return null;
893
+ }
894
+
895
+ try {
896
+ return await checkbox({
897
+ message: "Which hosts do you want to uninstall?",
898
+ choices,
899
+ loop: false,
900
+ theme: CHECKBOX_THEME,
901
+ validate: (selected) =>
902
+ selected.length > 0 || "Select at least one host.",
903
+ });
904
+ } catch {
905
+ return null;
906
+ }
907
+ }
886
908
 
887
- if (choices.every((choice) => Boolean(choice.disabled))) {
888
- log.info("Flywheel is not configured for the selected scope.");
909
+ async function resolveUninstallTargets(options, { explicitServerName }) {
910
+ const explicitHostsFromFlags = selectedHostsFromOptions(options);
911
+ const explicitHostsFromList =
912
+ explicitHostsFromFlags.length === 0 ? parseHostsList(options.hosts) : [];
913
+ const hasExplicitHosts =
914
+ explicitHostsFromFlags.length > 0 || explicitHostsFromList.length > 0;
915
+ const hasExplicitScope =
916
+ typeof options.scope === "string" && options.scope.trim().length > 0;
917
+
918
+ let scope = parseUninstallScope(options.scope || "all");
919
+ let hosts =
920
+ explicitHostsFromFlags.length > 0
921
+ ? explicitHostsFromFlags
922
+ : explicitHostsFromList.length > 0
923
+ ? explicitHostsFromList
924
+ : [...ALL_HOST_NAMES];
925
+
926
+ if (!options.yes) {
927
+ if (!hasExplicitScope) {
928
+ log.blank();
929
+ const selectedScope = await promptUninstallScope(scope);
930
+ if (!selectedScope) {
931
+ log.warn("Uninstall cancelled");
889
932
  return null;
933
+ }
934
+ scope = selectedScope;
890
935
  }
891
936
 
892
- try {
893
- return await checkbox({
894
- message: "Which hosts do you want to uninstall?",
895
- choices,
896
- loop: false,
897
- theme: CHECKBOX_THEME,
898
- validate: (selected) =>
899
- selected.length > 0 || "Select at least one host.",
900
- });
901
- } catch {
937
+ if (!hasExplicitHosts) {
938
+ const selectedHosts = await promptUninstallHosts(scope, {
939
+ explicitServerName,
940
+ });
941
+ if (!selectedHosts) {
942
+ log.warn("Uninstall cancelled");
902
943
  return null;
944
+ }
945
+ hosts = selectedHosts;
903
946
  }
904
- }
905
-
906
- async function resolveUninstallTargets(options, { explicitServerName }) {
907
- const explicitHostsFromFlags = selectedHostsFromOptions(options);
908
- const explicitHostsFromList =
909
- explicitHostsFromFlags.length === 0 ? parseHostsList(options.hosts) : [];
910
- const hasExplicitHosts =
911
- explicitHostsFromFlags.length > 0 || explicitHostsFromList.length > 0;
912
- const hasExplicitScope =
913
- typeof options.scope === "string" && options.scope.trim().length > 0;
914
-
915
- let scope = parseUninstallScope(options.scope || "all");
916
- let hosts =
917
- explicitHostsFromFlags.length > 0
918
- ? explicitHostsFromFlags
919
- : explicitHostsFromList.length > 0
920
- ? explicitHostsFromList
921
- : [...ALL_HOST_NAMES];
922
-
923
- if (!options.yes) {
924
- if (!hasExplicitScope) {
925
- log.blank();
926
- const selectedScope = await promptUninstallScope(scope);
927
- if (!selectedScope) {
928
- log.warn("Uninstall cancelled");
929
- return null;
930
- }
931
- scope = selectedScope;
932
- }
933
-
934
- if (!hasExplicitHosts) {
935
- const selectedHosts = await promptUninstallHosts(scope, {
936
- explicitServerName,
937
- });
938
- if (!selectedHosts) {
939
- log.warn("Uninstall cancelled");
940
- return null;
941
- }
942
- hosts = selectedHosts;
943
- }
944
- }
947
+ }
945
948
 
946
- return { scope, hosts };
949
+ return { scope, hosts };
947
950
  }
948
951
 
949
952
  async function removeHostConfig(hostName, scope, serverName) {
950
- const host = getHost(hostName);
951
- if (isSkillOnlyHost(host)) {
952
- return {
953
- host: host.displayName,
954
- scope,
955
- filePath: null,
956
- status: "not present",
957
- };
958
- }
959
- const filePath = await resolveMcpPath(mcpCandidatesForScope(host, scope));
960
-
961
- if (host.mcp.configType === "toml") {
962
- const result = await removeCodexTomlServer({
963
- filePath,
964
- serverName,
965
- });
966
- return {
967
- host: host.displayName,
968
- scope,
969
- filePath,
970
- status: result.changed ? "removed" : "not present",
971
- };
972
- }
953
+ const host = getHost(hostName);
954
+ if (isSkillOnlyHost(host)) {
955
+ return {
956
+ host: host.displayName,
957
+ scope,
958
+ filePath: null,
959
+ status: "not present",
960
+ };
961
+ }
962
+ const filePath = await resolveMcpPath(mcpCandidatesForScope(host, scope));
973
963
 
974
- const current =
975
- host.mcp.configType === "yaml"
976
- ? await readYamlConfig(filePath)
977
- : await readJsonConfig(filePath);
978
- const next = removeJsonServerEntry({
979
- config: current,
980
- configKey: host.mcp.configKey,
981
- serverName,
964
+ if (host.mcp.configType === "toml") {
965
+ const result = await removeCodexTomlServer({
966
+ filePath,
967
+ serverName,
982
968
  });
983
- if (next.changed) {
984
- if (host.mcp.configType === "yaml") {
985
- await writeYamlConfig(filePath, next.config);
986
- } else {
987
- await writeJsonConfig(filePath, next.config);
988
- }
989
- }
990
969
  return {
991
- host: host.displayName,
992
- scope,
993
- filePath,
994
- status: next.changed ? "removed" : "not present",
970
+ host: host.displayName,
971
+ scope,
972
+ filePath,
973
+ status: result.changed ? "removed" : "not present",
995
974
  };
975
+ }
976
+
977
+ const current =
978
+ host.mcp.configType === "yaml"
979
+ ? await readYamlConfig(filePath)
980
+ : await readJsonConfig(filePath);
981
+ const next = removeJsonServerEntry({
982
+ config: current,
983
+ configKey: host.mcp.configKey,
984
+ serverName,
985
+ });
986
+ if (next.changed) {
987
+ if (host.mcp.configType === "yaml") {
988
+ await writeYamlConfig(filePath, next.config);
989
+ } else {
990
+ await writeJsonConfig(filePath, next.config);
991
+ }
992
+ }
993
+ return {
994
+ host: host.displayName,
995
+ scope,
996
+ filePath,
997
+ status: next.changed ? "removed" : "not present",
998
+ };
996
999
  }
997
1000
 
998
1001
  async function runUninstallCommand(options) {
999
- const explicitServerName =
1000
- typeof options.name === "string" && options.name.trim().length > 0
1001
- ? normalizeServerName(options.name)
1002
- : null;
1003
- const resolved = await resolveUninstallTargets(options, {
1004
- explicitServerName,
1005
- });
1006
- if (!resolved) return;
1007
- const { scope, hosts } = resolved;
1008
- const scopes = scopesFromUninstallScope(scope);
1009
-
1010
- const mcpSpinner = ora("Removing Flywheel MCP entries...").start();
1011
- const mcpResults = [];
1012
- for (const singleScope of scopes) {
1013
- for (const host of hosts) {
1014
- mcpSpinner.text = `Removing from ${getHost(host).displayName} (${singleScope})...`;
1015
- // Resolve the concrete server name(s) to remove at the host/scope level.
1016
- // When --name was not given, this iterates every Flywheel-identifying
1017
- // entry (matching setup's prior-mode detector) so renamed or drifted
1018
- // entries (non-default TOML section names under `[mcp_servers.*]`) are
1019
- // actually cleared.
1020
- // eslint-disable-next-line no-await-in-loop
1021
- const targetNames = await resolveUninstallServerNamesForHost(
1022
- host,
1023
- singleScope,
1024
- { explicitServerName },
1025
- );
1026
- if (targetNames.length === 0) {
1027
- // eslint-disable-next-line no-await-in-loop
1028
- const hostForDisplay = getHost(host);
1029
- // Skill-only hosts (universal, antigravity) have no MCP surface
1030
- // at all — `host.mcp` is null, so dereferencing `projectPaths` via
1031
- // `mcpCandidatesForScope` throws. Report the absence without
1032
- // consulting a path that doesn't exist for them.
1033
- const filePath = isSkillOnlyHost(hostForDisplay)
1034
- ? null
1035
- : // eslint-disable-next-line no-await-in-loop
1036
- await resolveMcpPath(
1037
- mcpCandidatesForScope(hostForDisplay, singleScope),
1038
- );
1039
- mcpResults.push({
1040
- host: hostForDisplay.displayName,
1041
- scope: singleScope,
1042
- filePath,
1043
- status: "not present",
1044
- });
1045
- continue;
1046
- }
1047
- for (const targetName of targetNames) {
1048
- // eslint-disable-next-line no-await-in-loop
1049
- mcpResults.push(await removeHostConfig(host, singleScope, targetName));
1050
- }
1051
- }
1052
- }
1053
- mcpSpinner.succeed("MCP uninstall complete");
1054
-
1055
- const { supportedHosts, unsupportedHosts } =
1056
- partitionInstallSkillHosts(hosts);
1057
- const bundledSkillResults = [];
1058
- let bundledSkillNames = [];
1059
-
1060
- if (supportedHosts.length > 0) {
1061
- const packageRoot = resolvePackageRoot();
1062
- bundledSkillNames = await listBundledSkills(packageRoot);
1063
- if (bundledSkillNames.length > 0) {
1064
- const skillSpinner = ora("Removing Flywheel bundled skills...").start();
1065
- for (const singleScope of scopes) {
1066
- // Retain any skill directory still claimed by a non-uninstalled host.
1067
- // Two signals combine: (a) MCP-backed hosts whose Flywheel entries
1068
- // survived the MCP-removal pass above, and (b) any host with bundled
1069
- // skill artifacts still on disk (including skill-only hosts like
1070
- // universal/antigravity, which never advertise themselves via MCP
1071
- // entries). Without (b), uninstalling one MCP host would silently
1072
- // wipe a shared `.agents/skills/<skill>/` that another host still
1073
- // relies on.
1074
- // eslint-disable-next-line no-await-in-loop
1075
- const mcpRetained = await resolveHostsWithRemainingFlywheelMcpEntries({
1076
- scope: singleScope,
1077
- });
1078
- // eslint-disable-next-line no-await-in-loop
1079
- const skillOnlyRetained = await resolveSkillOnlyHostsRetainingArtifacts(
1080
- {
1081
- scope: singleScope,
1082
- excludedHostNames: supportedHosts,
1083
- },
1084
- );
1085
- const configuredRetainHostNames = [
1086
- ...new Set([...mcpRetained, ...skillOnlyRetained]),
1087
- ];
1088
- skillSpinner.text = `Removing bundled skills from ${supportedHosts.length} host(s) (${singleScope})...`;
1089
- // eslint-disable-next-line no-await-in-loop
1090
- bundledSkillResults.push(
1091
- ...(await removeInstalledSkillsForHosts({
1092
- projectRoot: process.cwd(),
1093
- hostNames: supportedHosts,
1094
- retainHostNames: configuredRetainHostNames,
1095
- scope: singleScope,
1096
- skillNames: bundledSkillNames,
1097
- })),
1098
- );
1099
- }
1100
- skillSpinner.succeed("Bundled skill uninstall complete");
1101
- }
1102
-
1103
- // Install-marker cleanup runs independently of bundled-skill discovery.
1104
- // A broken or trimmed package (missing `skills/`) can leave
1105
- // `bundledSkillNames` empty — the skill-removal pass above legitimately
1106
- // no-ops in that case, but the ownership markers must still be cleared,
1107
- // otherwise a later `uninstall`/`setup` would treat the uninstalled
1108
- // host as still owning shared skill dirs (wrong retention) or as a
1109
- // prior CLI install (false cross-mode conflict).
1110
- await cleanupHostInstallMarkers({
1111
- cwd: process.cwd(),
1112
- scopes,
1113
- hostNames: supportedHosts,
1002
+ const explicitServerName =
1003
+ typeof options.name === "string" && options.name.trim().length > 0
1004
+ ? normalizeServerName(options.name)
1005
+ : null;
1006
+ const resolved = await resolveUninstallTargets(options, {
1007
+ explicitServerName,
1008
+ });
1009
+ if (!resolved) return;
1010
+ const { scope, hosts } = resolved;
1011
+ const scopes = scopesFromUninstallScope(scope);
1012
+
1013
+ const mcpSpinner = ora("Removing Flywheel MCP entries...").start();
1014
+ const mcpResults = [];
1015
+ for (const singleScope of scopes) {
1016
+ for (const host of hosts) {
1017
+ mcpSpinner.text = `Removing from ${getHost(host).displayName} (${singleScope})...`;
1018
+ // Resolve the concrete server name(s) to remove at the host/scope level.
1019
+ // When --name was not given, this iterates every Flywheel-identifying
1020
+ // entry (matching setup's prior-mode detector) so renamed or drifted
1021
+ // entries (non-default TOML section names under `[mcp_servers.*]`) are
1022
+ // actually cleared.
1023
+ // eslint-disable-next-line no-await-in-loop
1024
+ const targetNames = await resolveUninstallServerNamesForHost(
1025
+ host,
1026
+ singleScope,
1027
+ { explicitServerName },
1028
+ );
1029
+ if (targetNames.length === 0) {
1030
+ // eslint-disable-next-line no-await-in-loop
1031
+ const hostForDisplay = getHost(host);
1032
+ // Skill-only hosts (universal, antigravity) have no MCP surface
1033
+ // at all — `host.mcp` is null, so dereferencing `projectPaths` via
1034
+ // `mcpCandidatesForScope` throws. Report the absence without
1035
+ // consulting a path that doesn't exist for them.
1036
+ const filePath = isSkillOnlyHost(hostForDisplay)
1037
+ ? null
1038
+ : // eslint-disable-next-line no-await-in-loop
1039
+ await resolveMcpPath(
1040
+ mcpCandidatesForScope(hostForDisplay, singleScope),
1041
+ );
1042
+ mcpResults.push({
1043
+ host: hostForDisplay.displayName,
1044
+ scope: singleScope,
1045
+ filePath,
1046
+ status: "not present",
1114
1047
  });
1048
+ continue;
1049
+ }
1050
+ for (const targetName of targetNames) {
1051
+ // eslint-disable-next-line no-await-in-loop
1052
+ mcpResults.push(await removeHostConfig(host, singleScope, targetName));
1053
+ }
1115
1054
  }
1116
-
1117
- log.blank();
1118
- log.plain(
1119
- pc.green("✔ Flywheel uninstall complete (MCP entries and bundled skills)"),
1120
- );
1121
- log.blank();
1122
- for (const result of mcpResults) {
1123
- const icon = result.status === "removed" ? pc.green("-") : pc.dim("~");
1124
- log.plain(` ${pc.bold(result.host)} ${pc.dim(`(${result.scope})`)}`);
1125
- log.plain(` ${icon} ${result.status}`);
1126
- log.plain(` ${pc.dim(result.filePath)}`);
1055
+ }
1056
+ mcpSpinner.succeed("MCP uninstall complete");
1057
+
1058
+ const { supportedHosts, unsupportedHosts } =
1059
+ partitionInstallSkillHosts(hosts);
1060
+ const bundledSkillResults = [];
1061
+ let bundledSkillNames = [];
1062
+
1063
+ if (supportedHosts.length > 0) {
1064
+ const packageRoot = resolvePackageRoot();
1065
+ bundledSkillNames = await listBundledSkills(packageRoot);
1066
+ if (bundledSkillNames.length > 0) {
1067
+ const skillSpinner = ora("Removing Flywheel bundled skills...").start();
1068
+ for (const singleScope of scopes) {
1069
+ // Retain any skill directory still claimed by a non-uninstalled host.
1070
+ // Two signals combine: (a) MCP-backed hosts whose Flywheel entries
1071
+ // survived the MCP-removal pass above, and (b) any host with bundled
1072
+ // skill artifacts still on disk (including skill-only hosts like
1073
+ // universal/antigravity, which never advertise themselves via MCP
1074
+ // entries). Without (b), uninstalling one MCP host would silently
1075
+ // wipe a shared `.agents/skills/<skill>/` that another host still
1076
+ // relies on.
1077
+ // eslint-disable-next-line no-await-in-loop
1078
+ const mcpRetained = await resolveHostsWithRemainingFlywheelMcpEntries({
1079
+ scope: singleScope,
1080
+ });
1081
+ // eslint-disable-next-line no-await-in-loop
1082
+ const skillOnlyRetained = await resolveSkillOnlyHostsRetainingArtifacts(
1083
+ {
1084
+ scope: singleScope,
1085
+ excludedHostNames: supportedHosts,
1086
+ },
1087
+ );
1088
+ const configuredRetainHostNames = [
1089
+ ...new Set([...mcpRetained, ...skillOnlyRetained]),
1090
+ ];
1091
+ skillSpinner.text = `Removing bundled skills from ${supportedHosts.length} host(s) (${singleScope})...`;
1092
+ // eslint-disable-next-line no-await-in-loop
1093
+ bundledSkillResults.push(
1094
+ ...(await removeInstalledSkillsForHosts({
1095
+ projectRoot: process.cwd(),
1096
+ hostNames: supportedHosts,
1097
+ retainHostNames: configuredRetainHostNames,
1098
+ scope: singleScope,
1099
+ skillNames: bundledSkillNames,
1100
+ })),
1101
+ );
1102
+ }
1103
+ skillSpinner.succeed("Bundled skill uninstall complete");
1127
1104
  }
1128
1105
 
1129
- log.blank();
1130
- log.plain(` ${pc.bold("Bundled skills")}`);
1131
- if (supportedHosts.length === 0) {
1132
- log.plain(` ${pc.dim("~")} no skill-supporting hosts selected`);
1133
- } else if (bundledSkillNames.length === 0) {
1134
- log.plain(` ${pc.dim("~")} no bundled skills found in this package`);
1135
- } else {
1136
- const groupedSkillResults = new Map();
1137
- for (const skillResult of bundledSkillResults) {
1138
- for (const hostName of skillResult.hostNames) {
1139
- const groupingKey = `${hostName}:${skillResult.scope}`;
1140
- const existingGroup = groupedSkillResults.get(groupingKey);
1141
- if (existingGroup) {
1142
- existingGroup.entries.push(skillResult);
1143
- continue;
1144
- }
1145
- groupedSkillResults.set(groupingKey, {
1146
- hostName,
1147
- scope: skillResult.scope,
1148
- entries: [skillResult],
1149
- });
1150
- }
1106
+ // Install-marker cleanup runs independently of bundled-skill discovery.
1107
+ // A broken or trimmed package (missing `skills/`) can leave
1108
+ // `bundledSkillNames` empty the skill-removal pass above legitimately
1109
+ // no-ops in that case, but the ownership markers must still be cleared,
1110
+ // otherwise a later `uninstall`/`setup` would treat the uninstalled
1111
+ // host as still owning shared skill dirs (wrong retention) or as a
1112
+ // prior CLI install (false cross-mode conflict).
1113
+ await cleanupHostInstallMarkers({
1114
+ cwd: process.cwd(),
1115
+ scopes,
1116
+ hostNames: supportedHosts,
1117
+ });
1118
+ }
1119
+
1120
+ log.blank();
1121
+ log.plain(
1122
+ pc.green("✔ Flywheel uninstall complete (MCP entries and bundled skills)"),
1123
+ );
1124
+ log.blank();
1125
+ for (const result of mcpResults) {
1126
+ const icon = result.status === "removed" ? pc.green("-") : pc.dim("~");
1127
+ log.plain(` ${pc.bold(result.host)} ${pc.dim(`(${result.scope})`)}`);
1128
+ log.plain(` ${icon} ${result.status}`);
1129
+ log.plain(` ${pc.dim(result.filePath)}`);
1130
+ }
1131
+
1132
+ log.blank();
1133
+ log.plain(` ${pc.bold("Bundled skills")}`);
1134
+ if (supportedHosts.length === 0) {
1135
+ log.plain(` ${pc.dim("~")} no skill-supporting hosts selected`);
1136
+ } else if (bundledSkillNames.length === 0) {
1137
+ log.plain(` ${pc.dim("~")} no bundled skills found in this package`);
1138
+ } else {
1139
+ const groupedSkillResults = new Map();
1140
+ for (const skillResult of bundledSkillResults) {
1141
+ for (const hostName of skillResult.hostNames) {
1142
+ const groupingKey = `${hostName}:${skillResult.scope}`;
1143
+ const existingGroup = groupedSkillResults.get(groupingKey);
1144
+ if (existingGroup) {
1145
+ existingGroup.entries.push(skillResult);
1146
+ continue;
1151
1147
  }
1148
+ groupedSkillResults.set(groupingKey, {
1149
+ hostName,
1150
+ scope: skillResult.scope,
1151
+ entries: [skillResult],
1152
+ });
1153
+ }
1154
+ }
1152
1155
 
1153
- const sortedGroups = [...groupedSkillResults.values()].sort(
1154
- (left, right) => {
1155
- const leftKey = `${left.hostName}:${left.scope}`;
1156
- const rightKey = `${right.hostName}:${right.scope}`;
1157
- return leftKey.localeCompare(rightKey);
1158
- },
1156
+ const sortedGroups = [...groupedSkillResults.values()].sort(
1157
+ (left, right) => {
1158
+ const leftKey = `${left.hostName}:${left.scope}`;
1159
+ const rightKey = `${right.hostName}:${right.scope}`;
1160
+ return leftKey.localeCompare(rightKey);
1161
+ },
1162
+ );
1163
+ for (const groupedResult of sortedGroups) {
1164
+ log.plain(
1165
+ ` ${pc.bold(getHost(groupedResult.hostName).displayName)} ${pc.dim(`(${groupedResult.scope})`)}`,
1166
+ );
1167
+ for (const entry of groupedResult.entries) {
1168
+ const icon =
1169
+ entry.status === "removed"
1170
+ ? pc.green("-")
1171
+ : entry.status === "retained"
1172
+ ? pc.yellow("~")
1173
+ : pc.dim("~");
1174
+ const retainedSuffix =
1175
+ entry.status === "retained" && Array.isArray(entry.retainedHostNames)
1176
+ ? ` (shared with configured host(s): ${entry.retainedHostNames.join(", ")})`
1177
+ : "";
1178
+ log.plain(
1179
+ ` ${icon} ${entry.status}${retainedSuffix}: ${entry.skillNames.join(", ")}`,
1159
1180
  );
1160
- for (const groupedResult of sortedGroups) {
1161
- log.plain(
1162
- ` ${pc.bold(getHost(groupedResult.hostName).displayName)} ${pc.dim(`(${groupedResult.scope})`)}`,
1163
- );
1164
- for (const entry of groupedResult.entries) {
1165
- const icon =
1166
- entry.status === "removed"
1167
- ? pc.green("-")
1168
- : entry.status === "retained"
1169
- ? pc.yellow("~")
1170
- : pc.dim("~");
1171
- const retainedSuffix =
1172
- entry.status === "retained" && Array.isArray(entry.retainedHostNames)
1173
- ? ` (shared with configured host(s): ${entry.retainedHostNames.join(", ")})`
1174
- : "";
1175
- log.plain(
1176
- ` ${icon} ${entry.status}${retainedSuffix}: ${entry.skillNames.join(", ")}`,
1177
- );
1178
- log.plain(` ${pc.dim(entry.installedSkillDir)}`);
1179
- }
1180
- }
1181
+ log.plain(` ${pc.dim(entry.installedSkillDir)}`);
1182
+ }
1181
1183
  }
1184
+ }
1182
1185
 
1183
- for (const unsupportedHostName of unsupportedHosts) {
1184
- for (const singleScope of scopes) {
1185
- log.plain(
1186
- ` ${pc.bold(getHost(unsupportedHostName).displayName)} ${pc.dim(`(${singleScope})`)}`,
1187
- );
1188
- log.plain(
1189
- ` ${pc.dim("~")} skill uninstall not supported (MCP-only host)`,
1190
- );
1191
- }
1186
+ for (const unsupportedHostName of unsupportedHosts) {
1187
+ for (const singleScope of scopes) {
1188
+ log.plain(
1189
+ ` ${pc.bold(getHost(unsupportedHostName).displayName)} ${pc.dim(`(${singleScope})`)}`,
1190
+ );
1191
+ log.plain(
1192
+ ` ${pc.dim("~")} skill uninstall not supported (MCP-only host)`,
1193
+ );
1192
1194
  }
1193
- log.blank();
1195
+ }
1196
+ log.blank();
1194
1197
  }
1195
1198
 
1196
1199
  function buildProgram({ exitOverride = false } = {}) {
1197
- const program = new Command();
1198
- if (exitOverride) {
1199
- program.exitOverride();
1200
- }
1201
- program
1202
- .name("flywheel")
1203
- .description("Flywheel setup CLI")
1204
- .addHelpText(
1205
- "after",
1206
- `
1200
+ const program = new Command();
1201
+ if (exitOverride) {
1202
+ program.exitOverride();
1203
+ }
1204
+ program
1205
+ .name("flywheel")
1206
+ .description("Flywheel setup CLI")
1207
+ .addHelpText(
1208
+ "after",
1209
+ `
1207
1210
  Examples:
1208
1211
  ${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp")}
1209
1212
  ${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp --install-skill")}
@@ -1213,28 +1216,28 @@ Examples:
1213
1216
  ${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp --yes --codex --claude --cursor")}
1214
1217
  ${pc.green("npx --yes @paradigma-inc/flywheel uninstall --yes --scope all")}
1215
1218
  `,
1216
- );
1219
+ );
1217
1220
 
1218
- const completionCommand = program
1219
- .command("completion")
1220
- .description("Generate a shell completion script")
1221
- .argument("[shell]", "Shell to generate completions for")
1222
- .addHelpText(
1223
- "before",
1224
- `${pc.bold(pc.cyan("✻ Flywheel Completion"))}
1221
+ const completionCommand = program
1222
+ .command("completion")
1223
+ .description("Generate a shell completion script")
1224
+ .argument("[shell]", "Shell to generate completions for")
1225
+ .addHelpText(
1226
+ "before",
1227
+ `${pc.bold(pc.cyan("✻ Flywheel Completion"))}
1225
1228
 
1226
1229
  Generate shell completion scripts from the public Flywheel Usage spec.
1227
1230
  Supported shells: ${COMPLETION_SHELL_CHOICES.join(", ")}.
1228
1231
  Requires the official Usage CLI executable on PATH.
1229
1232
  `,
1230
- )
1231
- .option(
1232
- "--include-bash-completion-lib",
1233
- "Include Usage's bash completion library in bash output",
1234
- )
1235
- .addHelpText(
1236
- "after",
1237
- `
1233
+ )
1234
+ .option(
1235
+ "--include-bash-completion-lib",
1236
+ "Include Usage's bash completion library in bash output",
1237
+ )
1238
+ .addHelpText(
1239
+ "after",
1240
+ `
1238
1241
  Usage CLI prerequisite:
1239
1242
  ${pc.green("mise use -g usage")}
1240
1243
  ${pc.green("brew install usage")}
@@ -1250,38 +1253,38 @@ Examples:
1250
1253
  ${pc.green("flywheel completion nu > ~/.config/nushell/autoload/flywheel.nu")}
1251
1254
  ${pc.green("flywheel completion nushell > ~/.config/nushell/autoload/flywheel.nu")}
1252
1255
  `,
1253
- )
1254
- .action(async (shell, options) => {
1255
- if (!shell) {
1256
- if (exitOverride) {
1257
- completionCommand.outputHelp();
1258
- return;
1259
- }
1260
- completionCommand.help();
1261
- return;
1262
- }
1263
- await runCompletionCommand(shell, options);
1264
- });
1256
+ )
1257
+ .action(async (shell, options) => {
1258
+ if (!shell) {
1259
+ if (exitOverride) {
1260
+ completionCommand.outputHelp();
1261
+ return;
1262
+ }
1263
+ completionCommand.help();
1264
+ return;
1265
+ }
1266
+ await runCompletionCommand(shell, options);
1267
+ });
1265
1268
 
1266
- completionCommand
1267
- .command("install <shell>")
1268
- .description("Install generated shell completion scripts")
1269
- .option("--dir <path>", "Override completion script destination directory")
1270
- .option("--force", "Replace an existing unmarked destination file")
1271
- .option("--dry-run", "Print planned changes without writing files")
1272
- .option("--update-profile", "Allow shell startup/profile file updates")
1273
- .option("-y, --yes", "Skip confirmation prompts")
1274
- .addHelpText(
1275
- "before",
1276
- `${pc.bold(pc.cyan("✻ Flywheel Completion Install"))}
1269
+ completionCommand
1270
+ .command("install <shell>")
1271
+ .description("Install generated shell completion scripts")
1272
+ .option("--dir <path>", "Override completion script destination directory")
1273
+ .option("--force", "Replace an existing unmarked destination file")
1274
+ .option("--dry-run", "Print planned changes without writing files")
1275
+ .option("--update-profile", "Allow shell startup/profile file updates")
1276
+ .option("-y, --yes", "Skip confirmation prompts")
1277
+ .addHelpText(
1278
+ "before",
1279
+ `${pc.bold(pc.cyan("✻ Flywheel Completion Install"))}
1277
1280
 
1278
1281
  Install generated Flywheel shell completions to user-level locations.
1279
1282
  Supported shells: ${COMPLETION_SHELL_CHOICES.join(", ")}.
1280
1283
  `,
1281
- )
1282
- .addHelpText(
1283
- "after",
1284
- `
1284
+ )
1285
+ .addHelpText(
1286
+ "after",
1287
+ `
1285
1288
  Examples:
1286
1289
  ${pc.green("flywheel completion install bash")}
1287
1290
  ${pc.green("flywheel completion install zsh --update-profile --yes")}
@@ -1289,29 +1292,29 @@ Examples:
1289
1292
  ${pc.green("flywheel completion install powershell --update-profile --yes")}
1290
1293
  ${pc.green("flywheel completion install nu")}
1291
1294
  `,
1292
- )
1293
- .action(async (shell, options) => {
1294
- await runCompletionInstallCommand(shell, options);
1295
- });
1295
+ )
1296
+ .action(async (shell, options) => {
1297
+ await runCompletionInstallCommand(shell, options);
1298
+ });
1296
1299
 
1297
- completionCommand
1298
- .command("uninstall <shell>")
1299
- .description("Uninstall Flywheel-managed shell completion scripts")
1300
- .option("--dir <path>", "Override completion script destination directory")
1301
- .option("--dry-run", "Print planned removals without writing files")
1302
- .option("--update-profile", "Allow shell startup/profile file updates")
1303
- .option("-y, --yes", "Skip confirmation prompts")
1304
- .addHelpText(
1305
- "before",
1306
- `${pc.bold(pc.cyan("✻ Flywheel Completion Uninstall"))}
1300
+ completionCommand
1301
+ .command("uninstall <shell>")
1302
+ .description("Uninstall Flywheel-managed shell completion scripts")
1303
+ .option("--dir <path>", "Override completion script destination directory")
1304
+ .option("--dry-run", "Print planned removals without writing files")
1305
+ .option("--update-profile", "Allow shell startup/profile file updates")
1306
+ .option("-y, --yes", "Skip confirmation prompts")
1307
+ .addHelpText(
1308
+ "before",
1309
+ `${pc.bold(pc.cyan("✻ Flywheel Completion Uninstall"))}
1307
1310
 
1308
1311
  Remove only Flywheel-managed shell completion files and profile blocks.
1309
1312
  Supported shells: ${COMPLETION_SHELL_CHOICES.join(", ")}.
1310
1313
  `,
1311
- )
1312
- .addHelpText(
1313
- "after",
1314
- `
1314
+ )
1315
+ .addHelpText(
1316
+ "after",
1317
+ `
1315
1318
  Examples:
1316
1319
  ${pc.green("flywheel completion uninstall bash")}
1317
1320
  ${pc.green("flywheel completion uninstall zsh --update-profile --yes")}
@@ -1319,73 +1322,74 @@ Examples:
1319
1322
  ${pc.green("flywheel completion uninstall powershell --update-profile --yes")}
1320
1323
  ${pc.green("flywheel completion uninstall nu")}
1321
1324
  `,
1322
- )
1323
- .action(async (shell, options) => {
1324
- await runCompletionUninstallCommand(shell, options);
1325
- });
1325
+ )
1326
+ .action(async (shell, options) => {
1327
+ await runCompletionUninstallCommand(shell, options);
1328
+ });
1326
1329
 
1327
- program
1328
- .command("setup")
1329
- .description("Set up Flywheel for your AI coding host")
1330
- .addHelpText(
1331
- "before",
1332
- `${pc.bold(pc.cyan("✻ Flywheel Setup"))}
1330
+ program
1331
+ .command("setup")
1332
+ .description("Set up Flywheel for your AI coding host")
1333
+ .addHelpText(
1334
+ "before",
1335
+ `${pc.bold(pc.cyan("✻ Flywheel Setup"))}
1333
1336
 
1334
1337
  Configure the Flywheel CLI, MCP host entries, and bundled skills without changing command names or setup modes.
1335
1338
  `,
1336
- )
1337
- .optionsGroup("Hosts:")
1338
- .option("--claude", "Set up for Claude Code")
1339
- .option("--cursor", "Set up for Cursor")
1340
- .option("--universal", "Set up for Universal (.agents/skills)")
1341
- .option("--antigravity", "Set up for Antigravity (.agent/skills)")
1342
- .option("--opencode", "Set up for OpenCode")
1343
- .option("--codex", "Set up for Codex")
1344
- .option("--gemini", "Set up for Gemini CLI")
1345
- .option("--pi-mono", "Set up for Pi (pi-mono)")
1346
- .option("--hermes-agent", "Set up for Hermes Agent")
1347
- .option("--openclaw", "Set up for OpenClaw")
1348
- .optionsGroup("Mode:")
1349
- .option(
1350
- "--mode <mode>",
1351
- "Install mode: mcp | cli (required in non-interactive; prompted in TTY, default: mcp)",
1352
- collectModeValues,
1353
- [],
1354
- )
1355
- .option("--mcp", "Alias for --mode mcp")
1356
- .option("--cli", "Alias for --mode cli")
1357
- .optionsGroup("Scope:")
1358
- .option(
1359
- "-p, --project",
1360
- "Configure for current project instead of globally",
1361
- )
1362
- .option("-y, --yes", "Skip confirmation prompts")
1363
- .optionsGroup("Authentication:")
1364
- .option("--api-key <key>", "Use API key authentication")
1365
- .option("--oauth", "Use OAuth endpoint (IDE handles auth flow)")
1366
- .optionsGroup("Skills:")
1367
- .option("--install-skill", "Install or refresh the bundled Flywheel skills")
1368
- .option("--skip-skill", "Skip bundled skill installation (MCP-only setup)")
1369
- .optionsGroup("Advanced:")
1370
- .option(
1371
- "--auth-mode <mode>",
1372
- "Device approval flow; default auto. " +
1373
- "Explicit loopback is retired and returns FLY-416 guidance",
1374
- normalizeAuthMode,
1375
- "auto",
1376
- )
1377
- .option(
1378
- "--base-url <url>",
1379
- `Public Flywheel origin used for setup and MCP config (default: ${resolveSetupBaseUrl()})`,
1380
- )
1381
- .option("--name <name>", `MCP server name (default: ${SERVER_NAME})`)
1382
- .option(
1383
- "--force",
1384
- "Reconcile prior install mode automatically via uninstall",
1385
- )
1386
- .addHelpText(
1387
- "after",
1388
- `
1339
+ )
1340
+ .optionsGroup("Hosts:")
1341
+ .option("--claude", "Set up for Claude Code")
1342
+ .option("--cursor", "Set up for Cursor")
1343
+ .option("--universal", "Set up for Universal (.agents/skills)")
1344
+ .option("--antigravity", "Set up for Antigravity (.agent/skills)")
1345
+ .option("--opencode", "Set up for OpenCode")
1346
+ .option("--codex", "Set up for Codex")
1347
+ .option("--gemini", "Set up for Gemini CLI")
1348
+ .option("--pi-mono", "Set up for Pi (pi-mono)")
1349
+ .option("--hermes-agent", "Set up for Hermes Agent")
1350
+ .option("--openclaw", "Set up for OpenClaw")
1351
+ .optionsGroup("Mode:")
1352
+ .option(
1353
+ "--mode <mode>",
1354
+ "Install mode: mcp | cli (required in non-interactive; prompted in TTY, default: mcp)",
1355
+ collectModeValues,
1356
+ [],
1357
+ )
1358
+ .option("--mcp", "Alias for --mode mcp")
1359
+ .option("--cli", "Alias for --mode cli")
1360
+ .optionsGroup("Scope:")
1361
+ .option(
1362
+ "-p, --project",
1363
+ "Configure for current project instead of globally",
1364
+ )
1365
+ .option("-y, --yes", "Skip confirmation prompts")
1366
+ .optionsGroup("Authentication:")
1367
+ .option("--api-key <key>", "Use API key authentication")
1368
+ .option("--api-key-stdin", "Read one API key privately from stdin without browser authentication")
1369
+ .option("--oauth", "Use OAuth endpoint (IDE handles auth flow)")
1370
+ .optionsGroup("Skills:")
1371
+ .option("--install-skill", "Install or refresh the bundled Flywheel skills")
1372
+ .option("--skip-skill", "Skip bundled skill installation (MCP-only setup)")
1373
+ .optionsGroup("Advanced:")
1374
+ .option(
1375
+ "--auth-mode <mode>",
1376
+ "Device approval flow; default auto. " +
1377
+ "Explicit loopback is retired and returns FLY-416 guidance",
1378
+ normalizeAuthMode,
1379
+ "auto",
1380
+ )
1381
+ .option(
1382
+ "--base-url <url>",
1383
+ `Public Flywheel origin used for setup and MCP config (default: ${resolveSetupBaseUrl()})`,
1384
+ )
1385
+ .option("--name <name>", `MCP server name (default: ${SERVER_NAME})`)
1386
+ .option(
1387
+ "--force",
1388
+ "Reconcile prior install mode automatically via uninstall",
1389
+ )
1390
+ .addHelpText(
1391
+ "after",
1392
+ `
1389
1393
  Examples:
1390
1394
  ${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp --install-skill")}
1391
1395
  ${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp --skip-skill --codex --project")}
@@ -1395,48 +1399,48 @@ Next steps:
1395
1399
  ${pc.green("flywheel help")}
1396
1400
  ${pc.green("flywheel auth:status")}
1397
1401
  `,
1398
- )
1399
- .action(async (options) => {
1400
- await runSetupCommandViaRouter(options);
1401
- });
1402
+ )
1403
+ .action(async (options) => {
1404
+ await runSetupCommandViaRouter(options);
1405
+ });
1402
1406
 
1403
- program
1404
- .command("uninstall")
1405
- .description(
1406
- "Remove Flywheel MCP entries and bundled skills from selected hosts",
1407
- )
1408
- .addHelpText(
1409
- "before",
1410
- `${pc.bold(pc.cyan("✻ Flywheel Uninstall"))}
1407
+ program
1408
+ .command("uninstall")
1409
+ .description(
1410
+ "Remove Flywheel MCP entries and bundled skills from selected hosts",
1411
+ )
1412
+ .addHelpText(
1413
+ "before",
1414
+ `${pc.bold(pc.cyan("✻ Flywheel Uninstall"))}
1411
1415
 
1412
1416
  Remove Flywheel MCP entries and bundled skills from selected hosts without changing command names or uninstall scopes.
1413
1417
  `,
1414
- )
1415
- .optionsGroup("Hosts:")
1416
- .option("--claude", "Uninstall for Claude Code")
1417
- .option("--cursor", "Uninstall for Cursor")
1418
- .option("--universal", "Uninstall bundled skills from .agents/skills")
1419
- .option("--antigravity", "Uninstall bundled skills from .agent/skills")
1420
- .option("--opencode", "Uninstall for OpenCode")
1421
- .option("--codex", "Uninstall for Codex")
1422
- .option("--gemini", "Uninstall for Gemini CLI")
1423
- .option("--pi-mono", "Uninstall for Pi (pi-mono)")
1424
- .option("--hermes-agent", "Uninstall for Hermes Agent")
1425
- .option("--openclaw", "Uninstall for OpenClaw")
1426
- .optionsGroup("Selection:")
1427
- .option(
1428
- "--hosts <list>",
1429
- "Comma-separated: claude,cursor,universal,antigravity,opencode,codex,gemini,pi-mono,hermes-agent,openclaw",
1430
- )
1431
- .option("--scope <scope>", "all | global | project")
1432
- .option(
1433
- "--name <name>",
1434
- `MCP server name to remove (default: ${SERVER_NAME})`,
1435
- )
1436
- .option("-y, --yes", "Skip uninstall selection prompts")
1437
- .addHelpText(
1438
- "after",
1439
- `
1418
+ )
1419
+ .optionsGroup("Hosts:")
1420
+ .option("--claude", "Uninstall for Claude Code")
1421
+ .option("--cursor", "Uninstall for Cursor")
1422
+ .option("--universal", "Uninstall bundled skills from .agents/skills")
1423
+ .option("--antigravity", "Uninstall bundled skills from .agent/skills")
1424
+ .option("--opencode", "Uninstall for OpenCode")
1425
+ .option("--codex", "Uninstall for Codex")
1426
+ .option("--gemini", "Uninstall for Gemini CLI")
1427
+ .option("--pi-mono", "Uninstall for Pi (pi-mono)")
1428
+ .option("--hermes-agent", "Uninstall for Hermes Agent")
1429
+ .option("--openclaw", "Uninstall for OpenClaw")
1430
+ .optionsGroup("Selection:")
1431
+ .option(
1432
+ "--hosts <list>",
1433
+ "Comma-separated: claude,cursor,universal,antigravity,opencode,codex,gemini,pi-mono,hermes-agent,openclaw",
1434
+ )
1435
+ .option("--scope <scope>", "all | global | project")
1436
+ .option(
1437
+ "--name <name>",
1438
+ `MCP server name to remove (default: ${SERVER_NAME})`,
1439
+ )
1440
+ .option("-y, --yes", "Skip uninstall selection prompts")
1441
+ .addHelpText(
1442
+ "after",
1443
+ `
1440
1444
  Examples:
1441
1445
  ${pc.green("npx --yes @paradigma-inc/flywheel uninstall --codex --scope project")}
1442
1446
  ${pc.green("npx --yes @paradigma-inc/flywheel uninstall --hosts claude,codex --scope all --yes")}
@@ -1445,43 +1449,43 @@ Next steps:
1445
1449
  ${pc.green("flywheel help setup")}
1446
1450
  ${pc.green("npx --yes @paradigma-inc/flywheel setup --mode mcp")}
1447
1451
  `,
1448
- )
1449
- .action(async (options) => {
1450
- await runUninstallCommand(options);
1451
- });
1452
+ )
1453
+ .action(async (options) => {
1454
+ await runUninstallCommand(options);
1455
+ });
1452
1456
 
1453
- return program;
1457
+ return program;
1454
1458
  }
1455
1459
 
1456
1460
  export async function runCli(argv = process.argv, { exitOverride = false } = {}) {
1457
- try {
1458
- const program = buildProgram({ exitOverride });
1459
- await program.parseAsync(argv);
1460
- return process.exitCode ?? 0;
1461
- } catch (error) {
1462
- if (error instanceof Error && error.name === "ExitPromptError") {
1463
- if (exitOverride) {
1464
- return 0;
1465
- }
1466
- process.exit(0);
1467
- }
1468
- if (error instanceof Error && /cancelled/i.test(error.message)) {
1469
- log.warn(error.message);
1470
- if (exitOverride) {
1471
- return 0;
1472
- }
1473
- process.exit(0);
1474
- }
1475
- if (
1476
- exitOverride &&
1477
- error &&
1478
- typeof error === "object" &&
1479
- typeof error.code === "string" &&
1480
- error.code.startsWith("commander.") &&
1481
- Number.isInteger(error.exitCode)
1482
- ) {
1483
- return error.exitCode;
1484
- }
1485
- throw error;
1461
+ try {
1462
+ const program = buildProgram({ exitOverride });
1463
+ await program.parseAsync(argv);
1464
+ return process.exitCode ?? 0;
1465
+ } catch (error) {
1466
+ if (error instanceof Error && error.name === "ExitPromptError") {
1467
+ if (exitOverride) {
1468
+ return 0;
1469
+ }
1470
+ process.exit(0);
1471
+ }
1472
+ if (error instanceof Error && /cancelled/i.test(error.message)) {
1473
+ log.warn(error.message);
1474
+ if (exitOverride) {
1475
+ return 0;
1476
+ }
1477
+ process.exit(0);
1478
+ }
1479
+ if (
1480
+ exitOverride &&
1481
+ error &&
1482
+ typeof error === "object" &&
1483
+ typeof error.code === "string" &&
1484
+ error.code.startsWith("commander.") &&
1485
+ Number.isInteger(error.exitCode)
1486
+ ) {
1487
+ return error.exitCode;
1486
1488
  }
1489
+ throw error;
1490
+ }
1487
1491
  }