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,718 @@
1
+ import { Terminal, Copy, Check } from "lucide-react";
2
+ import { useState } from "react";
3
+ import { cn } from "../../lib/utils";
4
+ import { Badge } from "../../app/components/ui/badge";
5
+
6
+ function CodeBlock({ code, language = "bash", multiLine = false }: { code: string; language?: string; multiLine?: boolean }) {
7
+ const [copied, setCopied] = useState(false);
8
+
9
+ const onCopy = () => {
10
+ navigator.clipboard.writeText(code);
11
+ setCopied(true);
12
+ setTimeout(() => setCopied(false), 2000);
13
+ };
14
+
15
+ const lines = code.split('\n');
16
+
17
+ return (
18
+ <div className="relative mt-4 mb-6 group">
19
+ <div className="absolute top-3 right-3 opacity-0 group-hover:opacity-100 transition-opacity z-10">
20
+ <button
21
+ onClick={onCopy}
22
+ className="p-1.5 rounded bg-zinc-700 hover:bg-zinc-600 text-zinc-300 transition-colors"
23
+ >
24
+ {copied ? <Check className="w-3.5 h-3.5 text-green-400" /> : <Copy className="w-3.5 h-3.5" />}
25
+ </button>
26
+ </div>
27
+ <div className="bg-zinc-900 rounded-lg border border-zinc-800 p-4 overflow-x-auto font-mono text-sm leading-relaxed">
28
+ {multiLine ? (
29
+ lines.map((line, i) => (
30
+ <div key={i} className="flex">
31
+ {language === 'bash' && line.trim() && !line.startsWith('#') && !line.startsWith('//') && (
32
+ <span className="text-zinc-500 select-none mr-2">$</span>
33
+ )}
34
+ <span className={line.startsWith('#') || line.startsWith('//') ? "text-zinc-500" : "text-zinc-300"}>{line}</span>
35
+ </div>
36
+ ))
37
+ ) : (
38
+ <>
39
+ {language === 'bash' && <span className="text-zinc-500 select-none mr-2">$</span>}
40
+ <span className="text-zinc-300">{code}</span>
41
+ </>
42
+ )}
43
+ </div>
44
+ </div>
45
+ );
46
+ }
47
+
48
+ function JsonBlock({ code }: { code: string }) {
49
+ const [copied, setCopied] = useState(false);
50
+
51
+ const onCopy = () => {
52
+ navigator.clipboard.writeText(code);
53
+ setCopied(true);
54
+ setTimeout(() => setCopied(false), 2000);
55
+ };
56
+
57
+ return (
58
+ <div className="relative mt-4 mb-6 group">
59
+ <div className="absolute top-3 right-3 opacity-0 group-hover:opacity-100 transition-opacity z-10">
60
+ <button
61
+ onClick={onCopy}
62
+ className="p-1.5 rounded bg-zinc-700 hover:bg-zinc-600 text-zinc-300 transition-colors"
63
+ >
64
+ {copied ? <Check className="w-3.5 h-3.5 text-green-400" /> : <Copy className="w-3.5 h-3.5" />}
65
+ </button>
66
+ </div>
67
+ <div className="bg-zinc-900 rounded-lg border border-zinc-800 p-4 overflow-x-auto font-mono text-sm leading-relaxed">
68
+ <pre className="text-zinc-300">{code}</pre>
69
+ </div>
70
+ </div>
71
+ );
72
+ }
73
+
74
+ export function DocsContent({ section }: { section: string }) {
75
+ switch (section) {
76
+ case "overview":
77
+ return (
78
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
79
+ <h1 className="text-4xl font-bold mb-6">Overview</h1>
80
+ <p className="text-xl text-zinc-400 mb-8 leading-relaxed">
81
+ GitSpace is a CLI tool for managing GitHub repository workspaces using git worktrees, with optional secure remote terminal access.
82
+ </p>
83
+
84
+ <h3 className="text-xl font-semibold text-white mb-4">Local Development</h3>
85
+ <ul className="list-disc list-inside space-y-2 text-zinc-400 mb-8 ml-2">
86
+ <li>Work on multiple branches simultaneously without stashing</li>
87
+ <li>Interactive TUI for visual workspace management</li>
88
+ <li>Convention-based scripts for automation</li>
89
+ <li>Team onboarding via repo config bundles</li>
90
+ </ul>
91
+
92
+ <h3 className="text-xl font-semibold text-white mb-4">Remote Access</h3>
93
+ <ul className="list-disc list-inside space-y-2 text-zinc-400 mb-8 ml-2">
94
+ <li>E2E encrypted terminal access from any browser or CLI</li>
95
+ <li>Zero-trust relay: routes traffic but cannot decrypt content</li>
96
+ <li>Identity-based auth using Ed25519/X25519 cryptographic keys</li>
97
+ <li>Instant hosting via gitspace.sh subdomains</li>
98
+ </ul>
99
+ </div>
100
+ );
101
+
102
+ case "quick-start":
103
+ return (
104
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
105
+ <h1 className="text-4xl font-bold mb-6">Quick Start</h1>
106
+
107
+ <h3 className="text-xl font-semibold text-white mb-4">5-Minute Setup with gitspace.sh</h3>
108
+ <CodeBlock code={`# 1. Install
109
+ bun install -g https://github.com/inkibra/gitspace.sh
110
+
111
+ # 2. Create identity
112
+ gssh identity init
113
+
114
+ # 3. Login to gitspace.sh
115
+ gssh auth login
116
+
117
+ # 4. Reserve your subdomain
118
+ gssh host reserve yourname
119
+
120
+ # 5. Start serving
121
+ gssh serve
122
+
123
+ # 6. Access from browser: https://yourname.gitspace.sh`} multiLine />
124
+
125
+ <h3 className="text-xl font-semibold text-white mb-4 mt-12">Local-Only Quick Start</h3>
126
+ <CodeBlock code={`# Install
127
+ bun install -g https://github.com/inkibra/gitspace.sh
128
+
129
+ # Authenticate GitHub
130
+ gh auth login
131
+
132
+ # Launch TUI
133
+ gssh
134
+
135
+ # Or via CLI:
136
+ gssh add project # Add a GitHub repo
137
+ gssh add my-feature # Create a workspace`} multiLine />
138
+ </div>
139
+ );
140
+
141
+ case "installation":
142
+ return (
143
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
144
+ <h1 className="text-4xl font-bold mb-6">Installation</h1>
145
+
146
+ <h3 className="text-xl font-semibold text-white mb-4">Prerequisites</h3>
147
+ <p className="text-zinc-400 mb-4">Required:</p>
148
+ <ul className="list-disc list-inside space-y-2 text-zinc-400 mb-8 ml-2">
149
+ <li><a href="https://bun.sh" className="text-green-400 hover:underline">Bun</a> - JavaScript runtime</li>
150
+ <li><a href="https://git-scm.com/" className="text-green-400 hover:underline">Git</a> - Version control</li>
151
+ <li><a href="https://cli.github.com/" className="text-green-400 hover:underline">GitHub CLI</a> - <code className="text-zinc-300">gh auth login</code> before using GitSpace</li>
152
+ <li><a href="https://stedolan.github.io/jq/" className="text-green-400 hover:underline">jq</a> - JSON processing</li>
153
+ </ul>
154
+
155
+ <p className="text-zinc-400 mb-4">Optional:</p>
156
+ <ul className="list-disc list-inside space-y-2 text-zinc-400 mb-8 ml-2">
157
+ <li><a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/" className="text-green-400 hover:underline">cloudflared</a> - For <code className="text-zinc-300">gssh host</code> commands</li>
158
+ </ul>
159
+
160
+ <h3 className="text-xl font-semibold text-white mb-4">Install GitSpace</h3>
161
+ <CodeBlock code="bun install -g https://github.com/inkibra/gitspace.sh" />
162
+ <CodeBlock code="gssh --version" />
163
+
164
+ <h3 className="text-xl font-semibold text-white mb-4">Authenticate GitHub CLI</h3>
165
+ <CodeBlock code="gh auth login" />
166
+ </div>
167
+ );
168
+
169
+ case "tui-interface":
170
+ return (
171
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
172
+ <h1 className="text-4xl font-bold mb-6">TUI Interface</h1>
173
+
174
+ <p className="text-zinc-400 mb-4">Launch the TUI with no arguments:</p>
175
+ <CodeBlock code="gssh" />
176
+
177
+ <p className="text-zinc-400 mb-8">
178
+ The TUI provides a two-panel interface:
179
+ </p>
180
+ <ul className="list-disc list-inside space-y-2 text-zinc-400 mb-8 ml-2">
181
+ <li><strong className="text-white">Left panel</strong>: Your projects</li>
182
+ <li><strong className="text-white">Right panel</strong>: Workspaces in the selected project</li>
183
+ </ul>
184
+
185
+ <h3 className="text-xl font-semibold text-white mb-4">Key Bindings</h3>
186
+ <div className="overflow-x-auto">
187
+ <table className="w-full text-sm text-left text-zinc-400 mb-8">
188
+ <thead className="text-xs text-zinc-500 uppercase bg-zinc-900">
189
+ <tr>
190
+ <th className="px-4 py-3">Key</th>
191
+ <th className="px-4 py-3">Action</th>
192
+ </tr>
193
+ </thead>
194
+ <tbody>
195
+ <tr className="border-b border-zinc-800">
196
+ <td className="px-4 py-3 font-mono text-green-400">Enter</td>
197
+ <td className="px-4 py-3">Select project / Open workspace</td>
198
+ </tr>
199
+ <tr className="border-b border-zinc-800">
200
+ <td className="px-4 py-3 font-mono text-green-400">Tab</td>
201
+ <td className="px-4 py-3">Switch between panels</td>
202
+ </tr>
203
+ <tr className="border-b border-zinc-800">
204
+ <td className="px-4 py-3 font-mono text-green-400">n</td>
205
+ <td className="px-4 py-3">New project / workspace</td>
206
+ </tr>
207
+ <tr className="border-b border-zinc-800">
208
+ <td className="px-4 py-3 font-mono text-green-400">d</td>
209
+ <td className="px-4 py-3">Delete selected item</td>
210
+ </tr>
211
+ <tr className="border-b border-zinc-800">
212
+ <td className="px-4 py-3 font-mono text-green-400">?</td>
213
+ <td className="px-4 py-3">Show help</td>
214
+ </tr>
215
+ <tr className="border-b border-zinc-800">
216
+ <td className="px-4 py-3 font-mono text-green-400">q</td>
217
+ <td className="px-4 py-3">Quit</td>
218
+ </tr>
219
+ </tbody>
220
+ </table>
221
+ </div>
222
+ </div>
223
+ );
224
+
225
+ case "cli-commands":
226
+ return (
227
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
228
+ <h1 className="text-4xl font-bold mb-6">CLI Commands</h1>
229
+
230
+ <h3 className="text-xl font-semibold text-white mb-4">Projects</h3>
231
+ <CodeBlock code={`gssh add project # Add from GitHub (interactive)
232
+ gssh add project --org myorg # Filter by organization
233
+ gssh switch project myapp # Switch to a project
234
+ gssh list projects # List all projects
235
+ gssh remove project myapp # Remove a project`} multiLine language="bash" />
236
+
237
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">Workspaces</h3>
238
+ <CodeBlock code={`gssh add my-feature # Create workspace
239
+ gssh add --from develop # Create from specific branch
240
+ gssh switch my-feature # Switch to workspace
241
+ gssh switch # Interactive selection
242
+ gssh list # List workspaces
243
+ gssh remove workspace my-feature`} multiLine language="bash" />
244
+
245
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">Other Commands</h3>
246
+ <CodeBlock code={`gssh directory # Print current project path
247
+ gssh status # Show daemon statuses`} multiLine language="bash" />
248
+
249
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">Command Options</h3>
250
+
251
+ <h4 className="text-lg font-medium text-zinc-300 mb-3">Options for <code className="text-green-400">gssh add project</code></h4>
252
+ <ul className="list-disc list-inside space-y-2 text-zinc-400 mb-6 ml-2 text-sm">
253
+ <li><code className="text-zinc-300">--bundle-url &lt;url&gt;</code> - Load bundle from remote URL (zip archive)</li>
254
+ <li><code className="text-zinc-300">--bundle-path &lt;path&gt;</code> - Load bundle from local directory</li>
255
+ <li><code className="text-zinc-300">--skip-bundle</code> - Skip bundle detection and onboarding</li>
256
+ <li><code className="text-zinc-300">--no-clone</code> - Create project structure without cloning</li>
257
+ <li><code className="text-zinc-300">--org &lt;org&gt;</code> - Filter repos to specific organization</li>
258
+ <li><code className="text-zinc-300">--linear-key &lt;key&gt;</code> - Provide Linear API key via flag</li>
259
+ </ul>
260
+
261
+ <h4 className="text-lg font-medium text-zinc-300 mb-3">Options for <code className="text-green-400">gssh add [workspace-name]</code></h4>
262
+ <ul className="list-disc list-inside space-y-2 text-zinc-400 mb-6 ml-2 text-sm">
263
+ <li><code className="text-zinc-300">--branch &lt;name&gt;</code> - Specify different branch name from workspace name</li>
264
+ <li><code className="text-zinc-300">--from &lt;branch&gt;</code> - Create from specific branch instead of base</li>
265
+ <li><code className="text-zinc-300">--no-setup</code> - Skip setup commands</li>
266
+ </ul>
267
+
268
+ <h4 className="text-lg font-medium text-zinc-300 mb-3">Options for <code className="text-green-400">gssh remove workspace</code></h4>
269
+ <ul className="list-disc list-inside space-y-2 text-zinc-400 mb-6 ml-2 text-sm">
270
+ <li><code className="text-zinc-300">--force</code> - Skip confirmation prompts</li>
271
+ <li><code className="text-zinc-300">--keep-branch</code> - Don't delete git branch when removing</li>
272
+ </ul>
273
+ </div>
274
+ );
275
+
276
+ case "custom-scripts":
277
+ return (
278
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
279
+ <h1 className="text-4xl font-bold mb-6">Custom Scripts</h1>
280
+
281
+ <p className="text-zinc-400 mb-4">
282
+ GitSpace uses convention-based scripts in <code className="text-zinc-300">~/gitspace/&lt;project&gt;/scripts/</code>:
283
+ </p>
284
+
285
+ <div className="bg-zinc-900 rounded-lg border border-zinc-800 p-4 font-mono text-sm mb-8">
286
+ <pre className="text-zinc-300">{`scripts/
287
+ ├── pre/ # Run before setup (once)
288
+ ├── setup/ # Run on workspace creation (once)
289
+ ├── select/ # Run every time workspace is opened
290
+ └── remove/ # Run before workspace deletion`}</pre>
291
+ </div>
292
+
293
+ <h3 className="text-xl font-semibold text-white mb-4">Rules</h3>
294
+ <ul className="list-disc list-inside space-y-2 text-zinc-400 mb-8 ml-2">
295
+ <li>Scripts must be executable (<code className="text-zinc-300">chmod +x</code>)</li>
296
+ <li>Run alphabetically (use <code className="text-zinc-300">01-</code>, <code className="text-zinc-300">02-</code> prefixes)</li>
297
+ <li>Working directory: the workspace</li>
298
+ <li>Arguments: <code className="text-zinc-300">$1</code> = workspace name, <code className="text-zinc-300">$2</code> = repository</li>
299
+ </ul>
300
+
301
+ <h3 className="text-xl font-semibold text-white mb-4">Example Script</h3>
302
+ <p className="text-zinc-500 text-sm mb-2">scripts/select/01-status.sh</p>
303
+ <JsonBlock code={`#!/bin/bash
304
+ echo "Switching to: $1"
305
+ git fetch origin
306
+ git status`} />
307
+ </div>
308
+ );
309
+
310
+ case "repo-bundles":
311
+ return (
312
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
313
+ <h1 className="text-4xl font-bold mb-6">Repo Config Bundles</h1>
314
+
315
+ <p className="text-zinc-400 mb-4">
316
+ Bundles allow teams to share onboarding configurations. Place in <code className="text-zinc-300">.gitspace/</code>:
317
+ </p>
318
+
319
+ <div className="bg-zinc-900 rounded-lg border border-zinc-800 p-4 font-mono text-sm mb-8">
320
+ <pre className="text-zinc-300">{`.gitspace/
321
+ ├── bundle.json # Manifest
322
+ ├── pre/ # Pre-setup scripts
323
+ ├── setup/ # Setup scripts
324
+ └── select/ # Select scripts`}</pre>
325
+ </div>
326
+
327
+ <h3 className="text-xl font-semibold text-white mb-4">Manifest Example</h3>
328
+ <JsonBlock code={`{
329
+ "version": "1.0",
330
+ "name": "my-app-bundle",
331
+ "onboarding": [
332
+ { "id": "node", "type": "confirm", "title": "Node.js", "checkCommand": "node" },
333
+ { "id": "api-key", "type": "secret", "title": "API Key", "configKey": "apiKey" }
334
+ ]
335
+ }`} />
336
+
337
+ <h3 className="text-xl font-semibold text-white mb-4">Step Types</h3>
338
+ <div className="overflow-x-auto">
339
+ <table className="w-full text-sm text-left text-zinc-400 mb-8">
340
+ <thead className="text-xs text-zinc-500 uppercase bg-zinc-900">
341
+ <tr>
342
+ <th className="px-4 py-3">Type</th>
343
+ <th className="px-4 py-3">Purpose</th>
344
+ <th className="px-4 py-3">Storage</th>
345
+ </tr>
346
+ </thead>
347
+ <tbody>
348
+ <tr className="border-b border-zinc-800">
349
+ <td className="px-4 py-3 font-mono text-green-400">info</td>
350
+ <td className="px-4 py-3">Display information</td>
351
+ <td className="px-4 py-3">N/A</td>
352
+ </tr>
353
+ <tr className="border-b border-zinc-800">
354
+ <td className="px-4 py-3 font-mono text-green-400">confirm</td>
355
+ <td className="px-4 py-3">Verify installation</td>
356
+ <td className="px-4 py-3">N/A</td>
357
+ </tr>
358
+ <tr className="border-b border-zinc-800">
359
+ <td className="px-4 py-3 font-mono text-green-400">secret</td>
360
+ <td className="px-4 py-3">Sensitive values</td>
361
+ <td className="px-4 py-3">OS Keychain</td>
362
+ </tr>
363
+ <tr className="border-b border-zinc-800">
364
+ <td className="px-4 py-3 font-mono text-green-400">input</td>
365
+ <td className="px-4 py-3">Plain text</td>
366
+ <td className="px-4 py-3">Config file</td>
367
+ </tr>
368
+ </tbody>
369
+ </table>
370
+ </div>
371
+
372
+ <h3 className="text-xl font-semibold text-white mb-4">Using Values in Scripts</h3>
373
+ <JsonBlock code={`echo "Team: $SPACE_VALUE_TEAMNAME"
374
+ echo "Has API key: $SPACE_SECRET_APIKEY"`} />
375
+ </div>
376
+ );
377
+
378
+ case "gitspace-managed":
379
+ return (
380
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
381
+ <h1 className="text-4xl font-bold mb-6">gitspace.sh (Managed)</h1>
382
+
383
+ <p className="text-zinc-400 mb-6">
384
+ The easiest way to get remote access:
385
+ </p>
386
+
387
+ <CodeBlock code={`# 1. Create identity
388
+ gssh identity init
389
+
390
+ # 2. Login with GitHub
391
+ gssh auth login
392
+
393
+ # 3. Reserve subdomain
394
+ gssh host reserve yourname
395
+
396
+ # 4. Start serving
397
+ gssh serve
398
+
399
+ # 5. Access: https://yourname.gitspace.sh`} multiLine />
400
+
401
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">Manage Subdomains</h3>
402
+ <CodeBlock code={`gssh host list # List your subdomains
403
+ gssh host set-primary name # Set primary
404
+ gssh host release name # Release subdomain
405
+ gssh host status # Show status`} multiLine language="bash" />
406
+ </div>
407
+ );
408
+
409
+ case "self-hosted-relay":
410
+ return (
411
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
412
+ <h1 className="text-4xl font-bold mb-6">Self-Hosted Relay</h1>
413
+
414
+ <p className="text-zinc-400 mb-6">For complete control, run your own relay:</p>
415
+
416
+ <h3 className="text-xl font-semibold text-white mb-4">1. Start Relay</h3>
417
+ <CodeBlock code="gssh relay start --port 4480" />
418
+
419
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">2. Authorize Machine</h3>
420
+ <CodeBlock
421
+ code={`# On the machine
422
+ gssh identity init --label "My Mac"
423
+ gssh identity show
424
+
425
+ # On the relay host
426
+ gssh relay authorize gssh-pub:<keys> --label "My Mac"`}
427
+ multiLine
428
+ />
429
+
430
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">3. Serve</h3>
431
+ <CodeBlock code="gssh serve --relay ws://localhost:4480/ws" />
432
+
433
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">4. Create Invite</h3>
434
+ <CodeBlock code="gssh share create" />
435
+ <p className="text-zinc-500 text-sm mt-2">Output: <code className="text-green-400">https://gitspace.sh/join#&lt;TOKEN&gt;</code></p>
436
+
437
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">5. Connect from Client</h3>
438
+ <CodeBlock code={`gssh identity init --label "Laptop"
439
+ gssh connect https://gitspace.sh/join#<TOKEN>`} multiLine />
440
+ </div>
441
+ );
442
+
443
+ case "identity-management":
444
+ return (
445
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
446
+ <h1 className="text-4xl font-bold mb-6">Identity Management</h1>
447
+
448
+ <p className="text-zinc-400 mb-6">
449
+ Every machine and client has a cryptographic identity:
450
+ </p>
451
+
452
+ <CodeBlock code={`gssh identity init [--label <name>] [--force]
453
+ gssh identity show [--fingerprint] [--json]`} multiLine language="bash" />
454
+
455
+ <p className="text-zinc-500 text-sm mt-4">
456
+ Identity storage: <code className="text-zinc-300">~/gitspace/.identity/</code>
457
+ </p>
458
+
459
+ <p className="text-zinc-400 mt-8 mb-4">
460
+ Identity is encrypted at rest and requires an unlock password when used for remote connections.
461
+ </p>
462
+ </div>
463
+ );
464
+
465
+ case "access-control":
466
+ return (
467
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
468
+ <h1 className="text-4xl font-bold mb-6">Access Control</h1>
469
+
470
+ <h3 className="text-xl font-semibold text-white mb-4">Grant Access</h3>
471
+ <CodeBlock code={`gssh access add gssh-pub:<keys> --label "Brad's Phone"`} />
472
+
473
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">Manage Access</h3>
474
+ <CodeBlock code={`gssh access list [--json]
475
+ gssh access remove "Brad's Phone"
476
+ gssh access remove <key-prefix> --force`} multiLine language="bash" />
477
+
478
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">Connect Without Invite (Pre-Authorized)</h3>
479
+ <CodeBlock code="gssh --relay ws://relay.example.com/ws" />
480
+
481
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">Public Key Format</h3>
482
+ <p className="text-zinc-400 mb-4 text-sm">
483
+ Public keys are displayed in this format:
484
+ </p>
485
+ <div className="bg-zinc-900 rounded-lg border border-zinc-800 p-4 font-mono text-sm text-green-400 break-all">
486
+ gssh-pub:&lt;BASE64_SIGNING_PUBLIC_KEY&gt;:&lt;BASE64_KEY_EXCHANGE_PUBLIC_KEY&gt;
487
+ </div>
488
+ </div>
489
+ );
490
+
491
+ case "configuration":
492
+ return (
493
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
494
+ <h1 className="text-4xl font-bold mb-6">Configuration</h1>
495
+
496
+ <h3 className="text-xl font-semibold text-white mb-4">Global Config</h3>
497
+ <p className="text-zinc-500 text-sm mb-2">~/gitspace/.config.json</p>
498
+ <JsonBlock code={`{
499
+ "currentProject": "my-app",
500
+ "projectsDir": "/Users/username/gitspace",
501
+ "defaultBaseBranch": "main"
502
+ }`} />
503
+
504
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">Project Config</h3>
505
+ <p className="text-zinc-500 text-sm mb-2">~/gitspace/&lt;project&gt;/.config.json</p>
506
+ <JsonBlock code={`{
507
+ "name": "my-app",
508
+ "repository": "myorg/my-app",
509
+ "baseBranch": "main"
510
+ }`} />
511
+
512
+ <h3 className="text-xl font-semibold text-white mb-4 mt-8">Environment Variables</h3>
513
+ <div className="overflow-x-auto">
514
+ <table className="w-full text-sm text-left text-zinc-400 mb-8">
515
+ <thead className="text-xs text-zinc-500 uppercase bg-zinc-900">
516
+ <tr>
517
+ <th className="px-4 py-3">Variable</th>
518
+ <th className="px-4 py-3">Description</th>
519
+ <th className="px-4 py-3">Default</th>
520
+ </tr>
521
+ </thead>
522
+ <tbody>
523
+ <tr className="border-b border-zinc-800">
524
+ <td className="px-4 py-3 font-mono text-green-400">RELAY_PORT</td>
525
+ <td className="px-4 py-3">Relay port</td>
526
+ <td className="px-4 py-3">4480</td>
527
+ </tr>
528
+ <tr className="border-b border-zinc-800">
529
+ <td className="px-4 py-3 font-mono text-green-400">SPACES_CURRENT_PROJECT</td>
530
+ <td className="px-4 py-3">Override project</td>
531
+ <td className="px-4 py-3">Config</td>
532
+ </tr>
533
+ </tbody>
534
+ </table>
535
+ </div>
536
+ </div>
537
+ );
538
+
539
+ case "troubleshooting":
540
+ return (
541
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
542
+ <h1 className="text-4xl font-bold mb-6">Troubleshooting</h1>
543
+
544
+ <div className="space-y-8">
545
+ <div className="p-4 rounded-lg border border-zinc-800 bg-zinc-900/50">
546
+ <h4 className="text-white font-bold mb-2">"command not found: gssh"</h4>
547
+ <p className="text-zinc-400 text-sm mb-2">Ensure Bun's global bin is in your PATH:</p>
548
+ <CodeBlock code={`export PATH="$HOME/.bun/bin:$PATH"`} />
549
+ <p className="text-zinc-500 text-sm">Add to your shell profile (<code className="text-zinc-300">~/.zshrc</code>, <code className="text-zinc-300">~/.bashrc</code>)</p>
550
+ </div>
551
+
552
+ <div className="p-4 rounded-lg border border-zinc-800 bg-zinc-900/50">
553
+ <h4 className="text-white font-bold mb-2">"No identity found"</h4>
554
+ <CodeBlock code="gssh identity init --label 'My Device'" />
555
+ </div>
556
+
557
+ <div className="p-4 rounded-lg border border-zinc-800 bg-zinc-900/50">
558
+ <h4 className="text-white font-bold mb-2">"Failed to unlock identity"</h4>
559
+ <p className="text-zinc-400 text-sm mb-2">You're entering the wrong password. If forgotten, recreate:</p>
560
+ <CodeBlock code="gssh identity init --force" />
561
+ <p className="text-zinc-500 text-sm">Warning: This invalidates existing invites and access grants</p>
562
+ </div>
563
+
564
+ <div className="p-4 rounded-lg border border-zinc-800 bg-zinc-900/50">
565
+ <h4 className="text-white font-bold mb-2">"Machine offline"</h4>
566
+ <ul className="list-disc list-inside text-zinc-400 text-sm space-y-1 ml-2">
567
+ <li>Ensure <code className="text-zinc-300">gssh serve</code> is running on the target machine</li>
568
+ <li>Check the machine can reach the relay URL</li>
569
+ <li>Verify the machine is authorized on the relay</li>
570
+ </ul>
571
+ </div>
572
+
573
+ <div className="p-4 rounded-lg border border-zinc-800 bg-zinc-900/50">
574
+ <h4 className="text-white font-bold mb-2">"Client not authorized"</h4>
575
+ <p className="text-zinc-400 text-sm mb-2">You need an invite or your public key must be added:</p>
576
+ <CodeBlock code="gssh access add <your-public-key> --label 'Name'" />
577
+ </div>
578
+
579
+ <div className="p-4 rounded-lg border border-zinc-800 bg-zinc-900/50">
580
+ <h4 className="text-white font-bold mb-2">"Invite expired"</h4>
581
+ <p className="text-zinc-400 text-sm mb-2">Create a new invite with longer expiration:</p>
582
+ <CodeBlock code="gssh share create --expires 7d" />
583
+ </div>
584
+
585
+ <div className="p-4 rounded-lg border border-zinc-800 bg-zinc-900/50">
586
+ <h4 className="text-white font-bold mb-2">"GitHub CLI not authenticated"</h4>
587
+ <CodeBlock code="gh auth login" />
588
+ </div>
589
+ </div>
590
+ </div>
591
+ );
592
+
593
+ case "security":
594
+ return (
595
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
596
+ <h1 className="text-4xl font-bold mb-6">Security</h1>
597
+
598
+ <div className="space-y-8">
599
+ <div className="p-6 rounded-xl bg-green-500/5 border border-green-500/20">
600
+ <h3 className="font-bold text-green-400 mb-2">End-to-End Encrypted</h3>
601
+ <p className="text-zinc-400 text-sm leading-relaxed">
602
+ Terminal traffic encrypted with AES-256-GCM. Relay cannot decrypt.
603
+ </p>
604
+ </div>
605
+
606
+ <div className="p-6 rounded-xl bg-blue-500/5 border border-blue-500/20">
607
+ <h3 className="font-bold text-blue-400 mb-2">Cryptographic Identity</h3>
608
+ <p className="text-zinc-400 text-sm leading-relaxed">
609
+ Ed25519 signing + X25519 key exchange. No passwords for authentication.
610
+ </p>
611
+ </div>
612
+
613
+ <div className="p-6 rounded-xl bg-purple-500/5 border border-purple-500/20">
614
+ <h3 className="font-bold text-purple-400 mb-2">X3DH Handshake</h3>
615
+ <p className="text-zinc-400 text-sm leading-relaxed">
616
+ Session keys derived per-connection for forward secrecy.
617
+ </p>
618
+ </div>
619
+
620
+ <div className="p-6 rounded-xl bg-yellow-500/5 border border-yellow-500/20">
621
+ <h3 className="font-bold text-yellow-500 mb-3">Current Limitations</h3>
622
+ <ul className="list-disc list-inside space-y-3 text-zinc-400 text-sm leading-relaxed">
623
+ <li>
624
+ <strong className="text-white">Client proof-of-possession</strong>: 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.
625
+ </li>
626
+ <li>
627
+ <strong className="text-white">Permission enforcement</strong>: Permission flags (<code className="text-zinc-300">read</code>/<code className="text-zinc-300">write</code>/<code className="text-zinc-300">manage</code>) 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.
628
+ </li>
629
+ </ul>
630
+ <p className="text-zinc-500 text-sm mt-4">These limitations are being addressed in future releases.</p>
631
+ </div>
632
+ </div>
633
+ </div>
634
+ );
635
+
636
+ case "glossary":
637
+ return (
638
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
639
+ <h1 className="text-4xl font-bold mb-6">Glossary</h1>
640
+
641
+ <dl className="grid gap-6">
642
+ <div>
643
+ <dt className="text-white font-bold mb-1">Machine</dt>
644
+ <dd className="text-zinc-400 text-sm">Device running <code className="text-zinc-300">gssh serve</code></dd>
645
+ </div>
646
+ <div>
647
+ <dt className="text-white font-bold mb-1">Client</dt>
648
+ <dd className="text-zinc-400 text-sm">Device connecting via browser or CLI</dd>
649
+ </div>
650
+ <div>
651
+ <dt className="text-white font-bold mb-1">Relay</dt>
652
+ <dd className="text-zinc-400 text-sm">WebSocket router (default: <code className="text-zinc-300">wss://relay.gitspace.sh</code>)</dd>
653
+ </div>
654
+ <div>
655
+ <dt className="text-white font-bold mb-1">Relay Identity</dt>
656
+ <dd className="text-zinc-400 text-sm">Ed25519 keypair used by the relay to sign messages and challenges</dd>
657
+ </div>
658
+ <div>
659
+ <dt className="text-white font-bold mb-1">Authorized Machine</dt>
660
+ <dd className="text-zinc-400 text-sm">Machine public key approved to register with a relay</dd>
661
+ </div>
662
+ <div>
663
+ <dt className="text-white font-bold mb-1">Identity</dt>
664
+ <dd className="text-zinc-400 text-sm">Ed25519 signing + X25519 key exchange keypairs, encrypted at rest</dd>
665
+ </div>
666
+ <div>
667
+ <dt className="text-white font-bold mb-1">Invite</dt>
668
+ <dd className="text-zinc-400 text-sm">Signed token that bootstraps trust and enables first connection</dd>
669
+ </div>
670
+ <div>
671
+ <dt className="text-white font-bold mb-1">ACL (Access Control List)</dt>
672
+ <dd className="text-zinc-400 text-sm">Machine-managed list of authorized client identities</dd>
673
+ </div>
674
+ <div>
675
+ <dt className="text-white font-bold mb-1">X3DH</dt>
676
+ <dd className="text-zinc-400 text-sm">Extended Triple Diffie-Hellman handshake for session key establishment</dd>
677
+ </div>
678
+ <div>
679
+ <dt className="text-white font-bold mb-1">PTY</dt>
680
+ <dd className="text-zinc-400 text-sm">Pseudo-terminal, the interface between your shell and the terminal</dd>
681
+ </div>
682
+ <div>
683
+ <dt className="text-white font-bold mb-1">Worktree</dt>
684
+ <dd className="text-zinc-400 text-sm">Git feature allowing multiple working directories for one repository</dd>
685
+ </div>
686
+ <div>
687
+ <dt className="text-white font-bold mb-1">Bundle</dt>
688
+ <dd className="text-zinc-400 text-sm">Repository configuration package for team onboarding</dd>
689
+ </div>
690
+ <div>
691
+ <dt className="text-white font-bold mb-1">Session</dt>
692
+ <dd className="text-zinc-400 text-sm">A terminal session managed by tmux-lite on the server</dd>
693
+ </div>
694
+ <div>
695
+ <dt className="text-white font-bold mb-1">TUI</dt>
696
+ <dd className="text-zinc-400 text-sm">Terminal User Interface, the interactive <code className="text-zinc-300">gssh</code> interface</dd>
697
+ </div>
698
+ <div>
699
+ <dt className="text-white font-bold mb-1">tmux-lite</dt>
700
+ <dd className="text-zinc-400 text-sm">Built-in terminal multiplexer for managing sessions</dd>
701
+ </div>
702
+ <div>
703
+ <dt className="text-white font-bold mb-1">Subdomain</dt>
704
+ <dd className="text-zinc-400 text-sm">Your custom URL on gitspace.sh (e.g., <code className="text-zinc-300">yourname.gitspace.sh</code>)</dd>
705
+ </div>
706
+ </dl>
707
+ </div>
708
+ );
709
+
710
+ default:
711
+ return (
712
+ <div className="max-w-3xl animate-in fade-in slide-in-from-bottom-4 duration-500">
713
+ <h1 className="text-4xl font-bold mb-6">Documentation</h1>
714
+ <p className="text-zinc-400">Select a section from the sidebar to get started.</p>
715
+ </div>
716
+ );
717
+ }
718
+ }