Feature request: path-independent project identity + memory sync across machines

Status Open
Maintainer reply None cached
Activity 4 comments · opened Oct 12, 2026

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 real C:\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

  1. Project identity independent of path. On first use, store a stable project ID in the project folder (e.g. .claude/project.json with 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.
  2. 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.
  3. 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

View original on GitHub ↗

4 Comments

John-Rood · 3 days ago

Point 3 is already shipped: autoMemoryDirectory does 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.

{ "autoMemoryDirectory": "~/OneDrive/Code/firmware/memory" }

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. While permissions.blockReadsOutsideWorkingDirectories is 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.

atopcu · 2 days ago

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:

  • Session history is still keyed by the path, so sessions started on one machine can’t be seen or resumed on the other. Even with shared memory, there’s no continuity between conversations across machines.
  • Project identity still depends on the path, so the same folder opened through a symlink counts as a different project for transcripts.

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.

John-Rood · 2 days ago

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.

bellowsai · 2 days ago

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.

  • After every turn Bellows writes a line to .bellows/memory.md in the project: which agent, what you asked, which files changed, whether the last test run passed, what it cost.
  • When you close a session, the agent writes a handover into the same file: where things stand, what's next, the decisions made and the gotchas.
  • Every new session starts from that memory, whichever machine, whichever path you opened the folder by, and whichever agent you pick. Your home PC and office PC read the same decisions.
  • In a git project Bellows asks once whether to share the memory through git or keep it on your machine, so keeping two PCs in step is a commit, not a junction per machine.
  • The log is written by Bellows itself, with no model call and no cost. Keys and tokens are stripped before anything is written.

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.