fix: Cursor IDE compat (platform source + empty stdin)#3049
Conversation
Cursor and Claude Code can share a content_session_id; last incoming platform_source wins so observations are not dropped with HTTP 500.
Default empty stdin on non-lifecycle hooks is a no-op (Cursor fires these routinely). Set CLAUDE_MEM_STRICT_STDIN=1 to restore issue thedotmack#2188 CAPTURE_BROKEN diagnostics for WSL/bash debugging.
Greptile SummaryThis PR updates Cursor and Claude Code hook handling for dual-IDE setups. The main changes are:
Confidence Score: 3/5Merge should wait for the session source handling to preserve existing Cursor attribution when incoming requests omit a source. The change addresses the previous conflict path, but a focused persistence check shows an omitted source can still relabel an existing Cursor session and affect source-scoped behavior. src/services/sqlite/SessionStore.ts
What T-Rex did
Reviews (2): Last reviewed commit: "fix(cursor): stop platform_source confli..." | Re-trigger Greptile |
….8.1) Set explicit platform on Cursor adapter payloads, allow omitted platformSource in ingestObservation, and rebuild worker bundles so mixed IDE sessions no longer return 500 Platform source conflict.
| } else if (storedPlatformSource !== resolved.platformSource) { | ||
| throw new Error( | ||
| `Platform source conflict for session ${contentSessionId}: existing=${storedPlatformSource}, received=${resolved.platformSource}` | ||
| ); | ||
| // Cursor and Claude Code can share a content_session_id across IDEs; | ||
| // last-writer wins instead of dropping observations with HTTP 500. | ||
| this.db.prepare(` | ||
| UPDATE sdk_sessions SET platform_source = ? | ||
| WHERE content_session_id = ? | ||
| `).run(resolved.platformSource, contentSessionId); |
There was a problem hiding this comment.
Default source overwrites
This update treats every conflicting platformSource as authoritative, but current summarize paths still call normalizePlatformSource(req.body.platformSource) / normalizePlatformSource(payload.platformSource), which converts an omitted source to claude. A Cursor session followed by a source-less summarize request now gets relabeled to claude, breaking source-scoped filtering instead of just avoiding the 500.
Artifacts
Repro: focused SessionStore sqlite reproduction script
- Contains supporting evidence from the run (text/typescript; charset=utf-8).
Repro: command output showing before cursor and after claude database state
- Keeps the command output available without making the summary code-heavy.
Two fixes for Cursor + Claude Code dual-IDE setups on macOS.\n\n1. Platform source conflict — update incoming platform_source instead of throwing (observations were dropped with HTTP 500).\n2. Empty stdin (#2188) — default no-op for non-lifecycle hooks; restore diagnostics via CLAUDE_MEM_STRICT_STDIN=1.\n\nTested locally on claude-mem 13.8.1.