Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion src/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,37 @@ const CURSOR_WORKSPACE_STORAGE = path.join(CURSOR_APP_DATA, 'User', 'workspaceSt
const HISTORY_FILE = path.join(CLAUDE_DIR, 'history.jsonl');
const PROJECTS_DIR = path.join(CLAUDE_DIR, 'projects');

// Scan Claude desktop app's local-agent-mode-sessions for embedded .claude dirs
// Structure: ~/Library/Application Support/Claude/local-agent-mode-sessions/<id>/<id>/local_<id>/.claude/
function detectLocalAgentModeClaudeDirs() {
const result = [];
if (process.platform !== 'darwin') return result;
const baseDir = path.join(ALL_HOMES[0], 'Library', 'Application Support', 'Claude', 'local-agent-mode-sessions');
if (!fs.existsSync(baseDir)) return result;
try {
for (const a of fs.readdirSync(baseDir)) {
const aDir = path.join(baseDir, a);
if (!fs.statSync(aDir).isDirectory()) continue;
for (const b of fs.readdirSync(aDir)) {
const bDir = path.join(aDir, b);
if (!fs.statSync(bDir).isDirectory()) continue;
for (const c of fs.readdirSync(bDir)) {
const cDir = path.join(bDir, c);
if (!fs.statSync(cDir).isDirectory()) continue;
const claudeDir = path.join(cDir, '.claude');
if (fs.existsSync(claudeDir)) result.push(claudeDir);
}
}
}
} catch {}
return result;
}

// On WSL, collect all alternative data dirs
const EXTRA_CLAUDE_DIRS = ALL_HOMES.slice(1).map(h => path.join(h, '.claude')).filter(d => fs.existsSync(d));
const EXTRA_CLAUDE_DIRS = [
...ALL_HOMES.slice(1).map(h => path.join(h, '.claude')).filter(d => fs.existsSync(d)),
...detectLocalAgentModeClaudeDirs(),
];
const EXTRA_CODEX_DIRS = ALL_HOMES.slice(1).map(h => path.join(h, '.codex')).filter(d => fs.existsSync(d));
const EXTRA_CURSOR_DIRS = ALL_HOMES.slice(1).map(h => path.join(h, '.cursor')).filter(d => fs.existsSync(d));

Expand Down Expand Up @@ -1550,6 +1579,7 @@ const SESSIONS_CACHE_TTL = 60000; // 60 seconds — hot cache, invalidated by fi
let _historyMtime = 0;
let _historySize = 0;
let _projectsDirMtime = 0;
let _projectsSubDirMtimes = {}; // { subDirPath: mtimeMs }

function _sessionsNeedRescan() {
// Check if history.jsonl or projects dir changed since last scan
Expand All @@ -1561,6 +1591,14 @@ function _sessionsNeedRescan() {
if (fs.existsSync(PROJECTS_DIR)) {
const st = fs.statSync(PROJECTS_DIR);
if (st.mtimeMs !== _projectsDirMtime) return true;
// Also check subdirectory mtimes — new sessions in existing project dirs
// don't change PROJECTS_DIR mtime, only their parent subdir mtime
for (const entry of fs.readdirSync(PROJECTS_DIR, { withFileTypes: true })) {
if (!entry.isDirectory()) continue;
const subDir = path.join(PROJECTS_DIR, entry.name);
const subSt = fs.statSync(subDir);
if (subSt.mtimeMs !== (_projectsSubDirMtimes[subDir] || 0)) return true;
}
}
} catch {}
return false;
Expand All @@ -1575,6 +1613,12 @@ function _updateScanMarkers() {
}
if (fs.existsSync(PROJECTS_DIR)) {
_projectsDirMtime = fs.statSync(PROJECTS_DIR).mtimeMs;
_projectsSubDirMtimes = {};
for (const entry of fs.readdirSync(PROJECTS_DIR, { withFileTypes: true })) {
if (!entry.isDirectory()) continue;
const subDir = path.join(PROJECTS_DIR, entry.name);
try { _projectsSubDirMtimes[subDir] = fs.statSync(subDir).mtimeMs; } catch {}
}
}
} catch {}
}
Expand Down
Loading