Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .planning/HANDOFF.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"version": "1.0",
"timestamp": "2026-05-19T21:40:59.129Z",
"phase": "7",
"phase_name": "SSH Transport + Codespaces Connect",
"phase_dir": ".planning/phases/07-ssh-transport-codespaces-connect",
"plan": null,
"task": null,
"total_tasks": null,
"status": "paused",
"completed_tasks": [
{"id": "debug-1", "name": "black-screen-render: double surface present fix", "status": "done", "commit": "uncommitted (in working tree)"},
{"id": "debug-2", "name": "terminal-partial-window: hardcoded 80x24 initial dims fix", "status": "done", "commit": "uncommitted (in working tree)"},
{"id": "debug-3", "name": "oauth-device-flow-broken: Accept:application/json + modal persistence", "status": "done", "commit": "uncommitted (in working tree)"},
{"id": "debug-4", "name": "codespace-tunnel-connect-fails: post-auth picker auto-open", "status": "done", "commit": "uncommitted (in working tree)"},
{"id": "debug-5", "name": "auth-completion-not-detected: GitHub HTTP-200 polling fix + reqwest user fetch + octocrab tower panic + codespace listing direct reqwest", "status": "done", "commit": "uncommitted (in working tree)"},
{"id": "test-1", "name": "8 regression tests for auth + codespaces listing", "status": "done", "commit": "uncommitted (in working tree)"},
{"id": "plan-7", "name": "Phase 7 plans: 5 plans across 4 waves", "status": "done", "commit": "53bb825"}
],
"remaining_tasks": [
{"id": "commit-fixes", "name": "Commit all debug session fixes from the working tree", "status": "not_started"},
{"id": "execute-7", "name": "Execute Phase 7 — SSH transport + Codespaces connect", "status": "not_started"},
{"id": "create-codespace", "name": "Create a GitHub Codespace at github.com/codespaces to test against", "status": "not_started", "type": "human_action"}
],
"blockers": [
{
"description": "User has no codespaces yet — picker shows empty (correct behavior). Need at least one codespace to test Phase 7.",
"type": "human_action",
"workaround": "Create a codespace at github.com/codespaces on any repo"
}
],
"human_actions_pending": [
{
"action": "Create a GitHub Codespace at github.com/codespaces",
"context": "Needed to test Phase 7 SSH transport end-to-end. The API returns total_count=0 meaning zero codespaces exist.",
"blocking": true
}
],
"decisions": [
{"decision": "Phase 7 v1 transport = gh codespace ssh --stdio subprocess", "rationale": "Sidesteps native russh+gRPC tunnel plumbing (v1.x). gh handles all tunnel protocol.", "phase": "7"},
{"decision": "CodespaceDomain lives in vector-ssh, not vector-mux", "rationale": "Keeps WIN-04 seam clean — mux takes Box<dyn PtyTransport> directly, not russh types.", "phase": "7"},
{"decision": "KeyManager title = 'vector-{hostname}' (no UUID)", "rationale": "Stable title prevents unbounded SSH key growth on github.com/settings/keys.", "phase": "7"},
{"decision": "All debug session fixes uncommitted", "rationale": "Multiple files modified across sessions, need to commit before executing phase 7.", "phase": "6"}
],
"uncommitted_files": [
"Makefile",
"crates/vector-app/src/app.rs",
"crates/vector-app/src/auth_actor.rs",
"crates/vector-codespaces/src/auth/device_flow.rs",
"crates/vector-codespaces/src/auth/error.rs",
"crates/vector-codespaces/tests/device_flow.rs",
"crates/vector-app/src/codespaces_actor.rs"
],
"next_action": "Run 'git add -p' to stage and commit all debug session fixes, then /clear and /gsd:execute-phase 7",
"context_notes": "Long debug session fixed: black screen, partial window, OAuth device flow (GitHub HTTP-200 non-RFC polling), auth completion detection (tower panic from octocrab on winit main thread), codespaces empty list (user simply has zero codespaces). All auth + codespaces infrastructure now works. Phase 7 fully planned and verified. Need to commit the working tree fixes before executing."
}
21 changes: 11 additions & 10 deletions .planning/PROJECT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

