Skip to content

feat(terminal): activate terminal with xterm.js + node-pty#595

Open
HUQIANTAO wants to merge 1 commit into
op7418:mainfrom
HUQIANTAO:feat/terminal-xterm-pty
Open

feat(terminal): activate terminal with xterm.js + node-pty#595
HUQIANTAO wants to merge 1 commit into
op7418:mainfrom
HUQIANTAO:feat/terminal-xterm-pty

Conversation

@HUQIANTAO
Copy link
Copy Markdown

@HUQIANTAO HUQIANTAO commented Jun 4, 2026

Motivation

The desktop app ships with a terminal backend (electron/terminal-manager.ts) and frontend components (TerminalDrawer, TerminalInstance), but the drawer was never mounted in the layout — users cannot access a terminal at all. The existing backend uses child_process.spawn with piped stdio, which lacks PTY semantics (no resize, no full-screen TUI apps, broken readline editing). The frontend renders ANSI output via ansi-to-react with a plain <input> field, falling far short of a real terminal emulator.

This PR activates the dormant terminal and upgrades it end-to-end: node-pty on the backend, xterm.js on the frontend.

What changed

Backend — real PTY via node-pty

electron/terminal-manager.ts — rewritten to use pty.spawn() instead of child_process.spawn. This enables:

  • resize(cols, rows) that actually works (was a no-op before)
  • Full-screen TUI programs (vim, htop, lazygit, etc.)
  • Proper readline/line-editing behavior
  • Native xterm-256color escape sequence handling

The IPC contract (terminal:create/write/resize/kill/onData/onExit) is unchanged; electron/main.ts and electron/preload.ts require no modifications.

Frontend — xterm.js terminal emulator

src/components/terminal/TerminalInstance.tsx — replaced ansi-to-react + <input> with a full @xterm/xterm Terminal instance:

  • FitAddon — auto-fits the terminal to its container on resize
  • WebLinksAddon — clickable URLs in output
  • Bidirectional PTY I/O: terminal.onData()write(), pty outputterminal.write()

Layout integration

  • AppShell.tsx — mounts <TerminalDrawer /> at the bottom of the data-app-shell flex column (below the content row). Lazy-loaded via next/dynamic following the existing AppShell pattern.
  • UnifiedTopBar.tsx — adds a terminal toggle button in the panel-controls area (between File Tree and Workspace Sidebar), consistent with existing panel toggle UX.
  • Keyboard shortcutCmd+`` (macOS) / Ctrl+`` (Windows/Linux) toggles the terminal drawer globally.

Build configuration

File Change
scripts/build-electron.mjs node-pty added to esbuild external
scripts/after-pack.js node-pty added to electron-rebuild -o and onlyModules
electron-builder.yml **/node-pty/** added to asarUnpack

Testing

  1. npm run electron:dev — launch desktop dev mode
  2. Click the terminal icon in the top bar, or press Cmd+`
  3. Verify: interactive shell prompt, colored output, resize auto-fit, TUI app support (e.g. vim, htop)
  4. Verify: close button kills the PTY process cleanly

- Install @xterm/xterm, @xterm/addon-fit, @xterm/addon-web-links, node-pty
- Rewrite electron/terminal-manager.ts to use node-pty for real PTY support
  (resize, full-screen programs, proper readline editing)
- Rewrite TerminalInstance.tsx to use xterm.js (replaces ansi-to-react)
  with FitAddon for auto-resize and WebLinksAddon for clickable links
- Mount TerminalDrawer in AppShell layout (bottom drawer, resizable)
- Add terminal toggle button in UnifiedTopBar
- Add Cmd+` / Ctrl+` keyboard shortcut for terminal toggle
- Update build configs: node-pty in esbuild externals, after-pack rebuild,
  electron-builder asarUnpack
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 4, 2026

Someone is attempting to deploy a commit to the op7418's projects Team on Vercel.

A member of the Team first needs to authorize it.

@HUQIANTAO HUQIANTAO changed the base branch from worktree-product-refactor-research to main June 5, 2026 05:29
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.

1 participant