What a team memory is
Claude Code keeps notes as it works: the commands that pass a build, the rule a reviewer gave last week, where a service is deployed. It writes each note as a small Markdown file in a memory/ folder and reads the index, MEMORY.md, at the start of every session. On its own, that folder lives on one computer. A colleague, or your own second laptop, starts from nothing.
A team memory is that folder kept in SystemDox, one per project, and synced file by file to every computer that works on the project. Each checkout points Claude Code at the synced folder with Claude Code’s own autoMemoryDirectory setting, so every session on every computer reads and writes the same notes.
The folder on your computer is ~/.claude/systemdox/<workspace>/memory/<project>/. Nothing about how Claude Code writes memory changes: it simply writes there.
Set up a computer
First, a key that can sync. In the console, open Settings › API keys and press Key for Claude Code team setup. It fills in the access a team memory needs: Developer, on all spaces, allowed to change content. A key made with the form’s defaults is a Reader key, which reads the team setup but cannot sync. Make one key per computer, named after it, so revoking one leaves the others working.
Then run one command in your own terminal, in the folder where you start Claude Code for the project. It asks for the key first, and the key is not shown as you paste it. On a computer that already has one, press Enter to keep it: running setup again never needs a new key, and it does not ask again for the API URL or your AI tools. To change those, add –choose.
npx -y @systemdox/mcp-server setupIt first shows you everything it will add, and changes nothing until you answer y: the team plugin with every hook command written out, the team instructions, each team memory with its file count, and the autoMemoryDirectory it will set in <checkout>/.claude/settings.local.json. Then it makes the project’s first sync on this computer.
The workspace’s first team memory needs a name. When your workspace has no team memory yet, setup asks you to name one for this checkout, for example after your company or the project. Press Enter to skip it. You can also give the name on the command line with –project. Every later computer finds the only team memory by itself, and with several it asks which one is this checkout’s.
npx -y @systemdox/mcp-server setup --project acme-platformA key that cannot sync is caught first. Before it shows anything, setup asks SystemDox whether the key may change the team memory. If it may not, setup leaves the memory out, gives you the link that makes the right key, and still sets up the plugin and the instructions.
Finish with the plugin. setup ends by printing the one command left for you: claude plugin install on a first setup, or claude plugin update when the plugin is already installed and a newer version exists. A workspace’s first sync publishes the version that carries the sync hooks, and setup shows their command before you answer. Run the command it prints, accept what it shows, and restart Claude Code.
Your second computer. Make it its own key and run the same setup there, without –project: it finds the only team memory by itself. Add –import to bring in any other copy of your notes. Both computers then converge as described below.
Your existing memory comes with you. On a project’s first sync, setup looks for the memory Claude Code has already kept for this checkout, in ~/.claude/projects/<folder>/memory/, and shows each folder it found with the number of files it will share, before you answer. It imports the files a team memory shares (below) and leaves the original folder exactly as it was. If you keep another copy, for example on a second drive, name it:
npx -y @systemdox/mcp-server setup --import /path/to/other/memory–import can be given more than once. A file present in two places with different text is kept twice, as a conflict copy (below). Later runs of setup import nothing: they update what changed.
What is shared, and what never leaves your computer
Claude Code labels each memory file with a type in its frontmatter, either at the top or under metadata:. The sync reads both forms.
Shared: memories of type
project,feedbackandreference, and the indexMEMORY.md.Never shared: a
usermemory, which describes one person; any file whose frontmatter saysshare: false; a conflict copy named<name>.local-<date>.md; and every other file. The sync never sends, deletes, renames or rewrites them.Secrets are refused. A file holding a key, a token or a recognisable key prefix is skipped and listed with its line, and the rest of the sync goes ahead.
People become identifiers. A person’s phone number or email address, and a home-folder path, are never sent as written. The next section says how.
Permissions, your theme and model, and any setting that is yours alone are not part of a team memory.
People in a memory
Notes often name someone: a reseller’s mobile, a colleague’s address. A team memory holds an identifier for that person, never their details, which stay in your organisation’s contacts.
The first time a sync in your terminal meets a value nobody has answered for, it asks you once, whatever number of files hold it, and shows you the words around its first appearance:
ma member’s contact,psomeone else (with a role such as reseller, sales, never a name),oours, not a person (a line or mailbox the organisation owns, shared as written),xleave these files out, orsskip for now.After one
y/Nover the whole change, each person is written as their identifier and role, for examplecon_01JC2… (reseller, sales), and a home folder as~. Every member’s copy then holds the same text.An answer counts for the whole workspace: a colleague is not asked again. An agent never answers for a person: without a terminal, a file still holding a value waits, and the sync names the command to run.
When a session needs the details, the MCP tool resolve_person reads them back by identifier for that session only, and only for someone allowed to see them.
How two computers converge without losing a word
Every sync compares three versions of each file: what it was at your last sync, what the team holds now, and what your folder holds now.
Changed on one side only: that side wins. Your edit goes up; a colleague’s comes down.
Deleted on one side, untouched on the other: it is deleted on both. A file deleted on one side and changed on the other is kept, with the change.
Changed on both sides, differently: the team’s text keeps the name and yours is written beside it as
<name>.local-<date>.md. Nothing is overwritten; you tidy the pair when it suits you, and the copy never leaves your computer.The index,
MEMORY.md, is merged line by line, keyed by the file each line links to, so two computers that each added notes end up with both lines and no conflict copy.Two members syncing at the same moment: the second push is refused because the team moved on; the sync pulls again, merges again and retries once. Neither loses a file.
Your first sync on a computer merges against nothing, so it only adds: it deletes nothing on either side.
Synced at the start and the end of every session
When your workspace has a team memory, the team plugin carries two hooks of SystemDox’s own, at SessionStart (a new or resumed session) and SessionEnd:
npx -y @systemdox/mcp-server sync-memory --hook <workspace>It syncs every project this computer has synced before. It never makes a first sync: that one is yours, in your terminal, because it may ask about people.
It asks nothing and rewrites nothing. At the start of a session Claude Code reads one line per project, for example Team memory acme/payments: version 42, 3 pulled, 1 pushed, 0 deleted. A line under it names any conflict copy to tidy, and another names the files that wait for you (the first five, then how many more), with the command to run. A file waits for you when it holds a person’s details that need your answer at a terminal. A value is never printed.
The full report of each run is appended to
~/.claude/systemdox/<workspace>/sync-memory.log.It never holds a session up. Offline, or slower than its 20-second budget, it prints one line saying the memory was not synced and the next session tries again, and it always ends as a success. A key for another workspace, or a team memory SystemDox no longer serves, gets the same line and leaves your folder exactly as it is. Every file is written whole, so a run cut short never leaves half a file behind. One sync runs at a time per workspace: a session that starts while another is syncing says so and leaves it the work.
The hooks reach your computer the way every team hook does: setup shows their command before you accept, and a new plugin version waits until you accept its command in your own terminal. Until your plugin carries them, run the sync yourself (next section). The console’s Docs › Team setup › Memory tab says whether the latest plugin syncs the memory.
The commands
# Set up this computer, or update it (shows everything first; asks once).
# The workspace's first team memory: setup asks for its name, or give it with --project <name>.
npx -y @systemdox/mcp-server setup [--project <name>] [--dir <checkout>] [--import <folder>]... [--yes] [--overwrite] [--choose]
# Sync a project's team memory yourself (answers people's values in your terminal)
npx -y @systemdox/mcp-server sync-memory [--project <name>] [--dir <folder>] [--import <folder>]... [--dry-run]
# Give a different answer about a phone number or email address
npx -y @systemdox/mcp-server sync-memory --project <name> --reanswer <value>
# What the team plugin runs at the start and end of a session (you never type it)
npx -y @systemdox/mcp-server sync-memory --hook <workspace>–dry-runshows what would be pulled, pushed, deleted, conflicted and skipped, and how many values are still to answer by kind. It asks, writes and sends nothing.sync-memoryexits0when synced (conflict copies and skipped files are listed, not errors),1on a usage error, no key or a refusal, and2when the team moved on twice during the sync: your folder holds the merge, so run it again.–hookalways exits0.The MCP tool
sync_memorydoes the same assync-memoryfrom inside a session, on your own computer only, and never answers for a person.
Every command reads your key from SYSTEMDOX_API_KEY, or from ~/.claude/systemdox/credentials.json, where setup stores it readable by you alone.
Good to know
The index is read in part. Claude Code loads the first 200 lines or 25 KB of
MEMORY.mdat the start of a session. A large shared memory works best with a short index that points to topic files.Limits per project: 10,000 files, 50 MB in all, 256 KB per file, text only.
Frontmatter must be valid YAML. A value holding a colon, such as
description: Rule: run tests, breaks it, and that file is refused on its own, with its name in the sync’s list. Quote the value and the next sync sends it.Keep a note to yourself by giving it type
useror addingshare: falseto its frontmatter.Where to read more: the MCP setup guide covers the rest of the team setup: the plugin, its hooks and MCP servers, and the team instructions.
A key was refused, or has expired. A key lasts 90 days.
setupsays the key you kept did not work and asks for a new one at the same question.No sync line at the start of a session. Run
claude plugin list. If the plugin is older than the version on the console’s Docs › Team setup page, runclaude plugin update <workspace>-setup@systemdox-<workspace>and start a new session. The full report of each run is insync-memory.log.A hook of your own cannot start. Claude Code runs hooks in a plain shell, which does not see your aliases. A hook that starts with
pythonneeds a realpythoncommand on your PATH.You gave the wrong answer about a value. Run
sync-memory –project <name> –reanswer <value>in your terminal, while a file still holds the value. The new answer replaces the old one.Something was shared by mistake. Remove it from the note and let the sync run. The latest version no longer holds it, and older versions leave the version history after 30 days. The stored copy of the old text stays in SystemDox, so if it must be erased, ask SystemDox to do it.
Keep keys out of chats.
setuphides a key as you paste it. If a key ever appears in a chat, a ticket or a screenshot, revoke it in Settings › API keys and make another.