## What This Is

Vector is a native macOS terminal — written in Rust, GPU-accelerated — with first-class GitHub Codespaces and Dev Tunnels support baked in. It is meant to replace iTerm/ghostty as a daily-driver local terminal *and* let me (and a few Adobe teammates) sign in with GitHub, pick a Codespace, and drop into a remote dev shell without ever opening VS Code or a browser.
Vector is a native macOS terminal — written in Rust, GPU-accelerated — with first-class VS Code Remote Tunnels support baked in. It is meant to replace iTerm/ghostty as a daily-driver local terminal *and* let me (and a few Adobe teammates) sign in with GitHub, attach to one of our own remote machines running `code tunnel`, and drop into a remote dev shell without ever opening VS Code or a browser.

**Pivoted 2026-05-19:** Original spec called for GitHub Codespaces support. Mid-Phase 7, user clarified the actual use case is connecting to *their own* machines via VS Code Remote Tunnels, not GitHub-managed codespace containers. Phase 7 codespace-specific code was reverted; transport scaffolding (russh client, SSH channel transport, tab tint + `[remote]` badge) kept for Phase 8.

## Core Value

**Open the app, pick a Codespace, get a fast remote shell — no VS Code, no browser, no clunky `gh codespace ssh` plumbing.** Local-terminal niceties (tabs, splits, GPU rendering) are table-stakes; the differentiator is that a Codespaces/Dev-Tunnels session feels native, not bolted on.
**Open the app, pick a remote machine running `code tunnel`, get a fast remote shell — no VS Code, no browser.** Local-terminal niceties (tabs, splits, GPU rendering) are table-stakes; the differentiator is that a Dev-Tunnels session feels native, not bolted on.

## Requirements

Expand All @@ -21,9 +23,9 @@ Vector is a native macOS terminal — written in Rust, GPU-accelerated — with

- [x] Polish local terminal to daily-driver quality — config hot-reload, theme engine, search bar, profile picker, OSC 52 clipboard, IME, Secure Keyboard Entry, hyperlinks, OSC 7 cwd, Cmd-N window spawning — Phase 5 operationally validated 2026-05-14: all 8 POLISH requirements verified; 16/16 plans complete; 332 tests passing; 10-item smoke matrix 10/10 approved.
- [x] GitHub OAuth sign-in flow (device-code) with token caching in macOS Keychain — Phase 6 code-complete 2026-05-14: AUTH-01/02/03 fully wired (device-flow + Keychain via vector-secrets + 401 silent-refresh chain); AppKit `AuthDeviceFlowModal` NSPanel + `Sign in with GitHub` menu item + Cmd-Shift-G; 363 workspace tests pass; Pitfall-14 arch-lint enforces zero-Debug-on-token discipline; token-leak grep 0 hits. Human smoke matrix (11 items) tracked in `06-HUMAN-UAT.md` — drive via `/gsd:verify-work 6`.
- [x] List / pick GitHub Codespaces from the UI (no `gh` CLI required) — Phase 6 code-complete 2026-05-14: CS-01/02/03 fully wired (`CodespacesPickerModal` NSPanel + `CodespacesClient` REST + start/409-swallow/poll + Save-as-profile via `vector-config::writer::append_codespace_profile`). `Connect` placeholder toast points at Phase 7. Connect/transport stays in Phase 7 (Dev Tunnels + gRPC + russh).
- [~] List / pick GitHub Codespaces from the UI (no `gh` CLI required) — Phase 6 code-complete 2026-05-14 but functionally dormant after 2026-05-19 pivot. CS-01/02/03 wiring (`CodespacesPickerModal` NSPanel + `CodespacesClient` REST + start/poll + Save-as-profile) survives in-tree; `Connect` is a placeholder toast. Will be repurposed or removed once the tunnel-picker UX is designed.
- [ ] Native macOS app distributed as an unsigned `.dmg` (right-click → Open), Universal binary
- [ ] Session persistence + transparent reconnect — wifi drop should not lose Codespace state
- [ ] Session persistence + transparent reconnect — wifi drop should not lose remote-session state
- [ ] tmux pass-through that "just works" — no double-multiplex visual glitches when remote tmux is running
- [ ] Connect to a remote machine running `code tunnel` (Microsoft Dev Tunnels) using GitHub auth
- [ ] Saved profiles (`my-cs-frontend`, `my-corp-box`, etc.) for one-click reconnect
Expand All @@ -34,10 +36,10 @@ Vector is a native macOS terminal — written in Rust, GPU-accelerated — with

