Skip to content

feat(memsync): key memory sync by project fingerprint, not local path#5

Open
mja00 wants to merge 1 commit into
MarimerLLC:mainfrom
mja00:feat/fingerprint-keyed-sync
Open

feat(memsync): key memory sync by project fingerprint, not local path#5
mja00 wants to merge 1 commit into
MarimerLLC:mainfrom
mja00:feat/fingerprint-keyed-sync

Conversation

@mja00

@mja00 mja00 commented Jul 13, 2026

Copy link
Copy Markdown

Problem

claude-memsync keyed the sync repo by Claude's per-project directory name, which is the project's absolute path with separators replaced by dashes (-Users-me-code-foo). That name differs per machine, so a repo checked out at /Users/me/code/foo on one machine and /home/me/repos/foo on another was seen as two separate projects and their memories never merged. This was previously documented as the "same paths required" limitation.

Solution

Key the mirror by a machine-independent fingerprint instead of the local path:

  • g-<hash> — normalized origin remote URL (all of git@github.com:Acme/app.git, https://github.com/acme/app, …/app.git collapse to one key)
  • r-<hash> — git root-commit SHA, when the repo has no remote (with a shallow-clone guard)
  • the dash-encoded path — fallback for non-git dirs (unchanged behavior; only merges across identical paths)

The Claude side stays keyed by its local dir name; a new internal/project package resolves each project's real path from the cwd Claude records in its session transcripts, derives the key, and keeps a per-PC ~/.claudesync/.state/index.json (gitignored) mapping localHash ↔ key. Reconcile/copy/remove and inbound propagation are now key-addressed. Projects synced from another machine but not yet opened locally materialize lazily on first open.

Migration: the first run after upgrading auto-migrates existing path-keyed mirror dirs to fingerprint keys, union-merging any that collapse to the same key via the existing claude-memmerge driver. Both machines must be upgraded for a project's divergent histories to converge. This is a pre-1.0 on-disk layout change → minor version bump.

Also: the foreground run daemon now logs startup and sync activity — previously it was silent, which read as a hang.

Verification

  • go build ./... && go vet ./... && gofmt -l . && go test ./... all clean
  • New unit tests: URL normalization, fingerprint tiering (remote/root/path incl. clone + shallow), cwd extraction, index round-trip, cross-path union reconcile, migration idempotency
  • End-to-end with a bare-repo remote: two "machines" at different paths but the same repo converge to one g- key with a unioned MEMORY.md; a legacy path-keyed remote dir migrates and merges on upgrade

Mirror directories are now keyed by a machine-independent fingerprint
(normalized git remote URL, then root-commit SHA, then the path fallback for
non-git dirs) instead of Claude's path-derived directory name, so the same repo
checked out at different paths on different machines syncs and merges. Real
project paths are recovered from the cwd in Claude's session transcripts, and a
per-PC .state/index.json maps localHash to key. Legacy path-keyed layouts
auto-migrate on upgrade, union-merging collisions. The foreground daemon now
logs startup and sync activity so it no longer looks hung.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant