Version: v7.1.1 (verified against 03a969dd96dc7ff701d92dbc8a8b8d6db4728834)
What happens
ContextSearch builds its transcript-search root from ~/.claude alone, so it only ever looks inside the single project dir that corresponds to ~/.claude. Claude Code writes one project dir per cwd. Any session run in any other directory — i.e. every session run inside a code repo — is invisible to recall, by construction.
Repro (30 seconds)
ls ~/.claude/projects/ # one dir per cwd you've worked in
On this machine that lists 11 dirs. ContextSearch searches exactly one of them.
Run a memorable session inside any code repo, then try to recall it with ContextSearch. It will not be found — not because the ranking missed it, but because the file was never a candidate.
Cause
|
const LIFEOS_DIR = join(HOME, ".claude"); |
|
const STATE_DIR = join(LIFEOS_DIR, "LIFEOS", "MEMORY", "STATE"); |
|
const WORK_DIR = join(LIFEOS_DIR, "LIFEOS", "MEMORY", "WORK"); |
|
// Claude Code names each project dir by its absolute path with "/" and "." mapped to "-", |
|
// e.g. $HOME/.claude -> "-Users-<user>--claude". Derive it from $HOME instead of hardcoding. |
|
const PROJECT_SLUG = LIFEOS_DIR.replace(/[/.]/g, "-"); |
|
const JSONL_DIR = join(LIFEOS_DIR, "Projects", PROJECT_SLUG); |
const LIFEOS_DIR = join(HOME, ".claude");
const PROJECT_SLUG = LIFEOS_DIR.replace(/[/.]/g, "-");
const JSONL_DIR = join(LIFEOS_DIR, "Projects", PROJECT_SLUG);
JSONL_DIR is pinned to the ~/.claude slug. The containment guard in searchJsonl then re-asserts that same single-slug root:
|
if (tokens.length === 0 || !existsSync(JSONL_DIR)) return []; |
|
const realDir = JSONL_DIR; |
|
if (!realDir.startsWith(join(HOME, ".claude", "Projects", PROJECT_SLUG))) return []; |
There is a second, independent consequence at the UUID join:
|
const jsonlPath = join(JSONL_DIR, `${uuid}.jsonl`); |
const jsonlPath = join(JSONL_DIR, `${uuid}.jsonl`);
A transcript actually lives at projects/<cwd-slug>/<uuid>.jsonl, and the slug varies by the cwd the session ran in — so a UUID cannot be joined onto one slug. Once the root is corrected this join must resolve across project dirs, or it breaks.
Fix
Point at the projects root and let ripgrep recurse; resolve UUIDs across project dirs.
const JSONL_DIR = join(HOME, ".claude", "projects");
function findTranscriptByUuid(uuid: string): string | null {
try {
for (const d of readdirSync(JSONL_DIR, { withFileTypes: true })) {
if (!d.isDirectory()) continue;
const p = join(JSONL_DIR, d.name, `${uuid}.jsonl`);
if (existsSync(p)) return p;
}
} catch {}
return null;
}
searchJsonl containment guard becomes realDir.startsWith(join(HOME, ".claude", "projects")) — still contained, now to all cwds rather than one slug.
- The
:243 join becomes findTranscriptByUuid(uuid).
Separately, searchIsaBodies globs *ISA.md only. Native sessions produce a SESSION.md durable record, so the artifact layer indexes Algorithm-mode sessions exclusively. Adding --glob *SESSION.md makes native work findable. Happy to split that into its own issue if you'd rather keep this one to the scope fix.
I have this working locally and will open a PR against main if you want it.
Version: v7.1.1 (verified against
03a969dd96dc7ff701d92dbc8a8b8d6db4728834)What happens
ContextSearchbuilds its transcript-search root from~/.claudealone, so it only ever looks inside the single project dir that corresponds to~/.claude. Claude Code writes one project dir per cwd. Any session run in any other directory — i.e. every session run inside a code repo — is invisible to recall, by construction.Repro (30 seconds)
On this machine that lists 11 dirs. ContextSearch searches exactly one of them.
Run a memorable session inside any code repo, then try to recall it with ContextSearch. It will not be found — not because the ranking missed it, but because the file was never a candidate.
Cause
LifeOS/LifeOS/install/skills/ContextSearch/Tools/ContextSearch.ts
Lines 9 to 15 in 03a969d
JSONL_DIRis pinned to the~/.claudeslug. The containment guard insearchJsonlthen re-asserts that same single-slug root:LifeOS/LifeOS/install/skills/ContextSearch/Tools/ContextSearch.ts
Lines 353 to 355 in 03a969d
There is a second, independent consequence at the UUID join:
LifeOS/LifeOS/install/skills/ContextSearch/Tools/ContextSearch.ts
Line 243 in 03a969d
A transcript actually lives at
projects/<cwd-slug>/<uuid>.jsonl, and the slug varies by the cwd the session ran in — so a UUID cannot be joined onto one slug. Once the root is corrected this join must resolve across project dirs, or it breaks.Fix
Point at the
projectsroot and let ripgrep recurse; resolve UUIDs across project dirs.searchJsonlcontainment guard becomesrealDir.startsWith(join(HOME, ".claude", "projects"))— still contained, now to all cwds rather than one slug.:243join becomesfindTranscriptByUuid(uuid).Separately,
searchIsaBodiesglobs*ISA.mdonly. Native sessions produce aSESSION.mddurable record, so the artifact layer indexes Algorithm-mode sessions exclusively. Adding--glob *SESSION.mdmakes native work findable. Happy to split that into its own issue if you'd rather keep this one to the scope fix.I have this working locally and will open a PR against
mainif you want it.