Workflow
Creating and Interacting with an Integrated Terminal
Mountain spawns a PTY process and streams I/O to the Wind frontend and Cocoon extension host.
Creating and Interacting with an Integrated Terminal
Deep dive into native process management: Mountain spawns a PTY process and streams its I/O to both the Wind frontend and the Cocoon extension host.
Data Flow
Extension calls vscode.window.createTerminal()
OR user executes terminal:new command
-> Request routed to Mountain TerminalProvider
Mountain:
-> TerminalProvider.CreateTerminal()
-> Generate unique TerminalId
-> Determine shell (from options or system default)
-> portable-pty: PtySystem.openpty() creates master/slave PTY pair
-> Spawn shell process (e.g. bash) as PTY child
-> Create TerminalStateDto (TerminalId, pid, reader/writer handles)
-> Spawn I/O tasks:
Writer Task: waits on mpsc channel, writes to PTY
Reader Task: reads PTY output, sends notifications
Waiter Task: monitors shell exit
-> Send $acceptTerminalOpened gRPC to Cocoon
-> Send $acceptTerminalProcessId gRPC to Cocoon
Cocoon:
-> Creates Terminal proxy object for extensions
-> Fires onDidWriteData events when data arrives
Mountain -> Wind/UI:
-> Reader Task emits Tauri event: sky://terminal/data
User Input Loop:
User types "ls -la" in terminal UI
-> Xterm.js captures keystrokes
-> TauriInvoke('mountain://terminal/send-text', { Id, Text })
-> Mountain: SendTextToTerminalLogic
-> Send text to mpsc sender channel
-> Writer Task writes bytes to PTY master
-> Shell executes command, writes to stdout
-> Reader Task captures output
-> Output sent to Cocoon and Wind/UI
-> xterm.write(data) displays outputPhase 1: Terminal Creation Request (Cocoon or Wind)
- Extension calls
vscode.window.createTerminal(...)or user runsworkbench.action.terminal.new. - Request is routed to Mountain’s
TerminalProviderasCommon::terminal::CreateTerminal.
Phase 2: Native PTY Spawning (Mountain)
TerminalProvider.CreateTerminal()gets a uniqueTerminalId, determines the shell.- Uses
portable-ptyto spawn a pseudo-terminal (PtySystem.openpty), creating a master/slave PTY pair. - Spawns the shell process as a child of the PTY slave.
- Creates
TerminalStateDtowith TerminalId, OS pid, and clones of the PTY master’s reader/writer handles. - Spawns three tokio tasks:
- Writer Task: waits on
mpscchannel, writes received strings to PTY master. - Reader Task: reads PTY output, sends
$acceptTerminalProcessDatagRPC to Cocoon. - Waiter Task: awaits shell termination, sends
$acceptTerminalClosedgRPC and cleans up.
- Writer Task: waits on
Phase 3: UI Rendering and State Sync (Cocoon -> Wind/Sky)
- Terminal service in Cocoon creates a local
Terminalproxy object for extensions. - Mountain’s Reader Task emits
sky://terminal/dataTauri event to Sky. - Terminal component (wrapping Xterm.js) receives the event and calls
xterm.write(data).
Phase 4: User Input (Wind/Sky -> Mountain -> Shell)
- User types in terminal UI. Xterm.js captures keystrokes.
TauriInvoke('mountain://terminal/send-text', { Id, Text })sends input to Mountain.SendTextToTerminalLogiclooks upTerminalStateDtoand sends text to the mpsc channel.- Writer Task writes bytes to PTY master. Shell executes command and produces output.
- Reader Task captures output, loop continues.
Key Source Files
Mountain/Source/Environment/TerminalProvider.rs— terminal creation and PTY managementMountain/Source/handlers/terminal/TerminalLogic.rs— send text handler
