Skip to content

Preserve terminal history across ANSI control sequences#1367

Merged
juliusmarminge merged 2 commits intomainfrom
t3code/terminal-jank-reopen
Mar 24, 2026
Merged

Preserve terminal history across ANSI control sequences#1367
juliusmarminge merged 2 commits intomainfrom
t3code/terminal-jank-reopen

Conversation

@juliusmarminge
Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge commented Mar 24, 2026

Summary

  • Sanitize PTY output before persisting terminal history so ANSI control sequences do not pollute reopened sessions.
  • Track partial control sequences across chunks to avoid dropping or corrupting history when escape sequences are split across emits.
  • Reset pending control-sequence state on restart, close, and process exit.
  • Add regression tests covering whole and chunk-split ANSI sequences.

Testing

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test apps/server/src/terminal/Layers/Manager.test.ts

Note

Medium Risk
Adds a custom parser to strip terminal query/reply control sequences while persisting PTY output, which could inadvertently drop or mangle legitimate escape sequences and affect users’ saved terminal history.

Overview
Terminal history persistence now sanitizes PTY output via sanitizeTerminalHistoryChunk, stripping replay-unsafe CSI/OSC (and related string) query/reply sequences while preserving normal output and style/clear sequences.

To avoid corrupting history when escape sequences are split across data events, session state now tracks pendingHistoryControlSequence and resets it on clear, restart, process stop, and exit; pure control-sequence chunks no longer trigger a persist write. Adds regression tests covering whole and chunk-split ANSI sequences and ensuring no byte leakage from ESC sequences.

Written by Cursor Bugbot for commit 56063fa. This will update automatically on new commits. Configure here.

Note

Preserve terminal history across ANSI control sequences by stripping replay-unsafe sequences

  • Adds sanitizeTerminalHistoryChunk in Manager.ts to parse incoming terminal data and strip CSI/OSC query and reply sequences (e.g. cursor position reports, color queries) that are unsafe to replay on session restore.
  • Visible text is appended to history as before; incomplete control sequences spanning chunk boundaries are buffered in pendingHistoryControlSequence and prepended to the next chunk.
  • Persistence is skipped entirely for chunks that produce no visible text.
  • pendingHistoryControlSequence is reset on process exit, stop, clear, and session restart/reopen.
  • Behavioral Change: history now excludes certain CSI/OSC sequences; sessions that previously stored these sequences will no longer do so going forward.

Macroscope summarized 56063fa.

- sanitize PTY output before persisting transcript history
- handle chunk-split control sequences and reset pending state on restart/exit
- add regression tests for reopened sessions
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 24, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0bad1630-0606-420d-be0d-5acffa210931

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch t3code/terminal-jank-reopen

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Mar 24, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Three-byte escape sequences leak final byte into history
    • Added detection for ECMA-48 intermediate bytes (0x20-0x2F) after ESC, consuming all intermediate bytes plus the final byte so sequences like ESC ( B are fully skipped instead of leaking the final byte into visibleText.

Create PR

Or push these changes by commenting:

@cursor push 87caa1b78f
Preview (87caa1b78f)
diff --git a/apps/server/src/terminal/Layers/Manager.ts b/apps/server/src/terminal/Layers/Manager.ts
--- a/apps/server/src/terminal/Layers/Manager.ts
+++ b/apps/server/src/terminal/Layers/Manager.ts
@@ -321,6 +321,22 @@
         continue;
       }
 
+      if (nextCodePoint >= 0x20 && nextCodePoint <= 0x2f) {
+        let cursor = index + 2;
+        while (
+          cursor < input.length &&
+          input.charCodeAt(cursor) >= 0x20 &&
+          input.charCodeAt(cursor) <= 0x2f
+        ) {
+          cursor++;
+        }
+        if (cursor >= input.length) {
+          return { visibleText, pendingControlSequence: input.slice(index) };
+        }
+        index = cursor + 1;
+        continue;
+      }
+
       index += 2;
       continue;
     }

- keep visible ANSI styling and screen clears in persisted terminal history
- strip replay-unsafe query/reply sequences and avoid chunk-boundary byte leakage
- add regression coverage for split escape sequences
@juliusmarminge juliusmarminge merged commit 529315b into main Mar 24, 2026
11 checks passed
@juliusmarminge juliusmarminge deleted the t3code/terminal-jank-reopen branch March 24, 2026 17:34
waaeel added a commit to dinweldik/fatma that referenced this pull request Mar 25, 2026
Merged upstream improvements while preserving fork identity:
- Claude Code adapter support (pingdotgg#179)
- Context window usage meter (pingdotgg#1351)
- Sidebar project/thread sorting by recency (pingdotgg#1372)
- Git action progress streaming (pingdotgg#1214, pingdotgg#1388)
- Terminal history ANSI preservation (pingdotgg#1367)
- Word wrapping setting (pingdotgg#1326)
- Resizable chat sidebar (pingdotgg#1347)
- Configurable timestamp format (pingdotgg#855)
- Selective file staging in commit dialog (pingdotgg#872)
- Fuzzy workspace search (pingdotgg#256)
- Scroll-to-bottom pill (pingdotgg#619)
- Numerous bug fixes and improvements

Preserved fork customizations:
- Fatma branding (all @t3tools -> @fatma)
- Mobile UI (swipe gestures, bottom nav, mobile shells)
- VSCode-like source control (staged/unstaged, file diffs)
- PWA support
- Custom CI/CD workflows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
emrezeytin pushed a commit to emrezeytin/t3code that referenced this pull request Mar 25, 2026
apexsloth pushed a commit to apexslothforks/t3code that referenced this pull request Mar 26, 2026
Chrono-byte pushed a commit to Chrono-byte/t3code that referenced this pull request Mar 31, 2026
hapwi pushed a commit to hapwi/hapcode that referenced this pull request Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant