Skip to content

feat(terminal): implement detached window terminal pop-out#6485

Draft
wolfiesch wants to merge 3 commits into
stablyai:mainfrom
wolfiesch:wolfiesch/pop-out-window-tab
Draft

feat(terminal): implement detached window terminal pop-out#6485
wolfiesch wants to merge 3 commits into
stablyai:mainfrom
wolfiesch:wolfiesch/pop-out-window-tab

Conversation

@wolfiesch

@wolfiesch wolfiesch commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Implement a new feature allowing users to detach terminal tabs into standalone, platform-native secondary windows ("Open in New Window" context menu action). The main window remains the PTY lifecycle owner, while detached windows subscribe to pty:data and route PTY controls through a main-process capability and ownership verification layer.

Screenshots

Pending visual proof for the window menu option and detached window display. Terminal output itself is unchanged. Keep draft until that recording or screenshot evidence is attached.

Testing

  • pnpm lint
  • pnpm typecheck
  • pnpm test
  • pnpm build
  • Added or updated high-quality tests that would catch regressions, or explained why tests were not needed

Targeted verification:

  • Run typecheck: pnpm run typecheck (Passed)
  • Run targeted Vitest suite: pnpm --filter @stablyai/terminal test
  • Run E2E: pnpm run test:e2e -- tests/e2e/tabs-detached.spec.ts (Passed)

AI Review Report

The code review checked:

  • Cross-platform compatibility: Verified modifier keys (CmdOrCtrl) and path separators are fully cross-platform.
  • PTY control security: Verified that detached renderers are restricted from signaling, reading, or writing to PTYs they do not own.
  • Window reuse auth: Added regression tests ensuring only the primary window or the detached window itself can call detachedTerminal:openWindow to focus an already open pop-out.
  • Hydration race conditions: Ensured Zustand state hydration is synchronous and blocks rendering until PTY mappings are fully seeded to avoid duplicate spawn requests.

Security Audit

  • IPC Gate Authorization: Hardened PTY write/resize/ack/signal channels to check both capability (pty) and direct ownership of the requested PTY in the pane registry.
  • Staging Validation: detachedTerminal:openWindow validates the entire tab layout and PTY bindings in the main process before creating the window or transferring ownership.
  • Close Window Gate: Restricted detachedTerminal:closeWindow to prevent unrelated renderers from closing target windows.

Notes

X handle: @wolfie_

@AmethystLiang AmethystLiang requested a review from Jinwoo-H June 27, 2026 16:49
@wolfiesch wolfiesch force-pushed the wolfiesch/pop-out-window-tab branch 2 times, most recently from aa82a77 to c1fe0f2 Compare June 29, 2026 06:12
- Create main-process registries for detached windows, trusted renderers, and pane ownership.
- Secure IPC routing and broadcasts by scoping PTY commands and window events.
- Implement window coordinator for creation, focusing, snapshot validation, and cleanup.
- Add detached preload APIs and branched renderer shell with Zustand state hydration.
- Wire context menu action for 'Open in New Window'.
Detached windows hide native chrome (hiddenInset on macOS, frameless on
Windows/Linux), leaving no OS drag handle. Add a renderer-owned drag
strip above the terminal; the terminal surface stays no-drag so xterm
keeps pointer selection and focus.
- Extract snapshot validation/authorization into
  detached-terminal-snapshot-validation.ts to clear max-lines.
- Localize the 'Open in New Window' menu item and detached shell
  aria-labels; sync locale catalogs.
- Allowlist the detached_terminal_tab_unavailable error code (machine
  error string, not user copy).
@wolfiesch wolfiesch force-pushed the wolfiesch/pop-out-window-tab branch from c1fe0f2 to 16585f6 Compare June 30, 2026 05:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants