Skip to content

Instantly share code, notes, and snippets.

@GGPrompts
Last active November 17, 2025 18:27
Show Gist options
  • Select an option

  • Save GGPrompts/94d74552271412bd1374f1122f7d20da to your computer and use it in GitHub Desktop.

Select an option

Save GGPrompts/94d74552271412bd1374f1122f7d20da to your computer and use it in GitHub Desktop.
Terminal Tabs Chrome Extension - Terminal Output Fix (November 2025) #bug-fix #chrome-extension #xterm.js #websocket #terminal #message-passing

Terminal Tabs Chrome Extension - Terminal Output Fix

The Problem

Chrome extension terminals were spawning successfully but only showing a blinking cursor. Typing worked (backend logs showed input being received), but no output was displayed in the terminal.

Root Cause

Message type mismatch in the background service worker

The backend sends terminal output with type 'terminal-output', but the background worker was only checking for 'output':

// ❌ BROKEN - Only checked for 'output'
if (message.type === 'output') {
  broadcastToClients({
    type: 'TERMINAL_OUTPUT',
    terminalId: message.terminalId,
    data: message.data,
  })
}

This caused terminal output to be wrapped in WS_MESSAGE instead of TERMINAL_OUTPUT, so the Terminal component never received it.

The Fix

File: extension/background/background.ts (line 39)

// βœ… FIXED - Check for both 'output' and 'terminal-output'
if (message.type === 'output' || message.type === 'terminal-output') {
  console.log('πŸ“Ÿ Terminal output received, broadcasting to clients:', message.terminalId?.slice(-8), message.data?.length, 'bytes')
  broadcastToClients({
    type: 'TERMINAL_OUTPUT',
    terminalId: message.terminalId,
    data: message.data,
  })
}

Additional Fixes

1. Unicode11 Addon for Emoji/TUI Support

File: extension/components/Terminal.tsx

import { Unicode11Addon } from '@xterm/addon-unicode11'

const xterm = new XTerm({
  // ... other options
  allowProposedApi: true,  // Required for Unicode11
})

const unicode11Addon = new Unicode11Addon()
xterm.loadAddon(unicode11Addon)
xterm.unicode.activeVersion = '11'

Why: Fixes emoji width issues and improves TUI app rendering (htop, lazygit, etc.)

2. Simplified Header Layout

File: extension/sidepanel/sidepanel.tsx

  • Removed redundant custom header (Chrome's sidepanel already provides one)
  • Created compact toolbar with just: connection status, session count, spawn button, settings
  • Removed footer that was covering tmux status bar

Before:

[Chrome Header: Terminal Tabs - Browser Edition]
[Custom Header: Terminal Tabs | Connected | Buttons]
[Session Tabs]
[Terminal View]
[Footer: 1 active session] ← Covered tmux status bar

After:

[Chrome Header: Terminal Tabs - Browser Edition]
[Compact Toolbar: Connected | 1 session | + | βš™οΈ]
[Session Tabs]
[Terminal View] ← Full height, tmux status bar visible

Debugging Process

  1. Backend logs showed terminals spawning successfully:

    [success] Spawned terminal { id: '...' }
    
  2. Backend logs showed output being generated:

    πŸ“¨ WS message received: terminal-output
    
  3. Background worker logs showed messages being received:

    πŸ“¨ WS message received: terminal-output
    
  4. BUT Terminal component never logged receiving output:

    // This never appeared:
    [Terminal] πŸ“Ÿ TERMINAL_OUTPUT received:
    
  5. The message flow was broken at the background worker:

    • Backend β†’ WebSocket β†’ Background Worker βœ…
    • Background Worker β†’ Terminal Component ❌ (wrong message type)

Message Flow (Corrected)

Backend (server.js)
  ↓ WebSocket sends: { type: 'terminal-output', terminalId: '...', data: '...' }
Background Worker (background.ts)
  ↓ Checks: message.type === 'output' || message.type === 'terminal-output' βœ…
  ↓ Broadcasts: { type: 'TERMINAL_OUTPUT', terminalId: '...', data: '...' }
Terminal Component (Terminal.tsx)
  ↓ Receives via port connection
  ↓ Checks: message.type === 'TERMINAL_OUTPUT' βœ…
  ↓ Writes to xterm: xtermRef.current.write(message.data)
Terminal Display βœ… Output visible!

Files Changed

  1. extension/background/background.ts - Fixed output message type check
  2. extension/components/Terminal.tsx - Added Unicode11 addon
  3. extension/sidepanel/sidepanel.tsx - Simplified header/footer

Testing

After the fix:

  • βœ… Terminal output displays correctly
  • βœ… Bash prompts appear
  • βœ… Command output shows
  • βœ… TUI apps render correctly (htop, lazygit, etc.)
  • βœ… Emojis display with correct width
  • βœ… Tmux status bar fully visible (no footer overlap)

Lessons Learned

  1. Always check message type strings exactly - Small differences like 'output' vs 'terminal-output' can break the entire flow
  2. Follow the message through each layer - Backend β†’ WebSocket β†’ Background Worker β†’ Component
  3. Add debug logging at each step - Made it easy to see where the message flow broke
  4. The Unicode11 addon is essential for modern terminal apps with emojis/special characters

Date: November 17, 2025 Issue: Terminal spawned but showed only blinking cursor Fix: Message type mismatch in background worker Time to Debug: ~2 hours Result: Fully functional Chrome extension terminal! πŸŽ‰

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment