gitspace 0.2.0-rc.12 → 0.2.0-rc.14

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 (190) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/.gitspace/select/01-status.sh +6 -7
  3. package/AGENTS.md +10 -11
  4. package/README.md +38 -39
  5. package/bun.lock +7 -6
  6. package/docs/CONNECTION.md +1 -1
  7. package/docs/REMOTE-DESIGN.md +15 -10
  8. package/docs/ROADMAP.md +1 -1
  9. package/docs/SITE_DOCS_FIGMA_MAKE.md +45 -39
  10. package/docs/UNIFIED_ARCHITECTURE.md +135 -289
  11. package/landing-page/src/components/docs/DocsContent.tsx +14 -11
  12. package/package.json +7 -6
  13. package/scripts/build.ts +3 -3
  14. package/src/app/input/__tests__/sessionCommands.test.ts +40 -0
  15. package/src/app/input/sessionCommands.ts +94 -0
  16. package/src/app/session/__tests__/useAttachController.test.ts +202 -0
  17. package/src/app/session/createSessionBackend.bun.ts +76 -0
  18. package/src/app/session/createSessionBackend.web.ts +104 -0
  19. package/src/app/session/types.ts +16 -0
  20. package/src/app/session/useAttachController.ts +212 -0
  21. package/src/app/session/useSessionClient.ts +35 -0
  22. package/src/app.tui.tsx +2591 -0
  23. package/src/{web/src/App.tsx → app.web.tsx} +311 -130
  24. package/src/commands/__tests__/connect-key.test.ts +10 -0
  25. package/src/commands/add.ts +27 -39
  26. package/src/commands/bundle.ts +12 -1
  27. package/src/commands/connect-key.ts +1 -0
  28. package/src/commands/connect.ts +363 -74
  29. package/src/commands/list.ts +6 -25
  30. package/src/commands/switch.ts +7 -5
  31. package/src/{web/src/components/DPad.tsx → components/DPad.web.tsx} +1 -2
  32. package/src/{web/src/components/FloatingControls.tsx → components/FloatingControls.web.tsx} +2 -2
  33. package/src/{web/src/components/FloatingJogWheel.tsx → components/FloatingJogWheel.web.tsx} +2 -2
  34. package/src/{shared/components → components}/Flow.tsx +12 -7
  35. package/src/{shared/components → components}/MachineList.tsx +4 -4
  36. package/src/{web/src/components/NumPad.tsx → components/NumPad.web.tsx} +1 -2
  37. package/src/{shared/components → components}/ProjectList.tsx +4 -5
  38. package/src/components/ProjectOnboardingStep.ts +23 -0
  39. package/src/components/ProjectOnboardingStep.tui.tsx +88 -0
  40. package/src/components/ProjectOnboardingStep.web.tsx +59 -0
  41. package/src/components/RemoteMachineScreen.tui.tsx +392 -0
  42. package/src/components/ScriptTerminal.tui.tsx +160 -0
  43. package/src/components/ScriptTerminal.web.tsx +89 -0
  44. package/src/components/SessionTerminal.tui.tsx +361 -0
  45. package/src/components/SessionTerminal.web.tsx +312 -0
  46. package/src/{shared/components → components}/SpacesBrowser.tsx +18 -17
  47. package/src/{web/src/components/TerminalControls.tsx → components/TerminalControls.web.tsx} +2 -3
  48. package/src/components/__tests__/script-terminal-buffer.tui.test.ts +72 -0
  49. package/src/components/script-terminal-buffer.tui.ts +37 -0
  50. package/src/{tui/terminal-bracketed-paste.test.ts → components/terminal-bracketed-paste.tui.test.ts} +1 -3
  51. package/src/{tui/terminal-bracketed-paste.ts → components/terminal-bracketed-paste.tui.ts} +0 -1
  52. package/src/core/__tests__/bundle-refresh.test.ts +392 -221
  53. package/src/core/__tests__/project-lifecycle.test.ts +137 -0
  54. package/src/core/__tests__/workspace-lifecycle.test.ts +136 -0
  55. package/src/core/bundle-refresh.ts +840 -127
  56. package/src/core/preferences-service.ts +17 -0
  57. package/src/core/project-catalog.ts +52 -0
  58. package/src/core/project-lifecycle.ts +163 -0
  59. package/src/core/shell.ts +18 -66
  60. package/src/core/workspace-lifecycle.ts +194 -0
  61. package/src/core/workspace.ts +25 -1
  62. package/src/hooks/__tests__/useLocalSession.tui.test.ts +544 -0
  63. package/src/hooks/index.ts +8 -0
  64. package/src/{tui/hooks/index.ts → hooks/index.tui.ts} +8 -11
  65. package/src/{tui/hooks/useDaemonStatus.ts → hooks/useDaemonStatus.tui.ts} +2 -2
  66. package/src/hooks/useLocalSession.tui.ts +356 -0
  67. package/src/hooks/useRelayConnection.web.ts +54 -0
  68. package/src/hooks/useRemoteMachines.tui.ts +166 -0
  69. package/src/hooks/useRemoteTerminal.tui.ts +22 -0
  70. package/src/hooks/useTerminal.web.ts +36 -0
  71. package/src/hooks/useUserActivity.ts +61 -0
  72. package/src/lib/preferences-service.web.ts +41 -0
  73. package/src/lib/remote-session/protocol.ts +66 -2
  74. package/src/lib/remote-session/session-handler.ts +188 -16
  75. package/src/lib/remote-session/workspace-scanner.ts +1 -7
  76. package/src/lib/sonner.web.ts +1 -0
  77. package/src/{web/src/lib/storage/identity-store.ts → lib/storage/identity-store.web.ts} +1 -1
  78. package/src/lib/tmux-lite/cli.ts +1 -9
  79. package/src/lib/tmux-lite/server-lifecycle.test.ts +4 -0
  80. package/src/{shared/notifications → notifications}/__tests__/useNotifications.test.ts +1 -1
  81. package/src/{shared/notifications → notifications}/policy.test.ts +7 -7
  82. package/src/{shared/notifications → notifications}/policy.ts +1 -1
  83. package/src/{shared/notifications → notifications}/types.ts +1 -1
  84. package/src/{shared/notifications → notifications}/useNotifications.ts +1 -1
  85. package/src/preferences/index.ts +1 -0
  86. package/src/preferences/types.ts +9 -0
  87. package/src/relay/server.ts +56 -22
  88. package/src/relay-client/__tests__/machine-directory-client.test.ts +152 -0
  89. package/src/relay-client/__tests__/useMachineDirectory.test.ts +172 -0
  90. package/src/relay-client/adapters/browser.ts +27 -0
  91. package/src/relay-client/adapters/node.ts +29 -0
  92. package/src/relay-client/index.ts +33 -0
  93. package/src/relay-client/machine-directory-client.ts +244 -0
  94. package/src/relay-client/useMachineDirectory.ts +175 -0
  95. package/src/session/__tests__/backend-manager.test.ts +89 -0
  96. package/src/session/__tests__/local-session-backend.test.ts +977 -0
  97. package/src/session/__tests__/reducer.test.ts +80 -0
  98. package/src/session/__tests__/remote-session-backend.test.ts +567 -0
  99. package/src/session/__tests__/useBundleRefreshAttachFlow.test.ts +431 -0
  100. package/src/session/__tests__/useRemoteSessionClient.test.ts +412 -0
  101. package/src/session/adapters/browser-remote.ts +101 -0
  102. package/src/session/adapters/node-remote.ts +135 -0
  103. package/src/session/backend-key.ts +5 -0
  104. package/src/session/backend-manager.ts +80 -0
  105. package/src/session/backend.ts +65 -0
  106. package/src/session/backends/local-session-backend.ts +839 -0
  107. package/src/session/backends/remote-session-backend.ts +980 -0
  108. package/src/{web/src/lib → session}/crypto/__tests__/web-terminal.test.ts +13 -13
  109. package/src/{web/src/lib/crypto/handshake.ts → session/crypto/handshake.web.ts} +2 -2
  110. package/src/{web/src/lib/crypto/identity.ts → session/crypto/identity.web.ts} +6 -1
  111. package/src/{web/src/lib/crypto/relay-signing.ts → session/crypto/relay-signing.web.ts} +1 -1
  112. package/src/session/events.ts +29 -0
  113. package/src/session/index.ts +115 -0
  114. package/src/session/reducer.ts +240 -0
  115. package/src/session/selectors.ts +28 -0
  116. package/src/session/types.ts +85 -0
  117. package/src/session/useBundleRefreshAttachFlow.ts +606 -0
  118. package/src/session/useRemoteSessionClient.ts +351 -0
  119. package/src/session/useSessionEngine.ts +310 -0
  120. package/src/tui/__tests__/input-text.test.ts +24 -0
  121. package/src/tui/__tests__/local-terminal-sync.test.ts +82 -0
  122. package/src/tui/app.tsx +2 -2555
  123. package/src/tui/index.ts +7 -13
  124. package/src/tui/input-text.ts +38 -0
  125. package/src/tui/local-terminal-sync.ts +41 -0
  126. package/src/types/bundle-refresh.ts +42 -0
  127. package/src/types/bundle.ts +21 -3
  128. package/src/types/config.ts +38 -14
  129. package/src/types/errors.ts +4 -2
  130. package/src/types/script-phase.ts +3 -0
  131. package/src/utils/__tests__/onboarding.test.ts +30 -24
  132. package/src/utils/__tests__/run-scripts.test.ts +80 -7
  133. package/src/utils/__tests__/run-workspace-scripts.test.ts +188 -26
  134. package/src/utils/__tests__/workspace-setup.integration.test.ts +563 -0
  135. package/src/utils/__tests__/workspace-state.test.ts +78 -0
  136. package/src/utils/onboarding.ts +24 -10
  137. package/src/utils/run-scripts.ts +76 -12
  138. package/src/utils/run-workspace-scripts.ts +271 -27
  139. package/src/utils/workspace-state.ts +397 -33
  140. package/tsconfig.json +7 -1
  141. package/{src/web/src → web}/index.css +2 -0
  142. package/{src/web → web}/index.html +1 -1
  143. package/{src/web/src → web}/main.tsx +1 -1
  144. package/{src/web → web}/public/vite.svg +1 -1
  145. package/{src/web → web}/tsconfig.app.json +6 -1
  146. package/{src/web → web}/vite.config.ts +5 -0
  147. package/src/shared/hooks/index.ts +0 -16
  148. package/src/shared/hooks/useNavigation.ts +0 -226
  149. package/src/shared/index.ts +0 -122
  150. package/src/shared/providers/LocalMachineProvider.ts +0 -425
  151. package/src/shared/providers/MachineProvider.ts +0 -165
  152. package/src/shared/providers/RemoteMachineProvider.ts +0 -439
  153. package/src/shared/providers/index.ts +0 -26
  154. package/src/shared/types.ts +0 -145
  155. package/src/tui/adapters.ts +0 -120
  156. package/src/tui/components/ScriptTerminal.tsx +0 -211
  157. package/src/tui/components/Terminal.tsx +0 -698
  158. package/src/tui/hooks/useAppState.ts +0 -314
  159. package/src/tui/hooks/useInboxTUI.ts +0 -114
  160. package/src/tui/hooks/useRemoteMachines.ts +0 -208
  161. package/src/tui/state.ts +0 -316
  162. package/src/web/src/assets/react.svg +0 -1
  163. package/src/web/src/components/Terminal.tsx +0 -326
  164. package/src/web/src/hooks/useRelayConnection.ts +0 -224
  165. package/src/web/src/hooks/useTerminal.ts +0 -763
  166. package/src/web/src/types/identity.ts +0 -45
  167. /package/src/{shared/components → components}/Flow.tui.tsx +0 -0
  168. /package/src/{shared/components → components}/Flow.web.tsx +0 -0
  169. /package/src/{shared/components → components}/Inbox.tsx +0 -0
  170. /package/src/{shared/components → components}/Inbox.tui.tsx +0 -0
  171. /package/src/{shared/components → components}/Inbox.web.tsx +0 -0
  172. /package/src/{shared/components → components}/MachineList.tui.tsx +0 -0
  173. /package/src/{shared/components → components}/MachineList.web.tsx +0 -0
  174. /package/src/{shared/components → components}/ProjectList.tui.tsx +0 -0
  175. /package/src/{shared/components → components}/ProjectList.web.tsx +0 -0
  176. /package/src/{shared/components → components}/SpacesBrowser.tui.tsx +0 -0
  177. /package/src/{shared/components → components}/SpacesBrowser.web.tsx +0 -0
  178. /package/src/{shared/components → components}/index.ts +0 -0
  179. /package/src/{web/src/hooks/useVisualViewport.ts → hooks/useVisualViewport.web.ts} +0 -0
  180. /package/src/{web/src/lib/invite.ts → lib/invite.web.ts} +0 -0
  181. /package/src/{shared/notifications → notifications}/index.ts +0 -0
  182. /package/src/{web/src/lib/crypto/frames.ts → session/crypto/frames.web.ts} +0 -0
  183. /package/src/{web/src/lib/crypto/keyexchange.ts → session/crypto/keyexchange.web.ts} +0 -0
  184. /package/src/{web/src/utils/device.ts → utils/device.web.ts} +0 -0
  185. /package/{src/web → web}/README.md +0 -0
  186. /package/{src/web → web}/bun.lock +0 -0
  187. /package/{src/web → web}/eslint.config.js +0 -0
  188. /package/{src/web → web}/package.json +0 -0
  189. /package/{src/web → web}/tsconfig.json +0 -0
  190. /package/{src/web → web}/tsconfig.node.json +0 -0
