Where does the bug appear (feature/product)?
Cursor CLI
Describe the Bug
Sorry this was written by AI - but I reviewed it - right now cursor-agent for me is unusable over ssh - it jitters so much that I can’t see the input box (like rapid scrolling up and down)
Impact
Basically unusable over SSH. Watching or interacting with a cursor-agent
session over any SSH-based connection (plain SSH, SSH with compression, tmux,
including iTerm2’s tmux control mode) is disruptive enough to make the session
hard to read and work with in real time — not a minor cosmetic glitch. This
affects any workflow where the agent runs on a remote dev box and is monitored
or driven from a separate machine over SSH, which is a common setup for
GPU/cluster development work.
Summary
cursor-agent’s interactive TUI redraws its entire status panel (spinner + status
line + footer, ~11 lines) from scratch on every animation tick — a full
clear-line/cursor-up sequence repeated once per visible line, then a full
rewrite — rather than updating only the single character that actually changed
(the spinner glyph). Over any connection with real latency/jitter, this makes the
session visually unusable: the terminal renders a burst partway, appears to
freeze, then “snaps” to a later frame once the next burst lands, discarding the
smooth in-between motion entirely.
This reproduces over plain SSH, SSH with compression (-C), and even tmux’s
“control mode” (-CC, where iTerm2 renders the pane via tmux’s structured
control protocol rather than replaying raw ANSI). It is greatly reduced — to an
occasional minor stutter rather than a session-breaking freeze/snap — over
mosh, but is not fully eliminated even there. The fact that it improves
substantially under mosh’s diff-based state sync, without disappearing
entirely, is itself useful evidence for the root cause below.
Environment
cursor-agentCLI version:2026.07.23-e383d2b- OS (remote host running the agent): Ubuntu 22.04.5 LTS, kernel
6.8.0-1052-nvidia - Terminal multiplexer:
tmux 3.2a - Local terminal: iTerm2 (macOS)
- Transport: SSH over a multi-hop
ProxyJump(bastion) connection — real,
variable latency (~2.4s just to establish a fresh connection); no direct
routable path to the remote host exists (confirmed viaping/ncto the
host’s own internal IP — it is fully isolated behind the bastion, VPN
included), which also rules outmoshas a workaround for this specific
host (mosh needs direct UDP reachability to the target, not just the bastion).
Steps to reproduce
- SSH into a remote host (ideally one reachable only via a multi-hop
ProxyJump/bastion, to reproduce realistic latency/jitter) and start a
tmuxsession there. - Inside tmux, run
cursor-agent(agent) and give it any moderately
long-running task (something that leaves it in a “Waiting”/thinking spinner
state for tens of seconds to minutes, or actively streaming tool-call output). - Attach to that tmux session from a local machine over the same
multi-hop SSH path, either:- plain
ssh -t <host> tmux attach -t <session>, or ssh -t <host> tmux -CC attach -t <session>(iTerm2 tmux integration /
control mode)
- plain
- Watch the panel while the spinner animates and/or the agent streams tool
output.
Note: build up a long-running session to reproduce reliably. The behavior
is most consistently visible after the agent session has been running for a
while (many tool calls, an extended back-and-forth, growing token/context
count) rather than immediately after a fresh start — a short-lived session may
not show it clearly. This is consistent with the root cause below: the redraw
burst includes/depends on status-line content (token count, file-edit count,
etc.) that grows over the session, so the redraw’s cost and/or frequency may
scale with session length/state rather than being constant from the first
tick. Recommend driving a real, extended session (tens of minutes, multiple
tool calls) rather than a quick smoke test when attempting to reproduce.
Expected behavior
The spinner glyph and any changed status text update smoothly, comparable to
watching the same session locally (no network hop) or over mosh.
Actual behavior
The panel visibly “snaps” — it appears to freeze for a beat, then jumps to a
later state all at once, repeatedly, for as long as the spinner/streaming is
active. Over plain SSH / SSH+compression / tmux control mode this makes the
session very difficult to read or interact with live. Over mosh the same
pattern still occurs but far less often and less severely — an occasional
stutter rather than a continuous freeze-and-catch-up cycle. (The underlying
agent process itself is unaffected in all cases — this is purely a
rendering/perception problem for whoever is watching.)
Root cause (confirmed via raw byte-level capture)
Captured the pane’s actual output stream with tmux pipe-pane -o (raw bytes as
written by the cursor-agent process into the pty, before tmux’s own
rendering) during a normal idle/“Waiting” spinner period. Analysis of ~240 KB /
~15–20 min of typical output:
full screen clear (ESC[2J): 0
alt-screen buffer switch: 0
synchronized-output mode (?2026): 0
clear-line (ESC[2K): 3,024
cursor-up (ESC[nA): 2,772
carriage return: 2,772
The literal repeating pattern found in the stream:
ESC[2K ESC[1A ESC[2K ESC[1A ESC[2K ESC[1A ESC[2K ESC[1A ESC[2K ESC[1A
ESC[2K ESC[1A ESC[2K ESC[1A ESC[2K ESC[1A ESC[2K ESC[1A ESC[2K ESC[1A
ESC[2K ESC[G <spinner glyph> Waiting <token count>
Tip: Use /mcp to connect Cursor to your tools and data sources.
...
i.e. 11 consecutive clear-line + cursor-up pairs, followed by a full
rewrite of the entire panel — repeated roughly every ~350–500ms even while the
agent is simply idle-waiting (no new content to show beyond the spinner glyph
advancing one frame). Notably absent: no use of terminal synchronized-output
mode (CSI ? 2026 h/l, supported by tmux ≥3.3 and most modern terminals
including iTerm2), which exists specifically to let an application batch a
multi-line redraw into one atomic frame so a partial receive never renders a
torn frame.
Why this is fine locally but breaks over any real network hop: on a
zero-latency local pty, 11 clear+redraw operations arrive and render
effectively instantaneously as one visual unit, so the inefficiency is
invisible. Over SSH (even compressed) or tmux control mode, the same burst has
to travel as a discrete chunk of network I/O; if that chunk is split, delayed,
or coalesced with the next tick’s burst (normal behavior under any real-world
jitter, and unavoidable over a multi-hop bastion path), the terminal ends up
rendering a partially-applied redraw, then “catching up” to a later
complete frame once more data arrives — which is exactly the visible
freeze-then-snap behavior being reported. A TUI that only wrote the single
changed glyph per tick (or used synchronized-output framing so an in-flight
redraw is never partially displayed) would be inherently insensitive to this
class of network jitter.
Why mosh greatly reduces (but doesn’t fully eliminate) the bug — supporting
evidence for the root cause, not just a workaround: mosh doesn’t relay the
literal byte/escape-sequence stream at all. It maintains a full terminal-state
model on both ends and syncs only the diff between the client’s
last-acknowledged state and the server’s current state, discarding
now-superseded intermediate frames rather than replaying them. Since
cursor-agent’s repeated full-panel redraws are, from a pure end-state
perspective, almost entirely redundant with each other (11 lines redrawn to
convey one changed glyph), mosh’s diffing collapses most of that burst history
down to the one glyph that actually changed — which is why the freeze-then-snap
behavior drops to an occasional minor stutter under mosh instead of a
session-breaking pattern. It isn’t fully eliminated because mosh still has to
compute and transmit a diff on (effectively) every one of those redundant
ticks, and under real jitter a diff can itself still arrive late/coalesced
occasionally — mosh reduces the amount of redundant rendering work that has
to survive the network, it doesn’t make the underlying redraw pattern free.
This is precisely why switching transport (mosh) mostly fixes the symptom while
switching rendering mode on the same transport (tmux control mode) does not:
the redundant byte-level work is still happening at the source in both cases;
mosh just discards most (not all) of the redundancy in transit.
Workarounds tried, and why each fell short
| Workaround | Result | Why it didn’t (fully) work |
|---|---|---|
ssh -C (compression) |
Partial improvement | The repeated ESC[2K/ESC[1A bursts are highly repetitive text and compress well, so some of the effective bandwidth cost drops — but compression doesn’t change delivery timing or ordering. A burst can still arrive split/delayed under jitter, so the freeze-then-snap pattern is reduced in severity but still clearly present. |
tmux -CC (iTerm2 control mode) |
No improvement | Control mode changes how tmux’s own rendering gets to iTerm2 (structured protocol instead of raw ANSI), but it doesn’t change what cursor-agent itself writes into the pty. The redundant 11-line redraw-per-tick still has to be relayed and re-rendered every tick; control mode doesn’t eliminate the redundant work at the source, so the symptom was unchanged. |
Lighter SSH cipher ([email protected]) |
Not conclusively tested / no meaningful change observed | Reduces per-packet CPU cost, not round-trip latency or jitter, which is the actual bottleneck here. |
mosh |
Best result, but not a full fix | See root-cause section above — mosh’s diff-based state sync discards most (not all) of the redundant redraw history, so the bug drops from “session-breaking” to “occasional minor stutter” rather than disappearing. Also not usable at all on hosts with no direct routable IP (see below) — mosh needs direct UDP reachability to the target and can’t traverse a jump-host-only network path, so it isn’t a universally available workaround even where it would otherwise help most. |
VPN direct routing (bypass the SSH bastion/ProxyJump entirely) |
Blocked, host-specific | On hosts reachable only through a bastion (no independently resolvable hostname, no routable IP even over VPN — confirmed via ping/nc timing out completely to the host’s own internal IP), there is no network-level workaround at all; the bastion is the only path. This is an infra/topology constraint unrelated to cursor-agent itself, but it does mean the most effective workaround (mosh) isn’t available on every affected host. |
Poll instead of watch live (tmux capture-pane snapshots) / send input via tmux send-keys without attaching |
Works, but defeats the purpose | Sidesteps the rendering path entirely (no live terminal stream involved), so it never shows the bug — but it means giving up the ability to watch the agent work in real time, which is the actual thing being asked for. Useful as a status-check/input mechanism, not a substitute for live observation. |
Cursor’s self-hosted “worker” mode + cursor.com/agents web dashboard (no SSH/terminal at all) |
Not tested — unavailable | Disabled on our Team plan for security/compliance reasons (org policy, not a technical limitation on our end), so couldn’t evaluate whether it avoids the issue structurally (it should, since there’s no terminal rendering involved at all — the whole session is driven through Cursor’s own web UI over a direct outbound HTTPS connection). Worth Cursor confirming whether this mode is immune to the bug, since if so it may be the only complete fix available today for hosts where mosh isn’t reachable. |
Suggested fix
Either (preferred, addresses root cause):
- Redraw only the lines/cells whose content actually changed each tick,
instead of clearing and rewriting the entire panel from scratch. For a
spinner glyph, this is a single-character in-place update, not an 11-line
clear-and-rewrite.
or (mitigates the symptom without changing the redraw strategy):
- Wrap each panel redraw in terminal synchronized-output framing
(CSI ?2026h…CSI ?2026l). Modern terminals/multiplexers (tmux ≥3.3,
iTerm2, kitty, WezTerm, etc.) buffer everything between those markers and
apply it as a single atomic frame, so a redraw that arrives split across
multiple network reads never renders in a half-applied state. This would
not reduce the redundant work, but would eliminate the visible tearing/snap
even under real jitter.
Additional notes
- No CLI flag exists today to reduce the TUI’s redraw rate or fall back to
simpler/plain output for an ongoing interactive session —--printmode
skips the fancy rendering entirely but only works for one-shot, non-interactive
invocations, not something that can be toggled on a running session. - This is independent of and additive to any tmux/SSH configuration — it
reproduces identically (full severity) over plain SSH, SSH with compression,
and tmux control mode. Switching to a genuinely diff-based transport (mosh)
substantially reduces — but does not fully eliminate — the symptom, because
mosh discards most of the redundant redraw history rather than because the
underlying inefficiency is fixed.
Steps to Reproduce
See above
Operating System
Linux
Version Information
ado@gpu-dp-qcqgp-p87dg:~$ agent about
About Cursor CLI
CLI Version 2026.07.23-e383d2b
Model Cursor Grok 4.5 High Fast
Subscription Tier Team
OS linux (x64)
Terminal iterm2
Shell bash
Does this stop you from using Cursor
Yes - Cursor is unusable