feat(doctor): detect Cursor IDE UNC-mode WSL repos where hooks never fire - #2078
feat(doctor): detect Cursor IDE UNC-mode WSL repos where hooks never fire#2078peyton-alt wants to merge 6 commits into
Conversation
…WSL repo Cursor IDE on Windows executes zero hooks when a WSL repo is opened via a \\wsl$ UNC path (verified empirically on Windows Server 2022 + WSL2 + Cursor 3.16.29: agent session completes, transcript written, no hook runs, no log mention), so Entire tracking silently never starts. The mode leaves a fingerprint: a Windows-side ~/.cursor/projects/<wsl...-distro-sanitized-path> directory, gaining agent-transcripts/ once an agent session ran there. This scanner finds that fingerprint from inside WSL via /mnt/c/Users so doctor can name the failure instead of leaving it to a support thread. The distro name is sanitized like the path (Ubuntu-22.04 → Ubuntu-22-04, matching Cursor's whole-UNC-path transform), names compare case-insensitively (Explorer preserves the user's spelling), and evidence must be a non-empty agent-transcripts dir with activity in the last 14 days so leftover state stops warning after a switch to WSL mode. UNCProjectDirNames is exported so tests and future callers share the naming rule instead of re-deriving it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s fire) The failure is otherwise perfectly silent: the agent works, transcripts save, and Entire never hears about the session. Warn-only next to the other agent-specific doctor checks; the only fix is user-side (reopen in WSL), so the check names it. Gated on WSL_DISTRO_NAME, cursor hooks installed in this repo, and an agent-transcripts-bearing Windows-side fingerprint dir, so every other environment stays silent. The healthy case prints no OK line on purpose: this is an environment probe, not an install-state check. The users root is a package var so the warning path is testable; guidance leads with Reopen Folder in WSL because the cursor shim in WSL only exists after a first WSL-remote connect. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Records the empirical finding backing the doctor check: Cursor fires hooks only in WSL-remote mode, never in \\wsl$ UNC mode. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a doctor warning to make a previously silent failure mode visible: when Cursor IDE on Windows opens a WSL repo via \\wsl$ UNC paths, Cursor runs the agent but executes no hooks, so Entire can’t track sessions. The PR introduces a WSL-side detector that fingerprints Cursor’s Windows-side project dirs and surfaces a warn-only remediation hint (“Reopen Folder in WSL”).
Changes:
- Add a
doctorcheck (checkCursorUNCMode) gated to WSL + repo worktree + Cursor hooks installed, warning when recent UNC-mode activity is detected. - Introduce
cursor.DetectUNCProjectDirsto detect UNC-mode project dirs via Windows-side Cursor fingerprints + recentagent-transcriptsevidence. - Add unit tests for both the detector and doctor integration, plus Cursor agent documentation updates for Windows+WSL behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
cmd/entire/cli/doctor.go |
Runs the new WSL-only Cursor UNC-mode diagnostic and prints a warn-only guidance message. |
cmd/entire/cli/doctor_test.go |
Adds tests covering the warning path and the “silent when hooks not installed” gate. |
cmd/entire/cli/agent/cursor/uncmode.go |
Implements UNC-mode fingerprint detection by scanning Windows user profiles and checking recent transcript evidence. |
cmd/entire/cli/agent/cursor/uncmode_test.go |
Adds unit tests for UNC spelling variants, case-insensitivity, and evidence/recency gating. |
cmd/entire/cli/agent/cursor/AGENT.md |
Documents Cursor’s WSL-remote vs UNC behavior and how doctor detects the UNC mode. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 92a6482. Configure here.
…itizing paths Cursor collapses runs of non-alphanumeric characters into a single "-" when building a project directory name; our per-character transform did not. Real project dirs on disk contain zero "--": a path with "/.worktrees/" becomes "...-cli-worktrees-..." on disk, while our transform produced "...-cli--worktrees-...". Both UNC fingerprint matching and the pre-existing GetSessionDir transcript resolution silently missed any repo path with adjacent non-alphanumerics as a result. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Evidence mtimes come from the Windows filesystem clock via DrvFs, and WSL2's own clock drifts behind the host after sleep. Without tolerance, a live UNC-mode session's newest transcript entry can read as "in the future" relative to WSL's now, and the age>=0 guard silently discarded exactly the freshest evidence. Bounded skew (up to 24h behind) now counts; mtimes far enough in the future to be bogus still don't. UNCEvidenceWindow is exported so doctor.go can name the actual window in its message instead of hardcoding "14 days". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- DetectUNCProjectDirs: match names via slices.ContainsFunc instead of
indexing into the two-element slice; slim its doc comment to the essentials
and defer spelling details to UNCProjectDirNames; fix the junction-skip
comment to name the actual NTFS stubs (All Users, Default User) instead of
a vague "profile-root junction symlinks".
- Move the C:-drive/default-automount caveat to a one-liner next to
doctor.go's cursorWindowsUsersRoot var, which is the thing that actually
assumes it.
- checkCursorUNCMode: point at cursor/AGENT.md's Windows + WSL section
instead of an unverifiable "verified empirically" comment; scope the
headline and body to what the evidence actually shows ("recent sessions
ran over \\wsl$" / "Sessions opened this way are never tracked"), so a user
who already switched to WSL-remote mode doesn't read an absolute "never
tracked" about their current setup; log a debug line (count only, no
paths) when the fingerprint matches.
- Tests: positive doctor test also asserts the "Reopen Folder in WSL" fix
hint; folded the versioned-distro case into the main detector test as a
second sub-fixture; folded the empty-transcripts helper into mkProjectDir
via a withEvidence flag instead of a separate one-off helper.
- AGENT.md: point the multi-root known-quirks sentence at PR #2078.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