@@ -3,7 +3,8 @@
3
3
  "allow": [
4
4
  "Bash(gh api:*)",
5
5
  "Bash(gh search code:*)",
6
- "Bash(curl:*)"
6
+ "Bash(curl:*)",
7
+ "Bash(bun scripts/build.ts:*)"
7
8
  ]
8
9
  }
9
10
  }
@@ -3,9 +3,8 @@
3
3
  #
4
4
  # This runs every time you switch to an existing workspace.
5
5
  #
6
- # Bundle values are available as environment variables:
7
- # SPACE_VALUE_<KEY> - Regular values from input steps
8
- # SPACE_SECRET_<KEY> - Secret values from secret steps
6
+ # Bundle values are available as environment variables using bundle key names.
7
+ # Example: DEVELOPERNAME, EXAMPLEAPITOKEN
9
8
 
10
9
  WORKSPACE_NAME=$1
11
10
  REPOSITORY=$2
@@ -15,14 +14,14 @@ echo "=== Workspace: $WORKSPACE_NAME ==="
15
14
  echo ""
16
15
 
17
16
  # Show bundle values (proof of concept)
18
- if [ -n "$SPACE_VALUE_DEVELOPERNAME" ]; then
19
- echo "Welcome back, $SPACE_VALUE_DEVELOPERNAME!"
17
+ if [ -n "$DEVELOPERNAME" ]; then
18
+ echo "Welcome back, $DEVELOPERNAME!"
20
19
  fi
