@starlove/orbit 1.4.1 → 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.4e6fbe20.js +0 -952
  204. package/dist/full/js/app.4e6fbe20.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 -230
  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/Dockerfile CHANGED
@@ -1,21 +1,23 @@
1
1
  # syntax=docker/dockerfile:1
2
+ # Build the web app and the server first, as npm pack does:
3
+ # node build.mjs --edition=full && npx tsc -p tsconfig.build.json
4
+ # The image installs only Orbit's runtime libraries (package.json dependencies).
2
5
 
3
- FROM node:22-slim AS runtime
6
+ FROM node:24-slim AS runtime
4
7
  WORKDIR /app
5
8
 
6
9
  ENV NODE_ENV=production \
7
10
  PORT=13701 \
8
- DATA_DIR=/data \
9
- ORBIT_USE_DIST=1
11
+ DATA_DIR=/data
10
12
 
11
- COPY package.json ./
12
- COPY SKILL-ORBIT.md ./SKILL-ORBIT.md
13
+ COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
14
+ RUN corepack enable && pnpm install --prod --frozen-lockfile --ignore-scripts
13
15
  COPY docs ./docs
14
- COPY src ./src
16
+ COPY lib ./lib
15
17
  COPY dist/full ./dist/full
16
18
 
17
19
  VOLUME ["/data"]
18
20
  EXPOSE 13701
19
21
 
20
- ENTRYPOINT ["node", "/app/src/cli/orbit.js"]
21
- CMD ["serve", "--cwd", "/workspace"]
22
+ ENTRYPOINT ["node", "/app/lib/cli/orbit.js"]
23
+ CMD ["run"]
package/README.md CHANGED
@@ -2,239 +2,221 @@
2
2
 
3
3
  *Spin up an Orbit to track the motion of your project.*
4
4
 
5
- **Orbit** by ***Starscape*** is a lightweight, kanban-style project management solution for human-agent collaboration.
5
+ **Tell your agent to use Orbit.** Your agent keeps the tickets, plans, and decisions. You get a calm, beautiful board to watch the work move.
6
6
 
7
- Use it when you want the board to live with the code: one SQLite file, one small service, one human UI, and one agent-first API.
7
+ Orbit is a local-first kanban board for people and their AI agents. Boards stand alone; a code repository is optional. Each board has its own SQLite database, and Orbit keeps every board together in one data folder on your computer or your own server. Agents work the board through one small command language, the same in a shell, over MCP and over HTTP; you watch it live in the browser.
8
8
 
9
- - Human UI for creating, editing, and moving tickets kanban-style.
10
- - Agent API/MCP for claiming work, reading context, updating implementation notes, commenting, and writing project memory.
9
+ ## Quick start
11
10
 
12
- ## Screenshots
11
+ Say this to your AI agent (Claude Code, Codex, Cursor, Hermes, or any MCP client):
13
12
 
14
- These screenshots show Orbit in dark and light mode. They were captured before the `AI Ready` lane was added to the board.
13
+ > Install Starscape Orbit and use it to manage this project. Setup: orbit.starscape.app/llms.txt
15
14
 
16
- ![Orbit app in dark mode](docs/SS-Orbit-Dark.png)
17
-
18
- ![Orbit app in light mode](docs/SS-Orbit-Light.png)
19
-
20
- ## 🛰️ Zero external runtime dependencies
21
-
22
- **Orbit's server, CLI, and MCP layer run with zero external runtime dependencies.** They use Node.js built-ins: `node:sqlite`, `node:http`, `node:crypto`, and friends.
23
-
24
- Build-time packages include Starscape's own `@starlove/ui` styling and [`esbuild`](https://esbuild.github.io/) for bundling the web UI. They are not needed by initialized project boards at runtime.
25
-
26
- ## Install and use Orbit
27
-
28
- Install the CLI:
29
-
30
- ```bash
31
- corepack enable
32
- pnpm add -g @starlove/orbit
33
-
34
- # or, from source:
35
- git clone git@github.com:brucestarlove/ss-orbit.git
36
- cd ss-orbit
37
- pnpm install
38
- pnpm run build:bundle
39
- pnpm link --global
40
- ```
41
-
42
- From the repo you want a board for:
15
+ Or do it yourself:
43
16
 
44
17
  ```bash
45
- cd path/to/your-app
46
- orbit init # creates .orbit/board.db + managed SKILL-ORBIT.md + AGENTS.md
47
- orbit init --example # optional: add onboarding example tickets
48
- orbit init --no-ai # optional: create or update the board with AI disabled
18
+ npm i -g @starlove/orbit && orbit run -d # starts Orbit at http://localhost:13701
19
+ claude mcp add --scope user orbit --env ORBIT_AGENT_NAME=claude -- orbit mcp # connect your agent (other apps: Help, Connect your agents)
49
20
  ```
50
21
 
