@starlove/orbit 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/Dockerfile +10 -8
  2. package/README.md +146 -164
  3. package/dist/full/csp.txt +1 -0
  4. package/dist/full/fonts/JetBrains_Mono/JetBrainsMono-subset.woff2 +0 -0
  5. package/dist/full/fonts/JetBrains_Mono/README.txt +5 -0
  6. package/dist/full/fonts/Mona_Sans/MonaSans-subset.woff2 +0 -0
  7. package/{public/fonts/Open_Sans → dist/full/fonts/Mona_Sans}/OFL.txt +93 -93
  8. package/dist/full/fonts/Mona_Sans/README.txt +10 -0
  9. package/{public/fonts/JetBrains_Mono → dist/full/fonts/Newsreader}/OFL.txt +93 -93
  10. package/dist/full/fonts/Newsreader/README.txt +8 -0
  11. package/dist/full/fonts/Newsreader/newsreader.woff2 +0 -0
  12. package/dist/full/index.html +36 -653
  13. package/dist/full/js/app.BmuponPJ.js +32 -0
  14. package/dist/full/js/app.BmuponPJ.js.map +1 -0
  15. package/dist/full/js/chunk.1fJGQGbW.js +2 -0
  16. package/dist/full/js/chunk.1fJGQGbW.js.map +1 -0
  17. package/dist/full/js/chunk.5D7JO2zp.js +2 -0
  18. package/dist/full/js/chunk.5D7JO2zp.js.map +1 -0
  19. package/dist/full/js/chunk.BrNn_D79.js +2 -0
  20. package/dist/full/js/chunk.BrNn_D79.js.map +1 -0
  21. package/dist/full/js/chunk.CokJXIqM.js +2 -0
  22. package/dist/full/js/chunk.CokJXIqM.js.map +1 -0
  23. package/dist/full/js/chunk.D_Haqy6R.js +2 -0
  24. package/dist/full/js/chunk.D_Haqy6R.js.map +1 -0
  25. package/dist/full/js/chunk.RO0jsH6I.js +15 -0
  26. package/dist/full/js/chunk.RO0jsH6I.js.map +1 -0
  27. package/dist/full/js/chunk.dqWOEtBM.js +2 -0
  28. package/dist/full/js/chunk.dqWOEtBM.js.map +1 -0
  29. package/dist/full/js/warm.f260bbbc.js +15 -0
  30. package/dist/full/orbits-favicon.png +0 -0
  31. package/dist/full/orbits-logo-bg-wide.png +0 -0
  32. package/dist/full/orbits-logo-bg.png +0 -0
  33. package/dist/full/orbits-logo.png +0 -0
  34. package/dist/full/styles.2b154ffe.css +1 -0
  35. package/dist/full/vendor/starlove-ui/theme-init.js +66 -0
  36. package/dist/full/version.json +2 -2
  37. package/docs/AGENT_GUIDE.md +114 -0
  38. package/docs/UPDATING.md +249 -64
  39. package/lib/adapters/indexeddb/blobs.d.ts +3 -0
  40. package/lib/adapters/indexeddb/blobs.js +54 -0
  41. package/lib/adapters/indexeddb/database.d.ts +60 -0
  42. package/lib/adapters/indexeddb/database.js +126 -0
  43. package/lib/adapters/indexeddb/index.d.ts +5 -0
  44. package/lib/adapters/indexeddb/index.js +3 -0
  45. package/lib/adapters/indexeddb/locks.d.ts +14 -0
  46. package/lib/adapters/indexeddb/locks.js +40 -0
  47. package/lib/adapters/indexeddb/store.d.ts +40 -0
  48. package/lib/adapters/indexeddb/store.js +424 -0
  49. package/lib/adapters/indexeddb/tables.d.ts +43 -0
  50. package/lib/adapters/indexeddb/tables.js +127 -0
  51. package/lib/adapters/memory/blobs.d.ts +3 -0
  52. package/lib/adapters/memory/blobs.js +44 -0
  53. package/lib/adapters/memory/board.d.ts +41 -0
  54. package/lib/adapters/memory/board.js +521 -0
  55. package/lib/adapters/memory/index.d.ts +2 -0
  56. package/lib/adapters/memory/index.js +2 -0
  57. package/lib/adapters/memory/search.d.ts +6 -0
  58. package/lib/adapters/memory/search.js +30 -0
  59. package/lib/adapters/memory/store.d.ts +34 -0
  60. package/lib/adapters/memory/store.js +266 -0
  61. package/lib/adapters/sqlite/backups.d.ts +53 -0
  62. package/lib/adapters/sqlite/backups.js +232 -0
  63. package/lib/adapters/sqlite/blobs.d.ts +14 -0
  64. package/lib/adapters/sqlite/blobs.js +109 -0
  65. package/lib/adapters/sqlite/board.d.ts +77 -0
  66. package/lib/adapters/sqlite/board.js +328 -0
  67. package/lib/adapters/sqlite/database.d.ts +67 -0
  68. package/lib/adapters/sqlite/database.js +285 -0
  69. package/lib/adapters/sqlite/index.d.ts +3 -0
  70. package/lib/adapters/sqlite/index.js +2 -0
  71. package/lib/adapters/sqlite/lock.d.ts +11 -0
  72. package/lib/adapters/sqlite/lock.js +34 -0
  73. package/lib/adapters/sqlite/records.d.ts +54 -0
  74. package/lib/adapters/sqlite/records.js +546 -0
  75. package/lib/adapters/sqlite/schema.d.ts +54 -0
  76. package/lib/adapters/sqlite/schema.js +276 -0
  77. package/lib/adapters/sqlite/store.d.ts +39 -0
  78. package/lib/adapters/sqlite/store.js +385 -0
  79. package/lib/browser/in-page.d.ts +31 -0
  80. package/lib/browser/in-page.js +46 -0
  81. package/lib/browser/old-preview.d.ts +13 -0
  82. package/lib/browser/old-preview.js +80 -0
  83. package/lib/browser/preview-board.d.ts +8 -0
  84. package/lib/browser/preview-board.js +69 -0
  85. package/lib/cli/main.d.ts +7 -0
  86. package/lib/cli/main.js +343 -0
  87. package/lib/cli/orbit.d.ts +8 -0
  88. package/lib/cli/orbit.js +25 -0
  89. package/lib/client/http.d.ts +38 -0
  90. package/lib/client/http.js +334 -0
  91. package/lib/client/local.d.ts +26 -0
  92. package/lib/client/local.js +190 -0
  93. package/lib/client/object-url.d.ts +8 -0
  94. package/lib/client/object-url.js +21 -0
  95. package/lib/client/types.d.ts +268 -0
  96. package/lib/client/types.js +8 -0
  97. package/lib/commands/agent-tools.d.ts +31 -0
  98. package/lib/commands/agent-tools.js +100 -0
  99. package/lib/commands/index.d.ts +56 -0
  100. package/lib/commands/index.js +298 -0
  101. package/lib/commands/parse.d.ts +73 -0
  102. package/lib/commands/parse.js +231 -0
  103. package/lib/commands/present.d.ts +134 -0
  104. package/lib/commands/present.js +198 -0
  105. package/lib/commands/session.d.ts +85 -0
  106. package/lib/commands/session.js +138 -0
  107. package/lib/commands/verbs.d.ts +35 -0
  108. package/lib/commands/verbs.js +842 -0
  109. package/lib/core/actors.d.ts +18 -0
  110. package/lib/core/actors.js +45 -0
  111. package/lib/core/agent.d.ts +128 -0
  112. package/lib/core/agent.js +323 -0
  113. package/lib/core/boards.d.ts +113 -0
  114. package/lib/core/boards.js +288 -0
  115. package/lib/core/bootstrap.d.ts +47 -0
  116. package/lib/core/bootstrap.js +100 -0
  117. package/lib/core/bytes.d.ts +10 -0
  118. package/lib/core/bytes.js +52 -0
  119. package/lib/core/card-paths.d.ts +25 -0
  120. package/lib/core/card-paths.js +44 -0
  121. package/lib/core/context.d.ts +60 -0
  122. package/lib/core/context.js +42 -0
  123. package/lib/core/cross-board.d.ts +81 -0
  124. package/lib/core/cross-board.js +228 -0
  125. package/lib/core/describe.d.ts +21 -0
  126. package/lib/core/describe.js +81 -0
  127. package/lib/core/errors.d.ts +159 -0
  128. package/lib/core/errors.js +160 -0
  129. package/lib/core/files.d.ts +79 -0
  130. package/lib/core/files.js +262 -0
  131. package/lib/core/history.d.ts +20 -0
  132. package/lib/core/history.js +53 -0
  133. package/lib/core/image-types.d.ts +16 -0
  134. package/lib/core/image-types.js +36 -0
  135. package/lib/core/model.d.ts +263 -0
  136. package/lib/core/model.js +34 -0
  137. package/lib/core/nebula-link.d.ts +14 -0
  138. package/lib/core/nebula-link.js +39 -0
  139. package/lib/core/relations.d.ts +58 -0
  140. package/lib/core/relations.js +112 -0
  141. package/lib/core/search.d.ts +38 -0
  142. package/lib/core/search.js +92 -0
  143. package/lib/core/sessions.d.ts +44 -0
  144. package/lib/core/sessions.js +158 -0
  145. package/lib/core/snapshot-schema.d.ts +295 -0
  146. package/lib/core/snapshot-schema.js +82 -0
  147. package/lib/core/snapshots.d.ts +75 -0
  148. package/lib/core/snapshots.js +409 -0
  149. package/lib/core/states.d.ts +25 -0
  150. package/lib/core/states.js +126 -0
  151. package/lib/core/text.d.ts +40 -0
  152. package/lib/core/text.js +113 -0
  153. package/lib/core/tickets.d.ts +69 -0
  154. package/lib/core/tickets.js +311 -0
  155. package/lib/core/trello.d.ts +17 -0
  156. package/lib/core/trello.js +269 -0
  157. package/lib/core/verdicts.d.ts +28 -0
  158. package/lib/core/verdicts.js +92 -0
  159. package/lib/core/views.d.ts +95 -0
  160. package/lib/core/views.js +186 -0
  161. package/lib/http/app.d.ts +46 -0
  162. package/lib/http/app.js +491 -0
  163. package/lib/mcp-server.d.ts +10 -0
  164. package/lib/mcp-server.js +120 -0
  165. package/lib/node/assets.d.ts +7 -0
  166. package/lib/node/assets.js +68 -0
  167. package/lib/node/data-folder.d.ts +21 -0
  168. package/lib/node/data-folder.js +34 -0
  169. package/lib/node/env.d.ts +38 -0
  170. package/lib/node/env.js +49 -0
  171. package/lib/node/host-check.d.ts +24 -0
  172. package/lib/node/host-check.js +53 -0
  173. package/lib/node/host-services.d.ts +9 -0
  174. package/lib/node/host-services.js +150 -0
  175. package/lib/node/local.d.ts +22 -0
  176. package/lib/node/local.js +61 -0
  177. package/lib/node/migrate.d.ts +53 -0
  178. package/lib/node/migrate.js +635 -0
  179. package/lib/node/package.d.ts +7 -0
  180. package/lib/node/package.js +14 -0
  181. package/lib/node/repo-board.d.ts +49 -0
  182. package/lib/node/repo-board.js +245 -0
  183. package/lib/node/serve.d.ts +8 -0
  184. package/lib/node/serve.js +106 -0
  185. package/lib/orbit.d.ts +47 -0
  186. package/lib/orbit.js +44 -0
  187. package/lib/quiet-sqlite-warning.d.ts +1 -0
  188. package/lib/quiet-sqlite-warning.js +18 -0
  189. package/lib/store/blob-path.d.ts +6 -0
  190. package/lib/store/blob-path.js +12 -0
  191. package/lib/store/conformance.d.ts +52 -0
  192. package/lib/store/conformance.js +1449 -0
  193. package/lib/store/search-words.d.ts +10 -0
  194. package/lib/store/search-words.js +19 -0
  195. package/lib/store/types.d.ts +452 -0
  196. package/lib/store/types.js +34 -0
  197. package/llms.txt +63 -0
  198. package/package.json +109 -25
  199. package/src/cli/orbit.js +11 -658
  200. package/src/mcp-server.js +16 -876
  201. package/SKILL-ORBIT.md +0 -151
  202. package/build.mjs +0 -210
  203. package/dist/full/js/app.62905fcb.js +0 -952
  204. package/dist/full/js/app.62905fcb.js.map +0 -7
  205. package/dist/full/styles.4e60d824.css +0 -1
  206. package/docs/AGENT_PROTOCOL.md +0 -424
  207. package/docs/MCP_SETUP.md +0 -54
  208. package/docs/ORBIT_DISPATCH.md +0 -280
  209. package/docs/SS-Orbit-Dark.png +0 -0
  210. package/docs/SS-Orbit-Light.png +0 -0
  211. package/docs/mcp-client.example.json +0 -13
  212. package/docs/setup/orbit-init-wizard.md +0 -174
  213. package/public/apple-touch-icon.png +0 -0
  214. package/public/cursors/live_arrow.cur +0 -0
  215. package/public/cursors/live_link.cur +0 -0
  216. package/public/cursors/live_move.cur +0 -0
  217. package/public/cursors/live_select.cur +0 -0
  218. package/public/cursors/live_unavail.cur +0 -0
  219. package/public/favicon-32x32.png +0 -0
  220. package/public/fonts/Chakra_Petch/ChakraPetch-Bold.ttf +0 -0
  221. package/public/fonts/Chakra_Petch/ChakraPetch-BoldItalic.ttf +0 -0
  222. package/public/fonts/Chakra_Petch/ChakraPetch-Italic.ttf +0 -0
  223. package/public/fonts/Chakra_Petch/ChakraPetch-Light.ttf +0 -0
  224. package/public/fonts/Chakra_Petch/ChakraPetch-LightItalic.ttf +0 -0
  225. package/public/fonts/Chakra_Petch/ChakraPetch-Medium.ttf +0 -0
  226. package/public/fonts/Chakra_Petch/ChakraPetch-MediumItalic.ttf +0 -0
  227. package/public/fonts/Chakra_Petch/ChakraPetch-Regular.ttf +0 -0
  228. package/public/fonts/Chakra_Petch/ChakraPetch-SemiBold.ttf +0 -0
  229. package/public/fonts/Chakra_Petch/ChakraPetch-SemiBoldItalic.ttf +0 -0
  230. package/public/fonts/Chakra_Petch/OFL.txt +0 -93
  231. package/public/fonts/Inter/Inter-Italic-VariableFont_opsz,wght.ttf +0 -0
  232. package/public/fonts/Inter/Inter-VariableFont_opsz,wght.ttf +0 -0
  233. package/public/fonts/Inter/OFL.txt +0 -93
  234. package/public/fonts/Inter/README.txt +0 -118
  235. package/public/fonts/JetBrains_Mono/JetBrainsMono-Italic-VariableFont_wght.ttf +0 -0
  236. package/public/fonts/JetBrains_Mono/JetBrainsMono-VariableFont_wght.ttf +0 -0
  237. package/public/fonts/JetBrains_Mono/README.txt +0 -79
  238. package/public/fonts/OpenRing-Regular.ttf +0 -0
  239. package/public/fonts/Open_Sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  240. package/public/fonts/Open_Sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
  241. package/public/fonts/Open_Sans/README.txt +0 -100
  242. package/public/fonts/Orbitron/OFL.txt +0 -93
  243. package/public/fonts/Orbitron/Orbitron-VariableFont_wght.ttf +0 -0
  244. package/public/fonts/Orbitron/README.txt +0 -68
  245. package/public/fonts/Rajdhani/OFL.txt +0 -93
  246. package/public/fonts/Rajdhani/Rajdhani-Bold.ttf +0 -0
  247. package/public/fonts/Rajdhani/Rajdhani-Light.ttf +0 -0
  248. package/public/fonts/Rajdhani/Rajdhani-Medium.ttf +0 -0
  249. package/public/fonts/Rajdhani/Rajdhani-Regular.ttf +0 -0
  250. package/public/fonts/Rajdhani/Rajdhani-SemiBold.ttf +0 -0
  251. package/public/fonts/runescape-uf.ttf +0 -0
  252. package/public/index.html +0 -769
  253. package/public/js/actor-labels.js +0 -65
  254. package/public/js/api.js +0 -39
  255. package/public/js/app.js +0 -45
  256. package/public/js/artifact-drawer.js +0 -79
  257. package/public/js/board-export.js +0 -161
  258. package/public/js/board-menu.js +0 -374
  259. package/public/js/card-actions.js +0 -545
  260. package/public/js/config.js +0 -20
  261. package/public/js/create-card.js +0 -190
  262. package/public/js/dom.js +0 -19
  263. package/public/js/drawer.js +0 -273
  264. package/public/js/font-preference.js +0 -229
  265. package/public/js/format.js +0 -433
  266. package/public/js/help-menu.js +0 -31
  267. package/public/js/icons.js +0 -16
  268. package/public/js/kanban.js +0 -694
  269. package/public/js/local-backend.js +0 -1015
  270. package/public/js/main.js +0 -161
  271. package/public/js/modal.js +0 -33
  272. package/public/js/motion-preference.js +0 -64
  273. package/public/js/panel.js +0 -58
  274. package/public/js/router.js +0 -134
  275. package/public/js/search.js +0 -56
  276. package/public/js/settings-tabs.js +0 -7
  277. package/public/js/settings.js +0 -1634
  278. package/public/js/sse.js +0 -159
  279. package/public/js/starscape.js +0 -332
  280. package/public/js/state.js +0 -129
  281. package/public/js/text-editing.js +0 -128
  282. package/public/js/theme-preference.js +0 -95
  283. package/public/js/ticket-detail.js +0 -1516
  284. package/public/js/ticket-typeahead.js +0 -49
  285. package/public/js/toast.js +0 -89
  286. package/public/js/topbar-notes.js +0 -155
  287. package/public/js/transport.js +0 -22
  288. package/public/js/typeahead.js +0 -206
  289. package/public/js/unread.js +0 -121
  290. package/public/js/update-check.js +0 -58
  291. package/public/js/url-routes.js +0 -94
  292. package/public/orbits-favicon.png +0 -0
  293. package/public/orbits-logo-bg-wide.png +0 -0
  294. package/public/orbits-logo-bg.png +0 -0
  295. package/public/orbits-logo.png +0 -0
  296. package/public/styles.css +0 -7709
  297. package/src/core/agent.js +0 -387
  298. package/src/core/agents-md.js +0 -109
  299. package/src/core/artifacts.js +0 -149
  300. package/src/core/attachments.js +0 -238
  301. package/src/core/auth.js +0 -85
  302. package/src/core/backups.js +0 -142
  303. package/src/core/board.js +0 -148
  304. package/src/core/boards.js +0 -409
  305. package/src/core/bootstrap.js +0 -170
  306. package/src/core/css-bundle.js +0 -30
  307. package/src/core/db.js +0 -315
  308. package/src/core/delete-board.js +0 -163
  309. package/src/core/dispatch.js +0 -1007
  310. package/src/core/events.js +0 -314
  311. package/src/core/http.js +0 -115
  312. package/src/core/migrate.js +0 -198
  313. package/src/core/paths.js +0 -55
  314. package/src/core/provision-repo-board.js +0 -119
  315. package/src/core/queries.js +0 -246
  316. package/src/core/registry.js +0 -211
  317. package/src/core/relations.js +0 -163
  318. package/src/core/review-verdicts.js +0 -138
  319. package/src/core/router.js +0 -556
  320. package/src/core/search.js +0 -183
  321. package/src/core/seed.js +0 -234
  322. package/src/core/snapshots.js +0 -692
  323. package/src/core/states.js +0 -167
  324. package/src/core/system-picker.js +0 -109
  325. package/src/core/tickets.js +0 -400
  326. package/src/core/util.js +0 -106
  327. package/src/core/version-check.js +0 -154
  328. package/src/mcp/orbit-client.js +0 -287
  329. package/src/server.js +0 -115
