Team workflows: sharing memory via git
The whole point of repo.ttl is that memory becomes a team asset — captured once by whoever learns it, available to every teammate and every AI agent forever.
The happy path
- Someone runs
fluree memory initin the repo and commits.fluree-memory/(minus the gitignored.local/). - Teammates pull and run
fluree memory initonce. The init picks up the committedrepo.ttland populates the ledger from it. No manual import. - As people add memories,
.fluree-memory/repo.ttlchanges in the working tree. Commit it like any other file. - Pulls bring in new memories automatically —
fluree memory recall(and the MCP server) read the ledger, which stays in sync with the TTL file.
That's it. No server, no sync daemon, no API tokens. Git is the sync mechanism.
What to commit
✅ Commit:
.fluree-memory/repo.ttl.fluree-memory/.gitignore- Any IDE config MCP-install created:
.cursor/mcp.json,.cursor/rules/fluree_rules.md,.vscode/mcp.json,.vscode/fluree_rules.md,.zed/settings.json
❌ Don't commit:
.fluree-memory/.local/user.ttl— your personal memories (handled by.fluree-memory/.gitignore).fluree-memory/.local/mcp.log— noisy and personal (handled by.fluree-memory/.gitignore).fluree/— the Fluree storage dir, can be re-hydrated fromrepo.ttl(add this to your project's root.gitignore—.fluree-memory/.gitignoreonly covers its own subtree)
Reviewing memory in PRs
Treat repo.ttl changes like documentation changes in code review:
- New memory? Is the kind right? Is the wording accurate? Are the tags useful?
- Updated memory? Is the new content better (not just different)?
- Forgot memory? Was that really wrong, or should it have been updated instead?
Memories are serialized as subject blocks with one predicate per line, so most diffs are readable.
Merge conflicts
Memories in repo.ttl are sorted by (branch, id) — memories from the same git branch cluster together, and different branches land in different regions of the file. This means two feature branches that each add memories will almost never conflict, because their blocks insert at different positions in the file.
The branch name is captured automatically when a memory is created, so memories from feature/auth sort separately from memories created on feature/indexer. Within each branch group, memories are ordered chronologically (ULID encodes creation time).
When conflicts do occur, they're usually because two branches modified the same existing memory (via update) or both worked on the same branch. These are typically clean to resolve:
<<<<<<< HEAD
mem:fact-01JD... a mem:Fact ;
mem:content "Tests use cargo nextest" ;
mem:tag "cargo" ;
mem:tag "testing" ;
...
=======
mem:fact-01JD... a mem:Fact ;
mem:content "Tests use cargo nextest with --no-fail-fast" ;
mem:tag "testing" ;
...
>>>>>>> their-branch
Pick the version you want or combine them, then re-run fluree memory status to make sure the store parses cleanly. If the merged file is genuinely messy, a cleaner path is to accept one side wholesale and then apply the other side's changes via fluree memory add / update on top.
Onboarding a new teammate
When someone new clones the repo:
git clone git@github.com:team/project
cd project
fluree memory init
After init, they can immediately:
fluree memory recall "testing" -n 10
…and get everything the team has captured. No setup beyond installing fluree.
Going further
- Keep PR review short by tagging memories with their domain (
auth,indexer,docs, etc.) so reviewers can filter. - Use
constraint --severity mustsparingly — they're the "policy layer" of memory. Prefershouldorpreferfor taste. - Periodically
fluree memory statusand prune stale memories withforget. The store should feel curated, not a dumping ground.