gitspace 0.2.0-rc.1

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 (318) hide show
  1. package/.claude/settings.local.json +21 -0
  2. package/.gitspace/bundle.json +50 -0
  3. package/.gitspace/select/01-status.sh +40 -0
  4. package/.gitspace/setup/01-install-deps.sh +12 -0
  5. package/.gitspace/setup/02-typecheck.sh +16 -0
  6. package/AGENTS.md +439 -0
  7. package/CLAUDE.md +1 -0
  8. package/LICENSE +25 -0
  9. package/README.md +607 -0
  10. package/bin/gssh +62 -0
  11. package/bun.lock +647 -0
  12. package/docs/CONNECTION.md +623 -0
  13. package/docs/GATEWAY-WORKER.md +319 -0
  14. package/docs/GETTING-STARTED.md +448 -0
  15. package/docs/GITSPACE-PLATFORM.md +1819 -0
  16. package/docs/INFRASTRUCTURE.md +1347 -0
  17. package/docs/PROTOCOL.md +619 -0
  18. package/docs/QUICKSTART.md +174 -0
  19. package/docs/RELAY.md +327 -0
  20. package/docs/REMOTE-DESIGN.md +549 -0
  21. package/docs/ROADMAP.md +564 -0
  22. package/docs/SITE_DOCS_FIGMA_MAKE.md +1167 -0
  23. package/docs/STACK-DESIGN.md +588 -0
  24. package/docs/UNIFIED_ARCHITECTURE.md +292 -0
  25. package/experiments/pty-benchmark.ts +148 -0
  26. package/experiments/pty-latency.ts +100 -0
  27. package/experiments/router/client.ts +199 -0
  28. package/experiments/router/protocol.ts +74 -0
  29. package/experiments/router/router.ts +217 -0
  30. package/experiments/router/session.ts +180 -0
  31. package/experiments/router/test.ts +133 -0
  32. package/experiments/socket-bandwidth.ts +77 -0
  33. package/homebrew/gitspace.rb +45 -0
  34. package/landing-page/ATTRIBUTIONS.md +3 -0
  35. package/landing-page/README.md +11 -0
  36. package/landing-page/bun.lock +801 -0
  37. package/landing-page/guidelines/Guidelines.md +61 -0
  38. package/landing-page/index.html +37 -0
  39. package/landing-page/package.json +90 -0
  40. package/landing-page/postcss.config.mjs +15 -0
  41. package/landing-page/public/_redirects +1 -0
  42. package/landing-page/public/favicon.png +0 -0
  43. package/landing-page/src/app/App.tsx +53 -0
  44. package/landing-page/src/app/components/figma/ImageWithFallback.tsx +27 -0
  45. package/landing-page/src/app/components/ui/accordion.tsx +66 -0
  46. package/landing-page/src/app/components/ui/alert-dialog.tsx +157 -0
  47. package/landing-page/src/app/components/ui/alert.tsx +66 -0
  48. package/landing-page/src/app/components/ui/aspect-ratio.tsx +11 -0
  49. package/landing-page/src/app/components/ui/avatar.tsx +53 -0
  50. package/landing-page/src/app/components/ui/badge.tsx +46 -0
  51. package/landing-page/src/app/components/ui/breadcrumb.tsx +109 -0
  52. package/landing-page/src/app/components/ui/button.tsx +57 -0
  53. package/landing-page/src/app/components/ui/calendar.tsx +75 -0
  54. package/landing-page/src/app/components/ui/card.tsx +92 -0
  55. package/landing-page/src/app/components/ui/carousel.tsx +241 -0
  56. package/landing-page/src/app/components/ui/chart.tsx +353 -0
  57. package/landing-page/src/app/components/ui/checkbox.tsx +32 -0
  58. package/landing-page/src/app/components/ui/collapsible.tsx +33 -0
  59. package/landing-page/src/app/components/ui/command.tsx +177 -0
  60. package/landing-page/src/app/components/ui/context-menu.tsx +252 -0
  61. package/landing-page/src/app/components/ui/dialog.tsx +135 -0
  62. package/landing-page/src/app/components/ui/drawer.tsx +132 -0
  63. package/landing-page/src/app/components/ui/dropdown-menu.tsx +257 -0
  64. package/landing-page/src/app/components/ui/form.tsx +168 -0
  65. package/landing-page/src/app/components/ui/hover-card.tsx +44 -0
  66. package/landing-page/src/app/components/ui/input-otp.tsx +77 -0
  67. package/landing-page/src/app/components/ui/input.tsx +21 -0
  68. package/landing-page/src/app/components/ui/label.tsx +24 -0
  69. package/landing-page/src/app/components/ui/menubar.tsx +276 -0
  70. package/landing-page/src/app/components/ui/navigation-menu.tsx +168 -0
  71. package/landing-page/src/app/components/ui/pagination.tsx +127 -0
  72. package/landing-page/src/app/components/ui/popover.tsx +48 -0
  73. package/landing-page/src/app/components/ui/progress.tsx +31 -0
  74. package/landing-page/src/app/components/ui/radio-group.tsx +45 -0
  75. package/landing-page/src/app/components/ui/resizable.tsx +56 -0
  76. package/landing-page/src/app/components/ui/scroll-area.tsx +58 -0
  77. package/landing-page/src/app/components/ui/select.tsx +189 -0
  78. package/landing-page/src/app/components/ui/separator.tsx +28 -0
  79. package/landing-page/src/app/components/ui/sheet.tsx +139 -0
  80. package/landing-page/src/app/components/ui/sidebar.tsx +726 -0
  81. package/landing-page/src/app/components/ui/skeleton.tsx +13 -0
  82. package/landing-page/src/app/components/ui/slider.tsx +63 -0
  83. package/landing-page/src/app/components/ui/sonner.tsx +25 -0
  84. package/landing-page/src/app/components/ui/switch.tsx +31 -0
  85. package/landing-page/src/app/components/ui/table.tsx +116 -0
  86. package/landing-page/src/app/components/ui/tabs.tsx +66 -0
  87. package/landing-page/src/app/components/ui/textarea.tsx +18 -0
  88. package/landing-page/src/app/components/ui/toggle-group.tsx +73 -0
  89. package/landing-page/src/app/components/ui/toggle.tsx +47 -0
  90. package/landing-page/src/app/components/ui/tooltip.tsx +61 -0
  91. package/landing-page/src/app/components/ui/use-mobile.ts +21 -0
  92. package/landing-page/src/app/components/ui/utils.ts +6 -0
  93. package/landing-page/src/components/docs/DocsContent.tsx +718 -0
  94. package/landing-page/src/components/docs/DocsSidebar.tsx +84 -0
  95. package/landing-page/src/components/landing/CTA.tsx +59 -0
  96. package/landing-page/src/components/landing/Comparison.tsx +84 -0
  97. package/landing-page/src/components/landing/FaultyTerminal.tsx +424 -0
  98. package/landing-page/src/components/landing/Features.tsx +201 -0
  99. package/landing-page/src/components/landing/Hero.tsx +142 -0
  100. package/landing-page/src/components/landing/Pricing.tsx +140 -0
  101. package/landing-page/src/components/landing/Roadmap.tsx +86 -0
  102. package/landing-page/src/components/landing/Security.tsx +81 -0
  103. package/landing-page/src/components/landing/TerminalWindow.tsx +27 -0
  104. package/landing-page/src/components/landing/UseCases.tsx +55 -0
  105. package/landing-page/src/components/landing/Workflow.tsx +101 -0
  106. package/landing-page/src/components/layout/DashboardNavbar.tsx +37 -0
  107. package/landing-page/src/components/layout/Footer.tsx +55 -0
  108. package/landing-page/src/components/layout/LandingNavbar.tsx +82 -0
  109. package/landing-page/src/components/ui/badge.tsx +39 -0
  110. package/landing-page/src/components/ui/breadcrumb.tsx +115 -0
  111. package/landing-page/src/components/ui/button.tsx +57 -0
  112. package/landing-page/src/components/ui/card.tsx +79 -0
  113. package/landing-page/src/components/ui/mock-terminal.tsx +68 -0
  114. package/landing-page/src/components/ui/separator.tsx +28 -0
  115. package/landing-page/src/lib/utils.ts +6 -0
  116. package/landing-page/src/main.tsx +10 -0
  117. package/landing-page/src/pages/Dashboard.tsx +133 -0
  118. package/landing-page/src/pages/DocsPage.tsx +79 -0
  119. package/landing-page/src/pages/LandingPage.tsx +31 -0
  120. package/landing-page/src/pages/TerminalView.tsx +106 -0
  121. package/landing-page/src/styles/fonts.css +0 -0
  122. package/landing-page/src/styles/index.css +3 -0
  123. package/landing-page/src/styles/tailwind.css +4 -0
  124. package/landing-page/src/styles/theme.css +181 -0
  125. package/landing-page/vite.config.ts +19 -0
  126. package/npm/darwin-arm64/bin/gssh +0 -0
  127. package/npm/darwin-arm64/package.json +20 -0
  128. package/package.json +74 -0
  129. package/scripts/build.ts +284 -0
  130. package/scripts/release.ts +140 -0
  131. package/src/__tests__/test-utils.ts +298 -0
  132. package/src/commands/__tests__/serve-messages.test.ts +190 -0
  133. package/src/commands/access.ts +298 -0
  134. package/src/commands/add.ts +452 -0
  135. package/src/commands/auth.ts +364 -0
  136. package/src/commands/connect.ts +287 -0
  137. package/src/commands/directory.ts +16 -0
  138. package/src/commands/host.ts +396 -0
  139. package/src/commands/identity.ts +184 -0
  140. package/src/commands/list.ts +200 -0
  141. package/src/commands/relay.ts +315 -0
  142. package/src/commands/remove.ts +241 -0
  143. package/src/commands/serve.ts +1493 -0
  144. package/src/commands/share.ts +456 -0
  145. package/src/commands/status.ts +125 -0
  146. package/src/commands/switch.ts +353 -0
  147. package/src/commands/tmux.ts +317 -0
  148. package/src/core/__tests__/access.test.ts +240 -0
  149. package/src/core/access.ts +277 -0
  150. package/src/core/bundle.ts +342 -0
  151. package/src/core/config.ts +510 -0
  152. package/src/core/git.ts +317 -0
  153. package/src/core/github.ts +151 -0
  154. package/src/core/identity.ts +631 -0
  155. package/src/core/linear.ts +225 -0
  156. package/src/core/shell.ts +161 -0
  157. package/src/core/trusted-relays.ts +315 -0
  158. package/src/index.ts +821 -0
  159. package/src/lib/remote-session/index.ts +7 -0
  160. package/src/lib/remote-session/protocol.ts +267 -0
  161. package/src/lib/remote-session/session-handler.ts +581 -0
  162. package/src/lib/remote-session/workspace-scanner.ts +167 -0
  163. package/src/lib/tmux-lite/README.md +81 -0
  164. package/src/lib/tmux-lite/cli.ts +796 -0
  165. package/src/lib/tmux-lite/crypto/__tests__/helpers/handshake-runner.ts +349 -0
  166. package/src/lib/tmux-lite/crypto/__tests__/helpers/mock-relay.ts +291 -0
  167. package/src/lib/tmux-lite/crypto/__tests__/helpers/test-identities.ts +142 -0
  168. package/src/lib/tmux-lite/crypto/__tests__/integration/authorization.integration.test.ts +339 -0
  169. package/src/lib/tmux-lite/crypto/__tests__/integration/e2e-communication.integration.test.ts +477 -0
  170. package/src/lib/tmux-lite/crypto/__tests__/integration/error-handling.integration.test.ts +499 -0
  171. package/src/lib/tmux-lite/crypto/__tests__/integration/handshake.integration.test.ts +371 -0
  172. package/src/lib/tmux-lite/crypto/__tests__/integration/security.integration.test.ts +573 -0
  173. package/src/lib/tmux-lite/crypto/access-control.test.ts +512 -0
  174. package/src/lib/tmux-lite/crypto/access-control.ts +320 -0
  175. package/src/lib/tmux-lite/crypto/frames.test.ts +262 -0
  176. package/src/lib/tmux-lite/crypto/frames.ts +141 -0
  177. package/src/lib/tmux-lite/crypto/handshake.ts +894 -0
  178. package/src/lib/tmux-lite/crypto/identity.test.ts +220 -0
  179. package/src/lib/tmux-lite/crypto/identity.ts +286 -0
  180. package/src/lib/tmux-lite/crypto/index.ts +51 -0
  181. package/src/lib/tmux-lite/crypto/invites.test.ts +381 -0
  182. package/src/lib/tmux-lite/crypto/invites.ts +215 -0
  183. package/src/lib/tmux-lite/crypto/keyexchange.ts +435 -0
  184. package/src/lib/tmux-lite/crypto/keys.test.ts +58 -0
  185. package/src/lib/tmux-lite/crypto/keys.ts +47 -0
  186. package/src/lib/tmux-lite/crypto/secretbox.test.ts +169 -0
  187. package/src/lib/tmux-lite/crypto/secretbox.ts +124 -0
  188. package/src/lib/tmux-lite/handshake-handler.ts +451 -0
  189. package/src/lib/tmux-lite/protocol.test.ts +307 -0
  190. package/src/lib/tmux-lite/protocol.ts +266 -0
  191. package/src/lib/tmux-lite/relay-client.ts +506 -0
  192. package/src/lib/tmux-lite/server.ts +1250 -0
  193. package/src/lib/tmux-lite/shell-integration.sh +37 -0
  194. package/src/lib/tmux-lite/terminal-queries.test.ts +54 -0
  195. package/src/lib/tmux-lite/terminal-queries.ts +49 -0
  196. package/src/relay/__tests__/e2e-flow.test.ts +1284 -0
  197. package/src/relay/__tests__/helpers/auth.ts +354 -0
  198. package/src/relay/__tests__/helpers/ports.ts +51 -0
  199. package/src/relay/__tests__/protocol-validation.test.ts +265 -0
  200. package/src/relay/authorization.ts +303 -0
  201. package/src/relay/embedded-assets.generated.d.ts +15 -0
  202. package/src/relay/identity.ts +352 -0
  203. package/src/relay/index.ts +57 -0
  204. package/src/relay/pipes.test.ts +427 -0
  205. package/src/relay/pipes.ts +195 -0
  206. package/src/relay/protocol.ts +804 -0
  207. package/src/relay/registries.test.ts +437 -0
  208. package/src/relay/registries.ts +593 -0
  209. package/src/relay/server.test.ts +1323 -0
  210. package/src/relay/server.ts +1092 -0
  211. package/src/relay/signing.ts +238 -0
  212. package/src/relay/types.ts +69 -0
  213. package/src/serve/client-session-manager.ts +622 -0
  214. package/src/serve/daemon.ts +497 -0
  215. package/src/serve/pty-session.ts +236 -0
  216. package/src/serve/types.ts +169 -0
  217. package/src/shared/components/Flow.tsx +453 -0
  218. package/src/shared/components/Flow.tui.tsx +343 -0
  219. package/src/shared/components/Flow.web.tsx +442 -0
  220. package/src/shared/components/Inbox.tsx +446 -0
  221. package/src/shared/components/Inbox.tui.tsx +262 -0
  222. package/src/shared/components/Inbox.web.tsx +329 -0
  223. package/src/shared/components/MachineList.tsx +187 -0
  224. package/src/shared/components/MachineList.tui.tsx +161 -0
  225. package/src/shared/components/MachineList.web.tsx +210 -0
  226. package/src/shared/components/ProjectList.tsx +176 -0
  227. package/src/shared/components/ProjectList.tui.tsx +109 -0
  228. package/src/shared/components/ProjectList.web.tsx +143 -0
  229. package/src/shared/components/SpacesBrowser.tsx +332 -0
  230. package/src/shared/components/SpacesBrowser.tui.tsx +163 -0
  231. package/src/shared/components/SpacesBrowser.web.tsx +221 -0
  232. package/src/shared/components/index.ts +103 -0
  233. package/src/shared/hooks/index.ts +16 -0
  234. package/src/shared/hooks/useNavigation.ts +226 -0
  235. package/src/shared/index.ts +122 -0
  236. package/src/shared/providers/LocalMachineProvider.ts +425 -0
  237. package/src/shared/providers/MachineProvider.ts +165 -0
  238. package/src/shared/providers/RemoteMachineProvider.ts +444 -0
  239. package/src/shared/providers/index.ts +26 -0
  240. package/src/shared/types.ts +145 -0
  241. package/src/tui/adapters.ts +120 -0
  242. package/src/tui/app.tsx +1816 -0
  243. package/src/tui/components/Terminal.tsx +580 -0
  244. package/src/tui/hooks/index.ts +35 -0
  245. package/src/tui/hooks/useAppState.ts +314 -0
  246. package/src/tui/hooks/useDaemonStatus.ts +174 -0
  247. package/src/tui/hooks/useInboxTUI.ts +113 -0
  248. package/src/tui/hooks/useRemoteMachines.ts +209 -0
  249. package/src/tui/index.ts +24 -0
  250. package/src/tui/state.ts +299 -0
  251. package/src/tui/terminal-bracketed-paste.test.ts +45 -0
  252. package/src/tui/terminal-bracketed-paste.ts +47 -0
  253. package/src/types/bundle.ts +112 -0
  254. package/src/types/config.ts +89 -0
  255. package/src/types/errors.ts +206 -0
  256. package/src/types/identity.ts +284 -0
  257. package/src/types/workspace-fuzzy.ts +49 -0
  258. package/src/types/workspace.ts +151 -0
  259. package/src/utils/bun-socket-writer.ts +80 -0
  260. package/src/utils/deps.ts +127 -0
  261. package/src/utils/fuzzy-match.ts +125 -0
  262. package/src/utils/logger.ts +127 -0
  263. package/src/utils/markdown.ts +254 -0
  264. package/src/utils/onboarding.ts +229 -0
  265. package/src/utils/prompts.ts +114 -0
  266. package/src/utils/run-commands.ts +112 -0
  267. package/src/utils/run-scripts.ts +142 -0
  268. package/src/utils/sanitize.ts +98 -0
  269. package/src/utils/secrets.ts +122 -0
  270. package/src/utils/shell-escape.ts +40 -0
  271. package/src/utils/utf8.ts +79 -0
  272. package/src/utils/workspace-state.ts +47 -0
  273. package/src/web/README.md +73 -0
  274. package/src/web/bun.lock +575 -0
  275. package/src/web/eslint.config.js +23 -0
  276. package/src/web/index.html +16 -0
  277. package/src/web/package.json +37 -0
  278. package/src/web/public/vite.svg +1 -0
  279. package/src/web/src/App.tsx +604 -0
  280. package/src/web/src/assets/react.svg +1 -0
  281. package/src/web/src/components/Terminal.tsx +207 -0
  282. package/src/web/src/hooks/useRelayConnection.ts +224 -0
  283. package/src/web/src/hooks/useTerminal.ts +699 -0
  284. package/src/web/src/index.css +55 -0
  285. package/src/web/src/lib/crypto/__tests__/web-terminal.test.ts +1158 -0
  286. package/src/web/src/lib/crypto/frames.ts +205 -0
  287. package/src/web/src/lib/crypto/handshake.ts +396 -0
  288. package/src/web/src/lib/crypto/identity.ts +128 -0
  289. package/src/web/src/lib/crypto/keyexchange.ts +246 -0
  290. package/src/web/src/lib/crypto/relay-signing.ts +53 -0
  291. package/src/web/src/lib/invite.ts +58 -0
  292. package/src/web/src/lib/storage/identity-store.ts +94 -0
  293. package/src/web/src/main.tsx +10 -0
  294. package/src/web/src/types/identity.ts +45 -0
  295. package/src/web/tsconfig.app.json +28 -0
  296. package/src/web/tsconfig.json +7 -0
  297. package/src/web/tsconfig.node.json +26 -0
  298. package/src/web/vite.config.ts +31 -0
  299. package/todo-security.md +92 -0
  300. package/tsconfig.json +23 -0
  301. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/12b7107e435bf1b9a8713a7f320472a63e543104d633d89a26f8d21f4e4ef182.sqlite +0 -0
  302. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/12b7107e435bf1b9a8713a7f320472a63e543104d633d89a26f8d21f4e4ef182.sqlite-shm +0 -0
  303. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/12b7107e435bf1b9a8713a7f320472a63e543104d633d89a26f8d21f4e4ef182.sqlite-wal +0 -0
  304. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/1a1ac3db1ab86ecf712f90322868a9aabc2c7dc9fe2dfbe94f9b075096276b0f.sqlite +0 -0
  305. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/1a1ac3db1ab86ecf712f90322868a9aabc2c7dc9fe2dfbe94f9b075096276b0f.sqlite-shm +0 -0
  306. package/worker/.wrangler/state/v3/d1/miniflare-D1DatabaseObject/1a1ac3db1ab86ecf712f90322868a9aabc2c7dc9fe2dfbe94f9b075096276b0f.sqlite-wal +0 -0
  307. package/worker/bun.lock +237 -0
  308. package/worker/package.json +22 -0
  309. package/worker/schema.sql +96 -0
  310. package/worker/src/handlers/auth.ts +451 -0
  311. package/worker/src/handlers/subdomains.ts +376 -0
  312. package/worker/src/handlers/user.ts +98 -0
  313. package/worker/src/index.ts +70 -0
  314. package/worker/src/middleware/auth.ts +152 -0
  315. package/worker/src/services/cloudflare.ts +609 -0
  316. package/worker/src/types.ts +96 -0
  317. package/worker/tsconfig.json +15 -0
  318. package/worker/wrangler.toml +26 -0
