DECSTBM scroll-region experiment (tengu_marlin_porch) corrupts inline TUI on wide panes / multi-line statuslines

Resolved 💬 1 comment Opened Jun 7, 2026 by justtestingthingsx Closed Jul 13, 2026

Summary

A server-gated rendering experiment (statsig gate tengu_marlin_porch, the DECSTBM scroll-region path) corrupts the inline TUI: the input caret renders in the wrong spot from session start, and as the conversation grows past one screen, whole rows/frames duplicate and stack downward. The duplication is present in the terminal's actual cell grid (verified by capturing the grid), so it's Claude Code's emitted output — not a display-only artifact.

The only thing that resolves it is disabling statsig gate-fetching entirely (CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1), which makes all gates fall back to defaults. There is no way to disable just this one experiment.

Environment

  • Claude Code 2.1.165 and 2.1.168 (native binary) — both reproduce
  • OS: Linux (Arch)
  • Terminal: WezTerm 20260331-040028. Also reproduces over plain SSH from Windows Terminal — so it is not terminal-specific.
  • Pane width: 255 columns (very wide)
  • A multi-line custom statusLine of type: "command" is configured (also reproduces with a single-line statusline)

Symptoms

  1. Input caret parked in the chat/output region instead of the input box, from the first frame.
  2. As the session scrolls past one screen, rows duplicate (e.g. the statusline and -- INSERT -- line appear 2–3× in the grid) and frames stack downward.
  3. Ctrl+L (full repaint) clears it momentarily; it re-accrues on subsequent incremental repaints.

Root cause (narrowed by elimination)

The relevant gate is tengu_marlin_porch (DECSTBM scroll-region; j$("tengu_marlin_porch", false)), enabled for this account's cohort. The only fix is CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 (stops gate-fetching → defaults).

Ruled out, each tested independently:

  • CC version (2.1.165 and 2.1.168 both break)
  • Terminal (WezTerm and Windows-Terminal-over-SSH both break)
  • Shell init / prompt
  • Statusline height (single-line still breaks)
  • OTEL telemetry (telemetry off + gate-fetching on still breaks)
  • Per-gate env overrides: CLAUDE_CODE_NATIVE_CURSOR, CLAUDE_CODE_DECSTBM, CLAUDE_CODE_DISABLE_VIRTUAL_SCROLL — none disable it. Notably CLAUDE_CODE_DECSTBM is read via a truthy parse that can only force the feature on; there is no force-off value (if (eH(env.CLAUDE_CODE_DECSTBM)) return enabled=true; return gate("tengu_marlin_porch", false)).
  • TERM_PROGRAM blanking (terminal is in the advanced-terminal allowlist, but removing detection still breaks)

Requests

  1. Fix the DECSTBM scroll-region path for wide panes (≥255 cols) and/or multi-line command statuslines — incremental repaint lands on the wrong rows, leaving duplicates that accumulate as the session scrolls.
  2. Provide a per-experiment opt-out — e.g. a force-OFF value for CLAUDE_CODE_DECSTBM, or a settings key. Right now the only off-switch is CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, which is an umbrella that also disables telemetry and every other gate-dependent feature, so there's no way to disable just the broken rendering experiment.

Repro

  1. Wide terminal (~255 cols), a type: "command" statusline.
  2. Use an interactive session past one screen of scrollback.
  3. Caret is misplaced immediately; rows duplicate as it scrolls. CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 makes it disappear.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