21
20
 
22
21
  # Show that we have access to the secret (masked)
23
- if [ -n "$SPACE_SECRET_EXAMPLEAPITOKEN" ]; then
22
+ if [ -n "$EXAMPLEAPITOKEN" ]; then
24
23
  # Only show first 4 characters to prove we have access
25
- TOKEN_PREVIEW="${SPACE_SECRET_EXAMPLEAPITOKEN:0:4}..."
24
+ TOKEN_PREVIEW="${EXAMPLEAPITOKEN:0:4}..."
26
25
  echo "API Token available: $TOKEN_PREVIEW (stored in OS keychain)"
27
26
  fi
28
27
 
package/AGENTS.md CHANGED
@@ -14,7 +14,7 @@ This document provides comprehensive information for AI assistants working on th
14
14
  - **X3DH handshake** for forward-secret session encryption
15
15
  - Web terminal interface (React + xterm.js)
16
16
  - Linear issue integration for workspace creation
17
- - Convention-based custom scripts in `.gitspace/` (pre, setup, select, remove phases)
17
+ - Convention-based custom scripts in `.gitspace/scripts/` (pre, setup, select, remove phases)
18
18
 
19
19
  ## Architecture
20
20
 
@@ -27,7 +27,7 @@ This document provides comprehensive information for AI assistants working on th
27
27
  2. **Workspaces**: Individual git worktrees for features/branches