51
- Start one runtime and keep using it:
52
-
53
- ```bash
54
- orbit run # host runtime, uses ~/.orbit, refreshes managed SKILL-ORBIT.md copies
55
- # or
56
- orbit docker # Docker runtime, uses <repo>/.orbit/docker-data
57
- ```
22
+ **For AI agents:** full setup steps for every client, including running Orbit on a private server, are at [orbit.starscape.app/llms.txt](https://orbit.starscape.app/llms.txt). Orbit speaks one small command language everywhere: `orbit view`, `orbit take`, `orbit finish 12 -m "..."` in a shell, or the same lines through the `orbit_read` and `orbit_write` MCP tools. `help` lists them all.
58
23
 
59
- Both runtimes serve from `http://localhost:13701` by default; `orbit run` auto-increments if that port is busy. Use `--port <n>` to force an exact port and `--cwd path/to/repo` to bind a specific repo. Use `orbit run -d` to start the host runtime in the background.
24
+ ![Orbit in dark mode](docs/SS-Orbit-Dark.png)
25
+ ![Orbit in light mode](docs/SS-Orbit-Light.png)
60
26
 
61
- `orbit run` and `orbit docker` run the same app but use different registries by default. A board registered in one mode will not appear in the other unless you share `DATA_DIR`, re-register it, or import a snapshot.
27
+ ## Install and run
62
28
 
63
- For multiple boards, run your chosen runtime once. In another terminal, `cd` into another repo and run `orbit init`; the board joins that runtime's board picker without a restart. `SKILL-ORBIT.md` is Orbit-managed guidance and may be overwritten by `orbit init` or refreshed by `orbit run`; keep repo/team-specific agent rules in `AGENTS.md` or board *Agent Instructions*.
64
-
65
- Docker options:
29
+ Requires **Node.js 22.16 or newer**; 24 is recommended. (Orbit searches with SQLite's full-text search, which Node's own SQLite has from 22.16; `orbit` says so on an older Node.) Orbit supports Node 22 until Node's own security support for it ends, on April 30, 2027; the first Orbit release after that needs Node 24. Node from [nodejs.org](https://nodejs.org) or a version manager starts each `orbit` command about three times faster than Ubuntu's `nodejs` package. Install once, then start Orbit **from any directory**:
66
30
 
67
31
  ```bash
68
- orbit docker # builds starscape-orbit:local, then serves http://localhost:13701
69
- orbit docker --port 13702 # force a different published port
70
- orbit docker --no-build # reuse an existing starscape-orbit:local image
32
+ npm install -g @starlove/orbit
33
+ orbit run
71
34
  ```
72
35
 
73
- `orbit docker` mounts the selected project into the container. Board data still lives in `.orbit/board.db`; Docker-only registry, exports, and backups live under `<repo>/.orbit/docker-data` by default.
74
-
75
- Wipe a single board and start over with `orbit reset` (deletes `.orbit/`, `SKILL-ORBIT.md`, and the registry row), then `orbit init` again. On Windows, close Orbit runtime terminals and restart any AI client using Orbit MCP before deleting or recloning a repo; those helper processes keep SQLite handles open while they are running.
36
+ Open the URL printed in the terminal (normally `http://localhost:13701`). Choose **Create a board** or **Import a board**. Orbit starts with no boards and makes only the ones you choose.
76
37
 
77
- ## Use with AI
38
+ The server listens on **127.0.0.1** by default. `orbit run -d` keeps it running in the background (its log: `orbit-run.log` in the data folder); `--port <n>` chooses an exact port, otherwise Orbit takes the first free port from 13701. Set `DATA_DIR` to choose where boards live, and give the server, the CLI and every MCP server the same value.
78
39
 
79
- Orbit ships with everything an agent needs to claim work, read tickets, and write back implementation notes. New boards have AI collaboration enabled by default; pass `orbit init --no-ai` or turn off **Enable AI** in Settings → AI if you want a human-only board.
40
+ **Coming from Orbit 1.x?** Orbit 2.0 keeps its boards in a new folder, `~/.starscape/orbit`, and doesn't open a 1.x data folder. From any 1.x (1.0 to 1.4) or the 2.0 preview:
80
41
 
81
- 1. **Confirm AI is enabled.** Open Settings (gear icon) → **AI** tab → toggle **Enable AI** if needed. Orbit provisions the `AI Ready`, `In Progress`, and `Review` lanes if they're missing, surfaces the agent-context fields, and reveals the MCP setup snippet.
82
- 2. **Fill in agent context.** Settings → AI → *Agent Instructions* is the project-level briefing every agent reads before touching a ticket. Describe what the project is, who it serves, the stack, and any rules of the road.
83
- 3. **Register the MCP server with your agent.** The AI tab generates copy-pasteable snippets for Claude Code, VS Code, Cursor, Codex, OpenCode, OpenClaw, and other MCP-capable clients — pick your OS + client and paste the command into your agent's MCP config.
84
- 4. **Restart the agent.** On its next boot it discovers the Orbit MCP tools (`board_claim_next`, `board_get_ticket_context`, `board_update_ticket`, etc.).
85
- 5. **Point the agent at a ticket.** From inside the repo, ask the agent to read `SKILL-ORBIT.md` and then work on a ticket via the Orbit MCP — e.g., *"Use the Orbit MCP to claim the next AI-ready card and start work."* It pulls a focused context pack, claims the ticket, and updates the board as it goes.
42
+ 1. Stop the old Orbit and its MCP servers, then `npm i -g @starlove/orbit@2`.
43
+ 2. `orbit migrate` brings every board, card, comment, image and journal entry from `~/.orbit`, boards 1.x kept inside a project included, checks each against the original, and never changes the old folder. Kept your boards somewhere else? `orbit migrate <old folder>`.
44
+ 3. `orbit run`.
45
+ 4. Reconnect your agents with `orbit mcp` (Settings, AI). Setups made by 1.x still start until Orbit 3.0.
46
+ 5. Remove the `SKILL-ORBIT.md` and `AGENTS.md` block 1.x wrote into your projects.
86
47
 
87
- If you initialized with `--example`, ticket #12 (`Try Orbit MCP on this ticket`) is a good first exercise once MCP is connected.
48
+ [Updating](docs/UPDATING.md) has the details, and the steps for a git checkout, a server and Docker. [The changelog](CHANGELOG.md) has what's new.
88
49
 
89
- ### Dispatch a local Hermes run
50
+ **Orbit 1.x stays.** 1.x's server, CLI and MCP run on Node's built-ins alone. It keeps that promise on its own line (`npm i -g @starlove/orbit@1`), and gets its own update after 2.0. Orbit 2.0 takes four runtime libraries, listed below, each for something 1.x wrote by hand.
90
51
 
91
- For a first-class handoff to a named Hermes profile, use `orbit dispatch` instead of writing an ad-hoc prompt file:
52
+ ### From source
92
53
 
93
54
  ```bash
94
- orbit dispatch --board my-app --ticket 12 --profile agent --worktree
95
- orbit dispatch 'http://orbit.example/#/b/my-app/t/<ticket-id>' --profile agent --worktree
96
- orbit dispatch --board my-app --ticket 12 --dry-run # preview only; no writes or spawn
97
- orbit dispatch --board my-app --ticket 12 --no-spawn # prepare handoff/comment; leave lane unchanged
55
+ git clone https://github.com/brucestarlove/ss-orbit.git
56
+ cd ss-orbit
57
+ pnpm install
58
+ npm run build:bundle && npm run build:node # the web app into dist/full, the server into lib/
59
+ node lib/cli/orbit.js run
98
60
  ```
99
61
 
100
- Dispatch validates the board, ticket, blockers, and Hermes availability before mutating a ticket. Normal spawn mode writes the generated handoff as a linked markdown artifact, stores only a terse plan summary in AI Plan, moves the ticket to **In Progress**, optionally preserves a git worktree/branch for review, starts Hermes, and comments a compact run record back onto the card. `--no-spawn` writes the handoff artifact/comment but does not move the ticket to In Progress. The default `agent-safe` policy allows local inspection, edits, tests, and commits while blocking Docker, pushes, deploys, package installs, destructive git commands, and common network/cloud escape hatches.
62
+ Node 24 also runs the TypeScript directly: `node src/cli/orbit.ts run`. `npm run verify` is the check before a change (types, lint, the tests and the contract fixtures); [contributing](CONTRIBUTING.md) has the rest.
101
63
 
102
- `orbit dispatch` supports hosted boards through a full Orbit ticket URL or `--server-url <url> --board <slug> --ticket <id-or-number>`. In remote mode, hosted Orbit is the planning-state source of truth while `--cwd` points at the local code checkout/worktree root. Full operator/user guide: [docs/ORBIT_DISPATCH.md](docs/ORBIT_DISPATCH.md).
64
+ ## How it's built
103
65
 
104
- ## Vocabulary
66
+ Orbit is one core with several doors, over a storage contract any database can implement.
105
67
 
106
- - **Board** — one repo's planning surface. Each board carries its own `agent_instructions`, lanes, tickets, and memory entries.
107
- - **Lane** — a column. Lanes are user-defined and freely named/reordered. The default seed gives you `Backlog`, `Todo`, `AI Ready`, `In Progress`, `Review`, `Done`, `Cancelled`; `AI Ready`, `In Progress`, and `Review` are anchor lanes the agent flow keys off. `AI Ready` is inserted between `Todo` and `In Progress` when AI is enabled.
108
- - **Ticket types**:
109
- - `epic` — index card for a multi-feature initiative. Owns child tickets via `parent_ticket_id`.
110
- - `feature` — a standalone capability or new behavior.
111
- - `task` — a smaller, scoped unit of work.
112
- - `bug` — defect, regression, or broken behavior.
113
- - **Checkpoint** — mid-work human judgment: call `checkpoint` with your question. The ticket moves to `Review`; the `checkpoint` comment marks the blocking fork. Use `complete` when work is finished.
114
- - **Two relationship models** — hierarchy (`parent_ticket_id`, set on the row, only epics own children) is separate from the relations table (`relates_to`, `blocks`, `blocked_by`). The server keeps them disjoint.
115
- - **Blockers** — a per-card `blocked_by` row in the relations table is the single source of truth. If the row exists, the ticket is blocked. Rows are removed two ways: the user deletes the relation manually in the UI, **or** the *blocking* ticket lands in the **Done** lane and the server auto-deletes every relation row that named it as a blocker. (Epic targets expand to their open children — see `GET /api/tickets/:id/blockers`.)
68
+ - **The core** (`src/core/`) holds every rule: boards, cards, lanes, the journal, search, imports and exports. It runs on Node and in a browser alike, and touches storage only through the **storage port** (`src/store/types.ts`), an async interface with a conformance suite every adapter passes.
69
+ - **Three adapters** implement the port: SQLite on a computer or server (`node:sqlite`, a database per board), IndexedDB in the browser, and memory for tests and embedding.
70
+ - **The command language** (`src/commands/`) is what agents speak: `view`, `take`, `finish #12` and the rest, as short text answers built for models. The CLI, the MCP server and `POST /api/cmd` all run it.
71
+ - **The doors:** `orbit run` serves the JSON API and the web app; `orbit mcp` is a stdio MCP server with two tools, `orbit_read` and `orbit_write`; the `orbit` CLI runs commands in a shell. Each works on the data folder directly or, with `ORBIT_MODE=remote`, against a server.
72
+ - **The web app** (`web/`) is React with zustand, built by Vite. The full edition talks to `orbit run`; the browser edition at [orbit.starscape.app/app/](https://orbit.starscape.app/app/) runs the whole core in the page over IndexedDB, offline once loaded.
116
73
 
117
- ## Requirements
74
+ [Architecture](docs/ARCHITECTURE.md) has the map, the contracts and how to write an adapter of your own.
118
75
 
119
- - **Node.js 22.13+**. The server uses the built-in `node:sqlite` module, which is available without an experimental flag starting in 22.13 (or 23.4+). You'll still see an experimental-feature warning on boot — that's expected until the module stabilizes.
120
- - **pnpm 10+ for development**. The repo pins pnpm through `packageManager`; use Corepack (`corepack enable`) to get the right version.
76
+ ### Runtime libraries
121
77
 
122
- Bun is not used as the Orbit runtime because Orbit depends on Node's built-in `node:sqlite` module.
78
+ What `npm install` brings, and what each is for:
123
79
 
124
- ## How it works
80
+ | Library | For |
81
+ | --- | --- |
82
+ | [`hono`](https://hono.dev) | The JSON API's routes. The same app answers `orbit run`'s requests and, in the browser edition, the page's own. |
83
+ | [`@hono/node-server`](https://github.com/honojs/node-server) | Serves that app on Node's HTTP server for `orbit run`. |
84
+ | [`@modelcontextprotocol/server`](https://github.com/modelcontextprotocol/typescript-sdk) | The MCP protocol for `orbit mcp`: the handshake, the tool list and the calls. |
85
+ | [`zod`](https://zod.dev) | Checks an imported board's file before anything is written. Loaded only when an import runs. |
125
86
 
126
- Each repo gets its own board database. Orbit keeps a small central registry that maps repo paths to their board files; the CLI, web app, and MCP server use explicit project roots when provided, then fall back to walking upward to find `.orbit/board.db`.
87
+ React, zustand and the web app's other code are compiled into the bundle Orbit ships (`dist/full`), so they aren't installed at runtime. SQLite is Node's own `node:sqlite`.
127
88
 
128
- - **Per-repo board** — `.orbit/board.db` lives in the repo it tracks. `orbit init` creates it, writes the managed `SKILL-ORBIT.md` at the repo root, and creates/updates `AGENTS.md` with a terse pointer so agents load the full Orbit protocol only when relevant. `orbit run` refreshes managed `SKILL-ORBIT.md` copies for registered repos on startup. Add `--example` to create onboarding cards, or `--no-ai` to disable AI collaboration for the board.
129
- - **Central registry** — `registry.db` records each board's path, slug, and last-active timestamp. Host `orbit run` uses `~/.orbit`; `orbit docker` uses `<repo>/.orbit/docker-data`. Keep one mode unless you intentionally share `DATA_DIR`, re-register boards, or import snapshots.
130
- - **Project-root discovery** — `orbit run`, `orbit mcp`, and MCP-attached agents resolve a board from an explicit `--cwd` / `PROJECT_ROOT` first, then fall back to walking up from process cwd to find `.orbit/board.db`. Persistent MCP configs should use an explicit root so the right board attaches even when the agent launches elsewhere.
131
- - **Two channels for AI** — `AGENTS.md` is the auto-loaded briefing, with an Orbit-managed pointer to `SKILL-ORBIT.md`; the *MCP config* tells the agent runtime how to launch Orbit's MCP server for the right project. The briefing travels with the repo; the MCP registration is per-agent-install.
132
- - **Snapshot-portable** — Settings → Data → Export downloads a `.orbit.json` snapshot, with an option to embed attached images. Import on another install (or in the browser preview at [orbit.starscape.app/app](https://orbit.starscape.app/app)) to restore the same board.
89
+ ## Boards
133
90
 
134
- ## Developing Orbit
135
-
136
- ```bash
137
- pnpm install
138
- pnpm run dev
139
- pnpm test
140
- pnpm run build
141
- ```
91
+ Make a board in **Board → New**, or let a connected agent run `boards new <name>` (`orbit boards new <name>` in a shell). A board's slug is its stable name. Every board lives in Orbit's data folder, whatever folder you or your agent work in.
142
92
 
143
- Open the URL printed by `orbit run` (normally `http://localhost:13701`).
93
+ Orbit never writes files into your repo. Agents learn Orbit from Orbit itself: the MCP instructions, `help`, and the guide. Put a project's rules for agents in the board's Agent Instructions (**Settings → AI**). Delete a board in **Settings → Data**; Orbit backs it up first.
144
94
 
145
- If you want an AI agent to work this board, point it at [SKILL-ORBIT.md](SKILL-ORBIT.md). Agent-facing HTTP/MCP details live in [docs/AGENT_PROTOCOL.md](docs/AGENT_PROTOCOL.md).
95
+ ### Agent use
146
96
 
147
- **Two channels:** MCP config tells your AI app where `mcp-server.js` lives. `SKILL-ORBIT.md` is the repo-local briefing the agent reads before working.
97
+ AI is on by default (**Settings → AI**), where you also write Agent Instructions and copy the setup for your agent's app. Agents work the board through one command language, the same in every client: a shell runs `orbit view`, MCP clients get two tools (`orbit_read`, `orbit_write`) that take the same command lines, and other programs `POST /api/cmd`. Answers are short text built for models: one line per card, cards as `#12`, lanes by name. An agent learns the loop from the server: short instructions on connect, the board's rules and next steps with every card it takes, `help`, and the full guide ([`docs/AGENT_GUIDE.md`](docs/AGENT_GUIDE.md)). Set `ORBIT_AGENT_NAME` so the board shows who did what.
148
98
 
149
- ## Typical Workflow
99
+ Day to day, move a card to **AI Ready** (the agent's `take` picks it up) or say "work on ticket 12" (`take #12`). The agent checks the card has enough context, asks if it doesn't, and hands finished work back in **Review**.
150
100
 
151
- A normal day on a shared board:
101
+ An agent picks a board by its slug. Starting MCP **makes no board**. With one board, commands use it; with several, name one (`view <board>`, `board#12`), let the repo name it (`orbit boards link <board>` writes a one-line `orbit.json` to commit, so every agent in the repo lands on it), or set a default with `orbit boards use <board>` in a terminal (for every folder on this computer) or `ORBIT_BOARD`. Over MCP, `boards use` chooses a board for that session only. See [MCP setup](docs/MCP_SETUP.md) and [the agent protocol](docs/AGENT_PROTOCOL.md).
152
102
 
153
- 1. **Human** creates an epic for a new initiative and fills in card description with the high-level breakdown.
154
- 2. **Human** or **Agent** breaks it into `feature` / `task` / `bug` cards under the epic and moves the workable ones to the `AI Ready` lane.
155
- 3. **Human** directs **Agent** to find a ticket by number or name, or tell it to call `claim-next` to get one from the `AI Ready` column, which gets context for the ticket and important project notes, and starts work. Blocked tickets are skipped automatically.
156
- 4. **Agent** either:
157
- - calls `complete` with a summary and PR link, moving the card to `Review`; or
158
- - calls `checkpoint` with a question if it is blocked mid-flight. Orbit moves the card to `Review` and records a checkpoint comment.
159
- 5. **Human** reviews, merges, and moves the card to the `Done` lane (or sends it back with comments).
103
+ ## Storage, backup, and moving machines
160
104
 
161
- ## MCP
105
+ By default Orbit uses `~/.starscape/orbit` (each Starscape product keeps its own folder under `~/.starscape`), made readable by you alone when Orbit creates it:
162
106
 
163
- Orbit ships a stdio MCP server for agents that prefer tools over raw HTTP. You don't normally start it yourself; your agent runtime spawns it from the snippet in **Settings → AI**. To run it standalone:
164
-
165
- ```bash
166
- orbit mcp
167
- # equivalent: node src/mcp-server.js
107
+ ```text
108
+ DATA_DIR/
109
+ registry.db the boards: ids, slugs, and each board's folder
110
+ boards/<slug>/board.db one SQLite database per board
111
+ boards/<slug>/attachments/ image bytes, beside the database
112
+ boards/<slug>/artifacts/ a card's markdown files (plans, handoffs)
113
+ backups/boards/<board id>/ a copy of a board before it is replaced or deleted, and one a day
114
+ after writes; the newest 30 are kept, each made of:
115
+ <time>-<reason>-<slug>.board.db the database
116
+ <time>-<reason>-<slug>.files/ its attachments/ and artifacts/, beside the database
117
+ <time>-<reason>-<slug>.board.db.json what it holds
118
+ backups/registry/ the same for the list of boards
119
+ exports/ saved exports
168
120
  ```
169
121
 
170
- MCP uses the same registry and board databases when launched with the same `DATA_DIR` and `--cwd` as the web runtime.
122
+ A board keeps its folder when its slug changes, and a new board whose folder name is taken gets `<slug>-2`. The registry names folders, not full paths, so a whole data folder can move.
171
123
 
172
- A copy-editable client config lives at [docs/mcp-client.example.json](docs/mcp-client.example.json). The web app also generates setup snippets from **Settings → AI**. More detail is in [docs/MCP_SETUP.md](docs/MCP_SETUP.md).
124
+ To move boards between machines, choose **Board → Export → Include attached images → Export All** to download a ZIP of `.orbit.json` snapshots. **Settings → Data → Version and updates → Back up all boards** downloads the same ZIP, images included. Import the ZIP on the other machine with **Import a board** on an empty install (or Board → Export → Import boards later). A single `.orbit.json` works too. **Matching slugs replace existing boards**, so take a backup before importing into an Orbit that has boards. Snapshots made without images keep the images' names but not their bytes. After importing, check the board and card counts and a few images.
173
125
 
174
- ### MCP tools
126
+ Orbit's own copies hold a board's database and its images and markdown files together, so a deleted or replaced board comes back whole. A copy's files are hard links to the board's files, so an image that never changes takes no more disk in thirty copies than in one; where links aren't possible (another disk, a file system without them) the files are copied, and the copy's `.json` says which (`how`: linked, copied or mixed). The files folder of a copy goes with its database when old copies are cleaned up. If a copy's files couldn't be kept, Orbit logs it and keeps the database copy anyway. These copies sit on the same disk as the boards: they cover a mistake, not a dead disk. Back up the **whole data folder**, `backups/` and the images included, somewhere else too, and copy it with a tool that keeps hard links (`rsync -aH`, `tar`) or accept that each linked image is stored once per copy. If you change the data folder, give it to the server and MCP alike (`DATA_DIR=/path/to/data orbit run` on Unix; `$env:DATA_DIR='C:\path\to\data'; orbit run` in PowerShell).
175
127
 
128
+ ### Restoring a copy
176
129
 
177
- | Purpose | Tool |
178
- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
179
- | Index | `board_list` (tiny registry), `board_set_active` |
180
- | Board context | `board_context` (settings + journal + deployment; optional board + `include_struck`) |
181
- | Read | `board_read_ticket`, `board_read_comments`, `board_get_ticket_context` (lean), `board_get_ticket_context_full` (manual/journal), `board_get_ticket_relations`, `board_get_ticket_blockers`, `board_search`, `board_list_archive` |
182
- | Agent flow | `board_claim_next`, `board_checkpoint`, `board_complete` |
183
- | Write | `board_update_ticket`, `board_add_comment`, `board_add_board_entry`, `board_archive_ticket`, `board_restore_ticket`, `board_delete_ticket` |
184
- | Admin | `board_export_board`, `board_update_settings` |
130
+ Restoring is putting a copy back, with Orbit stopped (`orbit run`, and any `orbit mcp` or CLI process):
185
131
 
132
+ 1. Open `backups/boards/<board id>/` and pick a copy: `<time>-<reason>-<slug>.board.db`, with a `.files/` folder of the same name beside it.
133
+ 2. Copy the database to the board's folder as `boards/<folder>/board.db` (the folder is the board's own under `boards/`; the slug it was made with, unless that was taken). Delete `board.db-wal` and `board.db-shm` there if they exist.
134
+ 3. Copy what is inside the `.files/` folder (`attachments/` and `artifacts/`) into the same board folder, beside `board.db`. Copy, don't move: the files in the copy stay as they are.
135
+ 4. Start Orbit and open the board.
186
136
 
187
- ## First-Run Seed
137
+ A board that was deleted is also off the list. Orbit copied the list before it deleted the board: put `backups/registry/<time>-pre-board-delete.registry.db` back as `registry.db` (delete `registry.db-wal` and `registry.db-shm`), then do steps 2 and 3 in a new `boards/<folder>/`. That puts the list back as it was then, so first copy the whole data folder, and expect boards made after it to leave the list. To keep them, export them first.
188
138
 
189
- `orbit init` (or first server start in a repo without a board) creates a universal board seed in the new `.orbit/board.db`:
139
+ ## On a server
190
140
 
191
- - **Board**: name from `BOARD_NAME` env var, otherwise inferred from `package.json` `name` or the repo folder name. Slug from `BOARD_SLUG` or derived from the name.
192
- - **Repo metadata**: `REPO_URL` env var or `git config --get remote.origin.url`; `SYSTEM_PATH` env var or the repo path passed to `orbit init`.
193
- - **Default branch**: `DEFAULT_BRANCH` env var, otherwise the current git branch.
194
- - **Lanes (7)**: `Backlog`, `Todo` (default), `AI Ready`, `In Progress`, `Review`, `Done`, `Cancelled`. Pass `--no-ai` to seed without `AI Ready` and leave AI collaboration disabled.
195
- - **Labels (7)**: `human-only`, `needs-human-input`, `needs-decomposition`, `needs-followup`, `tech-debt`, `security`, `onboarding`.
196
- - **Onboarding cards (optional)**: pass `--example` to create an epic `#1` plus children `#2`, `#3`, and `#12 — Try Orbit MCP on this ticket`.
197
- - **Free-form fields**: `project_notes` (Notes tab) and `agent_instructions` (AI tab) get placeholder text you should replace.
141
+ Orbit is one Node process and its data folder, so the simplest reliable way to run it on a VPS is as a system service. Linux's service manager, systemd, starts it at boot, restarts it if it stops, keeps its logs, and locks it down nearly as tightly as a container would.
198
142
 
199
- Set env vars before `orbit init` or first runtime start to skip the placeholders:
143
+ ### As a service (recommended)
200
144
 
201
- ```powershell
202
- $env:BOARD_NAME="My App"; $env:BOARD_SLUG="my-app"; $env:REPO_URL="https://github.com/you/my-app"; orbit init
203
- ```
145
+ As root, with Node installed:
204
146
 
205
- ```bash
206
- BOARD_NAME="My App" BOARD_SLUG=my-app REPO_URL=https://github.com/you/my-app orbit init
147
+ ```sh
148
+ npm install -g @starlove/orbit
149
+ useradd --system --home-dir /var/lib/orbit --shell /usr/sbin/nologin orbit
150
+ command -v orbit # the path for ExecStart below
207
151
  ```
208
152
 
209
- ## Troubleshooting
153
+ Save this as `/etc/systemd/system/orbit.service`, with that path in `ExecStart`:
154
+
155
+ ```ini
156
+ [Unit]
157
+ Description=Starscape Orbit
158
+ After=network-online.target
159
+ Wants=network-online.target
160
+
161
+ [Service]
162
+ User=orbit
163
+ ExecStart=/usr/local/bin/orbit run --port 13701
164
+ Environment=NODE_ENV=production
165
+ Environment=DATA_DIR=/var/lib/orbit
166
+ StateDirectory=orbit
167
+ StateDirectoryMode=0700
168
+ Restart=on-failure
169
+ RestartSec=5
170
+ MemoryMax=512M
171
+ # Locked down: a read-only system, no home folders, no new privileges.
172
+ NoNewPrivileges=yes
173
+ ProtectSystem=strict
174
+ ProtectHome=yes
175
+ PrivateTmp=yes
176
+ PrivateDevices=yes
177
+ ProtectKernelTunables=yes
178
+ ProtectKernelModules=yes
179
+ ProtectKernelLogs=yes
180
+ ProtectControlGroups=yes
181
+ RestrictSUIDSGID=yes
182
+ RestrictNamespaces=yes
183
+ RestrictRealtime=yes
184
+ LockPersonality=yes
185
+ ProtectClock=yes
186
+ ProtectHostname=yes
187
+ ProtectProc=invisible
188
+ CapabilityBoundingSet=
189
+ SystemCallArchitectures=native
190
+ RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
191
+ UMask=0077
192
+
193
+ [Install]
194
+ WantedBy=multi-user.target
195
+ ```
210
196
 
211
- - **UI loads but lanes are blank** — usually a cached `app.js`. Hard-refresh the page (Ctrl+Shift+R) and check the browser console.
212
- - **`node:sqlite` is not a known module** — you're on Node < 22. Upgrade to Node 22+.
213
- - **Windows says `.orbit/board.db` is busy during cleanup** - an Orbit web server, MCP helper, editor, or terminal still has the SQLite file open. Stop the Orbit runtime, close or restart AI clients with Orbit MCP enabled, then retry delete from Settings or run `orbit reset --cwd <repo>` before recloning or deleting the folder.
197
+ Then run `systemctl enable --now orbit` and check it with `curl http://127.0.0.1:13701/api/health`. Its logs are in `journalctl -u orbit`. Boards live in `/var/lib/orbit`: back up that whole folder.
214
198
 
215
- ## Data
199
+ Orbit listens on 127.0.0.1 only. Reach it through a private tunnel, never a public address: `ssh -N -L 13701:127.0.0.1:13701 you@server`, then open `http://localhost:13701`; or, on a tailnet, `tailscale serve --bg --https=13701 http://127.0.0.1:13701` (never Funnel). Agents on the server talk to it over HTTP: `ORBIT_MODE=remote ORBIT_API_URL=http://127.0.0.1:13701 orbit mcp`, or the same variables for the `orbit` command.
216
200
 
217
- Orbit stores each board in the repo it belongs to:
201
+ To update Orbit, run `npm install -g @starlove/orbit@latest`, then `systemctl restart orbit`. Take Node's security releases as they come, the same way you installed Node, then restart the service.
218
202
 
219
- - Board data: `.orbit/board.db`
220
- - Host registry and backups: `~/.orbit` by default
221
- - Docker registry and backups: `<repo>/.orbit/docker-data` by default
203
+ ### Docker (optional)
222
204
 
223
- Override runtime data with:
205
+ Orbit ships a `Dockerfile`, and Starscape's own Orbit runs in a locked-down container. From a source checkout, build the web app and the server first, then the image, and publish it only on **127.0.0.1**, with data kept on the host (`/data` in the container):
224
206
 
225
207
  ```bash
226
- DATA_DIR=/path/to/data orbit run
227
- orbit docker --data-dir /path/to/data
208
+ npm run build:bundle && npm run build:node && docker build --pull -t orbit .
209
+ docker run -d --name orbit --restart unless-stopped -p 127.0.0.1:13701:13701 -e HOST=0.0.0.0 -v ~/orbit-docker-data:/data orbit
228
210
  ```
229
211
 
230
- ```powershell
231
- $env:DATA_DIR="C:\path\to\data"; orbit run
232
- ```
212
+ `HOST=0.0.0.0` lets Docker's port mapping reach the server inside the container; the `127.0.0.1` in `-p` keeps it off your network. Behind a reverse proxy with its own domain, add `-e ORBIT_ALLOWED_HOSTS=orbit.example.com`: Orbit answers only names it knows (IP addresses, `localhost`, full `*.ts.net` names and `HOST`'s), and 421 to the rest, a short tailnet name or a `.local` name included, which go in `ORBIT_ALLOWED_HOSTS` too. Orbit on the host and Orbit in Docker have separate data folders this way; share one only if you understand what two processes on one folder mean for your file system. The image carries its own Node, so rebuild it with `--pull` when Node ships a security release.
213
+
214
+ ### Security
233
215
 
234
- The UI exposes **Export** and **Import** from **Settings → Data**.
216
+ Orbit's HTTP API serves **one trusted person and their agents**; it has no accounts. Keep Orbit's address private, the one agents on other computers use included: Orbit doesn't sign in remote clients, so anyone who reaches it owns your boards. Do **not** put it on a public address, rely on separate SQLite files to keep people apart, or treat a login page in front of it as hosted-service authorization. `HOST=0.0.0.0` deliberately opts into listening on the network; use it only inside a protected network. The API sends no CORS headers and refuses browser requests that come from another site (Fetch Metadata, falling back to `Origin`), so a web page you visit can't read or drive your boards through your browser; that adds to keeping the server private, it doesn't replace it. The app also refuses to be framed by other sites, sends a script policy that runs only its own scripts, and never shows an attachment as a page: images are PNG, JPEG, GIF, WebP or AVIF, and anything else (an SVG a shared board brought) is offered as a download. `orbit run` answers only a browser that reached it by an IP address, `localhost`, a full tailnet name (`*.ts.net`) or the name in `HOST`; any other name goes in `ORBIT_ALLOWED_HOSTS` (comma-separated), or Orbit answers 421: a reverse proxy's own domain, and also a short tailnet name (`http://mybox:13701`), a `.local` name or a name your LAN's DNS gives. That stops a DNS rebinding, where another site's name is pointed at your computer. Agents never see the server's folders, the board's private notes, or comments a person hid from AI. Accounts, board-scoped agent tokens and hosted multi-user Orbit are future work, not part of this setup.
235
217
 
236
- **Export** downloads a portable `.orbit.json` file you can move to another computer or import later. By default it stores image attachment records without image bytes; enable **Include attached images** to embed the images in the snapshot.
218
+ For updates and moving from 1.x, see [updating](docs/UPDATING.md).
237
219
 
238
- **Automatic backups** are separate from Export. Orbit quietly saves local backup copies after you make changes, waiting about two minutes after your last edit so it does not create a file for every click. Orbit also makes an immediate backup before risky actions like deleting a board, resetting Orbit, or replacing a board during import.
220
+ ## License
239
221
 
240
- Backups are stored under the active runtime data dir's `backups/` folder. They are for local recovery; Export is still the easiest way to intentionally save or share a board.
222
+ AGPL-3.0. See [LICENSE](LICENSE).
@@ -0,0 +1 @@
1
+ default-src 'self'; script-src 'self' 'sha256-kLYwoO3pLfw/PQENSuRkD8x0mBkQrv1A5fhVedYez3M=' 'sha256-UmjJBwGq+DKi5mG+H5TrVRzCLdnf+3YwUUV8EK/F77Y='; style-src 'self' 'unsafe-inline'; img-src 'self' blob: data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'
@@ -77,3 +77,8 @@ commercial or otherwise.
77
77
 
78
78
  This isn't legal advice, please consider consulting a lawyer and see the full
79
79
  license for all details.
80
+
81
+ JetBrainsMono-subset.woff2 is the same face (OFL.txt beside it) cut to
82
+ Starscape's subset, the file starscape.biz and Nebula serve: upright, weight
83
+ 400 to 500, Basic Latin, Latin-1 and common punctuation. Orbit's landing sets
84
+ its commands and paths in it.