orbital-command 0.1.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 (325) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +396 -0
  3. package/bin/orbital.js +362 -0
  4. package/dist/assets/WorkflowVisualizer-BZ21PIIF.js +84 -0
  5. package/dist/assets/WorkflowVisualizer-BZV40eAE.css +1 -0
  6. package/dist/assets/charts-D__PA1zp.js +72 -0
  7. package/dist/assets/index-D1G6i0nS.css +1 -0
  8. package/dist/assets/index-DpItvKpf.js +419 -0
  9. package/dist/assets/ui-BvF022GT.js +53 -0
  10. package/dist/assets/vendor-Dzv9lrRc.js +59 -0
  11. package/dist/index.html +19 -0
  12. package/dist/scanner-sweep.png +0 -0
  13. package/dist/server/server/adapters/index.js +34 -0
  14. package/dist/server/server/adapters/iterm2-adapter.js +29 -0
  15. package/dist/server/server/adapters/subprocess-adapter.js +21 -0
  16. package/dist/server/server/adapters/terminal-adapter.js +1 -0
  17. package/dist/server/server/config.js +156 -0
  18. package/dist/server/server/database.js +90 -0
  19. package/dist/server/server/index.js +372 -0
  20. package/dist/server/server/init.js +811 -0
  21. package/dist/server/server/parsers/event-parser.js +64 -0
  22. package/dist/server/server/parsers/scope-parser.js +188 -0
  23. package/dist/server/server/routes/config-routes.js +163 -0
  24. package/dist/server/server/routes/data-routes.js +461 -0
  25. package/dist/server/server/routes/dispatch-routes.js +215 -0
  26. package/dist/server/server/routes/git-routes.js +92 -0
  27. package/dist/server/server/routes/scope-routes.js +215 -0
  28. package/dist/server/server/routes/sprint-routes.js +116 -0
  29. package/dist/server/server/routes/version-routes.js +130 -0
  30. package/dist/server/server/routes/workflow-routes.js +185 -0
  31. package/dist/server/server/schema.js +90 -0
  32. package/dist/server/server/services/batch-orchestrator.js +253 -0
  33. package/dist/server/server/services/claude-session-service.js +352 -0
  34. package/dist/server/server/services/config-service.js +132 -0
  35. package/dist/server/server/services/deploy-service.js +51 -0
  36. package/dist/server/server/services/event-service.js +63 -0
  37. package/dist/server/server/services/gate-service.js +83 -0
  38. package/dist/server/server/services/git-service.js +309 -0
  39. package/dist/server/server/services/github-service.js +145 -0
  40. package/dist/server/server/services/readiness-service.js +184 -0
  41. package/dist/server/server/services/scope-cache.js +72 -0
  42. package/dist/server/server/services/scope-service.js +424 -0
  43. package/dist/server/server/services/sprint-orchestrator.js +312 -0
  44. package/dist/server/server/services/sprint-service.js +293 -0
  45. package/dist/server/server/services/workflow-service.js +397 -0
  46. package/dist/server/server/utils/cc-hooks-parser.js +49 -0
  47. package/dist/server/server/utils/dispatch-utils.js +305 -0
  48. package/dist/server/server/utils/logger.js +86 -0
  49. package/dist/server/server/utils/terminal-launcher.js +388 -0
  50. package/dist/server/server/utils/worktree-manager.js +98 -0
  51. package/dist/server/server/watchers/event-watcher.js +81 -0
  52. package/dist/server/server/watchers/scope-watcher.js +33 -0
  53. package/dist/server/shared/api-types.js +5 -0
  54. package/dist/server/shared/default-workflow.json +616 -0
  55. package/dist/server/shared/workflow-config.js +44 -0
  56. package/dist/server/shared/workflow-engine.js +353 -0
  57. package/index.html +15 -0
  58. package/package.json +110 -0
  59. package/postcss.config.js +6 -0
  60. package/schemas/orbital.config.schema.json +83 -0
  61. package/scripts/postinstall.js +24 -0
  62. package/scripts/start.sh +20 -0
  63. package/server/adapters/index.ts +41 -0
  64. package/server/adapters/iterm2-adapter.ts +37 -0
  65. package/server/adapters/subprocess-adapter.ts +25 -0
  66. package/server/adapters/terminal-adapter.ts +24 -0
  67. package/server/config.ts +234 -0
  68. package/server/database.ts +107 -0
  69. package/server/index.ts +452 -0
  70. package/server/init.ts +891 -0
  71. package/server/parsers/event-parser.ts +74 -0
  72. package/server/parsers/scope-parser.ts +240 -0
  73. package/server/routes/config-routes.ts +182 -0
  74. package/server/routes/data-routes.ts +548 -0
  75. package/server/routes/dispatch-routes.ts +275 -0
  76. package/server/routes/git-routes.ts +112 -0
  77. package/server/routes/scope-routes.ts +262 -0
  78. package/server/routes/sprint-routes.ts +142 -0
  79. package/server/routes/version-routes.ts +156 -0
  80. package/server/routes/workflow-routes.ts +198 -0
  81. package/server/schema.ts +90 -0
  82. package/server/services/batch-orchestrator.ts +286 -0
  83. package/server/services/claude-session-service.ts +441 -0
  84. package/server/services/config-service.ts +151 -0
  85. package/server/services/deploy-service.ts +98 -0
  86. package/server/services/event-service.ts +98 -0
  87. package/server/services/gate-service.ts +126 -0
  88. package/server/services/git-service.ts +391 -0
  89. package/server/services/github-service.ts +183 -0
  90. package/server/services/readiness-service.ts +250 -0
  91. package/server/services/scope-cache.ts +81 -0
  92. package/server/services/scope-service.ts +476 -0
  93. package/server/services/sprint-orchestrator.ts +361 -0
  94. package/server/services/sprint-service.ts +415 -0
  95. package/server/services/workflow-service.ts +461 -0
  96. package/server/utils/cc-hooks-parser.ts +70 -0
  97. package/server/utils/dispatch-utils.ts +395 -0
  98. package/server/utils/logger.ts +109 -0
  99. package/server/utils/terminal-launcher.ts +462 -0
  100. package/server/utils/worktree-manager.ts +104 -0
  101. package/server/watchers/event-watcher.ts +100 -0
  102. package/server/watchers/scope-watcher.ts +38 -0
  103. package/shared/api-types.ts +20 -0
  104. package/shared/default-workflow.json +616 -0
  105. package/shared/workflow-config.ts +170 -0
  106. package/shared/workflow-engine.ts +427 -0
  107. package/src/App.tsx +33 -0
  108. package/src/components/AgentBadge.tsx +40 -0
  109. package/src/components/BatchPreflightModal.tsx +115 -0
  110. package/src/components/CardDisplayToggle.tsx +74 -0
  111. package/src/components/ColumnHeaderActions.tsx +55 -0
  112. package/src/components/ColumnMenu.tsx +99 -0
  113. package/src/components/DeployHistory.tsx +141 -0
  114. package/src/components/DispatchModal.tsx +164 -0
  115. package/src/components/DispatchPopover.tsx +139 -0
  116. package/src/components/DragOverlay.tsx +25 -0
  117. package/src/components/DriftSidebar.tsx +140 -0
  118. package/src/components/EnvironmentStrip.tsx +88 -0
  119. package/src/components/ErrorBoundary.tsx +62 -0
  120. package/src/components/FilterChip.tsx +105 -0
  121. package/src/components/GateIndicator.tsx +33 -0
  122. package/src/components/IdeaDetailModal.tsx +190 -0
  123. package/src/components/IdeaFormDialog.tsx +113 -0
  124. package/src/components/KanbanColumn.tsx +201 -0
  125. package/src/components/MarkdownRenderer.tsx +114 -0
  126. package/src/components/NeonGrid.tsx +128 -0
  127. package/src/components/PromotionQueue.tsx +89 -0
  128. package/src/components/ScopeCard.tsx +234 -0
  129. package/src/components/ScopeDetailModal.tsx +255 -0
  130. package/src/components/ScopeFilterBar.tsx +152 -0
  131. package/src/components/SearchInput.tsx +102 -0
  132. package/src/components/SessionPanel.tsx +335 -0
  133. package/src/components/SprintContainer.tsx +303 -0
  134. package/src/components/SprintDependencyDialog.tsx +78 -0
  135. package/src/components/SprintPreflightModal.tsx +138 -0
  136. package/src/components/StatusBar.tsx +168 -0
  137. package/src/components/SwimCell.tsx +67 -0
  138. package/src/components/SwimLaneRow.tsx +94 -0
  139. package/src/components/SwimlaneBoardView.tsx +108 -0
  140. package/src/components/VersionBadge.tsx +139 -0
  141. package/src/components/ViewModeSelector.tsx +114 -0
  142. package/src/components/config/AgentChip.tsx +53 -0
  143. package/src/components/config/AgentCreateDialog.tsx +321 -0
  144. package/src/components/config/AgentEditor.tsx +175 -0
  145. package/src/components/config/DirectoryTree.tsx +582 -0
  146. package/src/components/config/FileEditor.tsx +550 -0
  147. package/src/components/config/HookChip.tsx +50 -0
  148. package/src/components/config/StageCard.tsx +198 -0
  149. package/src/components/config/TransitionZone.tsx +173 -0
  150. package/src/components/config/UnifiedWorkflowPipeline.tsx +216 -0
  151. package/src/components/config/WorkflowPipeline.tsx +161 -0
  152. package/src/components/source-control/BranchList.tsx +93 -0
  153. package/src/components/source-control/BranchPanel.tsx +105 -0
  154. package/src/components/source-control/CommitLog.tsx +100 -0
  155. package/src/components/source-control/CommitRow.tsx +47 -0
  156. package/src/components/source-control/GitHubPanel.tsx +110 -0
  157. package/src/components/source-control/GitHubSetupGuide.tsx +52 -0
  158. package/src/components/source-control/GitOverviewBar.tsx +101 -0
  159. package/src/components/source-control/PullRequestList.tsx +69 -0
  160. package/src/components/source-control/WorktreeList.tsx +80 -0
  161. package/src/components/ui/badge.tsx +41 -0
  162. package/src/components/ui/button.tsx +55 -0
  163. package/src/components/ui/card.tsx +78 -0
  164. package/src/components/ui/dialog.tsx +94 -0
  165. package/src/components/ui/popover.tsx +33 -0
  166. package/src/components/ui/scroll-area.tsx +54 -0
  167. package/src/components/ui/separator.tsx +28 -0
  168. package/src/components/ui/tabs.tsx +52 -0
  169. package/src/components/ui/toggle-switch.tsx +35 -0
  170. package/src/components/ui/tooltip.tsx +27 -0
  171. package/src/components/workflow/AddEdgeDialog.tsx +217 -0
  172. package/src/components/workflow/AddListDialog.tsx +201 -0
  173. package/src/components/workflow/ChecklistEditor.tsx +239 -0
  174. package/src/components/workflow/CommandPrefixManager.tsx +118 -0
  175. package/src/components/workflow/ConfigSettingsPanel.tsx +189 -0
  176. package/src/components/workflow/DirectionSelector.tsx +133 -0
  177. package/src/components/workflow/DispatchConfigPanel.tsx +180 -0
  178. package/src/components/workflow/EdgeDetailPanel.tsx +236 -0
  179. package/src/components/workflow/EdgePropertyEditor.tsx +251 -0
  180. package/src/components/workflow/EditToolbar.tsx +138 -0
  181. package/src/components/workflow/HookDetailPanel.tsx +250 -0
  182. package/src/components/workflow/HookExecutionLog.tsx +24 -0
  183. package/src/components/workflow/HookSourceModal.tsx +129 -0
  184. package/src/components/workflow/HooksDashboard.tsx +363 -0
  185. package/src/components/workflow/ListPropertyEditor.tsx +251 -0
  186. package/src/components/workflow/MigrationPreviewDialog.tsx +237 -0
  187. package/src/components/workflow/MovementRulesPanel.tsx +188 -0
  188. package/src/components/workflow/NodeDetailPanel.tsx +245 -0
  189. package/src/components/workflow/PresetSelector.tsx +414 -0
  190. package/src/components/workflow/SkillCommandBuilder.tsx +174 -0
  191. package/src/components/workflow/WorkflowEdgeComponent.tsx +145 -0
  192. package/src/components/workflow/WorkflowNode.tsx +147 -0
  193. package/src/components/workflow/graphLayout.ts +186 -0
  194. package/src/components/workflow/mergeHooks.ts +85 -0
  195. package/src/components/workflow/useEditHistory.ts +88 -0
  196. package/src/components/workflow/useWorkflowEditor.ts +262 -0
  197. package/src/components/workflow/validateConfig.ts +70 -0
  198. package/src/hooks/useActiveDispatches.ts +198 -0
  199. package/src/hooks/useBoardSettings.ts +170 -0
  200. package/src/hooks/useCardDisplay.ts +57 -0
  201. package/src/hooks/useCcHooks.ts +24 -0
  202. package/src/hooks/useConfigTree.ts +51 -0
  203. package/src/hooks/useEnforcementRules.ts +46 -0
  204. package/src/hooks/useEvents.ts +59 -0
  205. package/src/hooks/useFileEditor.ts +165 -0
  206. package/src/hooks/useGates.ts +57 -0
  207. package/src/hooks/useIdeaActions.ts +53 -0
  208. package/src/hooks/useKanbanDnd.ts +410 -0
  209. package/src/hooks/useOrbitalConfig.ts +54 -0
  210. package/src/hooks/usePipeline.ts +47 -0
  211. package/src/hooks/usePipelineData.ts +338 -0
  212. package/src/hooks/useReconnect.ts +25 -0
  213. package/src/hooks/useScopeFilters.ts +125 -0
  214. package/src/hooks/useScopeSessions.ts +44 -0
  215. package/src/hooks/useScopes.ts +67 -0
  216. package/src/hooks/useSearch.ts +67 -0
  217. package/src/hooks/useSettings.tsx +187 -0
  218. package/src/hooks/useSocket.ts +25 -0
  219. package/src/hooks/useSourceControl.ts +105 -0
  220. package/src/hooks/useSprintPreflight.ts +55 -0
  221. package/src/hooks/useSprints.ts +154 -0
  222. package/src/hooks/useStatusBarHighlight.ts +18 -0
  223. package/src/hooks/useSwimlaneBoardSettings.ts +104 -0
  224. package/src/hooks/useTheme.ts +9 -0
  225. package/src/hooks/useTransitionReadiness.ts +53 -0
  226. package/src/hooks/useVersion.ts +155 -0
  227. package/src/hooks/useViolations.ts +65 -0
  228. package/src/hooks/useWorkflow.tsx +125 -0
  229. package/src/hooks/useZoomModifier.ts +19 -0
  230. package/src/index.css +797 -0
  231. package/src/layouts/DashboardLayout.tsx +113 -0
  232. package/src/lib/collisionDetection.ts +20 -0
  233. package/src/lib/scope-fields.ts +61 -0
  234. package/src/lib/swimlane.ts +146 -0
  235. package/src/lib/utils.ts +15 -0
  236. package/src/main.tsx +19 -0
  237. package/src/socket.ts +11 -0
  238. package/src/types/index.ts +497 -0
  239. package/src/views/AgentFeed.tsx +339 -0
  240. package/src/views/DeployPipeline.tsx +59 -0
  241. package/src/views/EnforcementView.tsx +378 -0
  242. package/src/views/PrimitivesConfig.tsx +500 -0
  243. package/src/views/QualityGates.tsx +1012 -0
  244. package/src/views/ScopeBoard.tsx +454 -0
  245. package/src/views/SessionTimeline.tsx +516 -0
  246. package/src/views/Settings.tsx +183 -0
  247. package/src/views/SourceControl.tsx +95 -0
  248. package/src/views/WorkflowVisualizer.tsx +382 -0
  249. package/tailwind.config.js +161 -0
  250. package/templates/agents/AUTO-INVOKE.md +180 -0
  251. package/templates/agents/CONFLICT-RESOLUTION.md +128 -0
  252. package/templates/agents/QUICK-REFERENCE.md +122 -0
  253. package/templates/agents/README.md +188 -0
  254. package/templates/agents/SKILL-TRIGGERS.md +100 -0
  255. package/templates/agents/blue-team/frontend-designer.md +424 -0
  256. package/templates/agents/green-team/architect.md +526 -0
  257. package/templates/agents/green-team/rules-enforcer.md +131 -0
  258. package/templates/agents/red-team/attacker-learned.md +24 -0
  259. package/templates/agents/red-team/attacker.md +486 -0
  260. package/templates/agents/red-team/chaos.md +548 -0
  261. package/templates/agents/reference/component-registry.md +82 -0
  262. package/templates/agents/workflows/full-mode.md +218 -0
  263. package/templates/agents/workflows/quick-mode.md +118 -0
  264. package/templates/agents/workflows/security-mode.md +283 -0
  265. package/templates/anti-patterns/dangerous-shortcuts.md +427 -0
  266. package/templates/config/agent-triggers.json +92 -0
  267. package/templates/hooks/agent-team-gate.sh +31 -0
  268. package/templates/hooks/agent-trigger.sh +97 -0
  269. package/templates/hooks/block-push.sh +66 -0
  270. package/templates/hooks/block-workarounds.sh +61 -0
  271. package/templates/hooks/blocker-check.sh +28 -0
  272. package/templates/hooks/completion-checklist.sh +28 -0
  273. package/templates/hooks/decision-capture.sh +15 -0
  274. package/templates/hooks/dependency-check.sh +27 -0
  275. package/templates/hooks/end-session.sh +31 -0
  276. package/templates/hooks/exploration-logger.sh +37 -0
  277. package/templates/hooks/files-changed-summary.sh +37 -0
  278. package/templates/hooks/get-session-id.sh +49 -0
  279. package/templates/hooks/git-commit-guard.sh +34 -0
  280. package/templates/hooks/init-session.sh +93 -0
  281. package/templates/hooks/orbital-emit.sh +79 -0
  282. package/templates/hooks/orbital-report-deploy.sh +78 -0
  283. package/templates/hooks/orbital-report-gates.sh +40 -0
  284. package/templates/hooks/orbital-report-violation.sh +36 -0
  285. package/templates/hooks/orbital-scope-update.sh +53 -0
  286. package/templates/hooks/phase-verify-reminder.sh +26 -0
  287. package/templates/hooks/review-gate-check.sh +82 -0
  288. package/templates/hooks/scope-commit-logger.sh +37 -0
  289. package/templates/hooks/scope-create-cleanup.sh +36 -0
  290. package/templates/hooks/scope-create-gate.sh +80 -0
  291. package/templates/hooks/scope-create-tracker.sh +17 -0
  292. package/templates/hooks/scope-file-sync.sh +53 -0
  293. package/templates/hooks/scope-gate.sh +35 -0
  294. package/templates/hooks/scope-helpers.sh +188 -0
  295. package/templates/hooks/scope-lifecycle-gate.sh +139 -0
  296. package/templates/hooks/scope-prepare.sh +244 -0
  297. package/templates/hooks/scope-transition.sh +172 -0
  298. package/templates/hooks/session-enforcer.sh +143 -0
  299. package/templates/hooks/time-tracker.sh +33 -0
  300. package/templates/lessons-learned.md +15 -0
  301. package/templates/orbital.config.json +35 -0
  302. package/templates/presets/development.json +42 -0
  303. package/templates/presets/gitflow.json +712 -0
  304. package/templates/presets/minimal.json +23 -0
  305. package/templates/quick/rules.md +218 -0
  306. package/templates/scopes/_template.md +255 -0
  307. package/templates/settings-hooks.json +98 -0
  308. package/templates/skills/git-commit/SKILL.md +85 -0
  309. package/templates/skills/git-dev/SKILL.md +99 -0
  310. package/templates/skills/git-hotfix/SKILL.md +223 -0
  311. package/templates/skills/git-main/SKILL.md +84 -0
  312. package/templates/skills/git-production/SKILL.md +165 -0
  313. package/templates/skills/git-staging/SKILL.md +112 -0
  314. package/templates/skills/scope-create/SKILL.md +81 -0
  315. package/templates/skills/scope-fix-review/SKILL.md +168 -0
  316. package/templates/skills/scope-implement/SKILL.md +110 -0
  317. package/templates/skills/scope-post-review/SKILL.md +144 -0
  318. package/templates/skills/scope-pre-review/SKILL.md +211 -0
  319. package/templates/skills/scope-verify/SKILL.md +201 -0
  320. package/templates/skills/session-init/SKILL.md +62 -0
  321. package/templates/skills/session-resume/SKILL.md +201 -0
  322. package/templates/skills/test-checks/SKILL.md +171 -0
  323. package/templates/skills/test-code-review/SKILL.md +252 -0
  324. package/tsconfig.json +25 -0
  325. package/vite.config.ts +38 -0