- **Apple Developer signing & notarization** — deferred. v1 ships unsigned with right-click-Open instructions; revisit only if right-click flow is too painful for teammates.
- **Linux and Windows builds** — Mac-only for v1. The user runs Mac and so do the teammates. Cross-platform doubles the surface area for no payoff today.
- **Codespaces lifecycle management (create/delete/rebuild)** — v1 is connect-only; lifecycle stays in `gh` CLI. Adding it later is straightforward; locking down connect first is more valuable.
- **GitHub Codespaces support entirely** — descoped 2026-05-19. The actual use case is VS Code Remote Tunnels (own machines), not GitHub-managed containers. Phase 6 picker code stays in-tree but dormant; Phase 7 codespace-specific code was reverted.
- **Port-forwarding UI ("PORTS" panel)** — deferred to v2. Useful but not on the critical path; remote dev works without it for most flows.
- **File transfer (drag-drop / scp UI)** — deferred. `scp`/`rsync` in the shell suffice while we focus on terminal core.
- **Arbitrary SSH targets as first-class profiles** — deferred. v1 is Codespaces + Dev Tunnels. Plain SSH still works because the terminal launches whatever command you give it; there's just no special UI.
- **Arbitrary SSH targets as first-class profiles** — deferred. v1 is VS Code Remote Tunnels only. Plain SSH still works because the terminal launches whatever command you give it; there's just no special UI.
- **Browser-based / web companion (vscode.dev style)** — explicitly anti-goal. Native-only is a feature.
- **AI features beyond the optional Claude integration** — no command sharing, no analytics, no account system. Bloat is part of why we are not using Warp/Wave.
- **Fork of ghostty or VS Code** — we read them as reference but build fresh in Rust. Submodule references in this repo will be removed.
Expand All @@ -51,15 +53,14 @@ Vector is a native macOS terminal — written in Rust, GPU-accelerated — with
- **Alacritty** (Rust) — minimal GPU terminal. Reference for renderer architecture, escape-sequence parser, the `alacritty_terminal` crate (split out as a library).
- **WezTerm** (Rust) — closest existing Rust terminal to what we want; has SSH, multiplexing, tabs/splits, lua config. Reference for tab/split UX and SSH transport.
- **VS Code Remote Tunnels** — defines the Dev Tunnels client behavior we need to replicate. Microsoft Dev Tunnels has no public Rust SDK, so this is the riskiest piece.
- **`gh codespace ssh`** (Go, GitHub CLI) — defines the Codespaces SSH flow (auth → port allocation → SSH config). We will reimplement the relevant parts in Rust.

**Differentiators vs Warp / Wave / Tabby (which I tried):**
- They treat Codespaces as a second-class SSH target; we treat it as a headline UX (sign-in, picker, profile).
- They treat remote tunnels as a second-class SSH target; we treat them as headline UX (sign-in, picker, profile).
- They bundle cloud accounts, AI products, command sharing, analytics — we ship a terminal and a tunnel client, full stop.

**Why Rust:** I asked about Rust explicitly. We're not forking ghostty (Zig) or VS Code (TypeScript/Electron) — we're building fresh. Rust gives the right balance of performance, ecosystem (alacritty_terminal, vte, wgpu, tokio, octocrab/reqwest), and cross-platform potential when we eventually go beyond Mac.

**No GitHub approval needed:** GitHub Codespaces SSH and Dev Tunnels are public, documented, OAuth-authenticated APIs. Any GitHub user can call them. No special partner approval is required to ship a third-party client.
**No special approval needed:** Microsoft Dev Tunnels is a public, documented, OAuth-authenticated API (GitHub OAuth works as the identity provider). No partner approval is required to ship a third-party client.

