You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[bug] Sessions and dashboard ignore a relocated Cursor CLI or Muse data dir #1138
Follow-up to #725 and #939, which made Claude Code and Codex relocatable through the recorded toolRoots. #1135 extends that to their session stores. Other tools can also move their data, and TeamAI still reads their default paths.
What moves and what TeamAI reads
Tool
What moves its data
What TeamAI reads
Effect
Cursor CLI
CURSOR_DATA_DIR: transcripts under <dir>/projects (seen in cursor-agent 2026.09.28)
~/.cursor/projects (getCursorProjectsDir in src/session-flow/fs.ts)
session migrate does not find the transcripts, and copies land where Cursor does not look
Muse Code
XDG_DATA_HOME: sessions under $XDG_DATA_HOME/muse (seen in muse 1.4.6)
Not checked: none is installed where I looked. If a Claude Code or Codex fork reads CLAUDE_CONFIG_DIR or CODEX_HOME, its sessions are not found either
Why this is not a one-line change
A tool joins RELOCATABLE_TOOLS (src/types.ts) only after every TeamAI write for that tool follows the recorded root, so a partial move does not split its files in two places. Cursor uses two variables (CURSOR_CONFIG_DIR for configuration and CURSOR_DATA_DIR for project data), so adding it needs an audit of both, not a path change. Muse touches the dashboard collector, not session-flow.
Proposal
Cursor CLI: record CURSOR_DATA_DIR at teamai init the way toolRoots records CLAUDE_CONFIG_DIR, audit every Cursor read and write, then add it to RELOCATABLE_TOOLS.
Muse: read the sessions under $XDG_DATA_HOME/muse when it is set, recorded the same way so hooks without the variable agree.
Cursor IDE on Linux: confirm whether it honors XDG_CONFIG_HOME; if it does, resolve cursor-store the way ide-history does.
The forks: check which variable each one reads before changing anything.
Item 1 (Cursor CLI).getCursorProjectsDir() in src/session-flow/fs.ts:75 resolves ~/.cursor/projects with no argument. I'd give it a toolRoots? parameter the same way getClaudeCodeProjectsDir / getCodexSessionsDir received one in feat(session): safe session reads and copies for workflows, drivers, scorers, and benchmarks (#593 follow-up) #1135, add the spec to RELOCATABLE_TOOLS, and forward toolRoots from the cursor factory in adapters/index.ts. Then audit every Cursor read/write before it joins the allowlist, per the note in types.ts.
Item 3 (Cursor IDE on Linux).cursor-store.ts resolves ~/.config/Cursor from a bare homedir(). ide-history.ts already reads XDG_CONFIG_HOME ?? path.join(home, '.config') for the same class of path, so I'd follow that existing pattern instead of adding a second one.
RELOCATABLE_TOOLS (src/types.ts:2347) still has exactly two entries: claude-code → CLAUDE_CONFIG_DIR, codex → CODEX_HOME.
ADAPTER_REGISTRY (src/session-flow/adapters/index.ts:28) registers 11 platforms. AdapterFactory is typed (toolRoots?: LocalConfig['toolRoots']) => AgentAdapter, but only claude-code and codex forward the argument — the other nine (including cursor) are zero-arg factories.
fs.ts has nine get*Dir() helpers; only two take toolRoots?. getCursorProjectsDir() (:75) takes none.
No open PR touches session-flow/fs.ts, session-flow/adapters/cursor.ts, or session-flow/cursor-store.ts.
Item 2 is already taken by #1142. For item 4 I can't check the forks from outside — I have no way to see which variable any of them reads.
One thing I need confirmed before writing code. The "Why this is not a one-line change" section says: "Cursor uses two variables (CURSOR_CONFIG_DIR for configuration and CURSOR_DATA_DIR for project data)." But the table above lists only CURSOR_DATA_DIR, and searching main for literal env-var names turns up only CLAUDE_CONFIG_DIR and CODEX_HOME — CURSOR_CONFIG_DIR appears nowhere else in the tree. Is CURSOR_CONFIG_DIR a variable cursor-agent actually reads (i.e. item 1 has to audit two variables, not one), and does it also apply to Cursor IDE on Linux — or should item 3 still key off XDG_CONFIG_HOME?
CURSOR_CONFIG_DIR is real, and it changes the scope of item 1. I read it in the cursor-agent 2026.09.28 bundle (cursor-config/dist/paths.js). The CLI resolves two directories:
CURSOR_DATA_DIR (also set by --data-dir), else ~/.cursor
projects/ (the transcripts)
The user mcp.json, rules/ and commands/ stay hard-coded to ~/.cursor in that version, whatever these variables say.
For TeamAI this means:
Session-flow only reads transcripts, so getCursorProjectsDir follows the data root (CURSOR_DATA_DIR).
TeamAI also writes ~/.cursor/cli-config.json (src/coauthor-reconcile.ts:164, the co-author setting). The CLI reads that file from the config root. So with only XDG_CONFIG_HOME set, the CLI already reads $XDG_CONFIG_HOME/cursor/cli-config.json and TeamAI's write misses it. RELOCATABLE_TOOLS requires every write for a tool to follow its root. So Cursor needs both roots recorded at init (data and config, the config one with the XDG_CONFIG_HOME fallback), and the co-author target has to follow the config root. That is the two-variable audit the issue meant. The table missed the XDG_CONFIG_HOME fallback, sorry about that.
mcp.json, rules and commands keep their ~/.cursor paths.
Item 3: no, CURSOR_CONFIG_DIR does not apply to the IDE. Neither CURSOR_ variable appears in the IDE's own code (Cursor 3.16.29, out/). It shows up only in its bundled agent extensions. The IDE resolves its user data through the VS Code path logic (userDataPath.js): VSCODE_PORTABLE, then VSCODE_APPDATA, then --user-data-dir, and on Linux $XDG_CONFIG_HOME or ~/.config, joined with Cursor. So keying cursor-store off XDG_CONFIG_HOME, the way ide-history.ts does, is right. I read that from the macOS build, which ships the same Linux branch. I have not run it on Linux.
These are internals of a closed-source bundle. If a newer cursor-agent resolves differently, please note the version you checked in the PR.
Mechanism first, because it changes the fix's shape: readMuseSessionTokens has exactly one caller — the stop-hook branch of parseHookEvent (dashboard-collector.ts:1346) — so the reader runs inside muse's own hook process, inheriting muse's environment. Tokens are stamped onto the event at that moment, and the dashboard only replays the stamped events; nothing re-reads the muse tree from the server. That means a live $XDG_DATA_HOME read is sufficient — no toolRoots recording needed, the same resolution the OpenCode adapter already uses (session-flow/adapters/opencode.ts:305): root = ${XDG_DATA_HOME:-~/.local/share}/muse/sessions. Recording would only matter if a reader without the variable had to find the tree, and there is no such reader today (that's also why Muse never needed the RELOCATABLE_TOOLS write audit — TeamAI only ever reads it).
Red test first, then the one-line resolution change in findMuseSessionLog.
Scope. Item 1 registers the two roots Cursor CLI actually moves — cursor-data for CURSOR_DATA_DIR, cursor-config for CURSOR_CONFIG_DIR — and makes the transcript store and the cli-config.json write follow them, which is the widened scope you described. Item 3 makes session-flow/cursor-store.ts resolve the IDE user-data dir the way VS Code does ($XDG_CONFIG_HOME, else ~/.config, joined with Cursor) instead of hard-coding ~/.config/Cursor.
Versions read, as you asked: cursor-agent 2026.09.28 bundle (cursor-config/dist/paths.js) and Cursor IDE 3.16.29. Both are stated in the PR description.
State. 16 files, +594/-39, based on c57da5af. On d4990e12: Lint & Test green on ubuntu and macOS at Node 20/22/24, E2E (fork-safe, no credentials) green, and Codex PR Review reports no new findings.
Item 2 (Muse) is @kittimzhe's — that diff and this one do not overlap.
Activity
Smilewithoutfalling commentedon Oct 15, 2026
I'd like to take the two Cursor entries.
Scope I'd claim — items 1 and 3.
getCursorProjectsDir()insrc/session-flow/fs.ts:75resolves~/.cursor/projectswith no argument. I'd give it atoolRoots?parameter the same waygetClaudeCodeProjectsDir/getCodexSessionsDirreceived one in feat(session): safe session reads and copies for workflows, drivers, scorers, and benchmarks (#593 follow-up) #1135, add the spec toRELOCATABLE_TOOLS, and forwardtoolRootsfrom thecursorfactory inadapters/index.ts. Then audit every Cursor read/write before it joins the allowlist, per the note intypes.ts.cursor-store.tsresolves~/.config/Cursorfrom a barehomedir().ide-history.tsalready readsXDG_CONFIG_HOME ?? path.join(home, '.config')for the same class of path, so I'd follow that existing pattern instead of adding a second one.Checked on main
987a7466(after #1135 landed):RELOCATABLE_TOOLS(src/types.ts:2347) still has exactly two entries:claude-code→CLAUDE_CONFIG_DIR,codex→CODEX_HOME.ADAPTER_REGISTRY(src/session-flow/adapters/index.ts:28) registers 11 platforms.AdapterFactoryis typed(toolRoots?: LocalConfig['toolRoots']) => AgentAdapter, but onlyclaude-codeandcodexforward the argument — the other nine (includingcursor) are zero-arg factories.fs.tshas nineget*Dir()helpers; only two taketoolRoots?.getCursorProjectsDir()(:75) takes none.session-flow/fs.ts,session-flow/adapters/cursor.ts, orsession-flow/cursor-store.ts.Item 2 is already taken by #1142. For item 4 I can't check the forks from outside — I have no way to see which variable any of them reads.
One thing I need confirmed before writing code. The "Why this is not a one-line change" section says: "Cursor uses two variables (
CURSOR_CONFIG_DIRfor configuration andCURSOR_DATA_DIRfor project data)." But the table above lists onlyCURSOR_DATA_DIR, and searching main for literal env-var names turns up onlyCLAUDE_CONFIG_DIRandCODEX_HOME—CURSOR_CONFIG_DIRappears nowhere else in the tree. IsCURSOR_CONFIG_DIRa variable cursor-agent actually reads (i.e. item 1 has to audit two variables, not one), and does it also apply to Cursor IDE on Linux — or should item 3 still key offXDG_CONFIG_HOME?SaulMoro commentedon Oct 15, 2026
Thanks. Items 1 and 3 are yours.
CURSOR_CONFIG_DIRis real, and it changes the scope of item 1. I read it in the cursor-agent 2026.09.28 bundle (cursor-config/dist/paths.js). The CLI resolves two directories:CURSOR_CONFIG_DIR, else$XDG_CONFIG_HOME/cursor, else~/.cursorcli-config.json,permissions.json,chats/,acp-sessions/,acp-config.jsonCURSOR_DATA_DIR(also set by--data-dir), else~/.cursorprojects/(the transcripts)The user
mcp.json,rules/andcommands/stay hard-coded to~/.cursorin that version, whatever these variables say.For TeamAI this means:
getCursorProjectsDirfollows the data root (CURSOR_DATA_DIR).~/.cursor/cli-config.json(src/coauthor-reconcile.ts:164, the co-author setting). The CLI reads that file from the config root. So with onlyXDG_CONFIG_HOMEset, the CLI already reads$XDG_CONFIG_HOME/cursor/cli-config.jsonand TeamAI's write misses it.RELOCATABLE_TOOLSrequires every write for a tool to follow its root. So Cursor needs both roots recorded at init (data and config, the config one with theXDG_CONFIG_HOMEfallback), and the co-author target has to follow the config root. That is the two-variable audit the issue meant. The table missed theXDG_CONFIG_HOMEfallback, sorry about that.mcp.json, rules and commands keep their~/.cursorpaths.Item 3: no,
CURSOR_CONFIG_DIRdoes not apply to the IDE. NeitherCURSOR_variable appears in the IDE's own code (Cursor 3.16.29,out/). It shows up only in its bundled agent extensions. The IDE resolves its user data through the VS Code path logic (userDataPath.js):VSCODE_PORTABLE, thenVSCODE_APPDATA, then--user-data-dir, and on Linux$XDG_CONFIG_HOMEor~/.config, joined withCursor. So keyingcursor-storeoffXDG_CONFIG_HOME, the wayide-history.tsdoes, is right. I read that from the macOS build, which ships the same Linux branch. I have not run it on Linux.These are internals of a closed-source bundle. If a newer cursor-agent resolves differently, please note the version you checked in the PR.
kittimzhe commentedon Oct 16, 2026
Taking item 2 (Muse).
Mechanism first, because it changes the fix's shape:
readMuseSessionTokenshas exactly one caller — thestop-hook branch ofparseHookEvent(dashboard-collector.ts:1346) — so the reader runs inside muse's own hook process, inheriting muse's environment. Tokens are stamped onto the event at that moment, and the dashboard only replays the stamped events; nothing re-reads the muse tree from the server. That means a live$XDG_DATA_HOMEread is sufficient — notoolRootsrecording needed, the same resolution the OpenCode adapter already uses (session-flow/adapters/opencode.ts:305): root =${XDG_DATA_HOME:-~/.local/share}/muse/sessions. Recording would only matter if a reader without the variable had to find the tree, and there is no such reader today (that's also why Muse never needed the RELOCATABLE_TOOLS write audit — TeamAI only ever reads it).Red test first, then the one-line resolution change in
findMuseSessionLog.fix(session): honor Cursor CLI's two recorded tool roots
Smilewithoutfalling commentedon Oct 16, 2026
Delivered as #1165 — items 1 and 3 of this issue.
Scope. Item 1 registers the two roots Cursor CLI actually moves —
cursor-dataforCURSOR_DATA_DIR,cursor-configforCURSOR_CONFIG_DIR— and makes the transcript store and thecli-config.jsonwrite follow them, which is the widened scope you described. Item 3 makessession-flow/cursor-store.tsresolve the IDE user-data dir the way VS Code does ($XDG_CONFIG_HOME, else~/.config, joined withCursor) instead of hard-coding~/.config/Cursor.Versions read, as you asked: cursor-agent
2026.09.28bundle (cursor-config/dist/paths.js) and Cursor IDE3.16.29. Both are stated in the PR description.State. 16 files,
+594/-39, based onc57da5af. Ond4990e12:Lint & Testgreen on ubuntu and macOS at Node 20/22/24,E2E (fork-safe, no credentials)green, andCodex PR Reviewreports no new findings.Item 2 (Muse) is @kittimzhe's — that diff and this one do not overlap.
fix(dashboard): find Muse session logs under $XDG_DATA_HOME (#1138 it…
STiFLeR7 commentedon Oct 19, 2026
All three items here are merged:
CURSOR_DATA_DIR/CURSOR_CONFIG_DIR) and item 3 (the related widened scope) — fix(session): honor Cursor CLI's two recorded tool roots #1165$XDG_DATA_HOME) — fix(dashboard): find Muse session logs under $XDG_DATA_HOME (#1138 item 2) #1168Closing as fully resolved. (Triage access only — closing based on the linked merged PRs, no code changes from me.)