package/bin/orbital.js ADDED
@@ -0,0 +1,362 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { spawn, execFileSync } from 'child_process';
6
+ import crypto from 'crypto';
7
+ import { fileURLToPath } from 'url';
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // Paths
11
+ // ---------------------------------------------------------------------------
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+ const PACKAGE_ROOT = path.resolve(__dirname, '..');
15
+
16
+ /**
17
+ * Resolve a package binary (e.g. 'tsx', 'vite') to an absolute path.
18
+ * Checks PACKAGE_ROOT/node_modules/.bin first (global installs, non-hoisted),
19
+ * then the parent node_modules/.bin (hoisted local installs where deps are
20
+ * lifted to <project>/node_modules/.bin/). Returns null to fall back to npx.
21
+ */
22
+ function resolveBin(name) {
23
+ const local = path.join(PACKAGE_ROOT, 'node_modules', '.bin', name);
24
+ if (fs.existsSync(local)) return local;
25
+ const hoisted = path.join(PACKAGE_ROOT, '..', '.bin', name);
26
+ if (fs.existsSync(hoisted)) return path.resolve(hoisted);
27
+ return null;
28
+ }
29
+
30
+ // ---------------------------------------------------------------------------
31
+ // CLI Helpers
32
+ // ---------------------------------------------------------------------------
33
+
34
+ function detectProjectRoot() {
35
+ try {
36
+ return execFileSync('git', ['rev-parse', '--show-toplevel'], { encoding: 'utf8' }).trim();
37
+ } catch {
38
+ return process.cwd();
39
+ }
40
+ }
41
+
42
+ function loadConfig(projectRoot) {
43
+ const configPath = path.join(projectRoot, '.claude', 'orbital.config.json');
44
+ if (fs.existsSync(configPath)) {
45
+ try {
46
+ return JSON.parse(fs.readFileSync(configPath, 'utf8'));
47
+ } catch (err) {
48
+ console.warn(`Warning: could not parse ${configPath}: ${err.message}`);
49
+ }
50
+ }
51
+ return { serverPort: 4444, clientPort: 4445 };
52
+ }
53
+
54
+ function getPackageVersion() {
55
+ try {
56
+ const pkg = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf8'));
57
+ return pkg.version || '0.0.0';
58
+ } catch {
59
+ return '0.0.0';
60
+ }
61
+ }
62
+
63
+ function stampTemplateVersion(projectRoot) {
64
+ const configPath = path.join(projectRoot, '.claude', 'orbital.config.json');
65
+ if (!fs.existsSync(configPath)) return;
66
+
67
+ try {
68
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
69
+ const version = getPackageVersion();
70
+ if (config.templateVersion !== version) {
71
+ config.templateVersion = version;
72
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
73
+ console.log(` Stamped templateVersion: ${version}`);
74
+ }
75
+ } catch { /* ignore malformed config */ }
76
+ }
77
+
78
+ function checkTemplatesStaleness(projectRoot) {
79
+ const configPath = path.join(projectRoot, '.claude', 'orbital.config.json');
80
+ if (!fs.existsSync(configPath)) return;
81
+
82
+ try {
83
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
84
+ const projectVersion = config.templateVersion || null;
85
+ const packageVersion = getPackageVersion();
86
+
87
+ if (projectVersion && projectVersion === packageVersion) return;
88
+
89
+ if (projectVersion) {
90
+ console.log(`\n ⚠ Templates outdated (project: v${projectVersion}, package: v${packageVersion})`);
91
+ } else {
92
+ console.log(`\n ⚠ Templates have no version stamp`);
93
+ }
94
+ console.log(` Run \`orbital update\` to refresh templates.\n`);
95
+ } catch { /* ignore malformed config */ }
96
+ }
97
+
98
+ function openBrowser(url) {
99
+ const platform = process.platform;
100
+ if (platform === 'darwin') {
101
+ spawn('open', [url], { detached: true, stdio: 'ignore' }).unref();
102
+ } else if (platform === 'win32') {
103
+ spawn('cmd', ['/c', 'start', url], { detached: true, stdio: 'ignore' }).unref();
104
+ } else {
105
+ spawn('xdg-open', [url], { detached: true, stdio: 'ignore' }).unref();
106
+ }
107
+ }
108
+
109
+ // ---------------------------------------------------------------------------
110
+ // Shared Module Loader
111
+ // ---------------------------------------------------------------------------
112
+
113
+ /**
114
+ * Load the shared init module. Tries compiled JS first (production/global
115
+ * installs via npm publish), then TypeScript source (dev via tsx).
116
+ */
117
+ async function loadSharedModule() {
118
+ try {
119
+ // Production: compiled JS (tsconfig.server.json outputs to dist/server/server/)
120
+ return await import('../dist/server/server/init.js');
121
+ } catch {
122
+ try {
123
+ // Dev: TypeScript source loaded via tsx
124
+ return await import('../server/init.js');
125
+ } catch {
126
+ console.error('Error: Orbital Command server module not found.');
127
+ console.error('Try reinstalling: npm install -g orbital-command');
128
+ console.error('For local development: npm run build:server');
129
+ process.exit(1);
130
+ }
131
+ }
132
+ }
133
+
134
+ // ---------------------------------------------------------------------------
135
+ // Commands
136
+ // ---------------------------------------------------------------------------
137
+
138
+ async function cmdInit(args) {
139
+ const force = args.includes('--force');
140
+ const projectRoot = detectProjectRoot();
141
+
142
+ const { runInit } = await loadSharedModule();
143
+ runInit(projectRoot, { force });
144
+
145
+ stampTemplateVersion(projectRoot);
146
+ console.log(`Run \`orbital dev\` to start the development server.\n`);
147
+ }
148
+
149
+ function cmdDev() {
150
+ const shouldOpen = process.argv.includes('--open');
151
+ const projectRoot = detectProjectRoot();
152
+ const config = loadConfig(projectRoot);
153
+ const serverPort = config.serverPort || 4444;
154
+ const clientPort = config.clientPort || 4445;
155
+
156
+ console.log(`\nOrbital Command — dev`);
157
+ console.log(`Project root: ${projectRoot}`);
158
+ console.log(`Server: http://localhost:${serverPort}`);
159
+ console.log(`Client: http://localhost:${clientPort}\n`);
160
+
161
+ checkTemplatesStaleness(projectRoot);
162
+
163
+ const env = {
164
+ ...process.env,
165
+ ORBITAL_PROJECT_ROOT: projectRoot,
166
+ ORBITAL_SERVER_PORT: String(serverPort),
167
+ };
168
+
169
+ // Start the API server
170
+ const tsxBin = resolveBin('tsx');
171
+ const serverProcess = tsxBin
172
+ ? spawn(tsxBin, ['watch', path.join(PACKAGE_ROOT, 'server', 'index.ts')],
173
+ { stdio: 'inherit', env, cwd: PACKAGE_ROOT })
174
+ : spawn('npx', ['tsx', 'watch', path.join(PACKAGE_ROOT, 'server', 'index.ts')],
175
+ { stdio: 'inherit', env, cwd: PACKAGE_ROOT });
176
+
177
+ // Start the Vite dev server
178
+ const viteBin = resolveBin('vite');
179
+ const viteProcess = viteBin
180
+ ? spawn(viteBin, ['--config', path.join(PACKAGE_ROOT, 'vite.config.ts'), '--port', String(clientPort)],
181
+ { stdio: 'inherit', env, cwd: PACKAGE_ROOT })
182
+ : spawn('npx', ['vite', '--config', path.join(PACKAGE_ROOT, 'vite.config.ts'), '--port', String(clientPort)],
183
+ { stdio: 'inherit', env, cwd: PACKAGE_ROOT });
184
+
185
+ if (shouldOpen) {
186
+ setTimeout(() => openBrowser(`http://localhost:${clientPort}`), 2000);
187
+ }
188
+
189
+ let exiting = false;
190
+
191
+ function cleanup() {
192
+ if (exiting) return;
193
+ exiting = true;
194
+ serverProcess.kill();
195
+ viteProcess.kill();
196
+ process.exit(0);
197
+ }
198
+ process.on('SIGINT', cleanup);
199
+ process.on('SIGTERM', cleanup);
200
+
201
+ serverProcess.on('exit', (code) => {
202
+ if (exiting) return;
203
+ exiting = true;
204
+ console.log(`Server exited with code ${code}`);
205
+ viteProcess.kill();
206
+ process.exit(code || 0);
207
+ });
208
+ viteProcess.on('exit', (code) => {
209
+ if (exiting) return;
210
+ exiting = true;
211
+ console.log(`Vite exited with code ${code}`);
212
+ serverProcess.kill();
213
+ process.exit(code || 0);
214
+ });
215
+ }
216
+
217
+ function cmdBuild() {
218
+ console.log(`\nOrbital Command — build\n`);
219
+
220
+ const viteBin = resolveBin('vite');
221
+ const buildProcess = viteBin
222
+ ? spawn(viteBin, ['build', '--config', path.join(PACKAGE_ROOT, 'vite.config.ts')],
223
+ { stdio: 'inherit', cwd: PACKAGE_ROOT })
224
+ : spawn('npx', ['vite', 'build', '--config', path.join(PACKAGE_ROOT, 'vite.config.ts')],
225
+ { stdio: 'inherit', cwd: PACKAGE_ROOT });
226
+
227
+ buildProcess.on('exit', (code) => {
228
+ process.exit(code || 0);
229
+ });
230
+ }
231
+
232
+ function cmdEmit(args) {
233
+ const type = args[0];
234
+ const jsonStr = args.slice(1).join(' ');
235
+
236
+ if (!type) {
237
+ console.error('Usage: orbital emit <TYPE> <JSON>');
238
+ process.exit(1);
239
+ }
240
+
241
+ const projectRoot = detectProjectRoot();
242
+ const eventsDir = path.join(projectRoot, '.claude', 'orbital-events');
243
+ if (!fs.existsSync(eventsDir)) fs.mkdirSync(eventsDir, { recursive: true });
244
+
245
+ let payload;
246
+ try {
247
+ payload = jsonStr ? JSON.parse(jsonStr) : {};
248
+ } catch (err) {
249
+ console.error(`Invalid JSON: ${err.message}`);
250
+ process.exit(1);
251
+ }
252
+
253
+ const eventId = crypto.randomUUID();
254
+ const event = {
255
+ ...payload,
256
+ id: eventId,
257
+ type,
258
+ timestamp: new Date().toISOString(),
259
+ };
260
+
261
+ const filePath = path.join(eventsDir, `${eventId}.json`);
262
+ fs.writeFileSync(filePath, JSON.stringify(event, null, 2) + '\n', 'utf8');
263
+
264
+ console.log(`Event emitted: ${type} (${eventId})`);
265
+ console.log(` File: ${path.relative(projectRoot, filePath)}`);
266
+ }
267
+
268
+ async function cmdUpdate() {
269
+ const projectRoot = detectProjectRoot();
270
+
271
+ const { runUpdate } = await loadSharedModule();
272
+ runUpdate(projectRoot);
273
+
274
+ stampTemplateVersion(projectRoot);
275
+ }
276
+
277
+ async function cmdUninstall() {
278
+ const projectRoot = detectProjectRoot();
279
+
280
+ const { runUninstall } = await loadSharedModule();
281
+ runUninstall(projectRoot);
282
+ }
283
+
284
+ function printHelp() {
285
+ console.log(`
286
+ Orbital Command — CLI for the agentic project management system
287
+
288
+ Usage:
289
+ orbital <command> [options]
290
+
291
+ Commands:
292
+ init Scaffold Orbital Command into the current project
293
+ dev Start the development server (API + Vite)
294
+ build Production build of the dashboard
295
+ emit <TYPE> <JSON> Emit an orbital event
296
+ update Re-copy hooks/skills/agents from package templates
297
+ uninstall Remove Orbital artifacts from the project
298
+
299
+ Init Options:
300
+ --force Overwrite existing hooks, skills, and agents
301
+ --skip-plugins Skip plugin installation
302
+ --yes, -y Auto-accept all prompts
303
+
304
+ Dev Options:
305
+ --open Open the dashboard in the default browser
306
+
307
+ Examples:
308
+ orbital init
309
+ orbital init --force
310
+ orbital dev
311
+ orbital dev --open
312
+ orbital emit SCOPE_TRANSITION '{"scope":"042","from":"implementing","to":"review"}'
313
+ orbital update
314
+ orbital uninstall
315
+ `);
316
+ }
317
+
318
+ // ---------------------------------------------------------------------------
319
+ // Main
320
+ // ---------------------------------------------------------------------------
321
+
322
+ const [command, ...args] = process.argv.slice(2);
323
+
324
+ async function main() {
325
+ switch (command) {
326
+ case 'init':
327
+ await cmdInit(args);
328
+ break;
329
+ case 'dev':
330
+ cmdDev();
331
+ break;
332
+ case 'build':
333
+ cmdBuild();
334
+ break;
335
+ case 'emit':
336
+ cmdEmit(args);
337
+ break;
338
+ case 'update':
339
+ await cmdUpdate();
340
+ break;
341
+ case 'uninstall':
342
+ await cmdUninstall();
343
+ break;
344
+ case 'help':
345
+ case '--help':
346
+ case '-h':
347
+ printHelp();
348
+ break;
349
+ case undefined:
350
+ printHelp();
351
+ break;
352
+ default:
353
+ console.error(`Unknown command: ${command}`);
354
+ printHelp();
355
+ process.exit(1);
356
+ }
357
+ }
358
+
359
+ main().catch((err) => {
360
+ console.error(`Error: ${err.message}`);
361
+ process.exit(1);
362
+ });