Compiled 2026-03-02. Reflects latest stable releases of each terminal. "Yes*" means supported with caveats (see notes). "No" means not supported as of latest release.
| Terminal | Truecolor (24-bit) | 256-color | Unicode/Emoji | Kitty Keyboard Protocol | Bracketed Paste | Mouse Capture | Alt Screen | Notable Quirks |
|---|---|---|---|---|---|---|---|---|
| macOS Terminal.app | No (until macOS Tahoe/26) | Yes | Partial (emoji widths wrong, no ligatures) | No | Yes | Yes (basic SGR) | Yes | No truecolor - RGB silently clamped to 256. Emoji often render 1-cell wide instead of 2. TERM=xterm-256color only. |
| iTerm2 | Yes | Yes | Full (excellent emoji, ligatures) | Yes (3.5+) | Yes | Yes (SGR 1006) | Yes | Slight input latency on complex scenes. Proprietary inline image protocol. Occasionally misreports TERM_PROGRAM version to apps. |
| Ghostty | Yes | Yes | Full (grapheme clustering, good emoji) | Yes | Yes | Yes (SGR 1006) | Yes | Very new - occasional edge cases with rare combining sequences. GPU-rendered, minimal legacy quirks. |
| Handterm | Yes | Yes | Full (good emoji/Nerd Font handling) | Partial | Yes | Yes (SGR 1006) | Yes | Experimental Wayland-native GPU terminal. Smooth pixel-scroll behavior is terminal-native in its GPU path. Still evolving; some CLI/launcher integrations may lag behind established terminals. |
| Kitty | Yes | Yes | Full (grapheme clustering, emoji) | Yes (originator) | Yes | Yes (SGR 1006) | Yes | Strict spec compliance can break apps expecting xterm quirks. Does NOT set TERM=xterm-*; uses xterm-kitty. ssh may need terminfo transfer. |
| Alacritty | Yes | Yes | Full (good emoji support) | Yes (0.13+) | Yes | Yes (SGR 1006) | Yes | No tabs/splits (by design). No scrollback mouse-scroll passthrough to apps without config. No ligature support. |
| WezTerm | Yes | Yes | Full (ligatures, emoji, Nerd Fonts) | Yes | Yes | Yes (SGR 1006) | Yes | Lua config can cause startup delays. Multiplexer mode has rare sync artifacts. Very feature-complete. |
| Warp | Yes | Yes | Full (emoji, ligatures) | Yes* (partial, evolving) | Yes* (Warp intercepts paste for its own UI) | Yes* (limited - Warp's block model intercepts raw mouse) | Yes* (Warp overrides alt-screen for its own rendering) | Warp's non-traditional architecture (blocks, AI input) intercepts many escape sequences. TUI apps may render incorrectly because Warp interposes its own shell integration layer. |
| Windows Terminal | Yes | Yes | Full (emoji, CJK, good font fallback) | No | Yes | Yes (SGR 1006) | Yes | ConPTY layer can add latency and occasionally drops rapid escape sequences. Background color can bleed 1 cell on resize. Bold = bright color mapping surprises some apps. |
| VS Code Terminal | Yes | Yes | Full (inherits VS Code's font rendering) | Yes (xterm.js 5.x+) | Yes | Yes (SGR 1006) | Yes | xterm.js backend: slightly slower than native terminals. Canvas renderer can leave stale cells on rapid redraws. Emoji width depends on editor font. Extension host restarts can kill the PTY. |
| GNOME Terminal (VTE) | Yes | Yes | Full (system font emoji, no ligatures) | No | Yes | Yes (SGR 1006) | Yes | VTE rewrites COLORTERM=truecolor. Historically slow with large scrollback. Underline color/style support lagged. No ligatures (VTE limitation). |
| Konsole | Yes | Yes | Full (emoji, Nerd Fonts, ligatures) | No* (partial, basic CSI u only) | Yes | Yes (SGR 1006) | Yes | Reflow on resize can cause momentary display corruption. Older versions had SGR background bleed on line wrap. Generally very solid. |
| tmux | Yes* (needs set -g default-terminal "tmux-256color" + set -as terminal-features ',*:RGB') |
Yes | Partial (passes through but wcwidth mismatches with outer terminal) | No (strips kitty keyboard sequences) | Yes (passthrough) | Yes (passthrough) | Yes (own alt-screen layer) | Major source of rendering bugs. Interposes its own terminal emulation layer. Strips unknown escapes by default. Truecolor requires explicit config. passthrough DCS escape needed for some protocols. Double-width chars can desync between tmux's internal state and the outer terminal. |
| screen | No (256-color max without patches) | Yes | Partial (limited multi-byte, no emoji) | No | Yes* (recent versions only) | Yes* (basic, older protocol) | Yes (own alt-screen layer) | Most limited multiplexer. No truecolor. Ancient codebase with minimal Unicode support - CJK/emoji characters frequently render as wrong width or garble the line. Escape sequence filtering is aggressive. Largely superseded by tmux. |
- Truecolor: Supports
\e[38;2;R;G;Bm/\e[48;2;R;G;BmSGR sequences for 16M colors - 256-color: Supports
\e[38;5;Nm/\e[48;5;Nmindexed color - Unicode/Emoji: Full = correct grapheme clustering, proper double-width, emoji ZWJ sequences; Partial = basic multi-byte but broken widths or missing sequences
- Kitty Keyboard Protocol: Supports
CSI > flags uprogressive enhancement keyboard protocol - Bracketed Paste: Supports
\e[?2004hto wrap pasted content in begin/end markers - Mouse Capture: Supports SGR 1006 mouse reporting (
\e[?1006h) - Alt Screen: Supports
\e[?1049halternate screen buffer
Root cause: When a TUI sets a background color on a cell but the terminal fails to clear or repaint that cell correctly on the next frame, the cell retains its old content or falls back to the default background (often white on light themes).
Affected terminals and scenarios:
-
All terminals: If the app writes
\e[K(erase to end of line) without first setting the correct background color via SGR, the erased region inherits the terminal's default background, not the app's intended color. This is the #1 cause of white/light blocks in dark-themed TUIs. -
tmux: tmux emulates its own screen buffer. If the inner app uses BCE (Background Color Erase) and tmux's
default-terminaldoesn't advertise BCE support correctly, erased regions render with the wrong background. Fix: ensuretmux-256colorterminfo is used and matches the outer terminal's capabilities. -
Windows Terminal (ConPTY): ConPTY sometimes coalesces rapid SGR+erase sequences incorrectly, causing 1-2 cells at line boundaries to retain old background colors after a resize or rapid redraw.
-
VS Code Terminal (xterm.js): The canvas-based renderer can leave "ghost" cells when the terminal rapidly alternates between normal and alternate screen buffers, especially during resize events.
Root cause: The terminal and the application disagree on how many columns a character occupies. The app thinks an emoji is 2 columns wide (per Unicode East_Asian_Width), but the terminal renders it as 1 (or vice versa), causing every subsequent cell on that line to be shifted.
Affected terminals:
-
macOS Terminal.app: Particularly bad. Many emoji render at 1-cell width while apps (using libc
wcwidthor Unicode tables) assume 2. This desynchronizes the entire line, leaving "phantom" cells that appear as blank/white blocks. -
tmux: tmux has its own internal
wcwidthimplementation. If it disagrees with the outer terminal about a character's width (common with newer emoji added in recent Unicode versions), cursor positioning breaks and cells appear duplicated or blank. -
screen: Even worse than tmux. Its Unicode width tables are years out of date. Most emoji and many CJK characters will corrupt line layout.
-
Alacritty: Generally good, but Nerd Font glyphs that are PUA (Private Use Area) codepoints default to 1-cell width. If the app assumes 2, misalignment occurs.
Root cause: When the terminal window is resized, the app receives SIGWINCH and must redraw. If the redraw is partial or the terminal's line reflow logic conflicts with the app's assumptions, old content remains visible.
Affected terminals:
-
Konsole: Reflow on resize is aggressive - it reflows soft-wrapped lines, which can conflict with TUI apps that expect each line to be independent. This causes momentary "double rendering" artifacts.
-
tmux: Resize causes tmux to reflow its own buffer and then relay
SIGWINCHto the inner app. There's a race condition: if the app redraws before tmux finishes reflowing, old content appears for 1-2 frames. -
VS Code Terminal: The xterm.js resize handler can lag behind the actual viewport size, causing the app to draw for the wrong dimensions for 1-2 frames.
Root cause: When entering or leaving the alternate screen (\e[?1049h / \e[?1049l), some terminals don't fully clear the buffer, or they restore the wrong saved state.
Affected scenarios:
-
Warp: Warp's block-based architecture doesn't use a traditional alternate screen. TUI apps that rely on
\e[?1049hmay find their output mixed with Warp's shell integration UI elements. -
tmux + nested sessions: Nested tmux sessions (or tmux inside screen) can lose track of which alternate screen buffer is active, leaving the outer multiplexer's status bar overlaid on the inner app's content.
-
macOS Terminal.app: On older macOS versions (pre-Ventura), restoring from alternate screen occasionally leaves the cursor invisible until the user types.
Root cause: \e[?25l (hide cursor) and \e[?25h (show cursor) aren't always reliably paired, especially when apps crash or are killed with SIGKILL.
Affected terminals:
-
All terminals: If a TUI app crashes without restoring the cursor, it stays hidden. Most modern terminals (kitty, WezTerm, iTerm2) auto-restore on shell prompt, but GNOME Terminal and Terminal.app may leave cursor hidden until
resetortput cnorm. -
tmux: If the inner pane's app hides the cursor and then the user switches panes, the cursor visibility state can leak between panes (fixed in newer tmux versions but still observed in 3.3 and earlier).
Root cause: \e[0m (SGR reset) should reset all attributes, but some terminals handle it inconsistently with respect to underline style, underline color, or strikethrough.
- GNOME Terminal (VTE): Older VTE versions didn't reset underline color on SGR 0, causing colored underlines to persist across lines.
- Konsole: Historical bug where
\e[0mdidn't reset the overline attribute. - screen:
\e[0mdoesn't reliably reset 256-color foreground/background, leaving stale colors on subsequent text.
Root cause: Apps that enable the kitty keyboard protocol but don't properly disable it on exit (or crash) leave the terminal in an enhanced keyboard mode. Subsequent shell input may produce garbled escape sequences.
- Kitty, Alacritty, WezTerm, Ghostty: All affected if the app doesn't call
CSI < uon exit. Kitty itself auto-resets on shell prompt detection. Alacritty and WezTerm do not auto-reset - the user must runreset.
tmux is the most common source of rendering issues in TUI apps because it interposes a full VT100 emulation layer:
- Escape sequence filtering: tmux strips any escape sequences it doesn't recognize. This breaks kitty keyboard protocol, kitty graphics protocol, iTerm2 inline images, and some extended SGR attributes (e.g.,
CSI 4:3 mcurly underline requires tmux 3.4+). - Delayed passthrough: Even with
set -g allow-passthrough on, DCS passthrough adds latency and can fragment long sequences. - TERM mismatch: If the inner
TERMdoesn't match tmux's advertised capabilities (e.g., app seesxterm-256colorbut tmux only passesscreen-256color), color/capability negotiation fails silently. - Clipboard: OSC 52 clipboard support works but must be explicitly enabled (
set -g set-clipboard on).
-
Always set BGC before erasing: Before any
\e[K,\e[J, or\e[2J, set the intended background color via SGR. Never assume the terminal's default background matches your theme. -
Use
COLORTERMfor truecolor detection: CheckCOLORTERM=truecolororCOLORTERM=24bitrather than parsing terminfo, which is unreliable for RGB support. -
Handle emoji width defensively: Use Unicode 15.1+ width tables and accept that some terminals will disagree. Consider avoiding emoji in grid-aligned TUI layouts, or pad with explicit spaces.
-
Full redraw on SIGWINCH: Don't try to incrementally patch the screen on resize. Clear everything and redraw from scratch.
-
Always restore terminal state on exit: Use a cleanup handler (even for SIGTERM/SIGINT) that: restores cursor visibility, leaves alternate screen, disables mouse capture, disables bracketed paste, resets kitty keyboard protocol, and issues SGR reset.
-
Test under tmux: If your users might run inside tmux, test there explicitly. Many rendering bugs only appear under a multiplexer.
-
Degrade gracefully for Terminal.app and screen: These are the lowest-capability terminals still in common use. Detect them (via
TERM_PROGRAMorTERM) and fall back to 256-color mode with ASCII-safe UI elements.