-
Notifications
You must be signed in to change notification settings - Fork 1
Data and Backup
| Data | Path | Scope |
|---|---|---|
| User graph | ~/.claude/knowledge/user.json |
Global, all projects |
| Project graph | <project>/.claude/knowledge/graph.json |
Per-project |
| Sessions | ~/.claude/knowledge/sessions.json |
Active session tracking |
| Server logs | /tmp/mcp_server.log |
Ephemeral |
| Server PID | ...server/.mcp_server.pid |
Runtime |
Both user and project graphs use the same JSON structure:
{
"nodes": {
"node-id": {
"id": "node-id",
"gist": "Short description",
"notes": ["additional context"],
"touches": ["related/file.py"],
"_archived": true,
"_orphaned_ts": 1706000000.0
}
},
"edges": {
"source->target:relationship": {
"from": "source",
"to": "target",
"rel": "relationship",
"notes": ["edge context"]
}
},
"_meta": {
"versions": {
"node:node-id": {"v": 3, "ts": 1706000000.0, "session": "abc12345"}
},
"progress": {
"scout": {"last_ts": 1706000000, "sessions_reviewed": ["xyz"]}
}
}
}-
_archivedand_orphaned_tsare optional flags on nodes -
_meta.versionstracks change history for sync -
_meta.progressstores persistent task state (scout, extract)
All saves use atomic writes to prevent corruption:
- Write to
<file>.tmp -
fsyncto ensure data hits disk -
renametemp to final path (POSIX atomic operation)
If the process crashes mid-write, the temp file is left behind and cleaned up on next save attempt.
The system creates tiered backups automatically:
| Tier | Files | Retention | Interval |
|---|---|---|---|
| Recent |
.json.bak.1, .bak.2, .bak.3
|
3 copies | Minimum 1 hour apart |
| Daily |
.json.bak.daily.1 through .bak.daily.7
|
7 days | Once per day |
| Weekly |
.json.bak.weekly.1 through .bak.weekly.4
|
4 weeks | Once per week |
Backups rotate: when a new backup is created at a tier, the oldest at that tier is promoted to the next tier (if eligible).
Choose the appropriate backup based on when the issue occurred:
# Recent (last few hours)
cp ~/.claude/knowledge/user.json.bak.1 ~/.claude/knowledge/user.json
# Yesterday
cp ~/.claude/knowledge/user.json.bak.daily.1 ~/.claude/knowledge/user.json
# Last week
cp ~/.claude/knowledge/user.json.bak.weekly.2 ~/.claude/knowledge/user.json
# Same for project graphs
cp <project>/.claude/knowledge/graph.json.bak.1 <project>/.claude/knowledge/graph.jsonAfter restoring, restart the MCP server (or start a new Claude Code session) to reload from disk.
Each project's .claude/knowledge/ directory gets an auto-generated .gitignore:
Default behavior (private):
-
graph.jsonis gitignored — knowledge stays local - Backup files (
.bak.*) are always ignored
To share with team:
- Edit
.claude/knowledge/.gitignore— comment out thegraph.jsonline - Review
graph.jsonfor sensitive data (API keys, internal URLs, personal notes) - Commit the graph file
- Team members will get the shared graph on pull
Caveats of sharing:
- Last-write-wins — merge conflicts in JSON are messy
- Personal observations (user-level) stay private regardless
- No authentication — anyone with file access can read the graph
Graph files are plain JSON — you can edit them with any text editor. This is intentional.
Safe edits:
- Delete a node: remove its entry from
nodesand any edges referencing it - Edit a gist or notes: modify the text directly
- Unarchive: delete the
_archivedkey from a node
Don't edit while server is running — the in-memory store won't see your changes until restart, and the next periodic save will overwrite your edits.
Workflow: stop server → edit file → start server.
Typical graph sizes:
- Small project: 5-20 nodes, 10-30 edges, ~2-5 KB on disk
- Medium project: 20-50 nodes, 30-80 edges, ~10-30 KB on disk
- Active user graph after months: 30-100 nodes, ~15-50 KB on disk
The 5000-token compaction limit keeps the active graph small. Archived nodes stay on disk but don't count toward the limit.