## Constraints

Expand All @@ -75,7 +76,7 @@ Vector is a native macOS terminal — written in Rust, GPU-accelerated — with
| Decision | Rationale | Outcome |
|----------|-----------|---------|
| Build in Rust from scratch (not fork ghostty/VS Code) | User explicitly asked about Rust; ghostty is Zig and VS Code is Electron, neither matches the desired stack. Rust ecosystem (alacritty_terminal, wgpu, tokio) is mature enough. | — Pending |
| Connect to BOTH Codespaces SSH and Dev Tunnels | User confirmed both flows matter. Codespaces covers the "use a managed dev VM" case; Dev Tunnels covers "sign into my own remote box and connect". | — Pending |
| VS Code Remote Tunnels only (Codespaces dropped) | 2026-05-19 mid-Phase-7 pivot. User clarified they want "sign into my own remote box and connect" UX — Codespaces lifecycle ceremony (create/start/pick) was the wrong fit. CS-04..07 dropped from REQUIREMENTS.md; Phase 8 (DT-01..04) now owns the remote flow. | Confirmed 2026-05-19 |
| Replace iTerm/ghostty as default local terminal (not remote-only launcher) | Halving the surface area to remote-only would shrink scope, but the user explicitly wants a daily-driver. Local terminal is "free" once we have the rendering core. | — Pending |
| Defer signing/notarization to v2 | Apple Developer cert costs $99/yr and adds CI complexity. Right-click-Open is acceptable for an internal tool. Revisit if Gatekeeper friction becomes painful for teammates. | — Pending |
| Defer port-forwarding UI and file-transfer to v2 | They're VS-Code-terminal niceties but not on the critical path; remote dev works without them. Keeps v1 scope finite. | — Pending |
Expand Down
33 changes: 10 additions & 23 deletions .planning/REQUIREMENTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Requirements: Vector

**Defined:** 2026-05-10
**Core Value:** Open the app, pick a Codespace, get a fast remote shell — no VS Code, no browser, no clunky `gh codespace ssh` plumbing. Local-terminal niceties are table-stakes; the differentiator is that a Codespaces / Dev-Tunnels session feels native, not bolted on.
**Core Value:** Open the app, pick a remote machine via VS Code Remote Tunnels (`code tunnel`), get a fast remote shell — no VS Code, no browser. Local-terminal niceties are table-stakes; the differentiator is that a Dev-Tunnels session feels native, not bolted on.

## v1 Requirements

Expand Down Expand Up @@ -60,19 +60,12 @@ Requirements for initial release. Each maps to roadmap phases. Categories are de
- [x] **CS-02**: Selecting a Shutdown codespace from the picker triggers `POST /start`, polls until Available (with 409 swallowed), then connects _(Wave-0 scaffolded — start/poll test stubs landed in Plan 06-01; real impl lands in Plan 06-03)_
- [x] **CS-03**: A picked codespace can be saved as a one-click profile that survives app restart _(Wave-0 scaffolded — vector-config::writer module + profile_writer.rs test stubs landed in Plan 06-01; real impl lands in Plan 06-04)_

### Codespaces SSH Connect

- [ ] **CS-04**: Connecting to a codespace opens a remote shell in a Vector pane, end-to-end, via subprocess `gh codespace ssh --stdio` as the v1 transport
- [ ] **CS-05**: Vector generates and registers an SSH keypair (ed25519) per machine — no manual ssh-add dance for the user
- [ ] **CS-06**: A connected codespace tab is visually distinct (tinted tab + "remote" badge in the tab title) so the user always knows what they're typing into
- [ ] **CS-07**: Resize events propagate through the SSH transport (`window-change` request) so remote `vim`/`tmux` reflow correctly

### Dev Tunnels Connect

