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,1167 @@
1
+ You are Figma Make editing the gitspace.sh documentation site:
2
+
3
+ You do NOT have access to our codebase. Use ONLY the factual specification below (it is copied from the repo and must be treated as truth). Update the site copy to match it exactly.
4
+
5
+ Hard constraints:
6
+ - Preserve the existing design system, spacing, typography, and components.
7
+ - Preserve existing navigation/anchors as much as possible. If the docs are a single page, keep it single-page but add a TOC at the top with anchor links.
8
+ - Replace any incorrect commands/flags/URLs with the exact ones below.
9
+ - Do not invent commands, flags, defaults, URLs, or security guarantees.
10
+ - Security claims must match "Security notes / current limitations" below (do not overpromise).
11
+
12
+ ============================================================
13
+ A) PRODUCT FACTS (from the repo)
14
+ ============================================================
15
+
16
+ Product name: GitSpace CLI
17
+ Binary: `gssh`
18
+
19
+ What it is:
20
+ - A CLI tool for managing GitHub repository workspaces using git worktrees, with an interactive TUI.
21
+ - Optional Linear integration for workspace creation.
22
+ - Supports repo config bundles for onboarding + convention-based scripts.
23
+ - Secure remote terminal access via E2E encrypted relay.
24
+
25
+ Key features (safe to claim):
26
+ - Interactive TUI for managing projects and workspaces
27
+ - Git worktrees for parallel branch development
28
+ - Linear integration (optional)
29
+ - Custom scripts (pre/setup/select/remove phases)
30
+ - Repo config bundles (in-repo or provided)
31
+ - Secure secrets for bundles stored via OS keychain (Bun.secrets)
32
+ - E2E encrypted remote terminal access
33
+ - Identity-based access control (not passwords)
34
+ - gitspace.sh instant hosting with custom subdomains
35
+
36
+ Remote access:
37
+ - GitSpace supports remote terminal access via a "relay" server.
38
+ - The relay routes traffic but cannot read terminal content (end-to-end encryption).
39
+ - Remote access uses identity-based cryptography with:
40
+ - Ed25519 signing keys (identity)
41
+ - X25519 key exchange keys
42
+ - X3DH-style handshake
43
+ - HKDF-SHA256 key derivation
44
+ - AES-256-GCM encrypted frames after handshake
45
+ - Ed25519-signed relay messages for client routing
46
+ - Challenge-response machine registration (Ed25519)
47
+
48
+ ============================================================
49
+ B) EXACT CLI COMMANDS + FLAGS + DEFAULTS (must match)
50
+ ============================================================
51
+
52
+ Prereqs (list these on docs site):
53
+ - gh (GitHub CLI)
54
+ - git
55
+ - jq
56
+ - bun
57
+
58
+ Optional prereqs:
59
+ - cloudflared (for `gssh host` commands)
60
+ - Linear API key (for Linear integration)
61
+
62
+ Install:
63
+ - `bun install -g https://github.com/inkibra/gitspace.sh`
64
+ - Verify: `gssh --version`
65
+
66
+ ---
67
+
68
+ ### Workspace Management Commands
69
+
70
+ Local usage (examples you can show):
71
+ - `gssh` (launch TUI)
72
+ - `gssh add project`
73
+ - `gssh add [workspace-name]`
74
+ - `gssh switch [workspace-name]` (alias: `gssh sw`)
75
+ - `gssh switch project [project-name]`
76
+ - `gssh list projects` (alias: `gssh ls projects`)
77
+ - `gssh list workspaces` (alias: `gssh ls workspaces`; default `gssh list` lists workspaces)
78
+ - `gssh remove workspace [workspace-name]` (alias: `gssh rm workspace`)
79
+ - `gssh remove project [project-name]` (alias: `gssh rm project`)
80
+ - `gssh directory` (alias: `gssh dir`)
81
+
82
+ Options for `gssh add project`:
83
+ - `--bundle-url <url>` - Load bundle from remote URL (zip archive)
84
+ - `--bundle-path <path>` - Load bundle from local directory
85
+ - `--skip-bundle` - Skip bundle detection and onboarding
86
+ - `--no-clone` - Create project structure without cloning
87
+ - `--org <org>` - Filter repos to specific organization
88
+ - `--linear-key <key>` - Provide Linear API key via flag
89
+
90
+ Options for `gssh add [workspace-name]`:
91
+ - `--branch <name>` - Specify different branch name from workspace name
92
+ - `--from <branch>` - Create from specific branch instead of base
93
+ - `--no-setup` - Skip setup commands
94
+
95
+ Options for `gssh remove workspace`:
96
+ - `--force` - Skip confirmation prompts
97
+ - `--keep-branch` - Don't delete git branch when removing
98
+
99
+ ---
100
+
101
+ ### Identity Commands
102
+
103
+ - `gssh identity init [--label <name>] [--force]`
104
+ - `gssh identity show [--fingerprint] [--json]`
105
+
106
+ Identity is encrypted at rest and requires an unlock password when used for remote connections.
107
+
108
+ ---
109
+
110
+ ### Remote Access / Relay Commands
111
+
112
+ Start relay server:
113
+ - `gssh relay start [--port 4480] [--bind 0.0.0.0] [--hostname <host>] [--label <label>]`
114
+ - Default port: 4480
115
+
116
+ Relay management:
117
+ - `gssh relay authorize <pubkey>` - Authorize a machine by public key
118
+ - `gssh relay revoke <pubkey>` - Revoke a machine's authorization
119
+ - `gssh relay machines` - List authorized machines
120
+ - `gssh relay trusted` - List trusted relays (client-side)
121
+ - `gssh relay untrust <url>` - Remove relay trust (client-side)
122
+
123
+ ---
124
+
125
+ ### Serve Daemon Commands
126
+
127
+ - `gssh serve [--relay <url>] [--relay-pubkey <pubkey>]` - Start daemon (foreground)
128
+ - `gssh serve start [--relay <url>] [--relay-pubkey <pubkey>] [--password-stdin] [--foreground]` - Start daemon (background)
129
+ - `gssh serve stop` - Stop background daemon
130
+ - `gssh status` - Show all daemon statuses
131
+
132
+ Default relay URL for serving if not specified: `wss://relay.gitspace.sh`
133
+
134
+ When starting `gssh serve`, the user will be prompted:
135
+ - "Enter password to unlock identity:"
136
+
137
+ ---
138
+
139
+ ### Invite / Sharing Commands
140
+
141
+ Create share invite token:
142
+ - `gssh share create [--expires <duration>] [--session <id>] [--relay <url>]`
143
+ - Defaults:
144
+ - `--expires` default: `24h`
145
+ - `--relay` default: `wss://relay.gitspace.sh`
146
+ - Output includes a share URL of the form:
147
+ - `https://gitspace.sh/join#<TOKEN>`
148
+
149
+ ---
150
+
151
+ ### Connect Commands
152
+
153
+ Connect via invite:
154
+ - `gssh connect <invite-token-or-url>`
155
+ - Accepts raw token OR a URL like `https://gitspace.sh/join#<TOKEN>`
156
+ - Options:
157
+ - `--relay <url>` override relay URL (from token)
158
+
159
+ ---
160
+
161
+ ### Access Control List (ACL) Commands
162
+
163
+ - `gssh access add <pubkey> [--label <name>]`
164
+ - `gssh access list [--json]` (alias: `gssh access ls`)
165
+ - `gssh access remove <pubkey|label> [--force]` (alias: `gssh access rm`)
166
+
167
+ Public key format shown to users:
168
+ - `gssh-pub:<BASE64_SIGNING_PUBLIC_KEY>:<BASE64_KEY_EXCHANGE_PUBLIC_KEY>`
169
+
170
+ ---
171
+
172
+ ### tmux-lite Daemon Commands
173
+
174
+ - `gssh tmux start` - Start tmux-lite server daemon
175
+ - `gssh tmux stop` - Stop tmux-lite daemon
176
+ - `gssh tmux status` - Show tmux-lite daemon status
177
+ - `gssh tmux list` - List active terminal sessions
178
+ - `gssh tmux attach <id>` - Attach to session
179
+ - `gssh tmux new` - Create new session
180
+ - `gssh tmux kill <id>` - Kill session
181
+
182
+ ---
183
+
184
+ ### gitspace.sh Authentication Commands
185
+
186
+ - `gssh auth login` - Login via GitHub OAuth device flow
187
+ - `gssh auth logout` - Clear local credentials
188
+ - `gssh auth status` - Show authentication status
189
+
190
+ ---
191
+
192
+ ### gitspace.sh Hosting Commands
193
+
194
+ - `gssh host reserve <name>` - Reserve subdomain on gitspace.sh
195
+ - `gssh host release [name]` - Release a subdomain
196
+ - `gssh host list` - List your subdomains
197
+ - `gssh host set-primary <name>` - Set primary subdomain
198
+ - `gssh host status` - Show hosting status
199
+
200
+ ============================================================
201
+ C) REMOTE ACCESS: CANONICAL USER FLOWS
202
+ ============================================================
203
+
204
+ ### Flow 1: gitspace.sh (Managed Service) - RECOMMENDED
205
+
206
+ This is the easiest way to get remote access:
207
+
208
+ ```bash
209
+ # 1. Create identity (first time only)
210
+ gssh identity init --label "My MacBook"
211
+
212
+ # 2. Authenticate with GitHub
213
+ gssh auth login
214
+
215
+ # 3. Reserve your subdomain
216
+ gssh host reserve yourname
217
+ # You get: yourname.gitspace.sh and *.yourname.gitspace.sh
218
+
219
+ # 4. Start serving
220
+ gssh serve
221
+ # Automatically connects to gitspace.sh relay + Cloudflare tunnel
222
+
223
+ # 5. Access from browser
224
+ # Open: https://yourname.gitspace.sh
225
+ ```
226
+
227
+ ### Flow 2: Self-Hosted Relay
228
+
229
+ For complete control, run your own relay:
230
+
231
+ ```bash
232
+ # Terminal 1: Start relay server
233
+ gssh relay start --port 4480 --bind 0.0.0.0
234
+ ```
235
+
236
+ Relay listens at: `ws://<bind-or-hostname>:4480/ws`
237
+
238
+ ```bash
239
+ # Terminal 2: Create identity on the machine
240
+ gssh identity init --label "My MacBook"
241
+ gssh identity show
242
+ ```
243
+
244
+ ```bash
245
+ # Terminal 3: Authorize machine on relay host
246
+ gssh relay authorize gssh-pub:<keys> --label "My MacBook"
247
+ ```
248
+
249
+ ```bash
250
+ # Terminal 4: Start serving
251
+ gssh serve --relay ws://localhost:4480/ws
252
+ # This will prompt for the identity password
253
+ ```
254
+
255
+ ```bash
256
+ # Terminal 5: Create an invite (while serve is running)
257
+ gssh share create
258
+ # Output: https://gitspace.sh/join#<TOKEN>
259
+ ```
260
+
261
+ ```bash
262
+ # On client device: Connect
263
+ gssh identity init --label "Work Laptop" # First time only
264
+ gssh connect https://gitspace.sh/join#<TOKEN>
265
+ ```
266
+
267
+ ### Flow 3: Direct Connection (Pre-Authorized)
268
+
269
+ Once authorized, connect without an invite:
270
+
271
+ ```bash
272
+ gssh --relay ws://localhost:4480/ws
273
+ # Lists available machines, select one to connect
274
+ ```
275
+
276
+ ============================================================
277
+ D) CUSTOM SCRIPTS & BUNDLES
278
+ ============================================================
279
+
280
+ ### Custom Scripts
281
+
282
+ GitSpace uses convention-based scripts located at `~/gitspace/<project>/scripts/`:
283
+
284
+ ```
285
+ scripts/
286
+ ├── pre/ # Run before setup (once, in terminal)
287
+ ├── setup/ # Run on workspace creation (once)
288
+ ├── select/ # Run every time workspace is opened
289
+ └── remove/ # Run before workspace deletion
290
+ ```
291
+
292
+ Script execution rules:
293
+ - Scripts must be executable (`chmod +x`)
294
+ - Scripts run alphabetically (use `01-`, `02-` prefixes)
295
+ - Working directory: The workspace directory
296
+ - Arguments: `$1` = workspace name, `$2` = repository name
297
+ - Environment: Bundle values available as `SPACE_VALUE_*` and `SPACE_SECRET_*`
298
+
299
+ Example script (`scripts/select/01-status.sh`):
300
+ ```bash
301
+ #!/bin/bash
302
+ WORKSPACE_NAME=$1
303
+ REPOSITORY=$2
304
+
305
+ echo "Switching to workspace: $WORKSPACE_NAME"
306
+ git fetch origin
307
+ git status
308
+ ```
309
+
310
+ ### Repo Config Bundles
311
+
312
+ Bundles allow repository owners to share onboarding configurations. Place in `.gitspace-config/` in your repo:
313
+
314
+ ```
315
+ .gitspace-config/
316
+ ├── gitspace-bundle.json # Bundle manifest with onboarding steps
317
+ ├── pre/ # Scripts to run before setup
318
+ ├── setup/ # Scripts to run on first workspace creation
319
+ ├── select/ # Scripts to run every time workspace is opened
320
+ └── remove/ # Scripts to run before workspace deletion
321
+ ```
322
+
323
+ Bundle manifest example (`gitspace-bundle.json`):
324
+ ```json
325
+ {
326
+ "version": "1.0",
327
+ "name": "my-app-bundle",
328
+ "description": "Setup bundle for my-app",
329
+ "onboarding": [
330
+ {
331
+ "id": "welcome",
332
+ "type": "info",
333
+ "title": "Welcome",
334
+ "description": "Let's get you set up!"
335
+ },
336
+ {
337
+ "id": "node",
338
+ "type": "confirm",
339
+ "title": "Node.js",
340
+ "description": "Node.js 18+ is required",
341
+ "checkCommand": "node",
342
+ "installUrl": "https://nodejs.org"
343
+ },
344
+ {
345
+ "id": "api-key",
346
+ "type": "secret",
347
+ "title": "API Key",
348
+ "description": "Enter your API key",
349
+ "configKey": "apiKey"
350
+ },
351
+ {
352
+ "id": "team-name",
353
+ "type": "input",
354
+ "title": "Team Name",
355
+ "description": "Enter your team name",
356
+ "configKey": "teamName",
357
+ "defaultValue": "engineering"
358
+ }
359
+ ]
360
+ }
361
+ ```
362
+
363
+ Onboarding step types:
364
+
365
+ | Type | Purpose | Storage |
366
+ |------|---------|---------|
367
+ | `info` | Display information | N/A |
368
+ | `confirm` | Verify installation (can check command in PATH) | N/A |
369
+ | `secret` | Collect sensitive values (masked input) | OS Keychain |
370
+ | `input` | Collect plain text values | Project config |
371
+
372
+ Using bundle values in scripts:
373
+ ```bash
374
+ #!/bin/bash
375
+ # Values available as environment variables:
376
+ # SPACE_VALUE_<KEY> - Regular values from input steps
377
+ # SPACE_SECRET_<KEY> - Secret values from secret steps (from OS keychain)
378
+
379
+ if [ -n "$SPACE_VALUE_TEAMNAME" ]; then
380
+ echo "Welcome, $SPACE_VALUE_TEAMNAME team!"
381
+ fi
382
+
383
+ if [ -n "$SPACE_SECRET_APIKEY" ]; then
384
+ echo "API Key configured"
385
+ fi
386
+ ```
387
+
388
+ Bundle sources:
389
+ - **In-repo** (automatic): `.gitspace-config/`, `gitspace-config/`, or `.gitspace/` in the cloned repository
390
+ - **Local path**: `gssh add project --bundle-path /path/to/bundle/`
391
+ - **Remote URL**: `gssh add project --bundle-url https://example.com/bundle.zip`
392
+
393
+ ============================================================
394
+ E) CONFIGURATION REFERENCE
395
+ ============================================================
396
+
397
+ ### Global Configuration
398
+
399
+ Location: `~/gitspace/.config.json`
400
+
401
+ ```json
402
+ {
403
+ "currentProject": "my-app",
404
+ "projectsDir": "/Users/username/spaces",
405
+ "defaultBaseBranch": "main",
406
+ "staleDays": 30
407
+ }
408
+ ```
409
+
410
+ ### Project Configuration
411
+
412
+ Location: `~/gitspace/<project>/.config.json`
413
+
414
+ ```json
415
+ {
416
+ "name": "my-app",
417
+ "repository": "myorg/my-app",
418
+ "baseBranch": "main",
419
+ "linearApiKey": "lin_api_...",
420
+ "linearTeamKey": "ENG",
421
+ "bundleValues": {
422
+ "teamName": "engineering"
423
+ },
424
+ "bundleSecretKeys": ["apiKey"],
425
+ "appliedBundle": {
426
+ "name": "my-app-bundle",
427
+ "version": "1.0",
428
+ "source": "/path/to/bundle",
429
+ "appliedAt": "2025-01-01T00:00:00Z"
430
+ }
431
+ }
432
+ ```
433
+
434
+ ### Identity Storage
435
+
436
+ Location: `~/gitspace/.identity/`
437
+
438
+ | File | Purpose |
439
+ |------|---------|
440
+ | `keypair.json` | Encrypted Ed25519/X25519 keys (password-protected) |
441
+ | `access-list.json` | Authorized client public keys |
442
+ | `machine.json` | Machine ID and label |
443
+ | `relay.json` | Relay configuration cache |
444
+
445
+ ### Environment Variables
446
+
447
+ | Variable | Description | Default |
448
+ |----------|-------------|---------|
449
+ | `RELAY_PORT` | Relay server port | `4480` |
450
+ | `RELAY_BIND` | Relay bind address | `0.0.0.0` |
451
+ | `SPACES_CURRENT_PROJECT` | Override current project | From config |
452
+ | `GITSPACE_API_URL` | gitspace.sh API URL | `https://api.gitspace.sh` |
453
+
454
+ ### Directory Structure
455
+
456
+ ```
457
+ ~/gitspace/
458
+ ├── .config.json # Global configuration
459
+ ├── .identity/ # Identity files (see above)
460
+ ├── <project-name>/
461
+ │ ├── .config.json # Project configuration
462
+ │ ├── base/ # Base repository clone
463
+ │ ├── workspaces/ # Git worktrees
464
+ │ │ └── <workspace-name>/
465
+ │ │ ├── gitspace.lock # Setup completion marker
466
+ │ │ └── .prompt/ # Linear issue details (if applicable)
467
+ │ │ └── issue.md
468
+ │ └── scripts/ # Custom scripts
469
+ │ ├── pre/
470
+ │ ├── setup/
471
+ │ ├── select/
472
+ │ └── remove/
473
+ ```
474
+
475
+ ============================================================
476
+ F) SECURITY MODEL
477
+ ============================================================
478
+
479
+ ### Cryptographic Primitives
480
+
481
+ | Purpose | Algorithm | Notes |
482
+ |---------|-----------|-------|
483
+ | Identity signing | Ed25519 | Fast, secure signatures |
484
+ | Key exchange | X25519 | ECDH for shared secrets |
485
+ | Key derivation | HKDF-SHA256 | Domain-separated key derivation |
486
+ | Symmetric encryption | AES-256-GCM | Authenticated encryption |
487
+ | Password KDF | Scrypt (N=2^15, r=8, p=1) | Encrypts identity at rest |
488
+
489
+ ### What's Protected
490
+
491
+ | Data | Protection Level |
492
+ |------|------------------|
493
+ | Terminal keystrokes | E2E encrypted (AES-256-GCM) |
494
+ | Terminal output | E2E encrypted (AES-256-GCM) |
495
+ | Commands | E2E encrypted (AES-256-GCM) |
496
+ | Session content | E2E encrypted (AES-256-GCM) |
497
+ | Identity keys | Password-encrypted (Scrypt + AES-GCM) |
498
+ | Bundle secrets | OS Keychain (macOS Keychain, Linux libsecret) |
499
+
500
+ ### What Relay Can See (Metadata Only)
501
+
502
+ | Data | Visible to Relay |
503
+ |------|------------------|
504
+ | Machine ID | Yes (required for routing) |
505
+ | Client identity ID | Yes (required for routing) |
506
+ | Connection timestamps | Yes (metadata) |
507
+ | Data volume (bytes) | Yes (metadata) |
508
+ | Online/offline status | Yes |
509
+ | Terminal content | NO (encrypted) |
510
+ | Keystrokes | NO (encrypted) |
511
+ | Commands and output | NO (encrypted) |
512
+
513
+ ### Trust Boundaries
514
+
515
+ ```
516
+ YOU TRUST: YOU DON'T NEED TO TRUST:
517
+ ├── Your own machine ├── The relay operator
518
+ ├── Clients you've authorized ├── Network infrastructure
519
+ └── Devices holding your identity └── Anyone without an invite
520
+
521
+ IF THE RELAY IS COMPROMISED:
522
+ ✓ Terminal content is still safe (E2E encrypted)
523
+ ✓ Identity keys are still safe (never sent to relay)
524
+ ✗ Metadata is exposed (who connected when)
525
+ ✗ Relay could deny service
526
+ ```
527
+
528
+ ### Access Types
529
+
530
+ | Type | Description | Capabilities |
531
+ |------|-------------|--------------|
532
+ | `full` | Permanent access grant | Browse all projects/workspaces, create/attach/kill sessions, manage access |
533
+ | `session-invite` | One-time session access | View specific session only, no browsing, read-only |
534
+
535
+ ### Current Limitations
536
+
537
+ > **Important**: Include this callout on the site. These are known limitations.
538
+
539
+ 1. **Client proof-of-possession**: The handshake doesn't fully enforce that the client possesses the private key corresponding to their claimed public key. If an attacker learns an authorized public key, ACL identity spoofing is theoretically possible.
540
+
541
+ 2. **Permission enforcement**: Permission flags (`read`/`write`/`manage`) are not fully enforced server-side after the handshake completes. "View-only" access should be treated as intended behavior rather than a strict security guarantee.
542
+
543
+ These limitations are being addressed in future releases.
544
+
545
+ ============================================================
546
+ G) TROUBLESHOOTING
547
+ ============================================================
548
+
549
+ ### Installation Issues
550
+
551
+ **"command not found: spaces"**
552
+ - Ensure Bun's global bin is in your PATH
553
+ - Try: `export PATH="$HOME/.bun/bin:$PATH"`
554
+ - Add to your shell profile (`~/.zshrc`, `~/.bashrc`)
555
+
556
+ **"GitHub CLI not authenticated"**
557
+ ```bash
558
+ gh auth login
559
+ # Follow prompts to authenticate
560
+ ```
561
+
562
+ ### Identity Issues
563
+
564
+ **"No identity found"**
565
+ ```bash
566
+ gssh identity init --label "My Device"
567
+ ```
568
+
569
+ **"Failed to unlock identity"**
570
+ - You're entering the wrong password
571
+ - If forgotten, recreate: `gssh identity init --force`
572
+ - Warning: This invalidates existing invites and access grants
573
+
574
+ **"Identity already exists"**
575
+ - Use `--force` to overwrite: `gssh identity init --force`
576
+
577
+ ### Connection Issues
578
+
579
+ **"Machine offline"**
580
+ - Ensure `gssh serve` is running on the target machine
581
+ - Check the machine can reach the relay URL
582
+ - Verify the machine is authorized on the relay
583
+
584
+ **"Client not authorized"**
585
+ - You need an invite to connect first
586
+ - Or have the machine owner add your public key:
587
+ ```bash
588
+ gssh access add <your-public-key> --label "Name"
589
+ ```
590
+
591
+ **"Invite not found" or "Invite expired"**
592
+ - The invite may have expired (default: 24h)
593
+ - Already been used (single-use invites)
594
+ - Not been registered (ensure `gssh serve` was running when created)
595
+ - Create a new invite: `gssh share create --expires 7d`
596
+
597
+ **"Handshake timeout"**
598
+ - Check network connectivity
599
+ - Verify firewall allows WebSocket connections
600
+ - Both parties must have valid identities
601
+ - Try connecting again (transient network issue)
602
+
603
+ **"Connection refused" to relay**
604
+ - Verify relay URL is correct (`ws://` vs `wss://`)
605
+ - Check relay server is running
606
+ - Verify port is open/reachable
607
+
608
+ ### Workspace Issues
609
+
610
+ **"Workspace already exists"**
611
+ - Choose a different name
612
+ - Or remove existing: `gssh remove workspace <name>`
613
+
614
+ **"Failed to create worktree"**
615
+ - Check branch doesn't already exist
616
+ - Ensure you have git write permissions
617
+ - Try: `git fetch origin` first
618
+
619
+ **"Setup scripts failed"**
620
+ - Check script is executable: `chmod +x scripts/setup/*.sh`
621
+ - Run manually to see error: `./scripts/setup/01-script.sh`
622
+ - Check environment variables are set
623
+
624
+ ### Bundle/Secrets Issues
625
+
626
+ **"SPACE_SECRET_* variables are empty"**
627
+ 1. Ensure you completed onboarding secret steps
628
+ 2. Check OS keychain is accessible:
629
+ - macOS: Keychain Access should be running
630
+ - Linux: `libsecret` must be installed
631
+ 3. Re-run onboarding if needed
632
+
633
+ ### Hosting Issues (gitspace.sh)
634
+
635
+ **"Subdomain not available"**
636
+ - Name may be taken or reserved
637
+ - Try a different name
638
+ - Check your subdomains: `gssh host list`
639
+
640
+ **"Tunnel failed to connect"**
641
+ - Ensure `cloudflared` is installed
642
+ - Check internet connectivity
643
+ - Verify subdomain is reserved: `gssh host status`
644
+
645
+ **"Authentication failed" (gitspace.sh)**
646
+ - Token may be expired
647
+ - Re-authenticate: `gssh auth login`
648
+
649
+ ============================================================
650
+ H) GLOSSARY
651
+ ============================================================
652
+
653
+ | Term | Definition |
654
+ |------|------------|
655
+ | **Machine** | A device running `gssh serve` that accepts remote connections |
656
+ | **Client** | A device running `gssh connect` or browser accessing terminal |
657
+ | **Relay** | WebSocket server that routes encrypted traffic (default: `wss://relay.gitspace.sh`) |
658
+ | **Relay Identity** | Ed25519 keypair used by the relay to sign messages and challenges |
659
+ | **Authorized Machine** | Machine public key approved to register with a relay |
660
+ | **Identity** | Ed25519 signing + X25519 key exchange keypairs, encrypted at rest |
661
+ | **Invite** | Signed token that bootstraps trust and enables first connection |
662
+ | **ACL (Access Control List)** | Machine-managed list of authorized client identities |
663
+ | **X3DH** | Extended Triple Diffie-Hellman handshake for session key establishment |
664
+ | **PTY** | Pseudo-terminal, the interface between your shell and the terminal |
665
+ | **Worktree** | Git feature allowing multiple working directories for one repository |
666
+ | **Bundle** | Repository configuration package for team onboarding |
667
+ | **Session** | A terminal session managed by tmux-lite on the server |
668
+ | **Stream** | Encrypted channel within a connection (Stream 0 = master) |
669
+ | **TUI** | Terminal User Interface, the interactive `gssh` interface |
670
+ | **tmux-lite** | Built-in terminal multiplexer for managing sessions |
671
+ | **Subdomain** | Your custom URL on gitspace.sh (e.g., `yourname.gitspace.sh`) |
672
+
673
+ ============================================================
674
+ I) WHAT TO WRITE ON THE SITE
675
+ ============================================================
676
+
677
+ Update TWO pages: Home and Docs. Keep layout, replace text/code with the following.
678
+
679
+ -------------------------
680
+ HOME PAGE (replace copy)
681
+ -------------------------
682
+
683
+ Headline:
684
+ GitSpace: Git worktrees + secure remote access for parallel development
685
+
686
+ Subheadline:
687
+ Manage multiple features in one repo without stashing. Create isolated workspaces (git worktrees), switch instantly, and access your terminal remotely through end-to-end encrypted connections.
688
+
689
+ Primary CTA:
690
+ Get Started -> link to /docs
691
+
692
+ Feature bullets:
693
+ - **Interactive TUI**: Manage projects and workspaces visually
694
+ - **Git worktrees**: Multiple branches checked out at once
695
+ - **Repo onboarding bundles**: Team setup steps + custom scripts
696
+ - **Secure remote access**: E2E encrypted terminal from anywhere
697
+ - **gitspace.sh hosting**: Instant subdomains like `yourname.gitspace.sh`
698
+ - **Identity-based auth**: Cryptographic keys, not passwords
699
+
700
+ Short code example:
701
+ ```bash
702
+ # Install
703
+ bun install -g https://github.com/inkibra/gitspace.sh
704
+
705
+ # Launch the TUI
706
+ spaces
707
+
708
+ # Or via CLI
709
+ gssh add project # Add a GitHub repo
710
+ gssh add my-feature # Create a workspace
711
+ gssh switch my-feature
712
+
713
+ # Remote access (optional)
714
+ gssh auth login # Login to gitspace.sh
715
+ gssh host reserve myname # Get myname.gitspace.sh
716
+ gssh serve # Start serving
717
+ ```
718
+
719
+ -------------------------
720
+ DOCS PAGE (with TOC)
721
+ -------------------------
722
+
723
+ Title: Documentation
724
+
725
+ Table of Contents (anchor links):
726
+ - Overview
727
+ - Quick Start
728
+ - Installation
729
+ - Local Workflow
730
+ - TUI Interface
731
+ - CLI Commands
732
+ - Custom Scripts
733
+ - Repo Config Bundles
734
+ - Remote Access
735
+ - gitspace.sh (Managed)
736
+ - Self-Hosted Relay
737
+ - Identity Management
738
+ - Access Control
739
+ - Configuration
740
+ - Troubleshooting
741
+ - Security
742
+ - Glossary
743
+
744
+ ---
745
+
746
+ SECTION: Overview
747
+
748
+ GitSpace is a CLI tool for managing GitHub repository workspaces using git worktrees, with optional secure remote terminal access.
749
+
750
+ **Local Development:**
751
+ - Work on multiple branches simultaneously without stashing
752
+ - Interactive TUI for visual workspace management
753
+ - Convention-based scripts for automation
754
+ - Team onboarding via repo config bundles
755
+
756
+ **Remote Access:**
757
+ - E2E encrypted terminal access from any browser or CLI
758
+ - Zero-trust relay: routes traffic but cannot decrypt content
759
+ - Identity-based auth using Ed25519/X25519 cryptographic keys
760
+ - Instant hosting via gitspace.sh subdomains
761
+
762
+ ---
763
+
764
+ SECTION: Quick Start
765
+
766
+ ### 5-Minute Setup with gitspace.sh
767
+
768
+ ```bash
769
+ # 1. Install
770
+ bun install -g https://github.com/inkibra/gitspace.sh
771
+
772
+ # 2. Create identity
773
+ gssh identity init
774
+
775
+ # 3. Login to gitspace.sh
776
+ gssh auth login
777
+
778
+ # 4. Reserve your subdomain
779
+ gssh host reserve yourname
780
+
781
+ # 5. Start serving
782
+ gssh serve
783
+
784
+ # 6. Access from browser: https://yourname.gitspace.sh
785
+ ```
786
+
787
+ ### Local-Only Quick Start
788
+
789
+ ```bash
790
+ # Install
791
+ bun install -g https://github.com/inkibra/gitspace.sh
792
+
793
+ # Authenticate GitHub
794
+ gh auth login
795
+
796
+ # Launch TUI
797
+ spaces
798
+
799
+ # Or via CLI:
800
+ gssh add project # Add a GitHub repo
801
+ gssh add my-feature # Create a workspace
802
+ ```
803
+
804
+ ---
805
+
806
+ SECTION: Installation
807
+
808
+ ### Prerequisites
809
+
810
+ Required:
811
+ - [Bun](https://bun.sh) - JavaScript runtime
812
+ - [Git](https://git-scm.com/) - Version control
813
+ - [GitHub CLI](https://cli.github.com/) - `gh auth login` before using GitSpace
814
+ - [jq](https://stedolan.github.io/jq/) - JSON processing
815
+
816
+ Optional:
817
+ - [cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) - For `gssh host` commands
818
+
819
+ ### Install GitSpace
820
+
821
+ ```bash
822
+ bun install -g https://github.com/inkibra/gitspace.sh
823
+ gssh --version
824
+ ```
825
+
826
+ ### Authenticate GitHub CLI
827
+
828
+ ```bash
829
+ gh auth login
830
+ ```
831
+
832
+ ---
833
+
834
+ SECTION: Local Workflow - TUI Interface
835
+
836
+ Launch the TUI with no arguments:
837
+
838
+ ```bash
839
+ spaces
840
+ ```
841
+
842
+ The TUI provides a two-panel interface:
843
+ - **Left panel**: Your projects
844
+ - **Right panel**: Workspaces in the selected project
845
+
846
+ **Key Bindings:**
847
+ | Key | Action |
848
+ |-----|--------|
849
+ | `Enter` | Select project / Open workspace |
850
+ | `Tab` | Switch between panels |
851
+ | `n` | New project / workspace |
852
+ | `d` | Delete selected item |
853
+ | `?` | Show help |
854
+ | `q` | Quit |
855
+
856
+ ---
857
+
858
+ SECTION: Local Workflow - CLI Commands
859
+
860
+ ### Projects
861
+
862
+ ```bash
863
+ gssh add project # Add from GitHub (interactive)
864
+ gssh add project --org myorg # Filter by organization
865
+ gssh switch project myapp # Switch to a project
866
+ gssh list projects # List all projects
867
+ gssh remove project myapp # Remove a project
868
+ ```
869
+
870
+ ### Workspaces
871
+
872
+ ```bash
873
+ gssh add my-feature # Create workspace
874
+ gssh add --from develop # Create from specific branch
875
+ gssh switch my-feature # Switch to workspace
876
+ gssh switch # Interactive selection
877
+ gssh list # List workspaces
878
+ gssh remove workspace my-feature
879
+ ```
880
+
881
+ ### Other
882
+
883
+ ```bash
884
+ gssh directory # Print current project path
885
+ gssh status # Show daemon statuses
886
+ ```
887
+
888
+ ---
889
+
890
+ SECTION: Local Workflow - Custom Scripts
891
+
892
+ GitSpace uses convention-based scripts in `~/gitspace/<project>/scripts/`:
893
+
894
+ ```
895
+ scripts/
896
+ ├── pre/ # Run before setup (once)
897
+ ├── setup/ # Run on workspace creation (once)
898
+ ├── select/ # Run every time workspace is opened
899
+ └── remove/ # Run before workspace deletion
900
+ ```
901
+
902
+ **Rules:**
903
+ - Scripts must be executable (`chmod +x`)
904
+ - Run alphabetically (use `01-`, `02-` prefixes)
905
+ - Working directory: the workspace
906
+ - Arguments: `$1` = workspace name, `$2` = repository
907
+
908
+ **Example:**
909
+ ```bash
910
+ #!/bin/bash
911
+ # scripts/select/01-status.sh
912
+ echo "Switching to: $1"
913
+ git fetch origin
914
+ git status
915
+ ```
916
+
917
+ ---
918
+
919
+ SECTION: Local Workflow - Repo Config Bundles
920
+
921
+ Bundles allow teams to share onboarding configurations. Place in `.gitspace-config/`:
922
+
923
+ ```
924
+ .gitspace-config/
925
+ ├── gitspace-bundle.json # Manifest
926
+ ├── pre/ # Pre-setup scripts
927
+ ├── setup/ # Setup scripts
928
+ └── select/ # Select scripts
929
+ ```
930
+
931
+ **Manifest example:**
932
+ ```json
933
+ {
934
+ "version": "1.0",
935
+ "name": "my-app-bundle",
936
+ "onboarding": [
937
+ { "id": "node", "type": "confirm", "title": "Node.js", "checkCommand": "node" },
938
+ { "id": "api-key", "type": "secret", "title": "API Key", "configKey": "apiKey" }
939
+ ]
940
+ }
941
+ ```
942
+
943
+ **Step types:**
944
+ | Type | Purpose | Storage |
945
+ |------|---------|---------|
946
+ | `info` | Display information | N/A |
947
+ | `confirm` | Verify installation | N/A |
948
+ | `secret` | Sensitive values | OS Keychain |
949
+ | `input` | Plain text | Config file |
950
+
951
+ **Using values in scripts:**
952
+ ```bash
953
+ echo "Team: $SPACE_VALUE_TEAMNAME"
954
+ echo "Has API key: $SPACE_SECRET_APIKEY"
955
+ ```
956
+
957
+ ---
958
+
959
+ SECTION: Remote Access - gitspace.sh (Managed)
960
+
961
+ The easiest way to get remote access:
962
+
963
+ ```bash
964
+ # 1. Create identity
965
+ gssh identity init
966
+
967
+ # 2. Login with GitHub
968
+ gssh auth login
969
+
970
+ # 3. Reserve subdomain
971
+ gssh host reserve yourname
972
+
973
+ # 4. Start serving
974
+ gssh serve
975
+
976
+ # 5. Access: https://yourname.gitspace.sh
977
+ ```
978
+
979
+ **Manage subdomains:**
980
+ ```bash
981
+ gssh host list # List your subdomains
982
+ gssh host set-primary name # Set primary
983
+ gssh host release name # Release subdomain
984
+ gssh host status # Show status
985
+ ```
986
+
987
+ ---
988
+
989
+ SECTION: Remote Access - Self-Hosted Relay
990
+
991
+ For complete control:
992
+
993
+ **1. Start relay:**
994
+ ```bash
995
+ gssh relay start --port 4480
996
+ ```
997
+
998
+ **2. Authorize machine:**
999
+ ```bash
1000
+ gssh identity init --label "My Mac"
1001
+ gssh identity show
1002
+
1003
+ # On the relay host
1004
+ gssh relay authorize gssh-pub:<keys> --label "My Mac"
1005
+ ```
1006
+
1007
+ **3. Serve:**
1008
+ ```bash
1009
+ gssh serve --relay ws://localhost:4480/ws
1010
+ ```
1011
+
1012
+ **4. Create invite:**
1013
+ ```bash
1014
+ gssh share create
1015
+ # Output: https://gitspace.sh/join#<TOKEN>
1016
+ ```
1017
+
1018
+ **5. Connect from client:**
1019
+ ```bash
1020
+ gssh identity init --label "Laptop"
1021
+ gssh connect https://gitspace.sh/join#<TOKEN>
1022
+ ```
1023
+
1024
+ ---
1025
+
1026
+ SECTION: Remote Access - Identity Management
1027
+
1028
+ Every machine and client has a cryptographic identity:
1029
+
1030
+ ```bash
1031
+ gssh identity init [--label <name>] [--force]
1032
+ gssh identity show [--fingerprint] [--json]
1033
+ ```
1034
+
1035
+ Identity storage: `~/gitspace/.identity/`
1036
+
1037
+ ---
1038
+
1039
+ SECTION: Remote Access - Access Control
1040
+
1041
+ **Grant access:**
1042
+ ```bash
1043
+ gssh access add gssh-pub:<keys> --label "Brad's Phone"
1044
+ ```
1045
+
1046
+ **Manage access:**
1047
+ ```bash
1048
+ gssh access list [--json]
1049
+ gssh access remove "Brad's Phone"
1050
+ gssh access remove <key-prefix> --force
1051
+ ```
1052
+
1053
+ **Connect without invite (pre-authorized):**
1054
+ ```bash
1055
+ gssh --relay ws://relay.example.com/ws
1056
+ ```
1057
+
1058
+ ---
1059
+
1060
+ SECTION: Configuration
1061
+
1062
+ ### Global Config
1063
+
1064
+ `~/gitspace/.config.json`:
1065
+ ```json
1066
+ {
1067
+ "currentProject": "my-app",
1068
+ "projectsDir": "/Users/username/spaces",
1069
+ "defaultBaseBranch": "main"
1070
+ }
1071
+ ```
1072
+
1073
+ ### Project Config
1074
+
1075
+ `~/gitspace/<project>/.config.json`:
1076
+ ```json
1077
+ {
1078
+ "name": "my-app",
1079
+ "repository": "myorg/my-app",
1080
+ "baseBranch": "main"
1081
+ }
1082
+ ```
1083
+
1084
+ ### Environment Variables
1085
+
1086
+ | Variable | Description | Default |
1087
+ |----------|-------------|---------|
1088
+ | `RELAY_PORT` | Relay port | `4480` |
1089
+ | `SPACES_CURRENT_PROJECT` | Override project | Config |
1090
+
1091
+ ---
1092
+
1093
+ SECTION: Troubleshooting
1094
+
1095
+ **"No identity found"**
1096
+ ```bash
1097
+ gssh identity init --label "My Device"
1098
+ ```
1099
+
1100
+ **"Machine offline"**
1101
+ - Ensure `gssh serve` is running
1102
+ - Check relay connectivity
1103
+ - Verify the machine is authorized on the relay
1104
+
1105
+ **"Client not authorized"**
1106
+ - Use an invite: `gssh share create`
1107
+ - Or add public key: `gssh access add <key>`
1108
+
1109
+ **"Invite expired"**
1110
+ - Create new invite: `gssh share create --expires 7d`
1111
+
1112
+ **"GitHub CLI not authenticated"**
1113
+ ```bash
1114
+ gh auth login
1115
+ ```
1116
+
1117
+ ---
1118
+
1119
+ SECTION: Security
1120
+
1121
+ **End-to-end encrypted:** Terminal traffic encrypted with AES-256-GCM. Relay cannot decrypt.
1122
+
1123
+ **Cryptographic identity:** Ed25519 signing + X25519 key exchange. No passwords.
1124
+
1125
+ **X3DH handshake:** Session keys derived per-connection.
1126
+
1127
+ **Current limitations:**
1128
+ - Client proof-of-possession for identity signing keys is not fully enforced (ACL spoofing risk if attacker learns authorized public key)
1129
+ - Permission flags not fully enforced server-side after handshake; "view-only" is intended behavior, not strict guarantee
1130
+
1131
+ ---
1132
+
1133
+ SECTION: Glossary
1134
+
1135
+ | Term | Definition |
1136
+ |------|------------|
1137
+ | Machine | Device running `gssh serve` |
1138
+ | Client | Device connecting via browser or CLI |
1139
+ | Relay | WebSocket router (default: `wss://relay.gitspace.sh`) |
1140
+ | Relay Identity | Ed25519 keypair used by the relay to sign messages and challenges |
1141
+ | Authorized Machine | Machine public key approved to register with a relay |
1142
+ | Identity | Ed25519 + X25519 keypairs |
1143
+ | Invite | Signed token for first connection |
1144
+ | ACL | Access Control List |
1145
+ | X3DH | Key exchange handshake |
1146
+ | Worktree | Git feature for multiple working directories |
1147
+ | Bundle | Repo onboarding configuration |
1148
+
1149
+ ============================================================
1150
+ J) FINAL CHECKLIST
1151
+ ============================================================
1152
+
1153
+ Before finishing, verify:
1154
+
1155
+ - [ ] Every command uses exact subcommand names (especially `gssh relay start`, `gssh serve`)
1156
+ - [ ] Defaults match:
1157
+ - [ ] Relay port: 4480
1158
+ - [ ] Serve relay default: `wss://relay.gitspace.sh`
1159
+ - [ ] Share URL: `https://gitspace.sh/join#...`
1160
+ - [ ] Share expires default: 24h
1161
+ - [ ] Security notes are conservative and include "current limitations" callout
1162
+ - [ ] No mention of non-existent features (dashboards, OAuth flows on relay, etc.)
1163
+ - [ ] Custom scripts and bundles are documented
1164
+ - [ ] All troubleshooting items have solutions
1165
+ - [ ] Glossary includes all key terms
1166
+
1167
+ Now apply these changes to the Docs pages in the Figma site.