Skip to main content

jupyterlab_terminal_cpr_escape_fix

GitHub Actions npm version PyPI version Total PyPI downloads JupyterLab 4 Brought To You By KOLOMOLO Donate PayPal

Fix the JupyterLab terminado issue where returning to an idle terminal causes cursor position report (CPR) escape sequences to appear as literal text. This is particularly noticeable with fish shell, where sequences like [2;2R[3;1R or [?1;2c[>0;276;0c appear at the prompt after reconnecting.

How it works

When a JupyterLab terminal sits idle, the shell (especially fish) periodically queries terminal capabilities. These queries accumulate in terminado's buffer. On reconnect, terminado replays that buffer, xterm.js answers the old queries again, and the shell inserts the answers as literal text.

This extension patches TermSocket.on_pty_read() server-side to filter terminal query responses before they reach the browser. It handles both ESC-prefixed sequences and bare remnants where fish shell has stripped the ESC byte.

Filtered sequences (terminal query responses):

  • CPR - Cursor Position Report (ESC[row;colR)
  • DA/DA2 - Device Attributes (ESC[?...c, ESC[>...c)
  • DECRPM - DEC Report Mode (ESC[?mode;value$y)
  • OSC 4/10/11/12 - Color query responses

Preserved sequences (functional terminal output):

  • All SGR color codes, cursor movement, erase, scroll
  • OSC 0 (window/tab title), OSC 7 (cwd), OSC 8 (hyperlinks)
  • OSC 52 (clipboard - used by companion clipboard extension)
  • OSC 133 (shell integration prompt marks)
  • Bracketed paste mode, alternate screen, all DEC private modes

Repaint on attach (window refresh recovery):

  • After a client attaches and the buffer replay drains, the PTY is nudged one row taller and back
  • The kernel delivers SIGWINCH, so the foreground app (Claude Code, vim, htop) repaints its full screen
  • Without it, a refreshed browser shows a torn screen: the replay holds only incremental diff frames, so static regions (status line, input box) are never delivered and never self-heal
  • Toggle: DEFAULTS['repaint_on_attach'] in __init__.py (default on), debounced 5s per terminal

Replay query stripping (no replies on reconnect):

On attach, terminado replays the terminal's buffered output and xterm.js answers every query in it as if it were live, so the shell receives the answers as typed text. The extension removes those queries from the replay only.

  • Stripped: OSC 4/10/11/12 color queries, DA/DA2 queries, ESC[5n, ESC[6n, ESC[?6n, DECRQM, DECRQSS
  • Queries at the very end of the replay are kept, because the program that sent them may still wait for the answer
  • Live output after the attach passes every query unchanged
  • Toggle: DEFAULTS['strip_replay_queries'] in __init__.py (default on); suppress_buffer_replay takes precedence

Requirements

  • JupyterLab >= 4.0.0

Installation

pip install jupyterlab_terminal_cpr_escape_fix

Uninstall

pip uninstall jupyterlab_terminal_cpr_escape_fix

Release files for jupyterlab-terminal-cpr-escape-fix 1.0.15

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jupyterlab-terminal-cpr-escape-fix 1.0.15
File Size Uploaded
jupyterlab_terminal_cpr_escape_fix-1.0.15.tar.gz 470.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jupyterlab-terminal-cpr-escape-fix 1.0.15
File Interpreter ABI Platform
jupyterlab_terminal_cpr_escape_fix-1.0.15-py3-none-any.whl Python 3 none any Details

Total release size: 507.1 kB

Release files / jupyterlab_terminal_cpr_escape_fix-1.0.15.tar.gz

Download URL jupyterlab_terminal_cpr_escape_fix-1.0.15.tar.gz
Size 470.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a92cff62a56e3ab6f6cdbcdee3e5ed82c862c519943cbf8e9fe2d18d6e6f38f4
BLAKE2b-256 checksum
How to use checksums
7602146b5536b969be182b679d637abfea368704b49a47df86fcfa8bf56ca5b8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release files / jupyterlab_terminal_cpr_escape_fix-1.0.15-py3-none-any.whl

Download URL jupyterlab_terminal_cpr_escape_fix-1.0.15-py3-none-any.whl
Size 36.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4e515459785a25736013f3d4b5b6704103a0d0f96f338d606843167cbc42e354
BLAKE2b-256 checksum
How to use checksums
5f81754af6b10d8c36fe67cb06dedd7baa42104183e18bcb9a1bd0e158c622ce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.15

Release history Release notifications | RSS feed

This release

1.0.15 This release

2 release files

1.0.14

2 release files

1.0.13

2 release files

1.0.11

2 release files

1.0.10

2 release files

1.0.9

2 release files

1.0.8

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

0.9.23

2 release files

0.9.22

2 release files

0.9.21

2 release files

0.9.19

2 release files

0.9.18

2 release files

0.9.14

2 release files

0.9.8

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page