Two people, two clones, one remote. Share a project's memory through the same remote as the code, watch concurrent writes merge, and see the hook that keeps them in step. Along the way, confirm that personal memory never leaves your machine.
ynm is on your PATH. Prepare the sandbox and a personal store:
rm -rf /tmp/ynm-tutorial
mkdir -p /tmp/ynm-tutorial
export YNM_HOME=/tmp/ynm-tutorial/home
export YNM_USER=tutorial
cd /tmp/ynm-tutorial
ynm init --personalExpected: personal store created at /tmp/ynm-tutorial/home/store.git and nothing else.
The remote is an ordinary bare repository; a forge would do the same job. Alice creates the project and pushes its first commit; Bob clones it:
git init -q --bare -b main /tmp/ynm-tutorial/remote.git
git init -q -b main /tmp/ynm-tutorial/alice
git -C /tmp/ynm-tutorial/alice remote add origin /tmp/ynm-tutorial/remote.git
git -C /tmp/ynm-tutorial/alice -c user.name=alice -c user.email=alice@example.com commit -q --allow-empty -m "first commit"
git -C /tmp/ynm-tutorial/alice push -q -u origin main
git clone -q /tmp/ynm-tutorial/remote.git /tmp/ynm-tutorial/bob
git -C /tmp/ynm-tutorial/bob log --onelineExpected: one commit, <short sha> first commit. Both clones share it, and it is the anchor
their memory attaches to.
cd /tmp/ynm-tutorial/alice
ynm initExpected: an initialised <project path> line, then the anchor, the config path, the
refspecs ynm configured on origin, the hook, and a note that the local wiki and index
directories were excluded in .git/info/exclude. There is no "no remote" note this time, because
origin exists. The commit and memory lines are the same as in tutorial 2. Alice's clone uses no agent client, so there is no client line; an also line
naming clients found on your machine (tutorial 2) may appear, and varies.
initialised <project path>
anchor <40-hex sha> (root-commit)
config <project path>/.ynm/config.json
refspecs +refs/notes/ynm/distributed/*:refs/notes/ynm-remote/origin/distributed/*
hooks <project path>/.git/hooks/pre-push
note added .ynm/wiki/ and .ynm/index/ to .git/info/exclude
also <client names> on this machine but not used here; add one with `ynm client install <name>`
commit .ynm/config.json
the team shares these; commit them so every clone gets the same setup
memory lives in git notes, not in files; `ynm sync` and the pre-push hook share it
next: `ynm remember --type semantic --content "..."` and `ynm doctor`
That one refspec is a fetch. ynm init adds no push refspec: the pre-push hook, below, is the
only thing that pushes notes, so git's own push never races it. Git's own configuration is the
source of truth:
git -C /tmp/ynm-tutorial/alice config --get-all remote.origin.fetch
git -C /tmp/ynm-tutorial/alice config --get-all remote.origin.push || echo "no push refspec"Expected: the fetch lines are the ordinary branch refspec and a second one that brings the remote's distributed memory into a separate namespace, so it can be merged rather than overwritten:
+refs/heads/*:refs/remotes/origin/*
+refs/notes/ynm/distributed/*:refs/notes/ynm-remote/origin/distributed/*
The second command prints only no push refspec: there are no push lines. Only distributed is ever mapped; the
personal level has no refspec at all.
Now Bob:
cd /tmp/ynm-tutorial/bob
ynm initExpected: the same shape as Alice's, with Bob's project path and the same anchor sha: it is the root commit both clones share.
Each person writes a distributed memory. Neither knows about the other's yet:
cd /tmp/ynm-tutorial/alice
ynm remember --type semantic --level distributed --content "Alice: the API listens on port 8080."
cd /tmp/ynm-tutorial/bob
ynm remember --type semantic --level distributed --content "Bob: the worker reads its queue from Redis."Expected: remembered <26-character id> in project, level distributed, namespace common from each.
ynm sync fetches the remote's distributed memory, merges it into yours, and pushes. Alice goes
first:
cd /tmp/ynm-tutorial/alice
ynm syncExpected: nothing to fetch yet, one thing pushed.
project: fetched 0, merged 0, pushed 1, retries 0
Bob's sync has something to fetch, and merges it with what he wrote:
cd /tmp/ynm-tutorial/bob
ynm sync
ynm list --level distributedExpected: project: fetched 1, merged 1, pushed 1, retries 0, then both memories, Bob's and
Alice's:
<id> semantic distributed common Bob: the worker reads its queue from Redis.
<id> semantic distributed common Alice: the API listens on port 8080.
Alice syncs again to collect Bob's:
cd /tmp/ynm-tutorial/alice
ynm sync
ynm list --level distributedExpected: project: fetched 1, merged 1, pushed 0, retries 0, and the same two memories, in
the same order. Nothing is pushed: the remote already has everything Alice now has. The merge never loses a record because memory is an append-only log:
both sides only ever added lines.
Remember something personal in Alice's clone, then sync:
cd /tmp/ynm-tutorial/alice
ynm remember --type semantic --content "Alice: my notes live in the wiki."
ynm sync
git -C /tmp/ynm-tutorial/remote.git for-each-ref --format='%(refname)'Expected: remembered <id> in personal, level personal, namespace user/tutorial, a sync line, and
the remote's refs, only the code branch
and the distributed memory:
refs/heads/main
refs/notes/ynm/distributed/common/semantic/<yyyy-mm>
No personal ref exists on the remote. Sync never touches the personal store unless you
name it with --mount personal.
ynm init installed a hook, so a plain git push syncs memory too. Make a commit and push it
with git tracing on, keeping only the lines that mention the hook:
git -C /tmp/ynm-tutorial/alice -c user.name=alice -c user.email=alice@example.com commit -q --allow-empty -m "second commit"
GIT_TRACE=1 git -C /tmp/ynm-tutorial/alice push 2>&1 | grep "hooks/pre-push"Expected: two trace lines that run .git/hooks/pre-push origin <remote path>. The hook ran
ynm sync --quiet, which prints nothing when it works.
Two things to know about it. It never blocks a push: it ends with exit 0 even if sync fails,
and you can repair with a manual ynm sync. And the push above found nothing new to send; when
a push does carry new distributed memory, the hook publishes it first, then git pushes the branch and
exits 0.
To sync without pushing, set sync.auto to true in ~/.ynm/config.json. The agent's Stop hook
then runs ynm sync --quiet in the background after a turn that left unpushed distributed writes,
at most once per sync.intervalMinutes (see the
configuration reference).
cd /tmp/ynm-tutorial/alice
ynm doctorExpected: every line starts with ok. Among them are distributed fetch refspec, personal refs never pushed: no personal refspecs in remote config,
no personal refs in project repo: ok and pre-push hook. The two mount lines
report "remote":"origin". Any client lines at the end are agent clients found on your
machine, each saying ynm not registered: ynm init configured none in Alice's clone.
cd /tmp
rm -rf /tmp/ynm-tutorial
unset YNM_HOME YNM_USERNext: tutorial 7, connecting an agent, where an MCP client gets the same memory.