feat: adaptive VS Code resume via IDE lock file polling#109
Conversation
- isVSCodeProjectOpen(): check lock files for matching workspace + alive PID → instant URI handler if found - waitForVSCodeExtensionReady(): poll every 300ms until extension creates lock file (max 8s timeout) - Fallback to 2s delay if IDE lock dir doesn't exist - Also applied to launchNewClaudeSession() VS Code path - Fixes cold-start duplicate tab (waits for extension ready) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Active VS Code sessions were opening new sessions in the wrong window because openSessionInVSCode was called without projectPath — URI handler fired into whichever window was focused. Now always passes projectPath and uses open -b to focus the correct project window before URI handler. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
open -b callback fires before VS Code window is fully focused, causing URI handler to silently fail. 500ms delay gives VS Code time to complete window activation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… delay (cases 3, 5, 7) - Active VS Code sessions + project not open: only open -b, skip URI handler (VS Code restore handles the session tab) - Closed sessions + project not open: poll + 1.5s post-ready delay (lets VS Code finish restoring before URI handler, avoids duplicate tab) - Fixes cases 3, 5, and 7 from test matrix Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR shifts VS Code session resume timing from fixed 2-second delays to adaptive polling based on IDE lock file detection. The logic now distinguishes between already-open projects (faster focus + URI handler) and cold starts (project launch + polling + 1.5s delay + URI handler), with separate handling for active vs inactive sessions to prevent duplicate tabs. Changes
Sequence DiagramsequenceDiagram
participant User as User Action
participant CS as Claude Session<br/>Utility
participant VL as VS Code Lock<br/>Detection
participant VS as VS Code<br/>Instance
participant EXT as VS Code<br/>Extension
User->>CS: Open active session (project path provided)
alt Project Already Open
CS->>VS: Focus VS Code window
Note over CS: Wait 500ms
CS->>EXT: Fire URI handler
EXT-->>User: Session opens in active VS Code
else Project Not Open
CS->>VS: Launch project via open -b
CS->>VL: Poll ~/.claude/ide/*.lock<br/>(every 250ms, 5s timeout)
VL-->>CS: Ready (workspaceFolders match + PID alive)
Note over CS: Wait additional 1500ms
CS->>EXT: Fire URI handler
EXT-->>User: Session opens in new window
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace outdated '2s fixed delay' references with adaptive lock file polling description. Add latency numbers and VS Code-specific resume flow to README terminal table. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consolidates all differences between VS Code and terminal sessions across every layer (detection, switch, resume, readiness, restore conflict, etc.) in one table. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (2)
docs/vscode-session-support-design.md (1)
76-82: Add blank line before table for markdown compliance.Static analysis indicates the table at line 77 should be surrounded by blank lines (MD058). Add a blank line after "Measured latency:" for consistent markdown rendering.
📝 Suggested fix
Measured latency: + | Scenario | Time | |----------|------|🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/vscode-session-support-design.md` around lines 76 - 82, The markdown table under the "Measured latency:" header lacks a separating blank line which triggers MD058; edit the docs/vscode-session-support-design.md content around the "Measured latency:" heading and insert a single blank line immediately after the line that reads "Measured latency:" so the pipe-table (starting with "| Scenario | Time |") is preceded by an empty line, preserving existing text and spacing elsewhere.src/claude-session-utility.ts (1)
1414-1423: Consider logging errors from the focus command.Line 1417 uses an empty callback that ignores potential errors from
open -b bundleId projectPath. While this is a fire-and-forget focus operation, logging errors would help with debugging.♻️ Suggested improvement
- execFile('open', ['-b', bundleId, projectPath], () => { + execFile('open', ['-b', bundleId, projectPath], (error: any) => { + if (error) console.error('[openSessionInVSCode] failed to focus window:', error); setTimeout(() => { execFile('open', [uri]); }, 500); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/claude-session-utility.ts` around lines 1414 - 1423, The callback passed to execFile when focusing the IDE (inside the isVSCodeProjectOpen check) swallows errors; update the anonymous callback for execFile('open', ['-b', bundleId, projectPath], ...) to accept an error parameter and log any error (using the module's logger or console.error) along with context (include bundleId and projectPath), so failures from getCurrentIDEBundleId()/execFile are visible while keeping the existing setTimeout/execFile(uri) behavior intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@docs/vscode-session-support-design.md`:
- Around line 76-82: The markdown table under the "Measured latency:" header
lacks a separating blank line which triggers MD058; edit the
docs/vscode-session-support-design.md content around the "Measured latency:"
heading and insert a single blank line immediately after the line that reads
"Measured latency:" so the pipe-table (starting with "| Scenario | Time |") is
preceded by an empty line, preserving existing text and spacing elsewhere.
In `@src/claude-session-utility.ts`:
- Around line 1414-1423: The callback passed to execFile when focusing the IDE
(inside the isVSCodeProjectOpen check) swallows errors; update the anonymous
callback for execFile('open', ['-b', bundleId, projectPath], ...) to accept an
error parameter and log any error (using the module's logger or console.error)
along with context (include bundleId and projectPath), so failures from
getCurrentIDEBundleId()/execFile are visible while keeping the existing
setTimeout/execFile(uri) behavior intact.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1f097163-2af4-4833-b152-b2f1b6a01176
📒 Files selected for processing (5)
CHANGELOG.mdREADME.mddocs/vscode-session-support-design.mdpackage.jsonsrc/claude-session-utility.ts
Summary
Replace the fixed 2s delay in VS Code session resume with IDE lock file polling for adaptive timing. Fixes duplicate tab bug and non-working resume cases.
Three improvements in one
Latency comparison (vs PR #103)
How it works
Test matrix (all 8 cases pass)
IDE lock file details
~/.claude/ide/*.lock— created by Claude Code VS Code extension per windowworkspaceFolders+pid— can verify project is open + VS Code aliveLock file polling vs #106 (JSONL reads) — different problem, different scale
exec('tail | grep')= child processfs.readFileSync= direct I/OLock file reads use
fs.readFileSync+JSON.parse— no process spawning. Even with 60 VS Code windows open: 60 × 200 bytes = 12KB total I/O ≈ 1.5ms. No need for Rust/native optimization.Ref: #107
Test plan
🤖 On behalf of @grimmerk — generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Documentation