fix: support React Compiler and CC 2.1.85–2.1.88 patching#646
fix: support React Compiler and CC 2.1.85–2.1.88 patching#646sla-te wants to merge 4 commits intoPiebald-AI:mainfrom
Conversation
Claude Code 2.1.85+ uses the React Compiler, which moves props
destructuring from function parameters into the function body with
useMemoCache. This broke several regex patterns that assumed inline
destructuring.
Fixes:
- helpers.ts: Widen findTextComponent regex gap from .{0,20} to .{0,80}
(React Compiler gap is 21 chars, just 1 over the old limit)
- helpers.ts: Widen findBoxComponent Method 1 gap from .{0,200} to
.{0,500} (cache slot assignments expand the gap to ~336 chars)
- helpers.ts: Update findBoxComponent Method 2 to handle body-level
destructuring (.{0,200}children: instead of \(\{children:)
- agentsMd.ts: Support async split-function pattern where the single
sync CLAUDE.md reader was split into content processor (ol4), async
reader (Fb8), and error handler (al4). The patch now targets the
async reader when fs operations aren't found in the content processor.
- patchesAppliedIndication.ts: Handle memoized "Claude Code" createElement
(React Compiler caches it in a variable). PATCH 5 (indicator view
patches list) gracefully degrades when paren-counting fails on
flattened component trees.
- userMessageDisplay.ts: Widen regex gaps (.{0,150}->.{0,250},
.{0,100}->.{0,200}) and use flexible prop matching ([^}]* instead
of hardcoded thinkingMetadata).
- index.ts: Version-gate mcp-non-blocking patch to CC < 2.1.85 since
MCP_CONNECTION_NONBLOCKING was removed (non-blocking is now default).
Tested on CC 2.1.87 native installation (Linux). All default patches
apply successfully.
Closes Piebald-AI#643, closes Piebald-AI#645, closes Piebald-AI#628, closes Piebald-AI#624
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughDetects and patches two AGENTS.md reader shapes (sync vs async) with safe identifier escaping and alternate-filename retry; broadens multiple regex heuristics for minified React/Ink; adds version gating for one patch; improves version-display detection and error handling; enhances Bun/.bun repacking with wrapper handling and size-budgeted rebuilds. Changes
Sequence Diagram(s)(Skipped — changes are multiple and heterogeneous and do not introduce a single new multi-actor sequential flow that benefits from a diagram.) Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (4)
src/patches/userMessageDisplay.ts (1)
147-148: Pattern contains multiple\bword boundaries that should be replaced.The pattern uses
\bwhich violates coding guidelines due to V8 performance issues and improper handling of$in identifiers. Consider replacing with literal character alternatives.♻️ Suggested fix
const pattern = - /(No content found in user prompt message.{0,250}?\b)([$\w]+(?:\.default)?\.createElement.{0,30}\b[$\w]+(?:\.default)?\.createElement.{0,40}">.+?)?(([$\w]+(?:\.default)?\.createElement).{0,200})(\([$\w]+,(?:\{[^{}]+wrap:"wrap"\},([$\w]+)(?:\.trim\(\))?\)\)|\{text:([$\w]+)[^}]*\}\)\)?))/; + /(No content found in user prompt message.{0,250}?[,;{}])([$\w]+(?:\.default)?\.createElement.{0,30}[,;{}][$\w]+(?:\.default)?\.createElement.{0,40}">.+?)?(([$\w]+(?:\.default)?\.createElement).{0,200})(\([$\w]+,(?:\{[^{}]+wrap:"wrap"\},([$\w]+)(?:\.trim\(\))?\)\)|\{text:([$\w]+)[^}]*\}\)\)?))/;Note: The first
\bafter the "No content..." literal may need adjustment based on what actually precedes the identifier in minified code. You may want to verify the exact characters that appear at those positions.As per coding guidelines: "Avoid
\\bin regex patterns due to V8 performance issues; use literal character alternatives".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/userMessageDisplay.ts` around lines 147 - 148, The regex assigned to the variable pattern in userMessageDisplay.ts uses \b word boundaries which violate our guidelines; update the pattern to remove all \b tokens and instead express boundaries with explicit alternatives that account for JS identifier characters (letters, digits, underscore, dollar) and string delimiters—e.g., replace each \b with an explicit check for start/end or a non-identifier character (or a non-identifier char class) so `$` is treated correctly; keep the rest of the grouping and quantifiers intact and verify the first boundary after "No content found in user prompt message" matches the actual minified surrounding character(s).src/patches/agentsMd.ts (1)
27-34: Consider adding boundary to funcPattern.The pattern
(function ([$\w]+)could match mid-identifier. However, since this searches forSkipping non-text filewhich is a unique string, the pattern is likely specific enough in practice.♻️ Optional improvement
const funcPattern = - /(function ([$\w]+)\(([$\w]+),([^)]+?))\)(?:.|\n){0,500}Skipping non-text file in `@include/`; + /[;{}](function ([$\w]+)\(([$\w]+),([^)]+?))\)(?:.|\n){0,500}Skipping non-text file in `@include/`;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/agentsMd.ts` around lines 27 - 34, The regex in funcPattern can match inside identifiers because `(function ([$\w]+)` lacks a word boundary; update funcPattern to require a word boundary before "function" and after the function name (e.g., add \b around "function" and the captured name) so it only matches a real function declaration when searching for the CLAUDE.md reading function; adjust the pattern declared in funcPattern and keep the subsequent funcMatch logic unchanged.src/patches/helpers.ts (1)
298-299: Avoid\bin regex patterns per coding guidelines.The pattern uses
\bwhich has V8 performance issues and doesn't properly handle$in identifiers. Use a literal boundary character instead.♻️ Suggested fix
const textComponentPattern = - /\bfunction ([$\w]+).{0,80}color:[$\w]+,backgroundColor:[$\w]+,dimColor:[$\w]+(?:=![01])?,bold:[$\w]+(?:=![01])?/; + /[;,{}]function ([$\w]+).{0,80}color:[$\w]+,backgroundColor:[$\w]+,dimColor:[$\w]+(?:=![01])?,bold:[$\w]+(?:=![01])?/;As per coding guidelines: "Avoid
\\bin regex patterns due to V8 performance issues; use literal character alternatives" and "Use,;}{literal characters at regex start instead of\\bfor performance in patch patterns".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/helpers.ts` around lines 298 - 299, The regex in textComponentPattern uses \b which is disallowed; update the pattern to remove \b and instead anchor with a literal boundary alternative (e.g. a non-capturing group matching start-of-string or one of the literal characters like ',', ';', '{', '}') before the function name so identifiers with '$' still match; keep the rest of the pattern ([$\w]+ and the color/background/bold segments) unchanged and ensure the new prefix is non-capturing to preserve existing groups in textComponentPattern.src/patches/patchesAppliedIndication.ts (1)
50-54: Add word boundary to memoPattern to prevent mid-identifier matches.The
memoPatternlacks a leading boundary, so it could match a substring within a longer identifier (e.g., matchingfoo$X=insidebar$foo$X=...).♻️ Suggested fix
// Strategy 2: React Compiler memoized const memoPattern = - /([$\w]+)=([$\w]+)\.createElement\(([$\w]+),\{bold:!0\},"Claude Code"\)/; + /[,;{}]([$\w]+)=([$\w]+)\.createElement\(([$\w]+),\{bold:!0\},"Claude Code"\)/;As per coding guidelines: "Use
,;}{literal characters at regex start instead of\\bfor performance in patch patterns".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/patchesAppliedIndication.ts` around lines 50 - 54, The regex memoPattern can match inside longer identifiers; fix it by requiring a literal start-or-boundary prefix: change memoPattern to include a non-capturing prefix like (?:^|[;,{}]) before the first capture (e.g. /(?:^|[;,{}])([$\w]+)=([$\w]+)\.createElement\(([$\w]+),\{bold:!0\},"Claude Code"\)/) and then update any code that reads memoMatch capture indexes (memoMatch[1] etc.) to account for the added group offset (or destructure/match accordingly); update references to memoPattern, memoMatch, and fileContents where needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/patches/agentsMd.ts`:
- Around line 27-34: The regex in funcPattern can match inside identifiers
because `(function ([$\w]+)` lacks a word boundary; update funcPattern to
require a word boundary before "function" and after the function name (e.g., add
\b around "function" and the captured name) so it only matches a real function
declaration when searching for the CLAUDE.md reading function; adjust the
pattern declared in funcPattern and keep the subsequent funcMatch logic
unchanged.
In `@src/patches/helpers.ts`:
- Around line 298-299: The regex in textComponentPattern uses \b which is
disallowed; update the pattern to remove \b and instead anchor with a literal
boundary alternative (e.g. a non-capturing group matching start-of-string or one
of the literal characters like ',', ';', '{', '}') before the function name so
identifiers with '$' still match; keep the rest of the pattern ([$\w]+ and the
color/background/bold segments) unchanged and ensure the new prefix is
non-capturing to preserve existing groups in textComponentPattern.
In `@src/patches/patchesAppliedIndication.ts`:
- Around line 50-54: The regex memoPattern can match inside longer identifiers;
fix it by requiring a literal start-or-boundary prefix: change memoPattern to
include a non-capturing prefix like (?:^|[;,{}]) before the first capture (e.g.
/(?:^|[;,{}])([$\w]+)=([$\w]+)\.createElement\(([$\w]+),\{bold:!0\},"Claude
Code"\)/) and then update any code that reads memoMatch capture indexes
(memoMatch[1] etc.) to account for the added group offset (or destructure/match
accordingly); update references to memoPattern, memoMatch, and fileContents
where needed.
In `@src/patches/userMessageDisplay.ts`:
- Around line 147-148: The regex assigned to the variable pattern in
userMessageDisplay.ts uses \b word boundaries which violate our guidelines;
update the pattern to remove all \b tokens and instead express boundaries with
explicit alternatives that account for JS identifier characters (letters,
digits, underscore, dollar) and string delimiters—e.g., replace each \b with an
explicit check for start/end or a non-identifier character (or a non-identifier
char class) so `$` is treated correctly; keep the rest of the grouping and
quantifiers intact and verify the first boundary after "No content found in user
prompt message" matches the actual minified surrounding character(s).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ab5f1607-d245-4708-91da-576e94fa6f05
📒 Files selected for processing (5)
src/patches/agentsMd.tssrc/patches/helpers.tssrc/patches/index.tssrc/patches/patchesAppliedIndication.tssrc/patches/userMessageDisplay.ts
Two issues prevented tweakcc from working on fresh CC 2.1.87 native installations: 1. Bun CJS wrapper: Newer Bun native binaries wrap module contents in `// @Bun @bytecode @bun-cjs\n(function(...) { ... })`. Patches expect raw JS. Added stripBunCjsWrapper() during extraction and addBunCjsWrapper() during repack to handle this transparently. 2. ELF section overflow: Patches inject code (AGENTS.md fallback, tweakcc indicators, etc.) making the JS ~8KB larger. The .bun ELF section has a fixed size and cannot grow. Replaced LIEF binary.write() (which crashed with std::bad_alloc on 228MB binaries) with direct file I/O at the section offset. When the rebuilt data exceeds the section budget, expendable fields (sourcemaps, bytecodes, moduleInfo) are zeroed to free space. Tested: full clean cycle (delete backups → apply → verify) succeeds on CC 2.1.87 native Linux installation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/nativeInstallation.ts`:
- Around line 1407-1470: The temp .tmp file is only cleaned on rename failure;
ensure it is removed on any write-stage failure by extracting the
copy/write/chmod/rename logic from repackELFSection into a new helper (e.g.,
atomicWriteBinary or similar) that always performs cleanup in a single finally
block; move creation of tempPath, copyFileSync, openSync/writeSync, chmodSync
and renameSync into that helper, catch and map ETXTBSY/EBUSY/EPERM to the
friendly error there, and guarantee unlinkSync(tempPath) in the helper's finally
so failures from copyFileSync/openSync/writeSync/chmodSync also remove the temp
file.
- Around line 863-873: The re-wrap logic uses only a prefix check
(originalHadWrapper) and can double-wrap; make wrapper detection symmetric with
extractClaudeJsFromNativeInstallation by checking both BUN_CJS_PREFIX and
BUN_CJS_SUFFIX on the original contents before re-wrapping: read
originalContents via getStringPointerContent(bunData, module.contents), verify
it startsWith(BUN_CJS_PREFIX) AND endsWith(BUN_CJS_SUFFIX) (matching the same
trimming logic used in extractClaudeJsFromNativeInstallation), then only call
addBunCjsWrapper(modifiedClaudeJs) when both prefix and suffix are present;
otherwise leave modifiedClaudeJs as-is and assign to contentsBytes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f30aeaad-6087-4496-bd1b-a3254e9870c2
📒 Files selected for processing (1)
src/nativeInstallation.ts
…pper detection, temp file cleanup - Validate ELF section header format using BUN_TRAILER signature instead of strict 4KB size tolerance, fixing extraction on binaries where .bun section is much larger than the payload (e.g. 121MB section with 14MB data) - Use stripBunCjsWrapper() for symmetric prefix+suffix detection in rebuild, preventing double-wrapping if Bun changes the suffix format - Wrap entire temp file lifecycle in try/finally so .tmp is cleaned up on any write-stage failure, not just rename failures Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ection
Patches that CC now ships natively (opusplan[1m], fixLspSupport,
thinkingVisibility, agentsMd, modelCustomizations) gracefully detect
the already-present feature and skip instead of failing.
Updated pattern matching for React Compiler restructured code:
- thinkingVerbs: handle non-"ed" words like "Beboppin'" in past tense array
- thinkerFormat: match template literal `${expr}…` format
- userMessageDisplay: match simplified createElement chain
- statuslineUpdateThrottle: match setTimeout with passed-args pattern
- themes: match variable assignment prefix (not just `return`)
- patchesAppliedIndication: PATCH 4+5 gracefully skip on React Compiler
builds where indicator view layout changed
Tested on fresh CC 2.1.88 binary with both default and custom configs.
All patches succeed; restore→apply cycles are idempotent.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updated: full CC 2.1.85–2.1.88 patching supportThe previous commits handled ELF extraction and CJS wrapper detection. This new commit ( 1. Native feature detection (skip-if-already-present)CC 2.1.87+ now ships several features that tweakcc previously patched in. These patches now detect the native feature and gracefully skip:
2. React Compiler pattern updatesCC 2.1.85+ uses React Compiler which restructures components via
TestingVerified on fresh CC 2.1.88 binary (re-downloaded via
|
There was a problem hiding this comment.
🧹 Nitpick comments (8)
src/patches/userMessageDisplay.ts (1)
147-148: Consider replacing\bwith literal character alternatives for V8 performance.The pattern uses
\bword boundaries multiple times. As per coding guidelines,\bshould be avoided in patch patterns due to V8 performance issues. Consider using literal character alternatives like[^$\w]or anchoring on,,;,{,}instead.Note: This appears to be pre-existing code where only the gap widths were widened, so this is a recommended improvement rather than a blocker.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/userMessageDisplay.ts` around lines 147 - 148, The regex assigned to pattern uses multiple \b word-boundary tokens which are discouraged for V8 performance; update the regex in userMessageDisplay.ts (the const pattern) to replace each \b with explicit literal-character alternatives (e.g., [^$\w] or anchored separators like [,;{}]) or appropriate start/end anchors so the same token boundaries are matched without \b—ensure the replacements preserve the existing grouping and spacing logic (including the segments that reference .createElement and the surrounding capture groups) and run tests to verify no behavior change.src/patches/thinkingVerbs.ts (2)
66-69: Potential wrong-target replacement when custom list has 50+ verbsLine 66 now matches any large capitalized array, so
patchPastTenseVerbscan hit the
already-patched present array first and leave the real past array untouched.Based on learnings: in `src/patches/`, regexes should stay strict to minified Claude Code shapes to avoid ambiguous matches.Proposed hardening
- const pattern = /\[("[A-Z][a-z'é\-\\xA-F0-9]+",?){50,}\]/; - - const match = file.match(pattern); + const pattern = /\[("[A-Z][a-z'é\-\\xA-F0-9]+",?){50,}\]/g; + const presentReplacement = JSON.stringify(verbs); + const match = Array.from(file.matchAll(pattern)).find( + m => m.index !== undefined && m[0] !== presentReplacement + );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/thinkingVerbs.ts` around lines 66 - 69, The current regex in the pattern variable is too broad and will match any large capitalized array (causing patchPastTenseVerbs to pick the wrong target); tighten the pattern to only match the specific minified Claude code shape you expect (for example require the exact surrounding tokens used in the bundle such as the variable/assignment or property name that holds the past-tense list) — update the pattern (the const pattern and its use in file.match(pattern) inside patchPastTenseVerbs) so it includes the unique surrounding context (e.g., the minified variable name or assignment operator and boundary anchors) instead of just /\[("[A-Z][a-z'é\-\\xA-F0-9]+",?){50,}\]/ so the present-tense array cannot be mistaken for the past-tense array.
62-65: Remove new inline comments in this patch fileLines 62-65 add explanatory comments; repository rules for TS/JS files say not to add
comments unless explicitly requested.As per coding guidelines: "
**/*.{js,jsx,ts,tsx}: Do not add comments unless
explicitly requested".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/thinkingVerbs.ts` around lines 62 - 65, Remove the newly added inline comment block that begins "CC ≥ 2.1.87 includes non-"ed" words like "Beboppin'" in the past-tense array..." from the thinkingVerbs.ts patch; repository rules forbid adding comments to TS/JS files, so delete that explanatory comment (the lines referencing the past-tense array, present-tense pattern and the {50,} minimum) and leave only the code for the past-tense/present-tense matching logic intact.src/patches/patchesAppliedIndication.ts (2)
33-42: Remove newly added explanatory comments in this patch file.These comments violate the repo rule for TS files; keep intent in commit/PR
context and warning strings instead.As per coding guidelines "Do not add comments unless explicitly requested".
Also applies to: 467-470, 489-491, 510-513
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/patchesAppliedIndication.ts` around lines 33 - 42, Remove the newly added explanatory block comment that begins with "Find the Claude Code version display pattern." and the related explanatory comment blocks that describe "Inline (pre-React Compiler)" and "Memoized (React Compiler, CC ≥ 2.1.85)"; leave the code and any warning strings intact. Locate these comment blocks in patchesAppliedIndication.ts (the multi-line /** ... */ comments explaining the display patterns and examples) and delete them to comply with the TS file comment rule, ensuring no other code or string literals are changed.
46-59: Use literal punctuation anchors at regex start for patch patterns.These new patterns start with
[^$\w]; patch rules prefer literal delimiter
anchors in minified matching paths for performance and stability.Proposed anchor-style adjustment
- const inlinePattern = - /[^$\w]([$\w]+)\.createElement\(([$\w]+),\{bold:!0\},"Claude Code"\)," ",([$\w]+)\.createElement\(([$\w]+),\{dimColor:!0\},"v",[$\w]+\)/; + const inlinePattern = + /[{},;]([$\w]+)\.createElement\(([$\w]+),\{bold:!0\},"Claude Code"\)," ",([$\w]+)\.createElement\(([$\w]+),\{dimColor:!0\},"v",[$\w]+\)/; const versionPattern = new RegExp( - `[^$\\w][$\\w]+\\.createElement\\([$\\w]+,null,${escapeIdent(cachedVar)}," ",[$\\w]+\\.createElement\\([$\\w]+,\\{dimColor:!0\\},"v",[$\\w]+\\)` + `[{},;][$\\w]+\\.createElement\\([$\\w]+,null,${escapeIdent(cachedVar)}," ",[$\\w]+\\.createElement\\([$\\w]+,\\{dimColor:!0\\},"v",[$\\w]+\\)` );As per coding guidelines "Use
,;}{literal characters at regex start
instead of\\bfor performance in patch patterns."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/patchesAppliedIndication.ts` around lines 46 - 59, Replace the leading [^$\w] non-word predicate in inlinePattern and the versionPattern RegExp with a literal-delimiter anchor class per guidelines; e.g., change inlinePattern to begin with a group like (?:[,;{}]|^) before the capture (so the regex becomes /(?:[,;{}]|^)([$\w]+)\.createElement\(([$\w]+),\{bold:!0\},"Claude Code"\)," ",([$\w]+)\.createElement\(([$\w]+),\{dimColor:!0\},"v",[$\w]+\)/) and update the versionPattern new RegExp template similarly to use (?:[,;{}]|^) instead of [^$\w], keeping the same captures and using escapeIdent(cachedVar) as before; ensure memoPattern usage and escapeIdent/cachedVar references remain unchanged.src/patches/agentsMd.ts (1)
26-33: Use[$\w]+instead of\w+for identifier matching.The native detection regex uses
\w+which won't match identifiers containing$(common in minified code and React refs).🔧 Suggested fix
- if (/CLAUDE\.md.{0,100}for\(let \w+ of \["AGENTS\.md"/.test(file)) { + if (/CLAUDE\.md.{0,100}for\(let [$\w]+ of \["AGENTS\.md"/.test(file)) {As per coding guidelines: "Use
[\$\\w]+instead of\\w+for identifier matching in regex patterns to include$for React refs".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/agentsMd.ts` around lines 26 - 33, The regex used in agentsMd to detect the fallback loop currently uses \w+ which misses identifiers containing '$' (e.g., React refs/minified names); update the test regex in the if statement that checks file (the /CLAUDE\.md...for\(let \w+ of \["AGENTS\.md"/ pattern) to use [\$\w]+ instead of \w+ so identifiers with $ are matched; ensure the new pattern is properly escaped in the JS regex literal used in agentsMd.src/patches/themes.ts (1)
74-74: Remove the new inline comment in patch code.Line 74 adds a non-requested comment in a
.tspatch file.♻️ Proposed cleanup
- // Preserve the original prefix (either "return" or a variable assignment like "Lr9=") const objPrefix = locations.obj.identifiers?.[0] ?? 'return';As per coding guidelines "Do not add comments unless explicitly requested".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/themes.ts` at line 74, Remove the added inline comment "// Preserve the original prefix (either "return" or a variable assignment like "Lr9=")" from the patch in src/patches/themes.ts so the patch file contains no unsolicited comments; locate the comment text in the patch block and delete that line, leaving the surrounding patch logic unchanged.src/patches/statuslineUpdateThrottle.ts (1)
119-125: Outdated comments: capture group numbering is incorrect.The inline comments reference incorrect match indices:
- Line 119:
match[4]iscallbackVar, not the debounced invocation- Line 125: The function call is in
match[6], notmatch[5]The actual code logic is correct—this is just a documentation nit.
📝 Suggested comment fix
- // match[4] is the old debounced invocation (being replaced) - // match[5] is the old debounced invocation (being replaced) - // match[6] is the function call with param if newer format (e.g., "I(A)") - // match[7] is the argument if newer format (e.g., "A") - - // Determine the function call to make - // Newer format: match[5] contains "I(A)" - // Older format: just call the function with no args + // match[5] is the old debounced invocation (being replaced) + // match[6] is the function call with param if newer format (e.g., "I(A)") + // match[7] is the argument if newer format (e.g., "A") + + // Determine the function call to make + // Newer format: match[6] contains "I(A)" + // Older format: just call the function with no args🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/patches/statuslineUpdateThrottle.ts` around lines 119 - 125, Update the outdated inline comments in statuslineUpdateThrottle.ts to reflect the correct regex capture groups: change the comment that claims "match[4] is the old debounced invocation" to note that match[4] is actually callbackVar, and adjust the other comment to state that the function call with parameter (newer format) lives in match[6] (with its argument in match[7]) rather than match[5]; keep the surrounding explanation about which captures represent old vs newer formats consistent with the actual code logic in the block that inspects match.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/patches/agentsMd.ts`:
- Around line 26-33: The regex used in agentsMd to detect the fallback loop
currently uses \w+ which misses identifiers containing '$' (e.g., React
refs/minified names); update the test regex in the if statement that checks file
(the /CLAUDE\.md...for\(let \w+ of \["AGENTS\.md"/ pattern) to use [\$\w]+
instead of \w+ so identifiers with $ are matched; ensure the new pattern is
properly escaped in the JS regex literal used in agentsMd.
In `@src/patches/patchesAppliedIndication.ts`:
- Around line 33-42: Remove the newly added explanatory block comment that
begins with "Find the Claude Code version display pattern." and the related
explanatory comment blocks that describe "Inline (pre-React Compiler)" and
"Memoized (React Compiler, CC ≥ 2.1.85)"; leave the code and any warning strings
intact. Locate these comment blocks in patchesAppliedIndication.ts (the
multi-line /** ... */ comments explaining the display patterns and examples) and
delete them to comply with the TS file comment rule, ensuring no other code or
string literals are changed.
- Around line 46-59: Replace the leading [^$\w] non-word predicate in
inlinePattern and the versionPattern RegExp with a literal-delimiter anchor
class per guidelines; e.g., change inlinePattern to begin with a group like
(?:[,;{}]|^) before the capture (so the regex becomes
/(?:[,;{}]|^)([$\w]+)\.createElement\(([$\w]+),\{bold:!0\},"Claude Code"\),"
",([$\w]+)\.createElement\(([$\w]+),\{dimColor:!0\},"v",[$\w]+\)/) and update
the versionPattern new RegExp template similarly to use (?:[,;{}]|^) instead of
[^$\w], keeping the same captures and using escapeIdent(cachedVar) as before;
ensure memoPattern usage and escapeIdent/cachedVar references remain unchanged.
In `@src/patches/statuslineUpdateThrottle.ts`:
- Around line 119-125: Update the outdated inline comments in
statuslineUpdateThrottle.ts to reflect the correct regex capture groups: change
the comment that claims "match[4] is the old debounced invocation" to note that
match[4] is actually callbackVar, and adjust the other comment to state that the
function call with parameter (newer format) lives in match[6] (with its argument
in match[7]) rather than match[5]; keep the surrounding explanation about which
captures represent old vs newer formats consistent with the actual code logic in
the block that inspects match.
In `@src/patches/themes.ts`:
- Line 74: Remove the added inline comment "// Preserve the original prefix
(either "return" or a variable assignment like "Lr9=")" from the patch in
src/patches/themes.ts so the patch file contains no unsolicited comments; locate
the comment text in the patch block and delete that line, leaving the
surrounding patch logic unchanged.
In `@src/patches/thinkingVerbs.ts`:
- Around line 66-69: The current regex in the pattern variable is too broad and
will match any large capitalized array (causing patchPastTenseVerbs to pick the
wrong target); tighten the pattern to only match the specific minified Claude
code shape you expect (for example require the exact surrounding tokens used in
the bundle such as the variable/assignment or property name that holds the
past-tense list) — update the pattern (the const pattern and its use in
file.match(pattern) inside patchPastTenseVerbs) so it includes the unique
surrounding context (e.g., the minified variable name or assignment operator and
boundary anchors) instead of just /\[("[A-Z][a-z'é\-\\xA-F0-9]+",?){50,}\]/ so
the present-tense array cannot be mistaken for the past-tense array.
- Around line 62-65: Remove the newly added inline comment block that begins "CC
≥ 2.1.87 includes non-"ed" words like "Beboppin'" in the past-tense array..."
from the thinkingVerbs.ts patch; repository rules forbid adding comments to
TS/JS files, so delete that explanatory comment (the lines referencing the
past-tense array, present-tense pattern and the {50,} minimum) and leave only
the code for the past-tense/present-tense matching logic intact.
In `@src/patches/userMessageDisplay.ts`:
- Around line 147-148: The regex assigned to pattern uses multiple \b
word-boundary tokens which are discouraged for V8 performance; update the regex
in userMessageDisplay.ts (the const pattern) to replace each \b with explicit
literal-character alternatives (e.g., [^$\w] or anchored separators like [,;{}])
or appropriate start/end anchors so the same token boundaries are matched
without \b—ensure the replacements preserve the existing grouping and spacing
logic (including the segments that reference .createElement and the surrounding
capture groups) and run tests to verify no behavior change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9330f4b8-a37e-49e2-9f78-bca00cf24f9c
📒 Files selected for processing (11)
src/patches/agentsMd.tssrc/patches/fixLspSupport.tssrc/patches/modelSelector.tssrc/patches/opusplan1m.tssrc/patches/patchesAppliedIndication.tssrc/patches/statuslineUpdateThrottle.tssrc/patches/themes.tssrc/patches/thinkerFormat.tssrc/patches/thinkingVerbs.tssrc/patches/thinkingVisibility.tssrc/patches/userMessageDisplay.ts
Summary
Claude Code 2.1.85+ uses the React Compiler, which transforms component functions by moving props destructuring from the parameter list into the function body with
useMemoCache. This broke multiple patching regexes that assumed inline destructuring. Additionally, the CLAUDE.md reader was refactored from a single sync function into three async functions, andMCP_CONNECTION_NONBLOCKINGwas removed entirely (non-blocking is now the default).This PR fixes all 4 patches that were failing on CC 2.1.87.
Changes
helpers.ts— React Compiler regex wideningfindTextComponent:.{0,20}→.{0,80}(React Compiler gap is 21 chars, just 1 over the old limit)findBoxComponentMethod 1:.{0,200}→.{0,500}(cache slot assignments expand the gap to ~336 chars)findBoxComponentMethod 2: Handle body-level destructuring (.{0,200}children:instead of\(\{children:)agentsMd.ts— Async function split supportThe single sync CLAUDE.md reader was split into 3 functions in CC 2.1.85+:
ol4— content processor (has "Skipping non-text file" anchor but no fs ops)Fb8— async reader (callsreadFile, thenol4)al4— error handler (ENOENT / EISDIR / EACCES)The patch now auto-detects which pattern is present:
writeAgentsMdSync()writeAgentsMdAsync()targets the async readerpatchesAppliedIndication.ts— Memoized createElement supportfindVersionDisplay()helper with two strategies:createElement(TEXT,{bold:!0},"Claude Code")(pre-React Compiler)createElementcached in a variableuserMessageDisplay.ts— Flexible prop matching.{0,150}→.{0,250},.{0,100}→.{0,200}[^}]*instead of hardcodedthinkingMetadatanativeInstallation.ts— ELF extraction fix, CJS wrapper symmetry, temp cleanup.bunsection is much larger than the payloadstripBunCjsWrapper().hadWrapperfor symmetric prefix+suffix checking, preventing double-wrappingtry/finallyso.tmpis always cleaned up on any failureindex.ts— Version gatemcp-non-blockingpatch gated to CC < 2.1.85 (MCP_CONNECTION_NONBLOCKINGremoved, behavior is now native)Before / After (CC 2.1.87)
Before (tweakcc main):
After (this PR):
Code Review Summary
No security vulnerabilities. No breaking changes. Full backward compatibility with CC < 2.1.85.
Test plan
bun run buildpasses (tsc --noEmit + tsdown)npx vitest run— 221 passed, 0 failed, 4 skipped (pre-existing)bun dist/index.mjs --applyon CC 2.1.87 native Linux — all patches succeedKnown limitations
Closes #643, closes #645, closes #628, closes #624
Summary by CodeRabbit
New Features
Bug Fixes
Refactor