- [ ] **DT-01**: A 1–2 day spike at the start of the Dev Tunnels phase commits a written decision among (a) subprocess `code tunnel client`, (b) vendor `microsoft/dev-tunnels/rs/` at a pinned SHA, (c) defer to v2 — before any integration code is written
- [ ] **DT-02**: A signed-in user can list active Dev Tunnels alongside Codespaces in the picker
- [ ] **DT-03**: Connecting to a Dev Tunnel opens a remote shell in a Vector pane, end-to-end, using whichever transport the spike chose
- [ ] **DT-04**: Dev Tunnel sessions are visually distinct from Codespaces sessions (different tab tint color)
- [ ] **DT-04**: Dev Tunnel sessions are visually distinct from local sessions (tinted tab + `[remote]` badge so the user always knows what they're typing into)

### Persistence & Reconnect

Expand All @@ -92,10 +85,6 @@ Requirements for initial release. Each maps to roadmap phases. Categories are de

Deferred to a future release. Tracked but not in the current roadmap.

### Native Codespaces Transport

- **CS-V2-01**: Replace subprocess `gh codespace ssh --stdio` with native `russh` + `tonic` over the `cli/cli` port-16634 gRPC management API; vendor the `.proto` files from `cli/cli/internal/codespaces/rpc/`

### Distribution & Signing

- **DIST-V2-01**: Apple Developer ID signing + notarization workflow in CI (only if right-click-Open friction proves painful for teammates)
Expand Down Expand Up @@ -186,14 +175,10 @@ Every v1 requirement maps to exactly one phase. No orphans, no duplicates.
| CS-01 | Phase 6 | Complete |
| CS-02 | Phase 6 | Complete |
| CS-03 | Phase 6 | Complete |
| CS-04 | Phase 7 | Pending |
| CS-05 | Phase 7 | Pending |
| CS-06 | Phase 7 | Pending |
| CS-07 | Phase 7 | Pending |
| DT-01 | Phase 8 | Pending |
| DT-02 | Phase 8 | Pending |
| DT-03 | Phase 8 | Pending |
| DT-04 | Phase 8 | Pending |
| DT-01 | Phase 7 | Pending |
| DT-02 | Phase 7 | Pending |
| DT-03 | Phase 7 | Pending |
| DT-04 | Phase 7 | Pending |
| PERSIST-01 | Phase 9 | Pending |
| PERSIST-02 | Phase 9 | Pending |
| PERSIST-03 | Phase 9 | Pending |
Expand All @@ -204,10 +189,12 @@ Every v1 requirement maps to exactly one phase. No orphans, no duplicates.
| HARDEN-04 | Phase 10 | Pending |

**Coverage:**
- v1 requirements: 51 total (5 BUILD + 6 CORE + 5 RENDER + 5 WIN + 8 POLISH + 3 AUTH + 7 CS + 4 DT + 4 PERSIST + 4 HARDEN)
- Mapped to phases: 51 (100%)
- v1 requirements: 47 total (5 BUILD + 6 CORE + 5 RENDER + 5 WIN + 8 POLISH + 3 AUTH + 3 CS + 4 DT + 4 PERSIST + 4 HARDEN)
- Mapped to phases: 47 (100%)
- Unmapped: 0

**Pivot note (2026-05-19):** CS-04..07 (Codespaces SSH Connect) dropped — see ROADMAP §Phase 7. The original "pick a Codespace, get a remote shell" use case turned out to be the wrong product. The real use case is VS Code Remote Tunnels: the user runs `code tunnel` on their own remote machine (EC2, home server, etc.) and Vector attaches over the Microsoft Dev Tunnels relay. DT-01..04 now own that flow. CS-V2-01 (native russh+tonic Codespaces transport) was also removed as no longer relevant. Phase 6 (CS-01..03 picker) shipped and stays code-complete — currently dormant unless someone repurposes it.

---
*Requirements defined: 2026-05-10*
*Last updated: 2026-05-10 — Plan 01-06 closed: BUILD-04 (tagged-release half) and BUILD-05 (xattr in README) complete in commits 4dd0c4e + 75b77b1; BUILD-02 / BUILD-04 retain pending-real-CI-run / pending-real-tagged-release caveat per 01-05 + 01-06 Outstanding Verification Debt blocks*
Expand Down
Loading
Loading