fix: strip ANSI escape codes from session persistence hooks (#642) (#684)

Windows terminals emit control sequences (cursor movement, screen
clearing) that leaked into session.tmp files and were injected
verbatim into Claude's context on the next session start.

Add a comprehensive stripAnsi() to utils.js that handles CSI, OSC,
charset selection, and bare ESC sequences. Apply it in session-end.js
(when extracting user messages from the transcript) and in
session-start.js (safety net before injecting session content).
This commit is contained in:
Affaan Mustafa
2026-03-20 01:38:11 -07:00
committed by GitHub
parent 9a478ad676
commit 28de7cc420
4 changed files with 87 additions and 3 deletions

View File

@@ -464,6 +464,24 @@ function countInFile(filePath, pattern) {
return matches ? matches.length : 0;
}
/**
* Strip all ANSI escape sequences from a string.
*
* Handles:
* - CSI sequences: \x1b[ … <letter> (colors, cursor movement, erase, etc.)
* - OSC sequences: \x1b] … BEL/ST (window titles, hyperlinks)
* - Charset selection: \x1b(B
* - Bare ESC + single letter: \x1b <letter> (e.g. \x1bM for reverse index)
*
* @param {string} str - Input string possibly containing ANSI codes
* @returns {string} Cleaned string with all escape sequences removed
*/
function stripAnsi(str) {
if (typeof str !== 'string') return '';
// eslint-disable-next-line no-control-regex
return str.replace(/\x1b(?:\[[0-9;?]*[A-Za-z]|\][^\x07\x1b]*(?:\x07|\x1b\\)|\([A-Z]|[A-Z])/g, '');
}
/**
* Search for pattern in file and return matching lines with line numbers
*/
@@ -530,6 +548,9 @@ module.exports = {
countInFile,
grepFile,
// String sanitisation
stripAnsi,
// Hook I/O
readStdinJson,
log,