@@ -0,0 +1,19 @@
1
+ import { defineConfig } from 'vite'
2
+ import path from 'path'
3
+ import tailwindcss from '@tailwindcss/vite'
4
+ import react from '@vitejs/plugin-react'
5
+
6
+ export default defineConfig({
7
+ plugins: [
8
+ // The React and Tailwind plugins are both required for Make, even if
9
+ // Tailwind is not being actively used – do not remove them
10
+ react(),
11
+ tailwindcss(),
12
+ ],
13
+ resolve: {
14
+ alias: {
15
+ // Alias @ to the src directory
16
+ '@': path.resolve(__dirname, './src'),
17
+ },
18
+ },
19
+ })
Binary file
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@gitspace/darwin-arm64",
3
+ "version": "0.2.0-rc.1",
4
+ "description": "GitSpace CLI binary for darwin-arm64",
5
+ "os": [
6
+ "darwin"
7
+ ],
8
+ "cpu": [
9
+ "arm64"
10
+ ],
11
+ "bin": {
12
+ "gssh-darwin-arm64": "bin/gssh"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/inkibra/gitspace.sh.git"
17
+ },
18
+ "homepage": "https://gitspace.sh",
19
+ "license": "SEE LICENSE IN LICENSE"
20
+ }
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "gitspace",
3
+ "version": "0.2.0-rc.1",
4
+ "description": "CLI for managing GitHub workspaces with git worktrees and secure remote terminal access",
5
+ "bin": {
6
+ "gssh": "./bin/gssh"
7
+ },
8
+ "type": "module",
9
+ "scripts": {
10
+ "dev": "bun src/index.ts",
11
+ "typecheck": "tsc --noEmit",
12
+ "lint": "eslint src/",
13
+ "build:web": "cd src/web && bun install && bun run build",
14
+ "build": "bun scripts/build.ts",
15
+ "build:all": "bun scripts/build.ts --all",
16
+ "build:npm": "bun scripts/build.ts --npm",
17
+ "relay": "bun src/relay/index.ts"
18
+ },
19
+ "optionalDependencies": {
20
+ "@gitspace/darwin-arm64": "0.2.0-rc.1",
21
+ "@gitspace/darwin-x64": "0.2.0-rc.1",
22
+ "@gitspace/linux-x64": "0.2.0-rc.1",
23
+ "@gitspace/linux-arm64": "0.2.0-rc.1"
24
+ },
25
+ "keywords": [
26
+ "cli",
27
+ "git",
28
+ "worktree",
29
+ "workspace",
30
+ "terminal",
31
+ "remote",
32
+ "ssh",
33
+ "tui"
34
+ ],
35
+ "homepage": "https://gitspace.sh",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/inkibra/gitspace.sh.git"
39
+ },
40
+ "author": "inKibra, Inc.",
41
+ "license": "SEE LICENSE IN LICENSE",
42
+ "dependencies": {
43
+ "@inquirer/prompts": "^7.2.0",
44
+ "@linear/sdk": "^29.0.0",
45
+ "@noble/curves": "^2.0.1",
46
+ "@noble/hashes": "^2.0.1",
47
+ "@opentui/core": "^0.1.60",
48
+ "@opentui/react": "^0.1.60",
49
+ "@types/ws": "^8.18.1",
50
+ "@xterm/addon-serialize": "^0.13.0",
51
+ "@xterm/headless": "^5.5.0",
52
+ "ansi-escapes": "^7.2.0",
53
+ "chalk": "^5.3.0",
54
+ "commander": "^12.0.0",
55
+ "conf": "^12.0.0",
56
+ "ghostty-opentui": "^1.3.11",
57
+ "open": "^11.0.0",
58
+ "ora": "^8.0.1",
59
+ "react": "^19.2.3",
60
+ "simple-git": "^3.23.0",
61
+ "ws": "^8.18.3"
62
+ },
63
+ "devDependencies": {
64
+ "@types/bun": "^1.3.4",
65
+ "@types/node": "^20.11.20",
66
+ "@types/react": "^19.2.7",
67
+ "@types/react-dom": "^19.2.3",
68
+ "eslint": "^8.57.0",
69
+ "typescript": "^5.3.3"
70
+ },
71
+ "engines": {
72
+ "bun": ">=1.3.5"
73
+ }
74
+ }
@@ -0,0 +1,284 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Build script for creating standalone GitSpace CLI executables
4
+ *
5
+ * This script:
6
+ * 1. Builds the web app (Vite)
7
+ * 2. Generates an embedded assets module that imports all dist files
8
+ * 3. Compiles everything into a single executable
9
+ * 4. Optionally packages for npm distribution
10
+ *
11
+ * Usage:
12
+ * bun scripts/build.ts # Build for current platform
13
+ * bun scripts/build.ts --all # Build for all platforms
14
+ * bun scripts/build.ts --target=linux-x64
15
+ * bun scripts/build.ts --npm # Build + create npm packages
16
+ */
17
+
18
+ import { $ } from "bun";
19
+ import { join } from "path";
20
+ import { Glob } from "bun";
21
+ import { readFileSync, writeFileSync, mkdirSync, copyFileSync, chmodSync } from "fs";
22
+
23
+ const ROOT = join(import.meta.dir, "..");
24
+ const WEB_DIST = join(ROOT, "src/web/dist");
25
+ const EMBEDDED_ASSETS_PATH = join(ROOT, "src/relay/embedded-assets.generated.js");
26
+ const DIST_DIR = join(ROOT, "dist");
27
+ const NPM_DIR = join(ROOT, "npm");
28
+
29
+ // Read version from package.json
30
+ const PKG = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf-8"));
31
+ const VERSION = PKG.version;
32
+
33
+ // Supported targets for cross-compilation
34
+ const TARGETS = {
35
+ "darwin-arm64": "bun-darwin-arm64",
36
+ "darwin-x64": "bun-darwin-x64",
37
+ "linux-x64": "bun-linux-x64",
38
+ "linux-arm64": "bun-linux-arm64",
39
+ // "windows-x64": "bun-windows-x64", // Enable when needed
40
+ } as const;
41
+
42
+ type TargetKey = keyof typeof TARGETS;
43
+
44
+ /** Restore stub file before web build */
45
+ function restoreStub() {
46
+ const stub = `/**
47
+ * STUB FILE - Replaced during build
48
+ * Auto-generated by scripts/build.ts
49
+ */
50
+ export const EMBEDDED_ASSETS = {};
51
+ export function hasEmbeddedAssets() { return false; }
52
+ export function getEmbeddedFile(_) { return null; }
53
+ `;
54
+ writeFileSync(EMBEDDED_ASSETS_PATH, stub);
55
+ }
56
+
57
+ async function buildWeb() {
58
+ console.log("šŸ“¦ Building web app...");
59
+ restoreStub(); // Ensure stub is in place before web build
60
+ await $`cd ${join(ROOT, "src/web")} && bun install && bun run build`;
61
+ console.log("āœ“ Web app built");
62
+ }
63
+
64
+ async function generateEmbeddedAssets() {
65
+ console.log("šŸ”— Generating embedded assets module...");
66
+
67
+ const glob = new Glob("**/*");
68
+ const files: string[] = [];
69
+
70
+ for await (const file of glob.scan({ cwd: WEB_DIST, onlyFiles: true })) {
71
+ files.push(file);
72
+ }
73
+
74
+ // Generate imports for each file with { type: "file" } to embed them
75
+ const imports = files.map((file, i) => {
76
+ return `import file${i} from "../web/dist/${file}" with { type: "file" };`;
77
+ });
78
+
79
+ // Generate the assets map: URL path -> embedded file reference
80
+ const assetEntries = files.map((file, i) => ` "/${file}": file${i},`);
81
+
82
+ // Also map root to index.html
83
+ const indexIdx = files.findIndex(f => f === "index.html");
84
+ if (indexIdx >= 0) {
85
+ assetEntries.push(` "/": file${indexIdx},`);
86
+ }
87
+
88
+ const code = `/**
89
+ * AUTO-GENERATED - DO NOT EDIT
90
+ * Generated by: bun scripts/build.ts
91
+ *
92
+ * Embeds web assets for the compiled executable.
93
+ * Types are provided by embedded-assets.generated.d.ts
94
+ */
95
+
96
+ ${imports.join("\n")}
97
+
98
+ /** URL path -> embedded file path */
99
+ export const EMBEDDED_ASSETS = {
100
+ ${assetEntries.join("\n")}
101
+ };
102
+
103
+ /** True only in compiled binary with embedded files */
104
+ export function hasEmbeddedAssets() {
105
+ return typeof Bun !== "undefined" &&
106
+ Array.isArray(Bun.embeddedFiles) &&
107
+ Bun.embeddedFiles.length > 0;
108
+ }
109
+
110
+ /** Get embedded file blob by URL path */
111
+ export function getEmbeddedFile(urlPath) {
112
+ const assetPath = EMBEDDED_ASSETS[urlPath];
113
+ if (!assetPath) return null;
114
+
115
+ const fileName = String(assetPath).split("/").pop() || "";
116
+ for (const file of Bun.embeddedFiles) {
117
+ if (file.name.endsWith(fileName)) {
118
+ return file;
119
+ }
120
+ }
121
+ return null;
122
+ }
123
+ `;
124
+
125
+ await Bun.write(EMBEDDED_ASSETS_PATH, code);
126
+ console.log(`āœ“ Generated embedded assets (${files.length} files)`);
127
+ }
128
+
129
+ async function compile(target?: TargetKey) {
130
+ const targetFlag = target ? `--target=${TARGETS[target]}` : "";
131
+ const outName = target ? `gssh-${target}` : "gssh";
132
+ const outFile = join(DIST_DIR, outName);
133
+
134
+ console.log(`šŸ”Ø Compiling${target ? ` for ${target}` : ""}...`);
135
+
136
+ await $`mkdir -p ${DIST_DIR}`;
137
+
138
+ const args = [
139
+ "bun", "build",
140
+ "--compile",
141
+ "--minify",
142
+ `--outfile=${outFile}`,
143
+ targetFlag,
144
+ join(ROOT, "src/index.ts"),
145
+ ].filter(Boolean);
146
+
147
+ await $`${args}`;
148
+
149
+ const stat = await Bun.file(outFile).stat();
150
+ const sizeMB = (stat?.size || 0) / 1024 / 1024;
151
+
152
+ console.log(`āœ“ Built ${outFile} (${sizeMB.toFixed(1)} MB)`);
153
+ return outFile;
154
+ }
155
+
156
+ /**
157
+ * Create npm package for a specific platform
158
+ */
159
+ async function createPlatformPackage(target: TargetKey) {
160
+ const pkgName = `@gitspace/${target}`;
161
+ const pkgDir = join(NPM_DIR, target);
162
+ const binDir = join(pkgDir, "bin");
163
+
164
+ console.log(`šŸ“¦ Creating npm package: ${pkgName}`);
165
+
166
+ mkdirSync(binDir, { recursive: true });
167
+
168
+ // Copy binary
169
+ const binaryPath = join(DIST_DIR, `gssh-${target}`);
170
+ const destPath = join(binDir, "gssh");
171
+ copyFileSync(binaryPath, destPath);
172
+ chmodSync(destPath, 0o755);
173
+
174
+ // Create package.json
175
+ const pkg = {
176
+ name: pkgName,
177
+ version: VERSION,
178
+ description: `GitSpace CLI binary for ${target}`,
179
+ os: [target.startsWith("darwin") ? "darwin" : "linux"],
180
+ cpu: [target.endsWith("arm64") ? "arm64" : "x64"],
181
+ bin: {
182
+ [`gssh-${target}`]: "bin/gssh"
183
+ },
184
+ repository: {
185
+ type: "git",
186
+ url: "https://github.com/inkibra/gitspace.sh.git"
187
+ },
188
+ homepage: "https://gitspace.sh",
189
+ license: "SEE LICENSE IN LICENSE"
190
+ };
191
+
192
+ writeFileSync(join(pkgDir, "package.json"), JSON.stringify(pkg, null, 2));
193
+ console.log(`āœ“ Created ${pkgDir}`);
194
+ }
195
+
196
+ /**
197
+ * Update main package.json optionalDependencies versions
198
+ */
199
+ function updateMainPackage() {
200
+ const mainPkgPath = join(ROOT, "package.json");
201
+ const pkg = JSON.parse(readFileSync(mainPkgPath, "utf-8"));
202
+
203
+ // Update optional dependencies versions to match current version
204
+ if (pkg.optionalDependencies) {
205
+ for (const dep of Object.keys(pkg.optionalDependencies)) {
206
+ pkg.optionalDependencies[dep] = VERSION;
207
+ }
208
+ writeFileSync(mainPkgPath, JSON.stringify(pkg, null, 2) + "\n");
209
+ console.log(`āœ“ Updated optionalDependencies to v${VERSION}`);
210
+ }
211
+ }
212
+
213
+ /** Get current platform target key */
214
+ function getCurrentTarget(): TargetKey {
215
+ const platform = process.platform;
216
+ const arch = process.arch;
217
+
218
+ if (platform === "darwin" && arch === "arm64") return "darwin-arm64";
219
+ if (platform === "darwin" && arch === "x64") return "darwin-x64";
220
+ if (platform === "linux" && arch === "x64") return "linux-x64";
221
+ if (platform === "linux" && arch === "arm64") return "linux-arm64";
222
+
223
+ throw new Error(`Unsupported platform: ${platform}-${arch}`);
224
+ }
225
+
226
+ async function main() {
227
+ const args = process.argv.slice(2);
228
+ const buildAll = args.includes("--all");
229
+ const buildNpm = args.includes("--npm");
230
+ const targetArg = args.find(a => a.startsWith("--target="));
231
+ const target = targetArg?.split("=")[1] as TargetKey | undefined;
232
+
233
+ console.log(`šŸš€ GitSpace CLI Build v${VERSION}\n`);
234
+
235
+ await buildWeb();
236
+ await generateEmbeddedAssets();
237
+
238
+ // Determine which targets to build
239
+ let targetsToBuild: TargetKey[];
240
+
241
+ if (buildAll) {
242
+ targetsToBuild = Object.keys(TARGETS) as TargetKey[];
243
+ } else if (target) {
244
+ if (!(target in TARGETS)) {
245
+ console.error(`Unknown target: ${target}`);
246
+ console.error(`Available: ${Object.keys(TARGETS).join(", ")}`);
247
+ process.exit(1);
248
+ }
249
+ targetsToBuild = [target];
250
+ } else {
251
+ // Default: just current platform
252
+ targetsToBuild = [getCurrentTarget()];
253
+ }
254
+
255
+ // Build binaries
256
+ console.log(`\nšŸ“¦ Building for: ${targetsToBuild.join(", ")}...\n`);
257
+ for (const t of targetsToBuild) {
258
+ await compile(t);
259
+ }
260
+
261
+ // Create npm packages if requested
262
+ if (buildNpm) {
263
+ console.log("\nšŸ“¦ Creating npm packages...\n");
264
+ for (const t of targetsToBuild) {
265
+ await createPlatformPackage(t);
266
+ }
267
+ updateMainPackage();
268
+ }
269
+
270
+ console.log("\nāœ… Build complete!");
271
+
272
+ if (buildNpm) {
273
+ console.log("\nšŸ“‹ To publish to npm:");
274
+ console.log(" npm publish # main package (gitspace)");
275
+ for (const t of targetsToBuild) {
276
+ console.log(` cd npm/${t} && npm publish --access public`);
277
+ }
278
+ }
279
+ }
280
+
281
+ main().catch(e => {
282
+ console.error("Build failed:", e);
283
+ process.exit(1);
284
+ });
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Release script for GitSpace CLI
4
+ *
5
+ * Creates release artifacts:
6
+ * - Tarballs for each platform (for GitHub releases / Homebrew)
7
+ * - Updates Homebrew formula with SHA256 hashes
8
+ *
9
+ * Usage:
10
+ * bun scripts/release.ts # Create release artifacts
11
+ * bun scripts/release.ts --upload # Also upload to GitHub (requires gh CLI)
12
+ */
13
+
14
+ import { $ } from "bun";
15
+ import { join } from "path";
16
+ import { readFileSync, writeFileSync, existsSync } from "fs";
17
+ import { createHash } from "crypto";
18
+
19
+ const ROOT = join(import.meta.dir, "..");
20
+ const DIST_DIR = join(ROOT, "dist");
21
+ const RELEASE_DIR = join(ROOT, "release");
22
+ const HOMEBREW_FORMULA = join(ROOT, "homebrew", "gitspace.rb");
23
+
24
+ const PKG = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf-8"));
25
+ const VERSION = PKG.version;
26
+
27
+ const TARGETS = ["darwin-arm64", "darwin-x64", "linux-x64", "linux-arm64"];
28
+
29
+ async function createTarballs(): Promise<Map<string, string>> {
30
+ console.log("šŸ“¦ Creating release tarballs...\n");
31
+
32
+ await $`mkdir -p ${RELEASE_DIR}`;
33
+
34
+ const hashes = new Map<string, string>();
35
+
36
+ for (const target of TARGETS) {
37
+ const binaryPath = join(DIST_DIR, `gssh-${target}`);
38
+
39
+ if (!existsSync(binaryPath)) {
40
+ console.error(`Missing binary: ${binaryPath}`);
41
+ console.error("Run 'bun scripts/build.ts --all' first");
42
+ process.exit(1);
43
+ }
44
+
45
+ const tarballName = `gssh-${target}.tar.gz`;
46
+ const tarballPath = join(RELEASE_DIR, tarballName);
47
+
48
+ // Create tarball with just the binary named "gssh"
49
+ await $`cd ${DIST_DIR} && tar -czf ${tarballPath} -s '/gssh-${target}/gssh/' gssh-${target}`;
50
+
51
+ // Calculate SHA256
52
+ const content = readFileSync(tarballPath);
53
+ const hash = createHash("sha256").update(content).digest("hex");
54
+ hashes.set(target, hash);
55
+
56
+ const sizeMB = content.length / 1024 / 1024;
57
+ console.log(`āœ“ ${tarballName} (${sizeMB.toFixed(1)} MB)`);
58
+ console.log(` SHA256: ${hash}`);
59
+ }
60
+
61
+ return hashes;
62
+ }
63
+
64
+ function updateHomebrewFormula(hashes: Map<string, string>) {
65
+ console.log("\nšŸ“ Updating Homebrew formula...");
66
+
67
+ let formula = readFileSync(HOMEBREW_FORMULA, "utf-8");
68
+
69
+ // Update version
70
+ formula = formula.replace(/version "[^"]+"/g, `version "${VERSION}"`);
71
+
72
+ // Update SHA256 hashes
73
+ for (const [target, hash] of hashes) {
74
+ // Handle commented sha256 lines
75
+ formula = formula.replace(
76
+ new RegExp(`(gssh-${target}\\.tar\\.gz"\\s*\\n\\s*)# sha256 "[^"]*"`, "g"),
77
+ `$1sha256 "${hash}"`
78
+ );
79
+ // Handle existing sha256 lines
80
+ formula = formula.replace(
81
+ new RegExp(`(gssh-${target}\\.tar\\.gz"\\s*\\n\\s*)sha256 "[^"]*"`, "g"),
82
+ `$1sha256 "${hash}"`
83
+ );
84
+ }
85
+
86
+ writeFileSync(HOMEBREW_FORMULA, formula);
87
+ console.log(`āœ“ Updated ${HOMEBREW_FORMULA}`);
88
+ }
89
+
90
+ async function uploadToGitHub() {
91
+ console.log("\nšŸš€ Uploading to GitHub...");
92
+
93
+ const tag = `v${VERSION}`;
94
+
95
+ // Check if release exists
96
+ try {
97
+ await $`gh release view ${tag}`.quiet();
98
+ console.log(`Release ${tag} already exists, uploading assets...`);
99
+ } catch {
100
+ // Create release
101
+ console.log(`Creating release ${tag}...`);
102
+ await $`gh release create ${tag} --title "GitSpace CLI ${tag}" --generate-notes`;
103
+ }
104
+
105
+ // Upload tarballs
106
+ for (const target of TARGETS) {
107
+ const tarball = join(RELEASE_DIR, `gssh-${target}.tar.gz`);
108
+ console.log(`Uploading gssh-${target}.tar.gz...`);
109
+ await $`gh release upload ${tag} ${tarball} --clobber`;
110
+ }
111
+
112
+ console.log(`\nāœ… Release ${tag} published!`);
113
+ console.log(` https://github.com/inkibra/gitspace.sh/releases/tag/${tag}`);
114
+ }
115
+
116
+ async function main() {
117
+ const args = process.argv.slice(2);
118
+ const upload = args.includes("--upload");
119
+
120
+ console.log(`šŸŽ‰ GitSpace CLI Release v${VERSION}\n`);
121
+
122
+ const hashes = await createTarballs();
123
+ updateHomebrewFormula(hashes);
124
+
125
+ if (upload) {
126
+ await uploadToGitHub();
127
+ } else {
128
+ console.log("\nšŸ“‹ To upload to GitHub:");
129
+ console.log(" bun scripts/release.ts --upload");
130
+ console.log("\n Or manually:");
131
+ console.log(` gh release create v${VERSION} release/*.tar.gz`);
132
+ }
133
+
134
+ console.log("\nāœ… Release artifacts ready!");
135
+ }
136
+
137
+ main().catch(e => {
138
+ console.error("Release failed:", e);
139
+ process.exit(1);
140
+ });