Provides battle-tested patterns for xterm.js terminal implementations. Use when building or debugging xterm.js terminals, integrating with React, implementing WebSocket terminal I/O, managing terminal persistence with tmux, or debugging terminal initialization, resize, or rendering issues.
View on GitHubGGPrompts/TabzChrome
xterm-js
January 16, 2026
Select agents to install to:
npx add-skill https://github.com/GGPrompts/TabzChrome/blob/main/plugins/xterm-js/skills/xterm-js/SKILL.md -a claude-code --skill using-xterm-jsInstallation paths:
.claude/skills/using-xterm-js/# xterm.js Best Practices
Comprehensive patterns for building terminal applications with xterm.js, React, and WebSockets.
## Contents
- [Core Patterns](#core-patterns) - Essential patterns (always load)
- [Reference Files](#reference-files) - Detailed documentation by topic
## Core Patterns
### 1. Refs and State Management
**Clear refs when state changes.** Refs persist across state changes - when clearing state, also clear related refs.
```typescript
// CORRECT - Clear both state AND ref
if (terminal.agentId) {
clearProcessedAgentId(terminal.agentId) // Clear ref
}
updateTerminal(id, { agentId: undefined }) // Clear state
```
**Key Insight:** State = what the terminal is; Refs = what we've processed. See `references/refs-state-patterns.md`.
### 2. WebSocket Message Types
**Know your destructive operations.** Backend handlers have different semantics:
- `type: 'disconnect'` - Graceful disconnect, keep session alive
- `type: 'close'` - **FORCE CLOSE and KILL session**
```typescript
// WRONG - This KILLS the tmux session!
wsRef.current.send(JSON.stringify({ type: 'close', terminalId }))
// CORRECT - Use API endpoint only, let PTY disconnect naturally
await fetch(`/api/tmux/detach/${sessionName}`, { method: 'POST' })
```
See `references/websocket-patterns.md` for backend routing patterns.
### 3. React Hooks & Shared Refs
**Pass shared refs as parameters** when extracting hooks:
```typescript
// WRONG - Creates NEW ref, breaks sharing
export function useWebSocketManager(...) {
const wsRef = useRef<WebSocket | null>(null)
}
// RIGHT - Uses parent's ref
export function useWebSocketManager(
wsRef: React.MutableRefObject<WebSocket | null>,
) { }
```
See `references/react-hooks-patterns.md` for refactoring workflows.
### 4. Terminal Initialization
**xterm.js requires non-zero container dimensions.** Use visibility-based hiding, not display:none.
```typescript
// WRONG - Prevents xterm initialization
<div style={{ display: isActive ? 'block' : 'noIssues Found: