Session corruption from terminal escape sequences in tool output
Summary
When a Bash tool command emits raw terminal escape sequences (e.g., mouse tracking, alternate screen buffer), these get stored in the session JSONL file. When the session is later resumed with --resume, displaying the conversation history causes the terminal to interpret these escape sequences, corrupting the terminal state (enabling mouse tracking, messing up display, etc.).
Steps to Reproduce
- Run a command that emits terminal escape sequences, such as:
jj split(interactive by default)- Any command that opens a TUI and fails mid-execution
- Commands with
--interactiveflags
- The command fails with output containing raw ESC sequences like:
````
\x1b[?1049h\x1b[?1000h\x1b[?1002h\x1b[?1003h\x1b[?1015h\x1b[?1006h
- These sequences get stored in the session's
toolUseResult.stdoutfield
- Later, run
claude --resume <session-id>
- When the session history is displayed, the terminal interprets the escape sequences, enabling mouse tracking and corrupting the terminal
Expected Behavior
Terminal escape sequences in tool output should be:
- Stripped/sanitized before storing in the session log, OR
- Escaped when displaying session history so they render as text rather than being interpreted
Actual Behavior
Raw escape sequences are stored and later interpreted by the terminal when displaying session history, corrupting terminal state.
Suggested Fix
Options:
- Sanitize on capture: Strip ANSI/terminal escape sequences from Bash tool stdout/stderr before storing in session
- Sanitize on display: Escape or strip control sequences when rendering session history
- Both: Defense in depth
Relevant escape sequence patterns to filter:
\x1b[?1000h- Enable mouse tracking\x1b[?1049h- Alternate screen buffer\x1b[?1002h,\x1b[?1003h,\x1b[?1006h,\x1b[?1015h- Various mouse modes- Generally:
\x1b[followed by parameters and a letter
Environment
- Claude Code CLI
- macOS (likely affects all platforms)
- Triggered by
jj splitcommand (jujutsu VCS) but could happen with any TUI/interactive command
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