The Terminal component provides an embedded terminal interface using xterm.js, connected to a real shell process via node-pty in the Electron main process.
Usage
import Terminal from '@/components/Terminal';
function App() {
return (
<div className="terminal-container">
<Terminal />
</div>
);
}
Features
Terminal Initialization
The terminal is configured with xterm.js options:
const term = new XTerm({
cursorBlink: true,
fontSize: 13,
fontFamily: "Monaco, Menlo, Courier New, monospace",
theme: { background: "#1e1e1e", foreground: "#d4d4d4" },
});
Fit Addon
The FitAddon automatically resizes the terminal to fit its container:
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);
term.open(terminalRef.current);
fitAddon.fit();
Bidirectional Communication
The terminal sends user input to the shell and receives output:
Output (Shell → Terminal):
window.electronAPI.onTerminalData((data: string) => {
term.write(data);
});
Input (Terminal → Shell):
term.onData((data) => {
window.electronAPI.terminalInput(data);
});
Configuration
XTerm Options
Enable blinking cursor animation
fontFamily
string
default:"Monaco, Menlo, Courier New, monospace"
CSS font family for terminal text
Color theme object{
background: "#1e1e1e",
foreground: "#d4d4d4"
}
IPC Channels
The Terminal communicates with the Electron main process through three IPC channels:
create-terminal
window.electronAPI.createTerminal(): void
Creates a new pseudo-terminal (pty) process in the main process.
Channel: create-terminal (send)
Usage:
if (window.electronAPI?.createTerminal) {
window.electronAPI.createTerminal();
}
terminal-data
window.electronAPI.onTerminalData(callback: (data: string) => void): void
Listens for output from the shell process.
Channel: terminal-data (receive)
Parameters:
callback: Function called with shell output data
Usage:
window.electronAPI.onTerminalData((data: string) => {
term.write(data);
});
window.electronAPI.terminalInput(data: string): void
Sends user input to the shell process.
Channel: terminal-input (send)
Parameters:
data: User input string (keystrokes, commands, etc.)
Usage:
term.onData((data) => {
console.log("term data", data);
window.electronAPI.terminalInput(data);
});
Integration with node-pty
The Electron main process uses node-pty to spawn a real shell process. The Terminal component acts as the frontend UI, while the main process handles:
- Creating the pty process with
node-pty
- Forwarding input from renderer to pty
- Forwarding output from pty to renderer
- Handling pty lifecycle (spawn, resize, exit)
State Management
The component uses React refs to maintain terminal instances:
const terminalRef = useRef<HTMLDivElement>(null);
const xtermRef = useRef<XTerm | null>(null);
Lifecycle
- Mount: Create XTerm instance, load FitAddon, create pty process
- Active: Handle bidirectional data flow
- Unmount: Terminal cleanup is handled automatically by React
Styling
The terminal container uses full width and height:
<div className="w-full h-full" ref={terminalRef} />
CSS is imported from xterm.js:
import "@xterm/xterm/css/xterm.css";
Example: Terminal with Custom Theme
import { Terminal as XTerm } from "@xterm/xterm";
import { FitAddon } from "@xterm/addon-fit";
const term = new XTerm({
cursorBlink: true,
fontSize: 14,
fontFamily: "JetBrains Mono, monospace",
theme: {
background: "#282c34",
foreground: "#abb2bf",
cursor: "#528bff",
},
});
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);
term.open(containerElement);
fitAddon.fit();
Example: Handling Terminal Output
window.electronAPI.onTerminalData((data: string) => {
// Write output to terminal
term.write(data);
// Optional: Log or process output
console.log("Received:", data);
});
Example: Sending Commands
// Send a command programmatically
const runCommand = (cmd: string) => {
window.electronAPI.terminalInput(cmd + '\r');
};
runCommand('ls -la');
runCommand('npm install');
Reference
Source: src/components/Terminal.tsx
Dependencies:
@xterm/xterm - Terminal emulator core
@xterm/addon-fit - Auto-fit terminal to container
node-pty (main process) - Pseudo-terminal spawning
IPC Channels:
create-terminal - Spawn new pty process
terminal-data - Receive shell output
terminal-input - Send user input to shell