Feature request: path-independent project identity + memory sync across machines
Problem
Claude Code identifies a project by its filesystem path (~/.claude/projects/<path-slug>/). Memory and session history are stored under that slug, and they stay on the local machine. Because of this, the same project looks like several unrelated projects when:
- the user works on it from more than one computer (e.g. home and office), even if the project folder itself is synced (OneDrive, Dropbox, git);
- the same folder is opened through different paths on one machine (e.g. a symlink
C:\Projects\...vs. the realC:\Users\me\OneDrive - Org\...\project).
Real-world impact
I work on one embedded firmware project from two PCs. A design decision was changed in a session on one machine. A session on the other machine still had the old decision in its memory and confidently recommended an implementation based on it. Nothing in either session showed that they had diverged.
Current workaround
I moved memory into the repo (<repo>/.claude/memory/, synced by OneDrive) and replaced the local ~/.claude/projects/<slug>/memory with a directory junction pointing to it. This works, but it has to be done by hand on every machine and for every path the project is opened from. OneDrive can also create conflict copies when both machines write at the same time.
Proposal
- Project identity independent of path. On first use, store a stable project ID in the project folder (e.g.
.claude/project.jsonwith a UUID). If the file is missing, fall back to the git remote URL. Key memory and history by this ID instead of the path slug. Then any path or machine that sees the same folder resolves to the same project. - Optional cloud sync of project memory (and optionally session history) keyed by that ID, tied to the user's account, so the same project shares memory across machines without manual junctions.
- Until then, a simpler step would help a lot: a setting to choose the memory directory (e.g.
memoryDirectory: ".claude/memory"relative to the project), so it can live inside a synced or versioned folder.
Environment
- Claude Code (VS Code extension), Windows 11
- Project folder synced via OneDrive; also opened through a symlink path
4 Comments
Point 3 is already shipped:
autoMemoryDirectorydoes the choosing, with one constraint that rules out the exact form you proposed.The value must be an absolute path or start with
~/(https://code.claude.com/docs/en/memory). The repo-relative form (.claude/memory) is dropped, and you silently get the default back; I verified that on 2.1.292 and 2.1.296. The portable shape for two machines is a~/path into the folder you already sync, because each machine resolves it against its own local copy of that folder.Where it can live, all three tested on both builds:
~/.claude/settings.json(user scope): always applied, no trust gate. It covers every project on the machine, so it works as a fallback value or for one shared pool, not for scoping memory to a single repo..claude/settings.local.json(project, not checked in): applied for that project once the folder is trusted..claude/settings.json(checked in): same trust gate, travels with the repo. Whilepermissions.blockReadsOutsideWorkingDirectoriesis on, a repository-supplied value is not used at all. Both conditions are in the docs.When more than one scope sets it, my runs resolved local, then project, then user, so a user-level fallback with per-project overrides behaves the way you would expect.
Why this fixes your failure: the default memory directory is keyed to where the project sits on disk. Running from a repo subdirectory, my memory still resolved under the repo root's folder, while the transcripts keyed off the subdirectory. Your two PCs and your junction path each resolve to a different folder, which is how the two memories diverged with nothing showing it. A fixed directory removes the path from the memory equation and makes the per-machine, per-path junctions unnecessary.
Once, after switching: move the files (
mv ~/.claude/projects/<old-slug>/memory/* <new-dir>/) and start a fresh session rather than--continue, because a resumed conversation can keep naming the old path while the index loads from the new one (#101500). Simultaneous writes from both machines still produce sync-tool conflict copies; the setting does not add locking.What it does not cover: your items 1 and 2. Session history and project identity still key off the path, so two machines still produce two transcripts and two conversation histories. The memory directory converges today; identity does not yet.
Thanks, this is very helpful. I had missed autoMemoryDirectory. I’m replacing my per-machine junctions with a ~/-based path in the project’s .claude/settings.json, which already syncs between my machines through the project folder. That takes care of point 3.
One small follow-up on point 3: since a relative value is silently dropped and the default comes back, a warning (or a /doctor check) for an invalid autoMemoryDirectory would save others from thinking their memory is shared when it isn’t.
I’d like to keep this issue open for points 1 and 2, because the main gap is still there:
A stable project ID stored in the folder (or derived from the git remote), with history keyed by it and optional account-level sync, would close both gaps.
There's no check that catches it today. The value isn't validated when settings load; it's evaluated when the memory directory resolves for a session, and anything that fails the absolute-path rule (after
~/expansion) is dropped right there with the default coming back, no warning on that path.Doctor is silent on it as well: it parses and validates settings files (a malformed settings.json gets reported), but an invalid autoMemoryDirectory passes, verified on 2.1.292.
So the check you're describing is net-new, and doctor is the right home for it since it reads settings without the trust prompt.
Disclosure: I'm Rob, and I built this.
Bellows keeps project memory exactly where you ended up putting yours: in the repo. It's a desktop app (Windows, macOS, Linux) that runs Claude, Codex, Gemini CLI and any ACP agent, and the memory belongs to the project rather than to a path on one machine.
.bellows/memory.mdin the project: which agent, what you asked, which files changed, whether the last test run passed, what it cost.How it works: https://bellowsai.app/guides/project-memory-for-coding-agents?utm_source=github&utm_medium=reply
Give it a try and tell me what would make it fit your setup. We act fast on feedback: session hand-over was asked for on this tracker on 2 October and shipped in Bellows on 8 October.