Repository navigation
fix(cursor): deliver user-scope rules to workspaces outside the home directory (#1197) - #1198
Merged
jeff-r2026 merged 6 commits intoOct 17, 2026
Merged
Conversation
…directory (Tencent#1197) Cursor loads ~/.cursor/rules only by walking up from the workspace, so a workspace outside the home directory never got the user-scope rules while doctor reported them delivered. The sessionStart hook now adds them there, and doctor checks that hook.
… Windows workspace roots Cursor caps a hook reply at 10,000 characters and drops all of it when over, so the dispatcher now leaves the user-scope rules out when the merged reply would not fit, keeping the other session-start hints. The Cursor IDE sends each workspace root as a URI path (/c:/...), which no path API resolves on Windows; resolveHookCwd now drops the slash. Doctor names the real next step for invalid JSON, a team-disabled session-start built-in, and a dispatch for another tool.
… in doctor Doctor now fails past 9,000 characters, where the session's own hints can push the rules out of Cursor's 10,000-character reply. The dispatcher leaves the rules out only when the rest then fits. Doctor reads the --tool value whole and orders its causes: invalid JSON, a missing hook (naming a team builtin.disabled entry), then length.
…f a fixed headroom The rules check fails only past Cursor's real 10,000-character limit. An informational check measures the rules together with the team env hint, which shares every session's reply, using the hint handler itself, so it flags exactly the case where the dispatcher leaves the rules out.
jeff-r2026
approved these changes
Oct 17, 2026
|
No confident findings in the specified PR diff. The description documents sufficient testing: a representative real-CLI run covers user-scope initialization, pull, hook dispatch, and doctor checks. The disclosed Windows, live-Cursor, and extra-provider/agent limitations are not blocking under the review rules. No PR code was run, built, or installed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1197
Summary
Cursor never loaded the user-scope team rules in a workspace outside the home directory, and
doctorstill reported them delivered. Cursor (IDE and CLI) has no direct read of~/.cursor/rules.LocalCursorRulesService.loadRulesFromDirAndAncestorswalks up from the workspace root and loads<ancestor>/.cursor/rulesat each step, so the home copy loads only when$HOMEis an ancestor. On Windows, repositories underC:\WorkorD:\srcare common.The fix keeps the file for workspaces under home and uses the sessionStart hook teamai already installs in
~/.cursor/hooks.jsonfor the rest:cursor-user-rulesis a new session-start handler. It compares the canonical path of each<ancestor>/.cursor/ruleswith the user rules directory. A junction or symlink on the walk (the workaround in the report) therefore counts as reached, and the rules do not arrive twice. In a teamai project outside home it loads the user scope separately, since the project delivers its own rules into the workspace.additional_contextand drops the whole reply when over (verified in the bundle, counted as the trimmed text's.length). The dispatcher now leaves the rules out when the merged session-start reply would not fit and the rest then does. The env, MR and package hints still arrive. The MR and package hints are claimed once, so they keep priority over the rules, which come back every session.resolveHookCwdturns Cursor's/c:/...workspace roots intoc:/.... The IDE sendsfolders.map((f) => f.uri.path), which no path API resolves on Windows. Before this, a Windows Cursor hook could notchdirinto its workspace or find its project scope.doctor(user scope) gains two checks. "Team rules reach Cursor workspaces outside the home directory" passes when the hook is registered for--tool cursorand the rules fit the limit. Its fix text names the real cause: invalid JSON (repair by hand), a missing hook (naming a teambuiltin.disabledentry when there is one), or length. "Team rules and the team env hint fit one Cursor hook reply" is informational. It runs the env hint handler itself and flags the case where the dispatcher would keep the hint and drop the rules.Evidence
Unit tests: the handler through the hook registry (outside home, under home, a link on the walk, a project outside home, excluded tool, over the limit), the dispatcher guard, the
/c:/root, and the doctor checks. Each was observed failing before its implementation.npx tsc --noEmit,npm run lintandnpx vitest runpass (10859 passed, 21 skipped).Real CLI with an isolated
HOME, a local bare remote (gitprovider),init --scope user --agent cursorandpull. The steps dispatch Cursor's sessionStart payload (workspace_roots) for a workspace under home and one outside it, then rundoctor:mainat fe3b906):~/.cursor/hooks.json:✖ Team rules reach Cursor workspaces outside the home directory → ... registers no teamai sessionStart hook for Cursor, so those workspaces get none of them. Run teamai hooks inject to rewrite it.✖ Team rules and the team env hint fit one Cursor hook reply(10,208 characters), and the dispatched reply holds only the env hint (length=1246). Rules of 9,500 characters plus one variable: both checks pass, and the reply holds the rules and the hint (length=9818).Not checked here:
hookSpecificOutput.additionalContext) is the one teamai's other Cursor hints already use, and the IDE and CLI bundles enable Claude-nested output compatibility. I did not observe it in a live session./c:/roots and junctions are covered by reading Cursor's source and by POSIX tests only. CI has no Windows runner.sourcefield, and a guard on a missing field would drop the rules on a real start.Only the
gitprovider and the Cursor agent ran locally. CI coversgitlab/githuband the other agents.Merge Danger
Door: two-way
Nothing is written to disk by the new handler. A revert removes the hook text and the doctor checks.
One observable shift on Windows: Cursor IDE hook events record
cwdasc:/...instead of/c:/..., so session ids derived from the cwd (hosts that send no conversation id) and recorded dashboardcwdvalues change at the upgrade. The old values pointed at a path that did not exist.