28
28
  - Located at `~/gitspace/<project-name>/workspaces/<workspace-name>/`
29
29
  - Each workspace has its own branch
30
- - Scripts are sourced from `.gitspace/<phase>/` in the workspace (version-controlled)
30
+ - Scripts are sourced from `.gitspace/scripts/<phase>/` in the workspace (version-controlled)
31
31
 
32
32
  3. **Sessions**: PTY terminal sessions managed by tmux-lite
33
33
  - Can be attached from multiple clients
@@ -128,22 +128,21 @@ src/
128
128
  │ │ └── ProjectList.tui.tsx
129
129
  │ ├── providers/ # Machine access abstraction
130
130
  │ │ ├── MachineProvider.ts # Interface definition
131
- │ │ ├── LocalMachineProvider.ts # Direct tmux-lite access
132
- │ │ └── RemoteMachineProvider.ts # Via relay
131
+ │ │ └── LocalMachineProvider.ts # Direct tmux-lite access
133
132
  │ ├── hooks/
134
- │ │ └── useNavigation.ts # Navigation state management
133
+ │ │ └── useUserActivity.ts # Activity tracking for notifications
135
134
  │ └── types.ts # Shared type definitions
136
135
  ├── tui/ # Terminal UI (OpenTUI)
137
136
  │ ├── index.ts # TUI entry point
138
137
  │ ├── app.tsx # Main TUI application
139
- │ ├── state.ts # State management
140
- │ ├── adapters.ts # Local/remote machine adapters
141
138
  │ ├── components/
142
- │ │ └── Terminal.tsx # Embedded terminal
139
+ │ │ ├── RemoteMachineScreen.tsx # Remote machine browser screen
140
+ │ │ └── RemoteTerminal.tsx # Embedded session terminal
143
141
  │ └── hooks/
144
- │ ├── useAppState.ts
145
142
  │ ├── useRemoteMachines.ts
146
- └── useInboxTUI.ts
143
+ ├── useRemoteTerminal.ts
144
+ │ ├── useLocalSession.ts
145
+ │ └── useDaemonStatus.ts
147
146
  ├── web/ # Web application (Vite + React)
148
147
  │ └── src/
149
148
  │ ├── App.tsx # Main web app