package/src/cli/orbit.js CHANGED
@@ -1,662 +1,15 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Orbit CLI — `orbit init` provisions `.orbit/board.db`, registry row, and
4
- * copies managed SKILL-ORBIT.md into the target repo. Does not import board.js.
5
- */
2
+ // Orbit 1.x's bin lived here, and 1.x's `orbit init` registered MCP servers as
3
+ // `node <this file> mcp --cwd <repo>`. Orbit 2.0 installs over 1.x in place, so
4
+ // this file keeps those registrations starting: it runs 2.0's own bin with the
5
+ // same arguments. It says so on stderr only, because stdout is the MCP
6
+ // protocol. It stays until 3.0. Plain JavaScript, outside tsc and lint: npm
7
+ // ships it as it is.
6
8
 
7
- import { spawn, spawnSync } from "node:child_process";
8
- import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, unlinkSync } from "node:fs";
9
- import { homedir } from "node:os";
10
- import { dirname, join, resolve } from "node:path";
11
- import { fileURLToPath } from "node:url";
12
- import { removeOrbitAgentsSection, syncAgentsMd, syncSkillOrbitMd } from "../core/agents-md.js";
13
-
14
- const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
15
-
16
- function printUsage() {
17
- console.log(`Usage:
18
- orbit -v, --version Print the Orbit CLI version
19
- orbit init [options] Provision .orbit/board.db + SKILL-ORBIT.md + AGENTS.md
20
- orbit reset [options] Delete .orbit/ + SKILL-ORBIT.md + registry row
21
- orbit run [options] Start the Orbit web app + HTTP API
22
- orbit docker [options] Build/run Orbit's web app in Docker
23
- orbit mcp [options] Start the stdio MCP server (for agent clients)
24
- orbit dispatch [options] Dispatch a Hermes profile on a ticket
25
-
26
- Options (init / reset / run / docker / mcp / dispatch):
27
- --cwd <dir> Project root (default: process.cwd())
28
-
29
- Options (init only):
30
- --no-ai Create the board with AI collaboration disabled
31
- --example Create example onboarding tickets
32
-
33
- Options (run / docker):
34
- --port <n> HTTP port (run auto-starts at 13701; --port/$PORT is exact)
35
-
36
- Options (run):
37
- -d, --detach Run in the background and print the child PID/log path
38
-
39
- Options (dispatch):
40
- --board <slug-or-id> Local board to dispatch against (default: board for --cwd)
41
- --ticket <number-id> Ticket number or id to dispatch
42
- --profile <name> Hermes profile to run (default: agent)
43
- --policy <name> Autonomous policy wrappers to apply (default: agent-safe; use none to disable)
44
- --server-url <url> Hosted Orbit base URL for remote dispatch
45
- --remote Force hosted/remote dispatch mode
46
- --worktree Create and preserve a git worktree for review/testing
47
- --worktree-path <dir> Worktree path when --worktree is used
48
- --branch <name> Branch name for the preserved worktree
49
- --hermes-bin <cmd> Hermes executable (default: hermes)
50
- --verify-command <cmd> Declare an expected verification command (repeatable)
51
- --no-spawn Prepare card/worktree/run record but do not start Hermes or move In Progress
52
- --no-yolo Do not pass --yolo to Hermes (default dispatch passes --yolo)
53
- --foreground Attach spawned Hermes process to this terminal
54
- --keep-handoff-file Keep duplicate handoff file under DATA_DIR/dispatch-runs/<board>
55
- --force Dispatch even when blockers exist
56
- --dry-run Preview only; no files, worktrees, ticket fields, comments, or agents change
57
-
58
- Options (docker only):
59
- --image <name> Docker image tag (default: starscape-orbit:local)
60
- --data-dir <dir> Docker registry/export data dir (default: <cwd>/.orbit/docker-data)
61
- --name <name> Optional Docker container name
62
- -d, --detach Run the container in the background (default)
63
- --foreground Run attached in the foreground
64
- --no-build Skip docker build and run an existing image
65
- --dry-run Print docker commands without running them`);
66
- }
67
-
68
- function printVersion() {
69
- const packageJson = JSON.parse(readFileSync(resolve(PACKAGE_ROOT, "package.json"), "utf8"));
70
- console.log(packageJson.version);
71
- }
72
-
73
- function shellQuote(value) {
74
- return `"${String(value || "").replace(/"/g, '\\"')}"`;
75
- }
76
-
77
- function commandQuote(value) {
78
- const text = String(value);
79
- if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(text)) return text;
80
- return `'${text.replace(/'/g, "'\\''")}'`;
81
- }
82
-
83
- function formatCommand(executable, args) {
84
- return [executable, ...args].map(commandQuote).join(" ");
85
- }
86
-
87
- async function loadCliCore() {
88
- const [
89
- { disableAiCollaboration, enableAiCollaboration },
90
- { backupBoardDatabase, backupRegistry },
91
- { closeConnection, createRegistrySchema, openConnection },
92
- { DATA_DIR, ROOT_DIR },
93
- { provisionRepoBoard },
94
- { deleteBoard, getBoardByRepoPath },
95
- { normalizePath }
96
- ] = await Promise.all([
97
- import("../core/boards.js"),
98
- import("../core/backups.js"),
99
- import("../core/db.js"),
100
- import("../core/paths.js"),
101
- import("../core/provision-repo-board.js"),
102
- import("../core/registry.js"),
103
- import("../core/util.js")
104
- ]);
105
-
106
- return {
107
- DATA_DIR,
108
- ROOT_DIR,
109
- backupBoardDatabase,
110
- backupRegistry,
111
- closeConnection,
112
- createRegistrySchema,
113
- deleteBoard,
114
- disableAiCollaboration,
115
- enableAiCollaboration,
116
- getBoardByRepoPath,
117
- normalizePath,
118
- openConnection,
119
- provisionRepoBoard
120
- };
121
- }
122
-
123
- function enableAiIfEnabled(options, registryRow, core) {
124
- if (!options.ai || !registryRow) return;
125
- const { enableAiCollaboration, openConnection } = core;
126
- const db = openConnection(registryRow.db_path);
127
- enableAiCollaboration(db, registryRow.id, { stageOnboardingTicket: options.example, actor: "orbit init" });
128
- const suffix = options.example ? "; example ticket #12 is staged in AI Ready." : ".";
129
- console.log(`AI collaboration enabled — AI Ready, In Progress, and Review lanes are present${suffix}`);
130
- }
131
-
132
- function disableAiIfRequested(options, registryRow, core) {
133
- if (options.ai || !registryRow) return;
134
- const { disableAiCollaboration, openConnection } = core;
135
- const db = openConnection(registryRow.db_path);
136
- disableAiCollaboration(db, registryRow.id, { actor: "orbit init" });
137
- console.log("AI collaboration disabled for this board.");
138
- }
139
-
140
- function isBusyFilesystemError(error) {
141
- const message = String(error?.message || "").toLowerCase();
142
- return (
143
- ["EBUSY", "EPERM", "ENOTEMPTY"].includes(error?.code) ||
144
- (error?.code === "ERR_SQLITE_ERROR" && (message.includes("locked") || message.includes("busy")))
145
- );
146
- }
147
-
148
- function resetBusyError(error, projectRoot) {
149
- if (!isBusyFilesystemError(error)) return error;
150
- const message = [
151
- `Orbit could not remove local board files under ${projectRoot}.`,
152
- "",
153
- "On Windows this usually means an Orbit web server, MCP helper, editor, or terminal still has .orbit/board.db open.",
154
- "Close Orbit server terminals and restart any AI client with Orbit MCP enabled, then rerun:",
155
- ` orbit reset --cwd ${shellQuote(projectRoot)}`,
156
- "",
157
- `Original error: ${error.message}`
158
- ].join("\n");
159
- const wrapped = new Error(message);
160
- wrapped.code = error.code;
161
- wrapped.cause = error;
162
- return wrapped;
163
- }
164
-
165
- function invalidArgs(args, message) {
166
- console.error(message);
167
- args.command = "help";
168
- args.invalid = true;
169
- return args;
170
- }
171
-
172
- function parseArgs(argv) {
173
- const args = {
174
- command: null,
175
- cwd: process.env.PROJECT_ROOT ? resolve(process.env.PROJECT_ROOT) : process.cwd(),
176
- cwdProvided: false,
177
- ai: true,
178
- example: false,
179
- port: null,
180
- detachRequested: false,
181
- image: "starscape-orbit:local",
182
- dataDir: null,
183
- containerName: null,
184
- buildImage: true,
185
- detach: true,
186
- dryRun: false,
187
- board: null,
188
- ticket: null,
189
- ticketUrl: null,
190
- profile: "agent",
191
- policy: "agent-safe",
192
- serverUrl: null,
193
- worktree: false,
194
- worktreePath: null,
195
- branch: null,
196
- hermesBin: "hermes",
197
- verifyCommands: [],
198
- noSpawn: false,
199
- yolo: true,
200
- keepHandoffFile: false,
201
- force: false,
202
- foreground: false,
203
- remote: false,
204
- help: false,
205
- invalid: false
206
- };
207
- const rest = argv.slice(2);
208
- if (rest.length === 0 || rest[0] === "-h" || rest[0] === "--help") {
209
- args.command = "help";
210
- return args;
211
- }
212
- if (rest[0] === "-v" || rest[0] === "--version") {
213
- args.command = "version";
214
- return args;
215
- }
216
- if (rest[0] === "dispatch" && (rest[1] === "-h" || rest[1] === "--help")) {
217
- args.command = "dispatch";
218
- args.help = true;
219
- return args;
220
- }
221
- args.command = rest[0];
222
- for (let i = 1; i < rest.length; i++) {
223
- const a = rest[i];
224
- if (a === "--no-ai") args.ai = false;
225
- else if (a === "--example") args.example = true;
226
- else if (a === "--cwd" && rest[i + 1]) {
227
- args.cwdProvided = true;
228
- args.cwd = resolve(rest[++i]);
229
- } else if (a.startsWith("--cwd=")) {
230
- args.cwdProvided = true;
231
- args.cwd = resolve(a.slice("--cwd=".length));
232
- } else if (a === "--port" && rest[i + 1]) {
233
- args.port = rest[++i];
234
- } else if (a.startsWith("--port=")) {
235
- args.port = a.slice("--port=".length);
236
- } else if (a === "--board" && rest[i + 1]) {
237
- args.board = rest[++i];
238
- } else if (a.startsWith("--board=")) {
239
- args.board = a.slice("--board=".length);
240
- } else if (a === "--ticket" && rest[i + 1]) {
241
- args.ticket = rest[++i];
242
- } else if (a.startsWith("--ticket=")) {
243
- args.ticket = a.slice("--ticket=".length);
244
- } else if (a === "--profile" && rest[i + 1]) {
245
- args.profile = rest[++i];
246
- } else if (a.startsWith("--profile=")) {
247
- args.profile = a.slice("--profile=".length);
248
- } else if (a === "--policy" && rest[i + 1]) {
249
- args.policy = rest[++i];
250
- } else if (a.startsWith("--policy=")) {
251
- args.policy = a.slice("--policy=".length);
252
- } else if (a === "--server-url" && rest[i + 1]) {
253
- args.serverUrl = rest[++i];
254
- } else if (a.startsWith("--server-url=")) {
255
- args.serverUrl = a.slice("--server-url=".length);
256
- } else if (a === "--remote") {
257
- args.remote = true;
258
- } else if (a === "--worktree") {
259
- args.worktree = true;
260
- } else if (a === "--worktree-path" && rest[i + 1]) {
261
- args.worktreePath = resolve(rest[++i]);
262
- } else if (a.startsWith("--worktree-path=")) {
263
- args.worktreePath = resolve(a.slice("--worktree-path=".length));
264
- } else if (a === "--branch" && rest[i + 1]) {
265
- args.branch = rest[++i];
266
- } else if (a.startsWith("--branch=")) {
267
- args.branch = a.slice("--branch=".length);
268
- } else if (a === "--hermes-bin" && rest[i + 1]) {
269
- args.hermesBin = rest[++i];
270
- } else if (a.startsWith("--hermes-bin=")) {
271
- args.hermesBin = a.slice("--hermes-bin=".length);
272
- } else if (a === "--verify-command") {
273
- const value = rest[i + 1];
274
- if (!value || value.startsWith("--")) {
275
- return invalidArgs(args, "--verify-command requires a non-empty value. Use --verify-command=<cmd> for values that start with --.");
276
- }
277
- args.verifyCommands.push(rest[++i]);
278
- } else if (a.startsWith("--verify-command=")) {
279
- const value = a.slice("--verify-command=".length);
280
- if (!value) {
281
- return invalidArgs(args, "--verify-command requires a non-empty value.");
282
- }
283
- args.verifyCommands.push(value);
284
- } else if (a === "--no-spawn") {
285
- args.noSpawn = true;
286
- } else if (a === "--no-yolo") {
287
- args.yolo = false;
288
- } else if (a === "--yolo") {
289
- args.yolo = true;
290
- } else if (a === "--keep-handoff-file") {
291
- args.keepHandoffFile = true;
292
- } else if (a === "--force") {
293
- args.force = true;
294
- } else if (a === "--image" && rest[i + 1]) {
295
- args.image = rest[++i];
296
- } else if (a.startsWith("--image=")) {
297
- args.image = a.slice("--image=".length);
298
- } else if (a === "--data-dir" && rest[i + 1]) {
299
- args.dataDir = resolve(rest[++i]);
300
- } else if (a.startsWith("--data-dir=")) {
301
- args.dataDir = resolve(a.slice("--data-dir=".length));
302
- } else if (a === "--name" && rest[i + 1]) {
303
- args.containerName = rest[++i];
304
- } else if (a.startsWith("--name=")) {
305
- args.containerName = a.slice("--name=".length);
306
- } else if (a === "--no-build") {
307
- args.buildImage = false;
308
- } else if (a === "-d" || a === "--detach") {
309
- args.detach = true;
310
- args.detachRequested = true;
311
- } else if (a === "--foreground") {
312
- args.detach = false;
313
- args.foreground = true;
314
- } else if (a === "--dry-run") {
315
- args.dryRun = true;
316
- } else if (args.command === "dispatch" && /^https?:\/\//i.test(a) && !args.ticketUrl) {
317
- args.ticketUrl = a;
318
- args.remote = true;
319
- } else {
320
- console.error(`Unknown argument: ${a}`);
321
- args.command = "help";
322
- args.invalid = true;
323
- return args;
324
- }
325
- }
326
- return args;
327
- }
328
-
329
- async function runInit(options) {
330
- const core = await loadCliCore();
331
- const { DATA_DIR, ROOT_DIR, createRegistrySchema, normalizePath, provisionRepoBoard } = core;
332
- const projectRoot = normalizePath(resolve(options.cwd));
333
- mkdirSync(DATA_DIR, { recursive: true });
334
- createRegistrySchema();
335
-
336
- const result = provisionRepoBoard(projectRoot, { enableAi: options.ai, includeExamples: options.example });
337
- const skillSrc = resolve(ROOT_DIR, "SKILL-ORBIT.md");
338
- const skillDest = resolve(projectRoot, "SKILL-ORBIT.md");
339
-
340
- if (!existsSync(skillSrc)) {
341
- console.warn(`Warning: missing ${skillSrc} — skipped copying SKILL-ORBIT.md and AGENTS.md Orbit section.`);
342
- } else {
343
- const skillSync = syncSkillOrbitMd(projectRoot, skillSrc);
344
- if (skillSync.status === "same_file") {
345
- console.log("SKILL-ORBIT.md source is already the project copy — left unchanged.");
346
- } else {
347
- console.log(`Wrote ${skillDest}`);
348
- }
349
- syncAgentsMd(projectRoot);
350
- }
351
-
352
- enableAiIfEnabled(options, result.registryRow, core);
353
- disableAiIfRequested(options, result.registryRow, core);
354
-
355
- if (result.message && result.status === "skipped") {
356
- console.log(result.message);
357
- } else if (result.status === "created") {
358
- console.log(`Initialized Orbit board at ${result.registryRow?.db_path ?? "(unknown path)"}`);
359
- } else if (result.status === "repaired") {
360
- console.log(result.message || "Linked existing board database to the registry.");
361
- }
362
-
363
- const cliPath = resolve(ROOT_DIR, "src", "cli", "orbit.js");
364
- const mcpLine = ["claude mcp add starscape-orbit", "--", "node", shellQuote(cliPath), "mcp", "--cwd", shellQuote(projectRoot)].join(" ");
365
- console.log(`
366
- --- Next: MCP (run once per Claude Code install) ---
367
- ${mcpLine}
368
-
369
- --- Next: agent prompt (from this repo) ---
370
- Read AGENTS.md in this repository, then use the Orbit MCP tools. Use board_list, board_set_active, and ticket context tools per docs/AGENT_PROTOCOL.md before claiming or updating work.
371
-
372
- ${options.example ? (options.ai ? "Example ticket #12 is \"Try Orbit MCP on this ticket\" in AI Ready — good first exercise after MCP is connected." : "Example tickets were created. AI collaboration was disabled with `--no-ai`, so ticket #12 remains in Backlog.") : "No example tickets were created. Rerun on a fresh board with `orbit init --example` if you want the onboarding examples."}
373
- `);
374
-
375
- if (result.registryRow) {
376
- console.log(`Board: ${result.registryRow.name} (${result.registryRow.slug}) registry id: ${result.registryRow.id}`);
377
- }
378
- }
379
-
380
- async function runReset(options) {
381
- const {
382
- DATA_DIR,
383
- backupBoardDatabase,
384
- backupRegistry,
385
- closeConnection,
386
- createRegistrySchema,
387
- deleteBoard,
388
- getBoardByRepoPath,
389
- normalizePath,
390
- openConnection
391
- } = await loadCliCore();
392
- const projectRoot = normalizePath(resolve(options.cwd));
393
- mkdirSync(DATA_DIR, { recursive: true });
394
- createRegistrySchema();
395
-
396
- const orbitDir = resolve(projectRoot, ".orbit");
397
- const skillMd = resolve(projectRoot, "SKILL-ORBIT.md");
398
- const removed = [];
399
- const registryRow = getBoardByRepoPath(projectRoot);
400
-
401
- if (registryRow && existsSync(registryRow.db_path)) {
402
- const db = openConnection(registryRow.db_path);
403
- try {
404
- backupBoardDatabase(registryRow, db, "pre-cli-reset");
405
- } catch (error) {
406
- throw resetBusyError(error, projectRoot);
407
- } finally {
408
- closeConnection(registryRow.db_path);
409
- }
410
- }
411
- if (registryRow) backupRegistry("pre-cli-reset");
412
-
413
- try {
414
- // Remove the board database. With central storage the db lives outside the
415
- // project directory; with legacy in-repo storage it is inside orbitDir below.
416
- const isCentralDb = registryRow && !registryRow.db_path.startsWith(projectRoot + "/");
417
- if (isCentralDb && existsSync(registryRow.db_path)) {
418
- const boardDir = dirname(registryRow.db_path);
419
- rmSync(boardDir, { recursive: true, force: true });
420
- removed.push(boardDir);
421
- }
422
-
423
- // Remove central dispatch-runs for this board.
424
- if (registryRow) {
425
- const dispatchRunsDir = join(DATA_DIR, "dispatch-runs", registryRow.slug);
426
- if (existsSync(dispatchRunsDir)) {
427
- rmSync(dispatchRunsDir, { recursive: true, force: true });
428
- removed.push(dispatchRunsDir);
429
- }
430
- }
431
-
432
- // Remove the in-repo .orbit/ directory (covers legacy db, residual dispatch-runs, etc.).
433
- if (existsSync(orbitDir)) {
434
- rmSync(orbitDir, { recursive: true, force: true });
435
- removed.push(orbitDir);
436
- }
437
- if (existsSync(skillMd)) {
438
- unlinkSync(skillMd);
439
- removed.push(skillMd);
440
- }
441
- const agentsCleanup = removeOrbitAgentsSection(projectRoot);
442
- if (agentsCleanup.removed) {
443
- removed.push(`${agentsCleanup.path} Orbit section`);
444
- } else if (!agentsCleanup.ok) {
445
- console.warn(`Warning: skipped AGENTS.md cleanup (${agentsCleanup.reason}) in ${agentsCleanup.path}`);
446
- }
447
- } catch (error) {
448
- throw resetBusyError(error, projectRoot);
449
- }
450
-
451
- if (registryRow) {
452
- deleteBoard(registryRow.id);
453
- removed.push(`registry row "${registryRow.slug}"`);
454
- }
455
-
456
- if (removed.length === 0) {
457
- console.log(`Nothing to reset under ${projectRoot}.`);
458
- } else {
459
- for (const item of removed) console.log(`Removed ${item}`);
460
- console.log(`\nRun \`orbit init\` from ${projectRoot} to provision a fresh board.`);
461
- }
462
- }
463
-
464
- async function runServe(options) {
465
- // PROJECT_ROOT must be set BEFORE importing the server, because src/core/paths.js
466
- // captures it at module load. cwd defaults are equivalent for most users, but
467
- // an explicit --cwd lets a global install target a board outside cwd.
468
- process.env.PROJECT_ROOT = resolve(options.cwd);
469
- process.env.ORBIT_SYNC_MANAGED_SKILL_ORBIT = "1";
470
- if (options.port) process.env.PORT = String(options.port);
471
- await import("../server.js");
472
- }
473
-
474
- function orbitDataDir() {
475
- return process.env.DATA_DIR || join(homedir(), ".orbit");
476
- }
477
-
478
- function startDetachedRun(options) {
479
- const dataDir = orbitDataDir();
480
- mkdirSync(dataDir, { recursive: true });
481
- const logPath = join(dataDir, "orbit-run.log");
482
- const logFd = openSync(logPath, "a");
483
- const cliPath = fileURLToPath(import.meta.url);
484
- const childArgs = [cliPath, "run", "--cwd", resolve(options.cwd)];
485
- if (options.port) childArgs.push("--port", String(options.port));
486
- const child = spawn(process.execPath, childArgs, {
487
- cwd: process.cwd(),
488
- detached: true,
489
- env: { ...process.env },
490
- stdio: ["ignore", logFd, logFd]
491
- });
492
- child.unref();
493
- closeSync(logFd);
494
- const port = options.port || process.env.PORT || 13701;
495
- console.log("Started Orbit in detached mode.");
496
- console.log(`PID: ${child.pid}`);
497
- console.log(`Log: ${logPath}`);
498
- console.log(
499
- options.port || process.env.PORT
500
- ? `URL: http://localhost:${port}`
501
- : `URL: starts at http://localhost:${port} (auto-increments if busy; see log)`
502
- );
503
- }
504
-
505
- function containerPathFor(hostPath, fallbackPath) {
506
- // Linux/macOS Docker can mount the same absolute path into the container,
507
- // which keeps existing Orbit board metadata meaningful. Windows paths are
508
- // not valid Linux container paths, so use stable in-container fallbacks.
509
- return process.platform === "win32" ? fallbackPath : hostPath;
510
- }
511
-
512
- function buildDockerPlan(options) {
513
- const projectRoot = resolve(options.cwd);
514
- const dataDir = resolve(options.dataDir || resolve(projectRoot, ".orbit", "docker-data"));
515
- const containerProjectRoot = containerPathFor(projectRoot, "/workspace");
516
- const containerDataDir = containerPathFor(dataDir, "/data");
517
- const port = String(options.port || process.env.PORT || 13701);
518
-
519
- if (!existsSync(projectRoot)) {
520
- throw new Error(`Project root does not exist: ${projectRoot}`);
521
- }
522
- if (!existsSync(resolve(PACKAGE_ROOT, "Dockerfile"))) {
523
- throw new Error(`Dockerfile not found in Orbit package root: ${PACKAGE_ROOT}`);
524
- }
525
-
526
- const buildArgs = ["build", "-t", options.image, PACKAGE_ROOT];
527
- const runArgs = ["run", "--rm"];
528
- if (options.detach) {
529
- runArgs.push("--detach");
530
- } else if (process.stdin.isTTY && process.stdout.isTTY) {
531
- runArgs.push("-it");
532
- }
533
- if (options.containerName) runArgs.push("--name", options.containerName);
534
- runArgs.push(
535
- "-p",
536
- `${port}:${port}`,
537
- "-e",
538
- `PORT=${port}`,
539
- "-e",
540
- `PROJECT_ROOT=${containerProjectRoot}`,
541
- "-e",
542
- `DATA_DIR=${containerDataDir}`,
543
- "-e",
544
- `SYSTEM_PATH=${projectRoot}`,
545
- "-v",
546
- `${projectRoot}:${containerProjectRoot}`,
547
- "-v",
548
- `${dataDir}:${containerDataDir}`,
549
- "-w",
550
- containerProjectRoot,
551
- options.image,
552
- "run",
553
- "--cwd",
554
- containerProjectRoot,
555
- "--port",
556
- port
557
- );
558
-
559
- return { buildArgs, containerDataDir, containerProjectRoot, dataDir, port, projectRoot, runArgs };
560
- }
561
-
562
- function runDockerCommand(args) {
563
- const result = spawnSync("docker", args, { stdio: "inherit" });
564
- if (result.error) {
565
- throw new Error(`Failed to run docker: ${result.error.message}`);
566
- }
567
- if (result.signal) {
568
- process.exitCode = 1;
569
- return false;
570
- }
571
- if (result.status !== 0) {
572
- process.exitCode = result.status ?? 1;
573
- return false;
574
- }
575
- return true;
576
- }
577
-
578
- async function runDocker(options) {
579
- const plan = buildDockerPlan(options);
580
- const dryRun = options.dryRun || process.env.ORBIT_DOCKER_DRY_RUN === "1";
581
-
582
- if (dryRun) {
583
- console.log(`Project root: ${plan.projectRoot}`);
584
- console.log(`Docker data: ${plan.dataDir}`);
585
- if (options.buildImage) {
586
- console.log(`Docker build:\n ${formatCommand("docker", plan.buildArgs)}`);
587
- }
588
- console.log(`Docker run:\n ${formatCommand("docker", plan.runArgs)}`);
589
- return;
590
- }
591
-
592
- mkdirSync(plan.dataDir, { recursive: true });
593
- if (options.buildImage && !runDockerCommand(plan.buildArgs)) return;
594
- runDockerCommand(plan.runArgs);
595
- }
596
-
597
- async function runMcp(options) {
598
- process.env.PROJECT_ROOT = resolve(options.cwd);
599
- await import("../mcp-server.js");
600
- }
601
-
602
- async function runDispatch(options) {
603
- if (options.help) {
604
- printUsage();
605
- return;
606
- }
607
- process.env.PROJECT_ROOT = resolve(options.cwd);
608
- const { dispatchTicketAsync } = await import("../core/dispatch.js");
609
- const result = await dispatchTicketAsync(options);
610
- if (result.dry_run) {
611
- console.log(`Dry run: would dispatch ticket #${result.ticket.number} ${result.ticket.title}`);
612
- console.log(`Board: ${result.board.slug}`);
613
- console.log(`Profile: ${result.profile}`);
614
- console.log(`Mode: ${result.no_spawn ? "prepare-only" : "spawn"}`);
615
- console.log("No files, worktrees, ticket fields, comments, or agents were changed.");
616
- return;
617
- }
618
- console.log(`Dispatch ${result.spawned ? "started" : "prepared"}: ${result.run_id}`);
619
- console.log(`Board: ${result.board.slug}`);
620
- console.log(`Ticket: #${result.ticket.number} ${result.ticket.title}`);
621
- console.log(`Profile: ${result.profile}`);
622
- console.log(`Policy: ${result.policy}`);
623
- console.log(`Worktree: ${result.worktree_path}`);
624
- if (result.branch) console.log(`Branch: ${result.branch}`);
625
- if (result.run_record_path) console.log(`Run record: ${result.run_record_path}`);
626
- if (result.pid) console.log(`PID: ${result.pid}`);
627
- console.log("AI Plan updated with a terse summary and linked handoff artifact.");
628
- console.log("Run record comment added to the ticket.");
629
- if (result.no_spawn) console.log("No agent spawned; ticket state left unchanged.");
630
- }
631
-
632
- async function main() {
633
- const args = parseArgs(process.argv);
634
- try {
635
- if (args.command === "init") {
636
- await runInit(args);
637
- } else if (args.command === "reset") {
638
- await runReset(args);
639
- } else if (args.command === "run" || args.command === "serve") {
640
- if (args.detachRequested && args.detach) startDetachedRun(args);
641
- else await runServe(args);
642
- } else if (args.command === "docker") {
643
- await runDocker(args);
644
- } else if (args.command === "mcp") {
645
- await runMcp(args);
646
- } else if (args.command === "dispatch") {
647
- await runDispatch(args);
648
- } else if (args.command === "version") {
649
- printVersion();
650
- } else {
651
- printUsage();
652
- process.exitCode = args.command === "help" && !args.invalid ? 0 : 1;
653
- }
654
- } catch (err) {
655
- console.error(err?.message || err);
656
- process.exitCode = 1;
657
- }
9
+ if (process.argv[2] === "mcp") {
10
+ process.stderr.write("Orbit 2.0 starts as `orbit mcp`: this server was added the 1.x way, so re-add it as `orbit mcp` when convenient.\n");
11
+ } else {
12
+ process.stderr.write("Orbit 2.0's command is `orbit`: this path is 1.x's, so call `orbit` instead when convenient.\n");
658
13
  }
659
14
 
660
- await main();
661
- await new Promise((resolvePromise) => process.stdout.write("", resolvePromise));
662
- await new Promise((resolvePromise) => process.stderr.write("", resolvePromise));
15
+ await import("../../lib/cli/orbit.js");