Add a way to force-disable synchronized output (counterpart to CLAUDE_CODE_FORCE_SYNC_OUTPUT)

Status Open
Reported on v2.1.200
Maintainer reply None cached
Activity 0 comments · opened Jul 23, 2026

What happened?

CLAUDE_CODE_FORCE_SYNC_OUTPUT=1 exists to force synchronized output on for terminals that auto-detection misses. There is no counterpart to force it off.

That asymmetry currently has no workaround for users hitting a terminal whose synchronized-output implementation misbehaves with Claude Code's rendering pattern. Concretely, on Ghostty the fullscreen renderer accumulates progressive corruption — stale fragments from earlier frames (stray , box-drawing remnants) overlapping live UI, worsening over a session, cleared temporarily by Ctrl+L. Ghostty has three open/unresolved reports of this (ghostty-org/ghostty#12062, #11001, #12685), including a ~60-line reproduction containing no Claude Code code at all that garbles Ghostty with synchronized output + incremental cursor-positioned writes and renders correctly both with sync disabled and in Kitty.

So the defect is arguably Ghostty's — but Claude Code is the only party that can currently give affected users an escape, and it doesn't expose one.

Measurements

Captured through a pty (TERM=xterm-ghostty, TERM_PROGRAM=ghostty, TMUX unset, 40-row terminal, "tui": "fullscreen"), full startup + 18s idle:

| Observation | Value |
|---|---|
| Balanced ESC[?2026h / ESC[?2026l pairs | 16–18 per startup render |
| Absolute ESC[row;colH inside sync blocks | 34 |
| Same, outside sync blocks | 0 |
| Target rows of those CUPs | 35, 36, 40 (of 40) — status/input area |
| ESC[<n>A cursor-up sequences | 0 |
| DECSTBM sets | 1, and it is ESC[r (reset) |

Two notes that may be useful upstream:

  1. Synchronized output is active on Ghostty outside tmux. The 2.1.200 changelog entry frames sync output as a tmux fix; per-terminal auto-detection has it on for Ghostty independently. Worth confirming that's intended.
  2. This does not require DECSTBM. The Ghostty report describes the bug as involving a reserved scroll region, but in fullscreen mode Claude Code resets the scroll region and still triggers it. The sufficient ingredients are sync output wrapping incremental cursor-positioned writes to the bottom rows.

Corruption rate scales with status-area update frequency — it is markedly worse with background agents running and with a frequently-refreshing custom statusline.

Why the existing options don't cover it

  • CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT=1 does fix the corruption, but full-screen repaint per frame also clamps the frame interval to a 480ms floor (vs the 16ms default). The result is constant visible flicker at idle, which several users find worse than the artifacts it cures.
  • Changing TERM / TERM_PROGRAM so the terminal no longer matches the sync allowlist does work, but the same environment variables gate other behaviour — unsetting TERM_PROGRAM also stops the kitty keyboard protocol / modifyOtherKeys push (CSI >1u, CSI >4;2m), breaking Shift+Enter and modifier chords, and it degrades hyperlink and notification support. Lying about the terminal to disable one feature is not a reasonable ask of users.
  • Downgrading isn't viable; this is present on the current release.

Request

An env var (and ideally a settings.json key) to force synchronized output off, mirroring the existing force-on:

CLAUDE_CODE_FORCE_SYNC_OUTPUT=0     # or CLAUDE_CODE_DISABLE_SYNC_OUTPUT=1

Today CLAUDE_CODE_FORCE_SYNC_OUTPUT is truthy-checked, so =0 falls through to auto-detection rather than disabling. A three-line change would give affected users a clean escape that costs nothing for everyone else, and would also let people test whether sync output is implicated in other rendering reports.

Related: #69619 (documents CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT, which is otherwise undocumented).

Environment

  • Claude Code 2.1.218
  • Ghostty 1.3.1 (stable), macOS, Apple Silicon
  • "tui": "fullscreen", TERM=xterm-ghostty
  • Not running inside tmux

View original on GitHub ↗