feat: v1.3.0 — Claude Code 2.1.49 productivity improvements#18
feat: v1.3.0 — Claude Code 2.1.49 productivity improvements#18
Conversation
…e hook, smarter Stop hook 7 improvements for Claude Code 2.1.49 compatibility: 1. Native worktree flag (claude -w) in parallel command and skill 2. Background scout agent with worktree isolation 3. ConfigChange hook to detect settings changes mid-session 4. last_assistant_message in Stop hook for context-aware reminders 5. Default settings.json with quality gate permissions 6. Updated model preferences (Sonnet 4.6, adaptive thinking built-in) 7. Updated /learn command with new keybindings, modes, and hook types Cursor plugin compatibility verified — unknown frontmatter keys ignored.
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughAdds a ConfigChange hook and watcher, native worktree support and related docs, refactors session reminder/script logic for context-aware behavior, introduces Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant PluginHost as Plugin Host
participant FileSystem as File System
participant ConfigWatcher as config-watcher.js
User->>FileSystem: Edit sensitive config (settings.json/hooks.json/.claudeignore)
FileSystem-->>PluginHost: File change event
PluginHost->>ConfigWatcher: Invoke ConfigChange hook (stdin: JSON payload)
ConfigWatcher->>FileSystem: Read/verify changed file(s), append to session log
ConfigWatcher-->>PluginHost: Emit detection output (stdout JSON)
PluginHost-->>User: Present hook result / notify of config change
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 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.
Actionable comments posted: 5
🧹 Nitpick comments (5)
commands/parallel.md (1)
45-49: Add a language identifier to the fenced code block.Static analysis (markdownlint MD040) flags this code block as missing a language specifier. Since this is a terminal layout diagram,
textis appropriate.📝 Suggested fix
-``` +```text Terminal 1: ~/project → Main work (or `claude`) Terminal 2: ~/project-feat → claude --worktree (auto-isolated) Terminal 3: ~/project-fix → claude -w (shorthand)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@commands/parallel.md` around lines 45 - 49, The fenced code block in commands/parallel.md is missing a language identifier causing markdownlint MD040; update the block fence that currently contains the three "Terminal 1/2/3" lines to include a language specifier (use "text") after the opening triple backticks so the block becomes ```text and the terminal layout diagram (the lines with `Terminal 1: ~/project`, `Terminal 2: ~/project-feat`, `Terminal 3: ~/project-fix`) is correctly marked as plain text.scripts/session-check.js (1)
64-67: Session ID sourced from parsed JSON input is used directly in a file path.Line 66 falls back through
input.session_id, which comes from stdin JSON. If a caller passes a craftedsession_idcontaining path separators (e.g.,../../x),responseCountFileresolves outside the temp directory. In a local dev-tool context the risk is low, but a simple sanitization guard would eliminate it.🛡️ Suggested sanitization
const sessionId = input.session_id || process.env.CLAUDE_SESSION_ID || process.ppid || 'default'; - const responseCountFile = path.join(tempDir, `response-count-${sessionId}`); + const safeSessionId = String(sessionId).replace(/[^a-zA-Z0-9_-]/g, '_'); + const responseCountFile = path.join(tempDir, `response-count-${safeSessionId}`);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/session-check.js` around lines 64 - 67, Session ID from input.session_id is used directly to build responseCountFile, allowing path traversal; sanitize the session ID before composing the path by normalizing/restricting characters (e.g., allow only alphanumerics, dashes, underscores), stripping path separators, and enforcing a max length or falling back to 'default'; implement a small helper (e.g., sanitizeSessionId) and use it when setting sessionId (used to create responseCountFile and alongside tempDir/ensureDir) so that path.join cannot resolve outside tempDir.commands/learn.md (1)
43-43:Shift+Tabis documented with two different behaviors — worth clarifying.Line 43 lists
Shift+Tabas "Cycle modes (Normal/Auto-Accept/Plan)" in the global shortcuts table. Line 112 then describes it as "Delegate mode (Shift+Tab): restricts lead to coordination only" in the Agent Teams section. The same key does different things depending on context, but there's no hint of this in the shortcuts table.Consider adding a parenthetical to line 43, e.g.:
-| `Shift+Tab` | Cycle modes (Normal/Auto-Accept/Plan) | +| `Shift+Tab` | Cycle modes (Normal/Auto-Accept/Plan); Delegate mode when Agent Teams active |Also applies to: 112-112
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@commands/learn.md` at line 43, The global shortcuts table entry for `Shift+Tab` is ambiguous because `Shift+Tab` has a different behavior in the Agent Teams section; update the global table row "Shift+Tab | Cycle modes (Normal/Auto-Accept/Plan)" to note the context-specific behavior (e.g., append "(context-sensitive: cycles modes globally; in Agent Teams, toggles Delegate mode—restricts lead to coordination only)") and ensure the Agent Teams section still clearly documents the Delegate mode and references the global shortcut for clarity.scripts/config-watcher.js (2)
66-76: Log rotation truncates the entire file rather than rotating it.When the log exceeds 100 KB,
fs.writeFileSync(logFile, '')discards all history. This means a single log-rotation event silently removes all prior config-change entries, leaving no audit trail. For a security-auditing hook, preserving at least the previous generation could be useful.♻️ Suggested rename-based rotation
- try { - const stat = fs.statSync(logFile); - if (stat.size > MAX_LOG_SIZE) { - fs.writeFileSync(logFile, ''); - } - } catch (_e) { - // File doesn't exist yet - } + try { + const stat = fs.statSync(logFile); + if (stat.size > MAX_LOG_SIZE) { + fs.renameSync(logFile, logFile + '.old'); + } + } catch (_e) { + // File doesn't exist yet — nothing to rotate + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/config-watcher.js` around lines 66 - 76, Currently the rotation logic in scripts/config-watcher.js truncates the log with fs.writeFileSync(logFile, ''), which removes all history; change it to perform a rename-based rotation instead: when stat.size > MAX_LOG_SIZE, rename logFile to a rotated name (e.g., append a timestamp or “.1”) using fs.renameSync(logFile, rotatedName) so the prior generation is preserved, then create a new empty log file before calling fs.appendFileSync; update references to MAX_LOG_SIZE, logFile, fs.statSync, fs.renameSync and fs.appendFileSync in the rotation block and ensure errors are caught/handled similarly to the existing catch path.
30-89:async main()+ outer.catch()provide no additional error protection.
main()is declaredasyncbut contains noawaitexpressions. It registers two synchronous event listeners and returns immediately with a resolved promise. The outer.catch()at line 87 can therefore only fire ifprocess.stdin.on(...)itself throws synchronously — which never happens in practice. Every real code path (JSON parsing, file I/O,console.log) lives inside thetry-catchblock on lines 38–83, which already handles all runtime errors. Theasync/.catch()wrapper adds no protection and implies a false safety net to future maintainers.Consider either:
♻️ Option A — drop `async` and make the catch explicit
-async function main() { +function main() { let data = ''; process.stdin.on('data', chunk => { data += chunk; }); process.stdin.on('end', () => { try { // ... existing logic ... } catch (err) { console.error('[ProWorkflow] config-watcher error:', err.message); console.log(data || '{}'); } }); } -main().catch(err => { - console.error('[ProWorkflow] Error:', err.message); - process.exit(0); -}); +main();♻️ Option B — convert to a true async/await pattern using `stream/promises`
+const { buffer } = require('node:stream/consumers'); async function main() { - let data = ''; - process.stdin.on('data', chunk => { data += chunk; }); - await new Promise(resolve => process.stdin.on('end', resolve)); + const data = (await buffer(process.stdin)).toString(); try { // ... existing logic using data ... } catch (err) { ... } } main().catch(err => { console.error('[ProWorkflow] Error:', err.message); process.exit(0); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/config-watcher.js` around lines 30 - 89, The wrapper async main() + .catch() is misleading because main() never awaits anything; either remove async and the outer .catch() and call main() directly (make function main() non-async and replace main().catch(...) with just main();) or convert the stdin handling to a true async/await pattern (e.g. use stream/promises or an async helper to await reading process.stdin into `data`) so that `main()` actually awaits the read and the outer `.catch()` can catch runtime errors; update the `main`, `process.stdin.on('data'...)`, `process.stdin.on('end'...)` logic accordingly and keep the inner try/catch around JSON.parse/file I/O as needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.claude-plugin/settings.json:
- Line 21: The current pre-approval entry "Bash(git worktree *)" grants all
worktree subcommands (including destructive ones); replace it with more specific
entries (e.g., "Bash(git worktree list)", "Bash(git worktree add *") and
optionally "Bash(git worktree remove)" only if intended, or keep the wildcard
but add an inline comment explaining the intentional breadth for
parallel-worktrees; update the settings.json entry (the exact string "Bash(git
worktree *)") and add a short note in the README clarifying the security
tradeoff so adopters can opt to restrict or accept the broader pattern.
In `@commands/learn.md`:
- Around line 57-58: The Markdown table ending with the CLI shortcuts row is not
followed by a blank line, triggering markdownlint MD058; fix by inserting a
single blank line between the table (the row containing `/insights | Session
analytics and patterns`) and the following bullet line (`- **Docs:**
https://code.claude.com/docs/cli-reference`) so the table is separated from the
list.
In `@scripts/session-check.js`:
- Around line 69-75: The code that reads responseCountFile and uses parseInt can
yield NaN for corrupted/empty content and permanently break the counter; update
the block that reads and parses the file (the logic around responseCountFile,
fs.readFileSync and parseInt) to validate the parsed value and provide a safe
fallback: attempt to read and parse with radix 10, check that the result is a
finite integer (e.g., with Number.isFinite/Number.isInteger or !Number.isNaN),
and if parsing fails or reading throws, default count to 1 before incrementing
and then write the sanitized value back using fs.writeFileSync; ensure you
handle and log read errors from fs.readFileSync so corruption doesn't propagate.
- Around line 41-49: The detectLargeChange function currently matches any
numeric file count (e.g., "1 file changed"); update it to parse the captured
number from the message and only return true when that number meets a threshold
(suggested >=5). In practice, keep the existing patterns but change the logic to
extract the numeric capture (from the /(\d+) files?/ style match or similar),
convert it to an integer, compare against the threshold, and only treat it as a
large change when the integer >= threshold; ensure other non-count patterns
(like "across X files") are handled the same way and that detectLargeChange
returns false for counts below the threshold. Use the function name
detectLargeChange and the existing pattern set to locate where to implement this
check.
In `@skills/parallel-worktrees/SKILL.md`:
- Around line 57-61: Update the Terminal 3 label to match the worktree path and
purpose: change the description that currently reads "Feature development" for
"Terminal 3: ~/project-fix" to something like "Bug fix" (or "Bugfix work") so it
aligns with the worktree name `~/project-fix` and the earlier command `git
worktree add ../project-fix bugfix-branch`; ensure the line starting with
"Terminal 3:" and the text after the arrow reflect this corrected label.
---
Nitpick comments:
In `@commands/learn.md`:
- Line 43: The global shortcuts table entry for `Shift+Tab` is ambiguous because
`Shift+Tab` has a different behavior in the Agent Teams section; update the
global table row "Shift+Tab | Cycle modes (Normal/Auto-Accept/Plan)" to note the
context-specific behavior (e.g., append "(context-sensitive: cycles modes
globally; in Agent Teams, toggles Delegate mode—restricts lead to coordination
only)") and ensure the Agent Teams section still clearly documents the Delegate
mode and references the global shortcut for clarity.
In `@commands/parallel.md`:
- Around line 45-49: The fenced code block in commands/parallel.md is missing a
language identifier causing markdownlint MD040; update the block fence that
currently contains the three "Terminal 1/2/3" lines to include a language
specifier (use "text") after the opening triple backticks so the block becomes
```text and the terminal layout diagram (the lines with `Terminal 1: ~/project`,
`Terminal 2: ~/project-feat`, `Terminal 3: ~/project-fix`) is correctly marked
as plain text.
In `@scripts/config-watcher.js`:
- Around line 66-76: Currently the rotation logic in scripts/config-watcher.js
truncates the log with fs.writeFileSync(logFile, ''), which removes all history;
change it to perform a rename-based rotation instead: when stat.size >
MAX_LOG_SIZE, rename logFile to a rotated name (e.g., append a timestamp or
“.1”) using fs.renameSync(logFile, rotatedName) so the prior generation is
preserved, then create a new empty log file before calling fs.appendFileSync;
update references to MAX_LOG_SIZE, logFile, fs.statSync, fs.renameSync and
fs.appendFileSync in the rotation block and ensure errors are caught/handled
similarly to the existing catch path.
- Around line 30-89: The wrapper async main() + .catch() is misleading because
main() never awaits anything; either remove async and the outer .catch() and
call main() directly (make function main() non-async and replace
main().catch(...) with just main();) or convert the stdin handling to a true
async/await pattern (e.g. use stream/promises or an async helper to await
reading process.stdin into `data`) so that `main()` actually awaits the read and
the outer `.catch()` can catch runtime errors; update the `main`,
`process.stdin.on('data'...)`, `process.stdin.on('end'...)` logic accordingly
and keep the inner try/catch around JSON.parse/file I/O as needed.
In `@scripts/session-check.js`:
- Around line 64-67: Session ID from input.session_id is used directly to build
responseCountFile, allowing path traversal; sanitize the session ID before
composing the path by normalizing/restricting characters (e.g., allow only
alphanumerics, dashes, underscores), stripping path separators, and enforcing a
max length or falling back to 'default'; implement a small helper (e.g.,
sanitizeSessionId) and use it when setting sessionId (used to create
responseCountFile and alongside tempDir/ensureDir) so that path.join cannot
resolve outside tempDir.
| "Bash(pytest *)", | ||
| "Bash(go test ./...)", | ||
| "Bash(go test *)", | ||
| "Bash(git worktree *)", |
There was a problem hiding this comment.
"Bash(git worktree *)" pre-approves all worktree subcommands, including destructive ones.
The wildcard permits git worktree add <arbitrary-path>, git worktree remove, and git worktree prune --expire now without user confirmation. This is intentional for the parallel-worktrees workflow, but consumers of this template who don't use native worktrees may want to scope it to just git worktree list and git worktree add. Worth documenting the intentional breadth in a comment or the README so adopters can make an informed choice.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.claude-plugin/settings.json at line 21, The current pre-approval entry
"Bash(git worktree *)" grants all worktree subcommands (including destructive
ones); replace it with more specific entries (e.g., "Bash(git worktree list)",
"Bash(git worktree add *") and optionally "Bash(git worktree remove)" only if
intended, or keep the wildcard but add an inline comment explaining the
intentional breadth for parallel-worktrees; update the settings.json entry (the
exact string "Bash(git worktree *)") and add a short note in the README
clarifying the security tradeoff so adopters can opt to restrict or accept the
broader pattern.
| | `/insights` | Session analytics and patterns | | ||
| - **Docs:** https://code.claude.com/docs/cli-reference |
There was a problem hiding this comment.
Fix markdownlint MD058: add a blank line after the CLI shortcuts table.
The static analysis tool reports that the table ending at line 57 is not followed by a blank line before the - **Docs:** bullet at line 58.
🔧 Proposed fix
| `/insights` | Session analytics and patterns |
+
- **Docs:** https://code.claude.com/docs/cli-reference📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | `/insights` | Session analytics and patterns | | |
| - **Docs:** https://code.claude.com/docs/cli-reference | |
| | `/insights` | Session analytics and patterns | | |
| - **Docs:** https://code.claude.com/docs/cli-reference |
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 57-57: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@commands/learn.md` around lines 57 - 58, The Markdown table ending with the
CLI shortcuts row is not followed by a blank line, triggering markdownlint
MD058; fix by inserting a single blank line between the table (the row
containing `/insights | Session analytics and patterns`) and the following
bullet line (`- **Docs:** https://code.claude.com/docs/cli-reference`) so the
table is separated from the list.
| function detectLargeChange(message) { | ||
| if (!message) return false; | ||
| const patterns = [ | ||
| /(\d+) files? (changed|modified|updated|created)/i, | ||
| /across \d+ files/i, | ||
| /refactored? \d+ (files?|modules?|components?)/i | ||
| ]; | ||
| return patterns.some(p => p.test(message)); | ||
| } |
There was a problem hiding this comment.
detectLargeChange triggers on any file count, including "1 file changed".
The regex captures (\d+) files? but never inspects the captured count. A message like "1 file changed" will trigger the "Large change detected" reminder, which is misleading. Consider checking that the matched number exceeds a threshold (e.g., ≥ 5 files).
📝 Suggested fix
function detectLargeChange(message) {
if (!message) return false;
- const patterns = [
- /(\d+) files? (changed|modified|updated|created)/i,
- /across \d+ files/i,
- /refactored? \d+ (files?|modules?|components?)/i
- ];
- return patterns.some(p => p.test(message));
+ const thresholdPatterns = [
+ { pattern: /(\d+) files? (changed|modified|updated|created)/i, group: 1 },
+ { pattern: /across (\d+) files/i, group: 1 },
+ { pattern: /refactored? (\d+) (files?|modules?|components?)/i, group: 1 }
+ ];
+ return thresholdPatterns.some(({ pattern, group }) => {
+ const m = message.match(pattern);
+ return m && parseInt(m[group], 10) >= 5;
+ });
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/session-check.js` around lines 41 - 49, The detectLargeChange
function currently matches any numeric file count (e.g., "1 file changed");
update it to parse the captured number from the message and only return true
when that number meets a threshold (suggested >=5). In practice, keep the
existing patterns but change the logic to extract the numeric capture (from the
/(\d+) files?/ style match or similar), convert it to an integer, compare
against the threshold, and only treat it as a large change when the integer >=
threshold; ensure other non-count patterns (like "across X files") are handled
the same way and that detectLargeChange returns false for counts below the
threshold. Use the function name detectLargeChange and the existing pattern set
to locate where to implement this check.
| let count = 1; | ||
|
|
||
| process.exit(0); | ||
| if (fs.existsSync(responseCountFile)) { | ||
| count = parseInt(fs.readFileSync(responseCountFile, 'utf8').trim(), 10) + 1; | ||
| } | ||
|
|
||
| fs.writeFileSync(responseCountFile, String(count)); |
There was a problem hiding this comment.
parseInt of corrupted or empty file content silently produces NaN, permanently breaking the counter.
If the count file is corrupted (e.g., partial write, disk full), parseInt returns NaN, and all subsequent arithmetic yields NaN. The counter never recovers. Add a fallback:
📝 Suggested fix
let count = 1;
if (fs.existsSync(responseCountFile)) {
- count = parseInt(fs.readFileSync(responseCountFile, 'utf8').trim(), 10) + 1;
+ const raw = parseInt(fs.readFileSync(responseCountFile, 'utf8').trim(), 10);
+ count = (Number.isNaN(raw) ? 0 : raw) + 1;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let count = 1; | |
| process.exit(0); | |
| if (fs.existsSync(responseCountFile)) { | |
| count = parseInt(fs.readFileSync(responseCountFile, 'utf8').trim(), 10) + 1; | |
| } | |
| fs.writeFileSync(responseCountFile, String(count)); | |
| let count = 1; | |
| if (fs.existsSync(responseCountFile)) { | |
| const raw = parseInt(fs.readFileSync(responseCountFile, 'utf8').trim(), 10); | |
| count = (Number.isNaN(raw) ? 0 : raw) + 1; | |
| } | |
| fs.writeFileSync(responseCountFile, String(count)); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/session-check.js` around lines 69 - 75, The code that reads
responseCountFile and uses parseInt can yield NaN for corrupted/empty content
and permanently break the counter; update the block that reads and parses the
file (the logic around responseCountFile, fs.readFileSync and parseInt) to
validate the parsed value and provide a safe fallback: attempt to read and parse
with radix 10, check that the result is a finite integer (e.g., with
Number.isFinite/Number.isInteger or !Number.isNaN), and if parsing fails or
reading throws, default count to 1 before incrementing and then write the
sanitized value back using fs.writeFileSync; ensure you handle and log read
errors from fs.readFileSync so corruption doesn't propagate.
Mark Claude Code-specific sections with *(Claude Code)* labels so Cursor users know what to skip. Add Cursor equivalents in Commands table. Make parallel-worktrees skill show both claude -w and manual git worktree approaches side by side.
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 `@skills/pro-workflow/SKILL.md`:
- Line 200: The sentence "Sonnet 4.5 with 1M context has been retired — use
Sonnet 4.6" is misleading; update the SKILL.md text around the phrase "Opus 4.6
with adaptive thinking" to state that 1M-token context support was introduced in
Opus 4.6 and Sonnet 4.6 (not Sonnet 4.5, which used a 200K context), and add a
brief caveat that the 1M context is currently available as a beta option via the
context-1m-2025-08-07 beta header while the default context window remains 200K.
Ensure you edit the exact sentence mentioning "Sonnet 4.5" / "Sonnet 4.6" so it
clearly attributes 1M support to the 4.6 releases and notes the beta header and
default window.
- Around line 209-218: Update the "Adaptive Thinking" paragraph and the "Add to
CLAUDE.md" snippet to state that adaptive thinking applies to both Opus 4.6 and
Sonnet 4.6: edit the "Adaptive Thinking" header content to mention Sonnet 4.6
alongside Opus 4.6 (e.g., "Opus 4.6 and Sonnet 4.6 automatically calibrate..."),
and change the CLAUDE.md code block under "Model Hints" to read "Opus 4.6 and
Sonnet 4.6 auto-calibrate reasoning depth — no need to toggle thinking mode" so
the guidance for using subagents (Haiku, Sonnet 4.6) remains accurate.
…ive thinking - 1M context is beta (context-1m-2025-08-07 header), default remains 200K - Sonnet 4.5 had 200K context (not 1M) - Adaptive thinking applies to both Opus 4.6 and Sonnet 4.6
Summary
7 improvements to leverage new Claude Code 2.1.49 features for better productivity:
claude -wreplaces manualgit worktree add. Updated/parallelcommand, parallel-worktrees skill, and Pattern 2 in SKILL.mdbackground: true+isolation: worktreeso confidence scoring runs without blocking the userconfig-watcher.jswith log rotation (100KB cap)last_assistant_messageto detect task completion signals and large changes instead of blind response counting. Truncates to last 2000 chars for performancesettings.json— Ships quality gate permissions (lint, test, typecheck, git worktree) so users don't get prompted for common commandsopus-thinking(adaptive thinking is built-in). Updated Pattern 6 table/learncommand — New keybindings (Ctrl+Fkill agents), Simple mode includes Edit tool,Shift+Downonly for teammates, ConfigChange hook docs, Plugins sectionCursor Compatibility
.cursor-plugin/plugin.jsonversion bumped to 1.3.0background: trueandisolation: worktreein scout.md frontmatter — Cursor ignores unknown YAML keysReview fixes applied
refactorregex to avoid false positives in session-check.jscount === 50warning outside the if/else to always firelast_assistant_messageto last 2000 chars for performanceincludes())Test plan
claude plugin install pro-workflow@pro-workflowclaude -wdocumentation in/parallelcommand~/.claude/settings.jsonlast_assistant_messagefor context-aware remindersbackground: true/add-plugin pro-workflowand verify skills/agents load/learncommand shows updated keybindings and model infoSummary by CodeRabbit
New Features
Improvements
Chores