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
package/README.md ADDED
@@ -0,0 +1,607 @@
1
+ # GitSpace CLI
2
+
3
+ A powerful CLI tool for managing GitHub repository workspaces using git worktrees and optional Linear integration. Work on multiple features/tasks simultaneously, each in its own isolated workspace. Features an interactive TUI and support for repo config bundles for team onboarding.
4
+
5
+ ## Features
6
+
7
+ - **Interactive TUI**: Beautiful terminal interface for managing projects and workspaces
8
+ - **Git Worktrees**: Work on multiple branches simultaneously without stashing
9
+ - **Linear Integration**: Create workspaces directly from Linear issues with automatic markdown documentation
10
+ - **Smart Branch Management**: Automatic detection of remote branches
11
+ - **Workspace Status**: Track uncommitted changes, stale workspaces, and more
12
+ - **Custom Scripts**: Convention-based scripts for setup, select, pre-setup, and removal phases
13
+ - **Repo Config Bundles**: Share onboarding configurations with your team, including scripts and setup steps
14
+ - **Secure Secrets**: Store sensitive values in OS keychain via Bun.secrets
15
+
16
+ ## Prerequisites
17
+
18
+ The following tools must be installed and available in your PATH:
19
+
20
+ - [GitHub CLI (`gh`)](https://cli.github.com/) - for listing repositories
21
+ - [Git](https://git-scm.com/) - for worktree management
22
+ - [jq](https://stedolan.github.io/jq/) - for JSON processing
23
+ - [Bun](https://bun.sh) - runtime for the CLI
24
+
25
+ **GitHub Authentication**: You must authenticate the GitHub CLI before using GitSpace:
26
+
27
+ ```bash
28
+ gh auth login
29
+ ```
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ bun install -g https://github.com/inkibra/gitspace.sh
35
+
36
+ # Verify installation
37
+ gssh --version
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ ### Launch the TUI
43
+
44
+ Simply run `gssh` with no arguments to launch the interactive TUI:
45
+
46
+ ```bash
47
+ gssh
48
+ ```
49
+
50
+ The TUI provides a two-panel interface:
51
+ - **Left panel**: Your projects
52
+ - **Right panel**: Workspaces in the selected project
53
+
54
+ **Key Bindings:**
55
+ | Key | Action |
56
+ |-----|--------|
57
+ | `Enter` | Select project / Open workspace |
58
+ | `Tab` | Switch between panels |
59
+ | `n` | New project / workspace |
60
+ | `d` | Delete selected item |
61
+ | `?` | Show help |
62
+ | `q` | Quit |
63
+
64
+ ### CLI Commands
65
+
66
+ You can also use traditional CLI commands:
67
+
68
+ #### 1. Add Your First Project
69
+
70
+ ```bash
71
+ gssh add project
72
+ ```
73
+
74
+ Select a GitHub repository, and GitSpace will:
75
+ - Clone the repository to `~/gitspace/<project-name>/base`
76
+ - Detect the default branch
77
+ - Run onboarding steps if a bundle is present
78
+ - Create project configuration
79
+
80
+ #### 2. Create a Workspace
81
+
82
+ ```bash
83
+ # Create a workspace from a Linear issue (if configured)
84
+ gssh add
85
+
86
+ # Or create a workspace with a custom name
87
+ gssh add my-feature
88
+ ```
89
+
90
+ #### 3. Switch Between Workspaces
91
+
92
+ ```bash
93
+ # Interactive selection
94
+ gssh switch
95
+
96
+ # Switch to a specific workspace
97
+ gssh switch my-feature
98
+ ```
99
+
100
+ ## Repo Config Bundles
101
+
102
+ Repo config bundles allow repository owners to share onboarding configurations with their team. When someone clones a project that contains a bundle, they'll be guided through setup steps and have scripts automatically installed.
103
+
104
+ ### Bundle Structure
105
+
106
+ A bundle is a directory (typically `.gitspace/`) containing:
107
+
108
+ ```
109
+ .gitspace/
110
+ ├── bundle.json # Bundle manifest with onboarding steps
111
+ ├── pre/ # Scripts to run before setup
112
+ │ └── 01-copy-env.sh
113
+ ├── setup/ # Scripts to run on first workspace creation
114
+ │ └── 01-install-deps.sh
115
+ ├── select/ # Scripts to run every time workspace is opened
116
+ │ └── 01-status.sh
117
+ └── remove/ # Scripts to run before workspace deletion
118
+ └── 01-cleanup.sh
119
+ ```
120
+
121
+ ### Bundle Manifest (`bundle.json`)
122
+
123
+ ```json
124
+ {
125
+ "version": "1.0",
126
+ "name": "my-app-bundle",
127
+ "description": "Setup bundle for my-app",
128
+ "onboarding": [
129
+ {
130
+ "id": "welcome",
131
+ "type": "info",
132
+ "title": "Welcome",
133
+ "description": "Let's get you set up!"
134
+ },
135
+ {
136
+ "id": "node",
137
+ "type": "confirm",
138
+ "title": "Node.js",
139
+ "description": "Node.js 18+ is required",
140
+ "checkCommand": "node",
141
+ "installUrl": "https://nodejs.org"
142
+ },
143
+ {
144
+ "id": "api-key",
145
+ "type": "secret",
146
+ "title": "API Key",
147
+ "description": "Enter your API key",
148
+ "configKey": "apiKey"
149
+ },
150
+ {
151
+ "id": "team-name",
152
+ "type": "input",
153
+ "title": "Team Name",
154
+ "description": "Enter your team name",
155
+ "configKey": "teamName",
156
+ "defaultValue": "engineering"
157
+ }
158
+ ]
159
+ }
160
+ ```
161
+
162
+ ### Onboarding Step Types
163
+
164
+ | Type | Purpose | Storage |
165
+ |------|---------|---------|
166
+ | `info` | Display information | N/A |
167
+ | `confirm` | Verify installation (can check command in PATH) | N/A |
168
+ | `secret` | Collect sensitive values (masked input) | OS Keychain |
169
+ | `input` | Collect plain text values | Project config |
170
+
171
+ ### Using Bundle Values in Scripts
172
+
173
+ Bundle values are passed to scripts as environment variables:
174
+
175
+ - `SPACE_VALUE_<KEY>` - Regular values from input steps
176
+ - `SPACE_SECRET_<KEY>` - Secret values from secret steps (fetched from OS keychain)
177
+
178
+ **Example script:**
179
+
180
+ ```bash
181
+ #!/bin/bash
182
+ # .gitspace/select/01-status.sh
183
+
184
+ WORKSPACE_NAME=$1
185
+ REPOSITORY=$2
186
+
187
+ # Access bundle values
188
+ if [ -n "$SPACE_VALUE_TEAMNAME" ]; then
189
+ echo "Welcome, $SPACE_VALUE_TEAMNAME team!"
190
+ fi
191
+
192
+ # Access secrets (stored securely in OS keychain)
193
+ if [ -n "$SPACE_SECRET_APIKEY" ]; then
194
+ echo "API Key configured"
195
+ fi
196
+ ```
197
+
198
+ ### Bundle Sources
199
+
200
+ Bundles can be loaded from:
201
+
202
+ 1. **In-repo** (automatic): `.gitspace/`, `.gitspace-config/`, `.spaces-config/`, or `.spaces/` in the cloned repository
203
+ 2. **Local path**: `gssh add project --bundle-path /path/to/bundle/`
204
+ 3. **Remote URL**: `gssh add project --bundle-url https://example.com/bundle.zip`
205
+
206
+ ## Commands Reference
207
+
208
+ ### `gssh` (TUI)
209
+
210
+ Launch the interactive terminal UI.
211
+
212
+ ### `gssh add project`
213
+
214
+ Add a new project from GitHub.
215
+
216
+ ```bash
217
+ gssh add project [options]
218
+
219
+ Options:
220
+ --bundle-url <url> Load bundle from remote URL (zip archive)
221
+ --bundle-path <path> Load bundle from local directory
222
+ --skip-bundle Skip bundle detection and onboarding
223
+ --no-clone Create project structure without cloning
224
+ --org <org> Filter repos to specific organization
225
+ --linear-key <key> Provide Linear API key via flag
226
+ ```
227
+
228
+ ### `gssh add [workspace-name]`
229
+
230
+ Create a new workspace in the current project.
231
+
232
+ ```bash
233
+ gssh add [workspace-name] [options]
234
+
235
+ Options:
236
+ --branch <name> Specify different branch name from workspace name
237
+ --from <branch> Create from specific branch instead of base
238
+ --no-setup Skip setup commands
239
+ ```
240
+
241
+ ### `gssh switch [workspace-name]`
242
+
243
+ Switch to a workspace in the current project.
244
+
245
+ ```bash
246
+ gssh switch [workspace-name]
247
+ # Alias: gssh sw
248
+ ```
249
+
250
+ ### `gssh switch project [project-name]`
251
+
252
+ Switch to a different project.
253
+
254
+ ### `gssh list [subcommand]`
255
+
256
+ List projects or workspaces.
257
+
258
+ ```bash
259
+ gssh list [subcommand] [options]
260
+ # Alias: gssh ls
261
+
262
+ Subcommands:
263
+ projects List all projects
264
+ workspaces List workspaces in current project (default)
265
+
266
+ Options:
267
+ --json Output in JSON format
268
+ --verbose Show additional details
269
+ ```
270
+
271
+ ### `gssh remove workspace [workspace-name]`
272
+
273
+ Remove a workspace.
274
+
275
+ ```bash
276
+ gssh remove workspace [workspace-name] [options]
277
+ # Alias: gssh rm workspace
278
+
279
+ Options:
280
+ --force Skip confirmation prompts
281
+ --keep-branch Don't delete git branch when removing workspace
282
+ ```
283
+
284
+ ### `gssh remove project [project-name]`
285
+
286
+ Remove a project.
287
+
288
+ ```bash
289
+ gssh remove project [project-name] [options]
290
+ # Alias: gssh rm project
291
+
292
+ Options:
293
+ --force Skip confirmation prompts
294
+ ```
295
+
296
+ ### `gssh directory`
297
+
298
+ Print the current project directory path.
299
+
300
+ ```bash
301
+ gssh directory
302
+ # Alias: gssh dir
303
+ ```
304
+
305
+ ## Configuration
306
+
307
+ ### Global Configuration
308
+
309
+ Located at `~/gitspace/.config.json`:
310
+
311
+ ```json
312
+ {
313
+ "currentProject": "my-app",
314
+ "projectsDir": "/Users/username/gitspace",
315
+ "defaultBaseBranch": "main",
316
+ "staleDays": 30
317
+ }
318
+ ```
319
+
320
+ ### Project Configuration
321
+
322
+ Located at `~/gitspace/<project-name>/.config.json`:
323
+
324
+ ```json
325
+ {
326
+ "name": "my-app",
327
+ "repository": "myorg/my-app",
328
+ "baseBranch": "main",
329
+ "linearApiKey": "lin_api_...",
330
+ "linearTeamKey": "ENG",
331
+ "bundleValues": {
332
+ "teamName": "engineering"
333
+ },
334
+ "bundleSecretKeys": ["apiKey"],
335
+ "appliedBundle": {
336
+ "name": "my-app-bundle",
337
+ "version": "1.0",
338
+ "source": "/path/to/bundle",
339
+ "appliedAt": "2025-01-01T00:00:00Z"
340
+ }
341
+ }
342
+ ```
343
+
344
+ - `bundleValues`: Values collected from input steps during onboarding
345
+ - `bundleSecretKeys`: Keys of secrets stored in OS keychain (values are NOT stored in config)
346
+ - `appliedBundle`: Information about the bundle that was applied
347
+
348
+ ### Custom Scripts
349
+
350
+ GitSpace uses **convention over configuration** for custom scripts:
351
+
352
+ ```
353
+ ~/gitspace/<project-name>/scripts/
354
+ ├── pre/ # Run before setup (terminal)
355
+ ├── setup/ # Run once on workspace creation
356
+ ├── select/ # Run every time workspace is opened
357
+ └── remove/ # Run before workspace deletion
358
+ ```
359
+
360
+ #### Script Execution Rules
361
+
362
+ 1. Scripts must be **executable** (`chmod +x`)
363
+ 2. Scripts run **alphabetically** (use `01-`, `02-` prefixes)
364
+ 3. **Working directory**: The workspace directory
365
+ 4. **Arguments**: `$1` = workspace name, `$2` = repository name
366
+ 5. **Environment**: Bundle values available as `SPACE_VALUE_*` and `SPACE_SECRET_*`
367
+
368
+ #### Script Phases
369
+
370
+ | Phase | When | Use Case |
371
+ |-------|------|----------|
372
+ | `pre/` | Once, before setup | Copy .env files, create directories |
373
+ | `setup/` | Once, on workspace creation | Install dependencies, initial build |
374
+ | `select/` | Every workspace open | Git fetch, status checks |
375
+ | `remove/` | Before deletion | Cleanup, notifications |
376
+
377
+ ### Environment Variables
378
+
379
+ ```bash
380
+ # Set the current project (overrides global config)
381
+ export SPACES_CURRENT_PROJECT="my-app"
382
+
383
+ # Available in scripts (from bundle onboarding):
384
+ # SPACE_VALUE_<KEY> - Regular values
385
+ # SPACE_SECRET_<KEY> - Secret values (from OS keychain)
386
+ ```
387
+
388
+ ## Directory Structure
389
+
390
+ ```
391
+ ~/gitspace/
392
+ ├── .config.json # Global configuration
393
+ ├── <project-name>/
394
+ │ ├── .config.json # Project configuration
395
+ │ ├── base/ # Base repository clone
396
+ │ ├── workspaces/ # Git worktrees
397
+ │ │ └── <workspace-name>/
398
+ │ │ ├── gitspace.lock # Setup completion marker
399
+ │ │ └── .prompt/ # Linear issue details (if applicable)
400
+ │ │ └── issue.md
401
+ │ └── scripts/ # Custom scripts
402
+ │ ├── pre/
403
+ │ ├── setup/
404
+ │ ├── select/
405
+ │ └── remove/
406
+ ```
407
+
408
+ ## Remote Access
409
+
410
+ GitSpace provides secure remote terminal access with **end-to-end encryption**. Access your terminal sessions from anywhere via web browser or CLI.
411
+
412
+ ### gitspace.sh Platform
413
+
414
+ The easiest way to get remote access is through [gitspace.sh](https://gitspace.sh):
415
+
416
+ ```bash
417
+ # 1. Authenticate with GitHub
418
+ gssh auth login
419
+
420
+ # 2. Reserve your subdomain (e.g., yourname.gitspace.sh)
421
+ gssh host reserve yourname
422
+
423
+ # 3. Start serving (creates identity if needed)
424
+ gssh serve
425
+
426
+ # 4. Access from browser at https://yourname.gitspace.sh
427
+ ```
428
+
429
+ ### Self-Hosted Setup
430
+
431
+ For complete control, run your own relay:
432
+
433
+ ```bash
434
+ # Terminal 1: Start relay server
435
+ gssh relay start --port 4480
436
+
437
+ # Terminal 2: Initialize identity and start serving
438
+ gssh identity init --label "My MacBook"
439
+ gssh serve --relay ws://localhost:4480/ws
440
+
441
+ # Terminal 3: Create invite for remote access
442
+ gssh share create
443
+
444
+ # Share the invite URL with collaborators
445
+ ```
446
+
447
+ ### Identity Management
448
+
449
+ Every machine and client has a cryptographic identity (Ed25519 + X25519 keypair):
450
+
451
+ ```bash
452
+ # Create machine identity (stored in ~/gitspace/.identity/)
453
+ gssh identity init --label "My MacBook"
454
+
455
+ # View identity fingerprint
456
+ gssh identity show
457
+ ```
458
+
459
+ ### Access Control
460
+
461
+ Control who can connect to your machine:
462
+
463
+ ```bash
464
+ # List authorized clients
465
+ gssh access list
466
+
467
+ # Add a client by public key
468
+ gssh access add spcs_pk_abc123... --label "Work Laptop"
469
+
470
+ # Remove client access
471
+ gssh access remove spcs_pk_abc123...
472
+ ```
473
+
474
+ ### Creating Invites
475
+
476
+ Share access via signed invite tokens:
477
+
478
+ ```bash
479
+ # Create invite (24h default)
480
+ gssh share create
481
+
482
+ # Custom expiration
483
+ gssh share create --expires 7d
484
+ ```
485
+
486
+ ### Connecting Remotely
487
+
488
+ ```bash
489
+ # Connect using invite token
490
+ gssh connect <invite-token>
491
+
492
+ # Connect via TUI with relay
493
+ gssh --relay wss://relay.example.com
494
+ ```
495
+
496
+ ### Remote Access Commands
497
+
498
+ | Command | Description |
499
+ |---------|-------------|
500
+ | `gssh auth login` | Authenticate with gitspace.sh (GitHub OAuth) |
501
+ | `gssh auth logout` | Sign out of gitspace.sh |
502
+ | `gssh host reserve <name>` | Reserve a subdomain on gitspace.sh |
503
+ | `gssh host status` | Show hosting status |
504
+ | `gssh identity init` | Create machine/client identity |
505
+ | `gssh identity show` | Display identity fingerprint |
506
+ | `gssh access add <key>` | Authorize a client |
507
+ | `gssh access list` | List authorized clients |
508
+ | `gssh access remove <key>` | Revoke client access |
509
+ | `gssh serve` | Start machine daemon |
510
+ | `gssh serve start` | Start serve as background daemon |
511
+ | `gssh serve stop` | Stop background serve daemon |
512
+ | `gssh share create` | Create invite token |
513
+ | `gssh connect <token>` | Connect to remote machine |
514
+ | `gssh status` | Show all daemon statuses |
515
+
516
+ ### Relay Server Commands
517
+
518
+ For self-hosted relay servers:
519
+
520
+ | Command | Description |
521
+ |---------|-------------|
522
+ | `gssh relay start` | Start relay server |
523
+ | `gssh relay authorize <key>` | Authorize a machine |
524
+ | `gssh relay revoke <key>` | Revoke machine authorization |
525
+ | `gssh relay machines` | List registered machines |
526
+ | `gssh relay trusted` | List trusted relays |
527
+ | `gssh relay untrust <url>` | Remove relay trust |
528
+
529
+ ### Terminal Multiplexer (tmux-lite)
530
+
531
+ Manage terminal sessions:
532
+
533
+ | Command | Description |
534
+ |---------|-------------|
535
+ | `gssh tmux start` | Start tmux-lite daemon |
536
+ | `gssh tmux stop` | Stop tmux-lite daemon |
537
+ | `gssh tmux list` | List sessions |
538
+ | `gssh tmux attach <id>` | Attach to session |
539
+ | `gssh tmux new` | Create new session |
540
+ | `gssh tmux kill <id>` | Kill session |
541
+
542
+ ### Environment Variables
543
+
544
+ ```bash
545
+ # Relay server
546
+ RELAY_PORT=4480 # Default relay port
547
+ RELAY_BIND=0.0.0.0 # Bind address
548
+
549
+ # Machine identity
550
+ GSSH_IDENTITY_PATH=~/gitspace/.identity/ # Identity storage
551
+
552
+ # gitspace.sh
553
+ GITSPACE_API_URL=https://api.gitspace.sh # API endpoint
554
+ ```
555
+
556
+ ### Security Model
557
+
558
+ - **E2E Encryption**: All terminal I/O encrypted with AES-256-GCM
559
+ - **X3DH Handshake**: Forward-secret session key establishment
560
+ - **Ed25519 Signatures**: Cryptographic identity verification
561
+ - **Zero-knowledge Relay**: Relay cannot decrypt terminal content
562
+
563
+ See [docs/GETTING-STARTED.md](docs/GETTING-STARTED.md) for detailed setup and [docs/REMOTE-DESIGN.md](docs/REMOTE-DESIGN.md) for architecture.
564
+
565
+ ## Troubleshooting
566
+
567
+ ### GitHub CLI not authenticated
568
+
569
+ ```
570
+ Error: GitHub CLI is not authenticated
571
+ ```
572
+
573
+ **Solution:** Run `gh auth login` and follow the prompts.
574
+
575
+ ### Missing dependencies
576
+
577
+ **Solution:** Install the missing dependencies using the provided URLs in the error message.
578
+
579
+ ### Bundle secrets not available
580
+
581
+ If `SPACE_SECRET_*` variables are empty, ensure:
582
+ 1. You completed the onboarding secret steps
583
+ 2. Your OS keychain service is running (libsecret on Linux, Keychain on macOS)
584
+
585
+ ## Development
586
+
587
+ ```bash
588
+ # Install dependencies
589
+ bun install
590
+
591
+ # Development mode
592
+ bun run dev
593
+
594
+ # Type checking
595
+ bun run typecheck
596
+
597
+ # Run linter
598
+ bun run lint
599
+ ```
600
+
601
+ ## License
602
+
603
+ MIT
604
+
605
+ ## Contributing
606
+
607
+ Contributions are welcome! Please feel free to submit a Pull Request.
package/bin/gssh ADDED
@@ -0,0 +1,62 @@
1
+ #!/bin/sh
2
+ #
3
+ # gssh - GitSpace CLI Launcher
4
+ #
5
+ # Tries to run the compiled binary first, falls back to bun for development.
6
+ #
7
+ # Priority:
8
+ # 1. Compiled binary in dist/gssh-{platform}
9
+ # 2. Platform-specific npm package (@gitspace/darwin-arm64, etc.)
10
+ # 3. Development mode via bun src/index.ts
11
+ #
12
+
13
+ set -e
14
+
15
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
16
+ ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
17
+
18
+ # Get platform identifier
19
+ get_platform() {
20
+ case "$(uname -s)-$(uname -m)" in
21
+ Darwin-arm64) echo "darwin-arm64" ;;
22
+ Darwin-x86_64) echo "darwin-x64" ;;
23
+ Linux-x86_64) echo "linux-x64" ;;
24
+ Linux-aarch64) echo "linux-arm64" ;;
25
+ *) echo "" ;;
26
+ esac
27
+ }
28
+
29
+ PLATFORM=$(get_platform)
30
+
31
+ # 1. Check for local compiled binary (dev builds)
32
+ if [ -n "$PLATFORM" ] && [ -x "$ROOT_DIR/dist/gssh-$PLATFORM" ]; then
33
+ exec "$ROOT_DIR/dist/gssh-$PLATFORM" "$@"
34
+ fi
35
+ if [ -x "$ROOT_DIR/dist/gssh" ]; then
36
+ exec "$ROOT_DIR/dist/gssh" "$@"
37
+ fi
38
+
39
+ # 2. Check for platform-specific npm package
40
+ if [ -n "$PLATFORM" ]; then
41
+ for DIR in \
42
+ "$ROOT_DIR/node_modules/@gitspace/$PLATFORM" \
43
+ "$SCRIPT_DIR/../node_modules/@gitspace/$PLATFORM" \
44
+ "$SCRIPT_DIR/../../@gitspace/$PLATFORM" \
45
+ "$SCRIPT_DIR/../../../@gitspace/$PLATFORM"
46
+ do
47
+ if [ -x "$DIR/bin/gssh" ]; then
48
+ exec "$DIR/bin/gssh" "$@"
49
+ fi
50
+ done
51
+ fi
52
+
53
+ # 3. Fall back to bun for development
54
+ if command -v bun >/dev/null 2>&1; then
55
+ exec bun "$ROOT_DIR/src/index.ts" "$@"
56
+ fi
57
+
58
+ echo "Error: Could not find gssh binary."
59
+ echo ""
60
+ echo "For development, install bun: https://bun.sh"
61
+ echo "For production, ensure @gitspace/$PLATFORM is installed."
62
+ exit 1