Integrated terminal and Claude Code launch
Center tabs provide a real local terminal and can launch the locally installed Claude Code CLI directly from a new tab. Web mode does not expose host command execution or describe a local CLI as a remote cloud session.
Verified gaps
Ordinary pipes are not PTYs
The old draft used child_process.spawn, TERM=dumb and pipes. Interactive programs lacked a terminal device, so Claude Code cursor handling, fullscreen refresh, colors and shortcuts did not work correctly.
Input/output controls lack terminal semantics
<pre> and a single-line <input> do not interpret ANSI, cursor movement, alternate screens, paste or Ctrl+C.
Entry points do not match capabilities
The old entry showed only Terminal and submitted commands line by line, with no direct Claude Code launch entry.
The terminal view is not integrated with the theme contract
Terminal background, foreground, cursor and selection colors were hardcoded to a single dark palette, with no explicit ANSI 16-color palette. Light, warm and custom themes therefore differed from the rest of the App.
Missing process operations and state
The original view accepted input but provided no toolbar actions for copying selection, pasting, clearing, restarting or stopping; it did not distinguish starting, running, exited and error states.
Approach comparison
| Approach | Capabilities | Decision |
|---|---|---|
| node-pty | Real PTY supporting input, output, resize and lifecycle; official examples include Electron main + IPC + xterm.js. | Adopt; run only in Electron main. |
| xterm.js + FitAddon | Interpret terminal sequences, generate raw input and calculate cols/rows per pane. | Adopt; do not implement a custom terminal protocol. |
| Claude Code CLI | A local CLI running in the terminal. | Use the locally installed claude, resolving PATH through a login shell. |
| spawn + pipe | Suitable for noninteractive commands; lacks terminal modes and resize. | Rejected. |
Target interaction
Terminal
Open a login shell in the current project directory. Switching ordinary tabs does not terminate the session; closing the Terminal tab terminates the PTY.
Claude Code
Provide a separate entry that directly executes the following in the same project directory: claude.
Failure states
Show explicit errors when the bridge, PTY module or CLI is unavailable. Web mode must not show fake interactive controls. An unresolved project WebSocket must not leave a blank page: after a brief wait, start in the home directory. Once started, do not restart the terminal cwd because a project response arrives late.
Theme and ANSI
xterm background, foreground, cursor, selection and ANSI 16 colors all use site-wide semantic tokens. Theme or Custom CSS changes update only the xterm theme without restarting the PTY or losing the buffer.
Terminal toolbar
Show the preset, process state and actual cwd at the top; provide copy, paste, clear, restart and stop on the right. Buttons are compact and borderless; hover and focus follow site-wide tokens.
Keyboard and paste
Cmd/Ctrl+Shift+C copies only when a selection exists; Cmd/Ctrl+Shift+V reads the clipboard and writes to the PTY; ordinary Ctrl+C continues sending an interrupt character.Cmd+K clears only the current xterm viewport.
Data flow and trust boundaries
◀──────── terminal:data / exit ────────◀
- The renderer may select only the
shellorclaudepreset, and cannot submit arbitrary executable/argv. cwdis resolved through realpath and must be a directory; the PTY is bound to the renderer sender and terminal id.- Each input is limited to 64 KiB; cols/rows are bounded; replacement processes suppress old-process output.
- Processes follow tab lifecycles; switching ordinary tabs unmounts only the xterm view. Closing the tab, destroying the renderer or explicitly stopping releases the PTY.
- The PTY uses the current local App user permissions and provides no remote sandbox.
Implementation scope
Changes are limited to built-in tab id, label, launcher and renderer; terminal page/CSS and semantic theme tokens; desktop bridge, preload and main; two package manifests; global xterm CSS; and corresponding tests.
- Terminal and Claude Code both use PTY + xterm.js.
- Preserve existing session, file, browser, web, bookmark, history, split, close and drag behavior.
- Exclude remote cloud sessions, general terminal-session management, shell-profile editors, persistent command history, Windows and Web host terminals.
Acceptance criteria
- Terminal in the default App can execute
pwd. - The Claude Code entry directly displays the local CLI; input and Ctrl+C reach the process.
- When the project list responds normally, cwd is the current main project. If the connection does not respond, wait only briefly before providing an interactive shell in the home directory, without a blank page.
- Pane-width changes synchronize xterm and PTY cols/rows.
- The PTY pid stays unchanged across tab switches; closing Claude Code alone does not affect Terminal.
- Dark/light, warm and custom theme changes update the terminal and ANSI 16 colors without changing the PTY pid.
- Copy, paste, clear, restart and stop work; Ctrl+C retains interrupt semantics; the toolbar clearly shows running, exited and error.
- Focused checks, TypeScript and the Web production build pass, and default-App assets are updated.
Implementation status and evidence
| Stage | Status |
|---|---|
| Design and boundaries | Complete |
| Complete renderer and theme contract | Complete: ANSI 16 colors, live theme updates, state, cwd and all five toolbar actions are implemented |
| Focused checks / TypeScript / production build | check:integrated-terminal, tsc --noEmit and the Next.js production build passed |
| Default-App update | Updated /Applications/OpenProgram.app; installed acceptance on the default App at 18100 passed for input, ANSI, clear, paste, stop, restart, PID changes and cleanup on close |