https://entire.io/gh/entireio/cli/trails/1106
Summary
Customer report: Cursor IDE sessions on Windows + WSL2 never appear in
entire session listuntil a manualentire session attach, while Cursor CLI in the same repo tracks fine.Root cause, verified empirically on a Windows Server 2022 + WSL2 + Cursor 3.16.29 VM with paired sh-vs-cmd discriminator hooks: Cursor IDE executes zero hooks when a WSL repo is opened via a
\\wsl$UNC path (agent runs, transcript saves, not one hook fires, no log mention — Cursor's own dialog marks the mode "not recommended"). In WSL-remote mode ("Reopen Folder in WSL") the same repo's hooks execute inside WSL with correct CWD and Entire tracking works end-to-end. There is no CLI-side fix for UNC mode — nothing invokes us — so this PR makes the silent failure visible:cursor.DetectUNCProjectDirsfinds the Windows-side fingerprint from inside WSL:~/.cursor/projects/wsl[-localhost]-<distro>-<sanitized repo path>/dirs (both UNC spellings, case-insensitive, distro sanitized like the path —Ubuntu-22.04→Ubuntu-22-04) that carry a non-emptyagent-transcripts/with activity in the last 14 days.entire doctorgains a warn-onlycheckCursorUNCMode(gated: WSL env → worktree → cursor hooks installed → scan) telling the user to reopen in WSL. The recency window makes the warning self-clear after a user switches modes.AGENT.mddocuments the WSL-remote vs UNC split and the macOS-verified multi-root findings.Design decisions
/mnt/c/Usersare scanned because the WSL username need not match the Windows one; on shared machines this can warn user A about user B's usage — accepted for a warn-only probe.✓ OKline when healthy: this is an environment probe, not an install-state check; absence of the fingerprint isn't proof of health.DetectUNCProjectDirsreturns the matched paths (not a bool): the tests pin which dirs matched, which caught a real partial-match regression during review.automount.root, drive-letter mappings of\\wsl$.Also fixed along the way
A four-agent review pass on this branch surfaced a pre-existing production bug:
sanitizePathForCursormapped non-alphanumerics per-character while Cursor collapses runs to a single dash, so transcript resolution (GetSessionDir) — and this PR's fingerprint matching — silently missed any repo path with adjacent non-alphanumerics (e.g. anything under a.worktrees/layout). Fixed in the shared sanitizer ([^a-zA-Z0-9]+); all pre-existing sanitizer tests pass unchanged. The same pass added a ±clock-skew tolerance to the evidence window (WSL2 lags the Windows clock after host sleep, which would have suppressed the warning for live UNC sessions).Follow-ups (deliberate, not in this PR)
entire status(+--json): doctor is a command the affected user has no reason to run; status is where they look when "nothing is tracked".status.go'shooks_outdatedpattern is the ready-made home.transcript_pathkeys to the first root) — need a design pass on session-ownership semantics.attach/importdiscovery of the Windows-side transcript dirs.\\wsl$\/\\wsl.localhost\) — this PR's check only fires from inside WSL.Testing
TestDetectUNCProjectDirs(+ versioned-distro case): both UNC spellings, case-insensitivity, browsed-only/different-repo/native-Windows negatives, empty and 30-day-stale evidence negatives, empty-distro and missing-root nil contracts.mise run fmt && mise run lint && mise run test— clean, 9368 tests.🤖 Generated with Claude Code
Note
Cursor Bugbot is generating a summary for commit 92a6482. Configure here.