@@ -335,7 +334,7 @@ interface MachineProvider {
335
334
  ```
336
335
 
337
336
  - `LocalMachineProvider`: Direct filesystem + tmux-lite CLI
338
- - `RemoteMachineProvider`: Via relay WebSocket
337
+ - Remote machine access in UI now uses shared relay/session hooks + backend adapters (`shared/relay/*`, `shared/session/*`)
339
338
 
340
339
  ## Development Workflow
341
340
 
package/README.md CHANGED
@@ -117,14 +117,15 @@ A bundle is a directory (typically `.gitspace/`) containing:
117
117
  ```
118
118
  .gitspace/
119
119
  ├── bundle.json # Bundle manifest with onboarding steps
120
- ├── pre/ # Scripts to run before setup
121
- │ └── 01-copy-env.sh
122
- ├── setup/ # Scripts to run on first workspace creation
123
- │ └── 01-install-deps.sh
124
- ├── select/ # Scripts to run every time workspace is opened
125
- │ └── 01-status.sh
126
- └── remove/ # Scripts to run before workspace deletion
127
- └── 01-cleanup.sh
120
+ └── scripts/
121
+ ├── pre/ # Deprecated: migrate scripts into ordered setup/
122
+ │ └── 01-copy-env.sh
123
+ ├── setup/ # Scripts for setup runs (when bundle/value state changes)
124
+ │ └── 01-install-deps.sh
125
+ ├── select/ # Scripts to run on each new terminal attach
126
+ └── 01-status.sh
127
+ └── remove/ # Scripts to run before workspace deletion
128
+ └── 01-cleanup.sh
128
129
  ```
129
130
 
130
131
  ### Bundle Manifest (`bundle.json`)
@@ -179,27 +180,27 @@ A bundle is a directory (typically `.gitspace/`) containing:
179
180
 
180
181
  ### Using Bundle Values in Scripts
181
182
 
182
- Bundle values are passed to scripts as environment variables:
183
+ Bundle values are passed to scripts as environment variables using the configured bundle keys:
183
184
 
184
- - `SPACE_VALUE_<KEY>` - Regular values from input steps
185
- - `SPACE_SECRET_<KEY>` - Secret values from secret steps (fetched from OS keychain)
185
+ - `<KEY>` - Regular or secret value using the exact `configKey` from `bundle.json`
186
+ - Legacy aliases `SPACE_VALUE_<KEY>` / `SPACE_SECRET_<KEY>` are also provided for compatibility
186
187
 
187
188
  **Example script:**
188
189
 
189
190
  ```bash
190
191
  #!/bin/bash
191
- # .gitspace/select/01-status.sh
192
+ # .gitspace/scripts/select/01-status.sh
192
193
 
193
194
  WORKSPACE_NAME=$1
194
195
  REPOSITORY=$2
195
196
 
196
197
  # Access bundle values
197
- if [ -n "$SPACE_VALUE_TEAMNAME" ]; then
198
- echo "Welcome, $SPACE_VALUE_TEAMNAME team!"
198
+ if [ -n "$TEAMNAME" ]; then
199
+ echo "Welcome, $TEAMNAME team!"
199
200
  fi
200
201
 
201
202
  # Access secrets (stored securely in OS keychain)
202
- if [ -n "$SPACE_SECRET_APIKEY" ]; then
203
+ if [ -n "$APIKEY" ]; then
203
204
  echo "API Key configured"
204
205
  fi
205
206
  ```
@@ -361,10 +362,11 @@ inside each workspace so they can vary by branch:
361
362
 
362
363
  ```
363
364
  ~/gitspace/<project-name>/workspaces/<workspace-name>/.gitspace/
364
- ├── pre/ # Run before setup (terminal)
365
- ├── setup/ # Run once on workspace creation
366
- ├── select/ # Run every time workspace is opened
367
- └── remove/ # Run before workspace deletion
365
+ └── scripts/
366
+ ├── pre/ # Deprecated: run before setup (migrate to setup/)
367
+ ├── setup/ # Run when setup state requires refresh
368
+ ├── select/ # Run on each new terminal attach
369
+ └── remove/ # Run before workspace deletion
368
370
  ```
369
371
 
370
372
  #### Script Execution Rules
@@ -373,15 +375,15 @@ inside each workspace so they can vary by branch:
373
375
  2. Scripts run **alphabetically** (use `01-`, `02-` prefixes)
374
376
  3. **Working directory**: The workspace directory
375
377
  4. **Arguments**: `$1` = workspace name, `$2` = repository name
376
- 5. **Environment**: Bundle values available as `SPACE_VALUE_*` and `SPACE_SECRET_*`
378
+ 5. **Environment**: Bundle values available by key name (for example `REGION`, `PULUMI_ACCESS_TOKEN`)
377
379
 
378
380
  #### Script Phases
379
381
 
380
382
  | Phase | When | Use Case |
381
383
  |-------|------|----------|
382
- | `pre/` | Once, before setup | Copy .env files, create directories |
383
- | `setup/` | Once, on workspace creation | Install dependencies, initial build |
384
- | `select/` | Every workspace open | Git fetch, status checks |
384
+ | `pre/` | Deprecated | Move scripts into ordered `setup/` files |
385
+ | `setup/` | When setup state changes | Install dependencies, initial build |
386
+ | `select/` | Every new terminal attach | Git fetch, status checks |
385
387
  | `remove/` | Before deletion | Cleanup, notifications |
386
388
 
387
389
  ### Environment Variables
@@ -391,8 +393,9 @@ inside each workspace so they can vary by branch:
391
393
  export SPACES_CURRENT_PROJECT="my-app"
392
394
 
393
395
  # Available in scripts (from bundle onboarding):
394
- # SPACE_VALUE_<KEY> - Regular values
395
- # SPACE_SECRET_<KEY> - Secret values (from OS keychain)
396
+ # <KEY> - Value by bundle config key name
397
+ # SPACE_VALUE_<KEY> - Legacy alias for regular values
398
+ # SPACE_SECRET_<KEY> - Legacy alias for secret values
396
399
  ```
397
400
 
398
401
  ## Directory Structure
@@ -406,19 +409,15 @@ export SPACES_CURRENT_PROJECT="my-app"
406
409
  │ ├── workspaces/ # Git worktrees
407
410
  │ │ └── <workspace-name>/
408
411
  │ │ ├── gitspace.lock # Setup completion marker
409
- │ │ └── .prompt/ # Linear issue details (if applicable)
410
- │ │ └── issue.md
411
- │ └── workspaces/
412
- └── <workspace-name>/
413
- │ └── .gitspace/ # Custom scripts (per worktree)
414
- │ ├── pre/
415
- │ ├── setup/
416
- │ ├── select/
417
- │ └── remove/
418
- │ ├── pre/
419
- │ ├── setup/
420
- │ ├── select/
421
- │ └── remove/
412
+ │ │ ├── .prompt/ # Linear issue details (if applicable)
413
+ │ │└── issue.md
414
+ └── .gitspace/
415
+ │ ├── bundle.json
416
+ └── scripts/ # Custom scripts (per worktree)
417
+ ├── pre/
418
+ ├── setup/
419
+ ├── select/
420
+ └── remove/
422
421
  ```
423
422
 
424
423
  ## Remote Access
@@ -594,7 +593,7 @@ Error: GitHub CLI is not authenticated
594
593
 
595
594
  ### Bundle secrets not available
596
595
 
597
- If `SPACE_SECRET_*` variables are empty, ensure:
596
+ If expected bundle key environment variables are empty, ensure:
598
597
  1. You completed the onboarding secret steps
599
598
  2. Your OS keychain service is running (libsecret on Linux, Keychain on macOS)
600
599
 
package/bun.lock CHANGED
@@ -24,6 +24,7 @@
24
24
  "open": "^11.0.0",
25
25
  "ora": "^8.2.0",
26
26
  "react": "^19.2.4",
27
+ "react-dom": "^19.2.4",
27
28
  "simple-git": "^3.30.0",
28
29
  "ws": "^8.19.0",
29
30
  },
@@ -38,10 +39,10 @@
38
39
  "typescript": "^5.9.3",
39
40
  },
40
41
  "optionalDependencies": {
41
- "@gitspace/darwin-arm64": "0.2.0-rc.11",
42
- "@gitspace/darwin-x64": "0.2.0-rc.11",
43
- "@gitspace/linux-arm64": "0.2.0-rc.11",
44
- "@gitspace/linux-x64": "0.2.0-rc.11",
42
+ "@gitspace/darwin-arm64": "0.2.0-rc.12",
43
+ "@gitspace/darwin-x64": "0.2.0-rc.12",
44
+ "@gitspace/linux-arm64": "0.2.0-rc.12",
45
+ "@gitspace/linux-x64": "0.2.0-rc.12",
45
46
  },
46
47
  },
47
48
  },
@@ -62,7 +63,7 @@
62
63
 
63
64
  "@eslint/js": ["@eslint/js@8.57.1", "", {}, "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q=="],
64
65
 
65
- "@gitspace/darwin-arm64": ["@gitspace/darwin-arm64@0.2.0-rc.11", "", { "os": "darwin", "cpu": "arm64", "bin": { "gssh-darwin-arm64": "bin/gssh" } }, "sha512-MCApLGdB9iScZ/IW1TiUlt+HwdYACfTJxw3m8tShb15IjhrNxn06GvKlTIIq5fR13XkPlPZNuX6/IxO00TVa5A=="],
66
+ "@gitspace/darwin-arm64": ["@gitspace/darwin-arm64@0.2.0-rc.12", "", { "os": "darwin", "cpu": "arm64", "bin": { "gssh-darwin-arm64": "bin/gssh" } }, "sha512-FUCz7f6EThB1/epRZ+X3SV7wDq/m4mFRDy2AVXGurVK6OWAA+D8tddUYeGmxvYT9+PXEZDATu5ukBh2RKpr5OQ=="],
66
67
 
67
68
  "@graphql-typed-document-node/core": ["@graphql-typed-document-node/core@3.2.0", "", { "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ=="],
68
69
 
@@ -578,7 +579,7 @@
578
579
 
579
580
  "react-devtools-core": ["react-devtools-core@7.0.1", "", { "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, "sha512-C3yNvRHaizlpiASzy7b9vbnBGLrhvdhl1CbdU6EnZgxPNbai60szdLtl+VL76UNOt5bOoVTOz5rNWZxgGt+Gsw=="],
580
581
 
581
- "react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="],
582
+ "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
582
583
 
583
584
  "react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
584
585
 
@@ -4,7 +4,7 @@ This document describes how GitSpace handles WebSocket connections, disconnectio
4
4
 
5
5
  > **Related:** See [PROTOCOL.md](./PROTOCOL.md) for message/frame format, [REMOTE-DESIGN.md](./REMOTE-DESIGN.md) for security model.
6
6
 
7
- > **Implementation Note:** The web client (`src/web/`) currently lacks the
7
+ > **Implementation Note:** The web client tooling (`web/`) currently lacks the
8
8
  > auto-reconnection logic described below. While the relay connection has a
9
9
  > 15-second heartbeat, neither the relay nor terminal connections implement
10
10
  > exponential backoff reconnection. This is a known gap - disconnections
@@ -293,14 +293,18 @@ Key responsibilities:
293
293
  **Role:** User interface, decryption endpoint
294
294
 
295
295
  ```
296
- src/web/src/
297
- ├── App.tsx # Main application
296
+ web/
297
+ ├── index.html # Vite entry document
298
+ └── main.tsx # Lightweight web entrypoint
299
+
300
+ src/
301
+ ├── app.web.tsx # Main web application
298
302
  ├── hooks/
299
- │ ├── useRelayConnection.ts # WebSocket + machine list
300
- │ └── useTerminal.ts # Terminal session management
303
+ │ ├── useRelayConnection.web.ts
304
+ │ └── useTerminal.web.ts
301
305
  ├── components/
302
- │ └── Terminal.tsx # xterm.js wrapper
303
- └── lib/crypto/ # Client-side X3DH + encryption
306
+ │ └── SessionTerminal.web.tsx
307
+ └── session/crypto/ # Client-side X3DH + encryption
304
308
  ```
305
309
 
306
310
  Key responsibilities:
@@ -319,10 +323,11 @@ src/
319
323
  ├── commands/connect.ts # CLI connect command
320
324
  ├── tui/
321
325
  │ ├── app.tsx # TUI application
322
- │ ├── adapters.ts # Machine provider adapters
323
- │ └── hooks/useRemoteMachines.ts
324
- └── shared/providers/
325
- └── RemoteMachineProvider.ts
326
+ │ ├── hooks/useRemoteMachines.ts
327
+ │ └── hooks/useRemoteTerminal.ts
328
+ └── shared/
329
+ ├── relay/ # Shared relay directory client/hooks
330
+ └── session/ # Shared session backends + engine
326
331
  ```
327
332
 
328
333
  ---
package/docs/ROADMAP.md CHANGED
@@ -159,7 +159,7 @@ VM-per-workspace isolation using Lima. Works on all Apple Silicon (M1/M2/M3+).
159
159
  - `src/core/lima/manager.ts` - VM lifecycle (start/stop/status)
160
160
  - `src/core/lima/config.ts` - Generate Lima YAML from workspace config
161
161
  - `src/core/lima/connection.ts` - Connect to tmux-lite inside VM
162
- - `src/shared/providers/LimaMachineProvider.ts` - MachineProvider implementation
162
+ - `src/session/backends/lima-session-backend.ts` - Session backend implementation
163
163
 
164
164
  **Session Lifecycle:**
165
165
  1. User selects workspace in TUI
@@ -281,14 +281,15 @@ D) CUSTOM SCRIPTS & BUNDLES
281
281
 
282
282
  ### Custom Scripts
283
283
 
284
- GitSpace uses convention-based scripts stored per workspace in `.gitspace/`:
284
+ GitSpace uses convention-based scripts stored per workspace in `.gitspace/scripts/`:
285
285
 
286
286
  ```
287
287
  ~/gitspace/<project>/workspaces/<workspace>/.gitspace/
288
- ├── pre/ # Run before setup (once, in terminal)
289
- ├── setup/ # Run on workspace creation (once)
290
- ├── select/ # Run every time workspace is opened
291
- └── remove/ # Run before workspace deletion
288
+ └── scripts/
289
+ ├── pre/ # Run before setup (once, in terminal)
290
+ ├── setup/ # Run on workspace creation (once)
291
+ ├── select/ # Run every time workspace is opened
292
+ └── remove/ # Run before workspace deletion
292
293
  ```
293
294
 
294
295
  Script execution rules:
@@ -296,9 +297,9 @@ Script execution rules:
296
297
  - Scripts run alphabetically (use `01-`, `02-` prefixes)
297
298
  - Working directory: The workspace directory
298
299
  - Arguments: `$1` = workspace name, `$2` = repository name
299
- - Environment: Bundle values available as `SPACE_VALUE_*` and `SPACE_SECRET_*`
300
+ - Environment: Bundle values available by key name (for example `REGION`, `PULUMI_ACCESS_TOKEN`)
300
301
 
301
- Example script (`.gitspace/select/01-status.sh`):
302
+ Example script (`.gitspace/scripts/select/01-status.sh`):
302
303
  ```bash
303
304
  #!/bin/bash
304
305
  WORKSPACE_NAME=$1
@@ -316,10 +317,11 @@ Bundles allow repository owners to share onboarding configurations. Place in `.g
316
317
  ```
317
318
  .gitspace/
318
319
  ├── bundle.json # Bundle manifest with onboarding steps
319
- ├── pre/ # Scripts to run before setup
320
- ├── setup/ # Scripts to run on first workspace creation
321
- ├── select/ # Scripts to run every time workspace is opened
322
- └── remove/ # Scripts to run before workspace deletion
320
+ └── scripts/
321
+ ├── pre/ # Scripts to run before setup
322
+ ├── setup/ # Scripts to run on first workspace creation
323
+ ├── select/ # Scripts to run every time workspace is opened
324
+ └── remove/ # Scripts to run before workspace deletion
323
325
  ```
324
326
 
325
327
  Bundle manifest example (`bundle.json`):
@@ -375,14 +377,15 @@ Using bundle values in scripts:
375
377
  ```bash
376
378
  #!/bin/bash
377
379
  # Values available as environment variables:
378
- # SPACE_VALUE_<KEY> - Regular values from input steps
379
- # SPACE_SECRET_<KEY> - Secret values from secret steps (from OS keychain)
380
+ # <KEY> - Value by bundle config key name
381
+ # SPACE_VALUE_<KEY> - Legacy alias for regular values
382
+ # SPACE_SECRET_<KEY> - Legacy alias for secret values
380
383
 
381
- if [ -n "$SPACE_VALUE_TEAMNAME" ]; then
382
- echo "Welcome, $SPACE_VALUE_TEAMNAME team!"
384
+ if [ -n "$TEAMNAME" ]; then
385
+ echo "Welcome, $TEAMNAME team!"
383
386
  fi
384
387
 
385
- if [ -n "$SPACE_SECRET_APIKEY" ]; then
388
+ if [ -n "$APIKEY" ]; then
386
389
  echo "API Key configured"
387
390
  fi
388
391
  ```
@@ -465,15 +468,15 @@ Location: `~/gitspace/.identity/`
465
468
  │ ├── workspaces/ # Git worktrees
466
469
  │ │ └── <workspace-name>/
467
470
  │ │ ├── gitspace.lock # Setup completion marker
468
- │ │ └── .prompt/ # Linear issue details (if applicable)
469
- │ │ └── issue.md
470
- │ └── workspaces/
471
- └── <workspace-name>/
472
- │ └── .gitspace/ # Custom scripts (per worktree)
473
- │ ├── pre/
474
- │ ├── setup/
475
- │ ├── select/
476
- │ └── remove/
471
+ │ │ ├── .prompt/ # Linear issue details (if applicable)
472
+ │ │└── issue.md
473
+ └── .gitspace/
474
+ │ ├── bundle.json
475
+ └── scripts/ # Custom scripts (per worktree)
476
+ ├── pre/
477
+ ├── setup/
478
+ ├── select/
479
+ └── remove/
477
480
  ```
478
481
 
479
482
  ============================================================
@@ -621,13 +624,13 @@ gssh identity init --label "My Device"
621
624
  - Try: `git fetch origin` first
622
625
 
623
626
  **"Setup scripts failed"**
624
- - Check script is executable: `chmod +x .gitspace/setup/*.sh`
625
- - Run manually to see error: `./.gitspace/setup/01-script.sh`
627
+ - Check script is executable: `chmod +x .gitspace/scripts/setup/*.sh`
628
+ - Run manually to see error: `./.gitspace/scripts/setup/01-script.sh`
626
629
  - Check environment variables are set
627
630
 
628
631
  ### Bundle/Secrets Issues
629
632
 
630
- **"SPACE_SECRET_* variables are empty"**
633
+ **"Bundle key variables are empty"**
631
634
  1. Ensure you completed onboarding secret steps
632
635
  2. Check OS keychain is accessible:
633
636
  - macOS: Keychain Access should be running
@@ -893,14 +896,15 @@ gssh status # Show daemon statuses
893
896
 
894
897
  SECTION: Local Workflow - Custom Scripts
895
898
 
896
- GitSpace uses convention-based scripts stored per workspace in `.gitspace/`:
899
+ GitSpace uses convention-based scripts stored per workspace in `.gitspace/scripts/`:
897
900
 
898
901
  ```
899
902
  ~/gitspace/<project>/workspaces/<workspace>/.gitspace/
900
- ├── pre/ # Run before setup (once)
901
- ├── setup/ # Run on workspace creation (once)
902
- ├── select/ # Run every time workspace is opened
903
- └── remove/ # Run before workspace deletion
903
+ └── scripts/
904
+ ├── pre/ # Run before setup (once)
905
+ ├── setup/ # Run on workspace creation (once)
906
+ ├── select/ # Run every time workspace is opened
907
+ └── remove/ # Run before workspace deletion
904
908
  ```
905
909
 
906
910
  **Rules:**
@@ -912,7 +916,7 @@ GitSpace uses convention-based scripts stored per workspace in `.gitspace/`:
912
916
  **Example:**
913
917
  ```bash
914
918
  #!/bin/bash
915
- # .gitspace/select/01-status.sh
919
+ # .gitspace/scripts/select/01-status.sh
916
920
  echo "Switching to: $1"
917
921
  git fetch origin
918
922
  git status
@@ -927,9 +931,11 @@ Bundles allow teams to share onboarding configurations. Place in `.gitspace/`:
927
931
  ```
928
932
  .gitspace/
929
933
  ├── bundle.json # Manifest
930
- ├── pre/ # Pre-setup scripts
931
- ├── setup/ # Setup scripts
932
- └── select/ # Select scripts
934
+ └── scripts/
935
+ ├── pre/ # Pre-setup scripts
936
+ ├── setup/ # Setup scripts
937
+ ├── select/ # Select scripts
938
+ └── remove/ # Remove scripts
933
939
  ```
934
940
 
935
941
  **Manifest example:**
@@ -954,8 +960,8 @@ Bundles allow teams to share onboarding configurations. Place in `.gitspace/`:
954
960
 
955
961
  **Using values in scripts:**
956
962
  ```bash
957
- echo "Team: $SPACE_VALUE_TEAMNAME"
958
- echo "Has API key: $SPACE_SECRET_APIKEY"
963
+ echo "Team: $TEAMNAME"
964
+ echo "Has API key: $APIKEY"
959
965
  ```
960
966
 
961
967
  ---