Visual Studio Marketplace Open VSX GitHub Sponsors
Open TUI terminal MUX for VS Code with tmux, zellij, and native terminal support.
If this project helps your workflow, you can support it on GitHub Sponsors.
- Backend-first terminal: Starts a plain shell for your chosen backend (
native,tmux, orzellij) — no AI tool picker on open - Full TUI Support: Complete terminal emulation with xterm.js and WebGL rendering
- ULW Terminal Manager: Dedicated tmux session management surface with inline pane and window controls
- Tmux Integration: Automatic tmux session discovery, workspace-scoped session filtering, and tmux status bar hidden in sidebar
- Native shell switching: Switch to a normal shell in the sidebar when you need it
- Return to Workspace Banner: Quick navigation back to the active workspace from ULW Terminal Manager
- HTTP API Integration: Bidirectional communication with OpenCode CLI via HTTP API
- Auto-Context Sharing: Automatically shares editor context when terminal opens
- File References with Line Numbers: Send file references with
@filename#L10-L20syntax - Code Actions: Diagnostic-triggered code actions for errors and warnings
- Keyboard Shortcuts: Quick access with
Cmd+Alt+L,Cmd+Alt+A, andCmd+Alt+T - Drag & Drop Support: Hold Shift and drag files/folders to send as references
- Context Menu Integration: Right-click files in Explorer or text in Editor to send to OpenCode
- Secondary Sidebar: Dock the terminal in the secondary sidebar for split-screen workflows
- Configurable: Customize font, terminal settings, backend (
ulw.terminalBackend), and HTTP API behavior
This extension provides a sidebar-only terminal MUX experience. A normal shell (or your tmux / zellij session) runs in the VS Code sidebar instead of the native terminal panel. OpenCode and other AI CLIs are optional — start them yourself in the terminal when you want them.
The extension consists of two primary sidebar views:
- ULW Terminal (secondary sidebar): The main interactive TUI session.
- ULW Terminal Manager: A dedicated surface for managing tmux sessions, panes, and windows.
The extension uses a hybrid communication approach:
-
HTTP API: Primary communication channel with OpenCode CLI
- Port range: 16384-65535 (ephemeral ports)
- Endpoints:
/health,/tui/append-prompt - Auto-discovery of OpenCode CLI HTTP server
-
WebView Messaging: Terminal I/O between extension host and sidebar WebView
- xterm.js for terminal rendering
- Bidirectional message passing for input/output
- Open VS Code
- Go to Extensions (
Cmd+Shift+X/Ctrl+Shift+X) - Search for "ULW"
- Click Install
For VSCodium, Gitpod, Eclipse Theia, and other VS Code-compatible IDEs:
- Open your IDE's extension view
- Search for "ULW"
- Click Install
Or visit the OpenVSX page.
- Clone the repository:
git clone https://github.com/islee23520/ulwcode.git
cd ulwcode- Install dependencies:
npm install
- Build the extension:
npm run compile
- Package the extension:
npx @vscode/vsce package
- Install in VS Code:
- Open VS Code
- Go to Extensions (
Cmd+Shift+X/Ctrl+Shift+X) - Click "..." menu → "Install from VSIX"
- Select the generated
.vsixfile
- Click the ULW icon in the Activity Bar (sidebar) to open ULW Terminal Manager
- The ULW Terminal is available in the secondary sidebar
- With
ulw.autoStartOnOpenenabled, ULW starts your configured backend (plain shell / tmux / zellij) when the view opens - Run any CLI (including OpenCode) manually in that terminal
- Start ULW Terminal - Manually start the sidebar terminal session
- ULW Terminal: Paste - Paste text into the terminal
- Send File Reference (@file) (
Cmd+Alt+L/Ctrl+Alt+L) - Send current file with line numbers- No selection:
@filename - Single line:
@filename#L10 - Multiple lines:
@filename#L10-L20
- No selection:
- Send All Open File References (
Cmd+Alt+A/Ctrl+Alt+A) - Send all open file references - Send to OpenCode - Send selected text or file from context menu
- Send to Active Terminal - Send selected text to the active terminal
- Open Tmux Session in New Window - Open the current tmux session in a new VS Code window
- Spawn Tmux Session for Workspace - Create a new tmux session scoped to the current workspace
- Select OpenCode Tmux Session - Choose from a list of available tmux sessions
- Switch Tmux Session - Switch to a different tmux session
- Browse Tmux Sessions (
Cmd+Alt+T/Ctrl+Alt+T) - Browse and switch between tmux sessions - Switch to Native Shell - Toggle between OpenCode and a native shell
- Open ULW Terminal Manager - Open the ULW Terminal Manager view
- Switch to Pane - Switch focus to a specific tmux pane
- Split Pane Horizontal - Split the current pane horizontally
- Split Pane Vertical - Split the current pane vertically
- Split Pane with Command - Split the pane and run a specific command
- Send Text to Pane - Send text directly to a specific tmux pane
- Resize Pane - Adjust the size of the current tmux pane
- Swap Panes - Swap positions of two tmux panes
- Kill Pane - Close the current tmux pane
- Next Window - Switch to the next tmux window
- Previous Window - Switch to the previous tmux window
- Create Window - Create a new tmux window
- Select Window - Choose from available tmux windows
- Kill Window - Close the current tmux window
- Kill Session - Kill the current tmux session
- Refresh ULW Terminal Manager - Refresh ULW Terminal Manager
| Shortcut | Command | Context |
|---|---|---|
Cmd+Alt+L / Ctrl+Alt+L |
Send File Reference | Editor or Terminal |
Cmd+Alt+A / Ctrl+Alt+A |
Send All Open Files | Editor or Terminal |
Cmd+Alt+T / Ctrl+Alt+T |
Browse Tmux Sessions | Terminal focused |
Cmd+V / Ctrl+V |
Paste | Terminal focused |
Ctrl+P |
Quick Open (native) | Terminal focused (passthrough) |
- Explorer: Right-click any file or folder → "Send to OpenCode"
- Editor: Right-click anywhere → "Send File Reference (@file)"
- Hold Shift and drag files/folders to the terminal to send as
@filereferences
The ULW Terminal Manager view provides advanced tmux session and pane management directly within the VS Code sidebar:
- Session Discovery: Automatically detects existing tmux sessions on your system.
- Workspace Filtering: Filters sessions to show those relevant to your current workspace.
- Pane Controls: Inline buttons to split panes (horizontal/vertical), switch focus, resize, swap, and kill panes.
- Window Controls: Navigate, create, select, and kill tmux windows.
- Return to Workspace: A quick-access banner to navigate back to the active workspace session.
- Clean UI: The tmux status bar is automatically hidden within the sidebar terminal to maximize vertical space.
The extension communicates with OpenCode CLI via an HTTP API for reliable bidirectional communication:
- Auto-Discovery: Automatically discovers OpenCode CLI HTTP server port
- Health Checks: Validates OpenCode CLI availability before sending commands
- Retry Logic: Exponential backoff for reliable communication
- Context Sharing: Automatically shares editor context on terminal open
- When OpenCode starts, it launches an HTTP server on an ephemeral port (16384-65535)
- The extension discovers the port and establishes communication
- File references and context are sent via HTTP POST to
/tui/append-prompt - Health checks ensure OpenCode is ready before sending data
{
"ulw.enableHttpApi": true,
"ulw.httpTimeout": 5000,
"ulw.autoShareContext": true
}When enabled, the extension automatically shares editor context with OpenCode when the terminal opens:
- Open Files: Lists all currently open files
- Active Selection: Includes line numbers for selected text
- Format:
@path/to/file#L10-L20
This feature eliminates the need to manually share context when starting a new OpenCode session.
Available settings in VS Code settings (Cmd+, / Ctrl+,):
| Setting | Type | Default | Description |
|---|---|---|---|
ulw.autoStart |
boolean | true |
Automatically start OpenCode when the view is activated |
ulw.autoStartOnOpen |
boolean | true |
Automatically start OpenCode when sidebar is opened |
ulw.fontSize |
number | 14 |
Terminal font size in pixels (6-25) |
ulw.fontFamily |
string | Nerd Font stack* | Terminal font family |
ulw.cursorBlink |
boolean | true |
Enable cursor blinking |
ulw.cursorStyle |
string | "block" |
Cursor style: block, underline, or bar |
ulw.scrollback |
number | 10000 |
Maximum lines in scrollback buffer (0-100000) |
ulw.autoSwitchKoreanKeyboard |
boolean | false |
Auto-switch the macOS system input source when likely Korean/English layout mistakes are detected |
ulw.terminal.defaultLocation |
string | "editor" |
Default terminal location: editor or sidebar |
ulw.autoFocusOnSend |
boolean | true |
Auto-focus ULW after sending file references |
ulw.shellPath |
string | "" |
Custom shell path (empty = VS Code default) |
ulw.shellArgs |
array | [] |
Custom shell arguments |
* Default: 'JetBrainsMono Nerd Font', 'FiraCode Nerd Font', 'CascadiaCode NF', Menlo, monospace
| Setting | Type | Default | Description |
|---|---|---|---|
ulw.enableHttpApi |
boolean | true |
Enable HTTP API for OpenCode communication |
ulw.httpTimeout |
number | 5000 |
HTTP API request timeout in ms (1000-30000) |
ulw.autoShareContext |
boolean | true |
Auto-share editor context with OpenCode |
ulw.contextDebounceMs |
number | 500 |
Debounce delay for context updates (100-5000 ms) |
| Setting | Type | Default | Description |
|---|---|---|---|
ulw.terminalBackend |
string | "tmux" |
Terminal backend: native, tmux, or zellij (unavailable backends fall back to native) |
ulw.enableAutoSpawn |
boolean | false |
When enabled, discovery may spawn OpenCode in the background if no instance is found (does not affect sidebar terminal startup) |
ulw.showTmuxWindowControls |
boolean | true |
Show tmux session/window controls in the terminal toolbar |
| Setting | Type | Default | Description |
|---|---|---|---|
ulw.logLevel |
string | "info" |
Log level: debug, info, warn, error |
ulw.maxDiagnosticLength |
number | 500 |
Maximum length of diagnostic messages (100-2000) |
ulw.codeActionSeverities |
array | ["error", "warning"] |
Diagnostic severities that trigger code actions |
{
"ulw.autoStart": true,
"ulw.fontSize": 14,
"ulw.fontFamily": "'JetBrainsMono Nerd Font', monospace",
"ulw.cursorBlink": true,
"ulw.cursorStyle": "block",
"ulw.scrollback": 10000,
"ulw.enableHttpApi": true,
"ulw.httpTimeout": 5000,
"ulw.autoShareContext": true,
"ulw.terminalBackend": "tmux",
"ulw.enableAutoSpawn": false
}- VS Code 1.106.0 or higher
- Node.js 20.0.0 or higher
- Optional: OpenCode (or another AI CLI) if you use HTTP prompts, auto-context, or
ulw.enableAutoSpawn
npm run compile # Development build npm run watch # Watch mode npm run package # Production build npm run test # Run tests npm run test:watch # Watch mode tests npm run test:coverage # Run tests with coverage npm run lint # Lint source npm run format # Format source
src/
├── extension.ts # VS Code entry (activate/deactivate)
├── types.ts # Shared host↔webview message contracts
├── types.test.ts # Type contract tests
├── core/
│ ├── ExtensionLifecycle.ts # Service wiring + activation/deactivation
│ ├── ExtensionLifecycle.test.ts # Lifecycle tests
│ └── commands/ # Command registration
│ ├── index.ts # registerCommands() orchestrator
│ ├── terminalCommands.ts # start, restart, paste, file references
│ ├── tmuxSessionCommands.ts # session switch, create, spawn, browse
│ └── tmuxPaneCommands.ts # pane + window commands + QuickPick helpers
├── providers/
│ ├── TerminalProvider.ts # Main sidebar terminal webview provider
│ ├── TerminalProvider.test.ts # Provider tests
│ ├── TerminalDashboardProvider.ts # ULW Terminal Manager provider
│ ├── TerminalDashboardProvider.test.ts # Dashboard tests
│ ├── CodeActionProvider.ts # Diagnostic code action provider
│ ├── CodeActionProvider.test.ts # Code action tests
│ └── opencode/ # Terminal core modules
│ ├── OpenCodeMessageRouter.ts # Message dispatch + handlers
│ └── OpenCodeSessionRuntime.ts # Start/restart/tmux/instance switching
├── terminals/
│ └── TerminalManager.ts # node-pty process lifecycle
├── services/
│ ├── InstanceStore.ts # In-memory instance state + EventEmitter
│ ├── InstanceController.ts # Instance lifecycle orchestration
│ ├── InstanceDiscoveryService.ts # Running instance discovery + auto-spawn
│ ├── InstanceRegistry.ts # Instance persistence (globalState)
│ ├── ConnectionResolver.ts # 4-tier port resolution + client pool
│ ├── OpenCodeApiClient.ts # HTTP client (retry/backoff)
│ ├── PortManager.ts # Ephemeral port allocation
│ ├── TmuxSessionManager.ts # tmux CLI wrapper (sessions, panes, windows)
│ ├── ContextManager.ts # Active editor/selection observer
│ ├── ContextSharingService.ts # @file#L context formatter
│ ├── FileReferenceManager.ts # File reference serialization
│ ├── InstanceQuickPick.ts # Quick pick UI for instance selection
│ ├── OutputChannelService.ts # Singleton logging service
│ └── OutputCaptureManager.ts # Terminal output capture
├── webview/
│ ├── main.ts # Terminal webview (xterm.js + WebGL)
│ ├── terminal.html # Terminal webview HTML
│ ├── terminal.css # Terminal webview styles
│ ├── dashboard-manager.ts # Dashboard webview logic
│ ├── dashboard.html # Dashboard webview HTML
│ └── dashboard.css # Dashboard webview styles
├── utils/
│ └── PromptFormatter.ts # Prompt formatting utilities
├── test/
│ └── mocks/ # Manual vscode + node-pty mocks
└── __tests__/
└── setup.ts # Vitest global setup
Webpack 2 bundles: extension.js (node), webview.js (web)
Based on the vscode-sidebar-terminal extension, streamlined specifically for ULW Terminal:
- Terminal Backend: node-pty for PTY support
- Terminal Frontend: xterm.js with WebGL rendering
- Process Management: Automatic OpenCode lifecycle
- Communication: HTTP API + WebView messaging
- Port Management: Ephemeral port allocation (16384-65535)
MIT
- Based on vscode-sidebar-terminal by s-hiraoku
- Development assisted by Sisyphus from oh-my-opencode
- Uses xterm.js for terminal emulation
- Uses node-pty for PTY support