obsidian/wiki/concepts/memory-compiler-mac-migration.md
2026-04-26 21:10:46 +01:00

155 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "Memory Compiler — Migrating Between Mac Users"
aliases: [memory-compiler-migration, cc-memory-migration, claude-code-path-migration]
tags: [memory-compiler, claude-code, hooks, macos, migration, knowledge-base]
sources:
- "daily/2026-04-24.md"
- "daily/2026-04-22.md"
created: 2026-04-24
updated: 2026-04-25
---
# Memory Compiler — Migrating Between Mac Users
Migrating the Claude Code memory-compiler system from one Mac user account to another (or between machines with different usernames) requires several manual fixes that are not obvious from the README. The hooks, `cc-collector.py`, and the wiki structure all have hardcoded or derived path assumptions that break on a new user path. Missing any of these produces silent failures — sessions appear to flush correctly but no data reaches the knowledge base.
## Key Points
- **All 3 hooks** (SessionStart, PreCompact, SessionEnd) must have `PROJECTS_ROOT` explicitly set as an environment variable — if missing, the obsidian session-start script silently produces empty context
- **`cc-collector.py` has a folder name bug**: `_root_prefix()` derives the project identifier using underscores, but the session storage folder name uses hyphens (e.g., `ai-leed` not `ai_leed`) — the fix is to ensure the prefix conversion maps `_``-`
- **`wiki/reports/_index.md`** must exist for the reports topic to appear in the master index — it is not auto-created and must be created manually when setting up a fresh wiki
- **`projects-overview` article count** must be updated in the master index after migration (was 36 on old Mac; 37 on new Mac after project was added)
- **macOS system `python3` = 3.9** — hooks that use Python 3.10+ syntax (`Path | None` union types) silently fail when invoked with `/usr/bin/python3`; replace with `/opt/homebrew/bin/python3` in all hook commands
- **Fish Fisher plugins** require fresh reinstall after conf.d files are copied — delete manually copied conf.d files and run `fisher update` to regenerate them cleanly
- **`time_tracker.py`** had two bugs after migration: missing `xlsxwriter` package and a hardcoded `/Volumes/SSD/Projects/Oliver` path; fix uses `OLIVER_ROOT` auto-detection supporting both old SSD and new `~/Documents/Projects/Oliver` prefixes
- The old Mac's files are accessible via SSH if needed — no need to manually recreate plugin caches or config files
## Details
### Hook Environment Variables (PROJECTS_ROOT)
The obsidian hooks (`obsidian-session-start.py`, `obsidian-pre-compact.py`, `obsidian-stop.py`) read a `PROJECTS_ROOT` environment variable to find project directories. On the old Mac this was set in the hook command line; when migrating, it must be re-added to the global `~/.claude/settings.json` for each hook.
The format in `~/.claude/settings.json`:
```json
{
"hooks": {
"SessionStart": [
{
"hooks": [{
"type": "command",
"command": "PROJECTS_ROOT=/Users/ai_leed/Projects python3 ~/.claude/obsidian-session-start.py ...",
"statusMessage": "Loading Obsidian context..."
}]
}
]
}
}
```
If `PROJECTS_ROOT` is missing, the hook runs but finds no projects — `additionalContext` is empty. The session proceeds without any Obsidian note context injected, and no error appears. This is the silent failure mode.
### cc-collector.py Folder Name Bug
The `cc-collector.py` script (part of the Claude Code dashboard collector) uses `_root_prefix()` to derive a project identifier from the project directory path. The function was converting the macOS username portion of the path to an identifier using underscores: `/Users/ai_leed/...``ai_leed_...`.
However, Claude Code stores session data in folders named with hyphens: `ai-leed` not `ai_leed`. The mismatch meant `cc-collector.py` was looking for session files in a folder that didn't exist.
**Fix applied to `_root_prefix()`:**
```python
def _root_prefix(path: str) -> str:
# Convert path separators to hyphens, not underscores
# Folder names use hyphens: /Users/ai_leed -> ai-leed (not ai_leed)
parts = path.strip("/").split("/")
return "-".join(parts).replace("_", "-")
```
The general pattern: whenever deriving a folder name from a user path, use hyphens throughout.
### Creating wiki/reports/_index.md
The reports section of the master index (`| [[wiki/reports/_index\|reports/]] | ... | 0 |`) requires the file to exist. A fresh wiki setup does not create it automatically.
Minimal file to create at `wiki/reports/_index.md`:
```markdown
# Reports — Topic Index
> Weekly and monthly knowledge base summaries generated by report-generator.py.
> Compiled automatically via launchd on Mondays (weekly) and the 1st of each month (monthly).
| Report | Period | Generated |
|--------|--------|-----------|
<!-- Reports added automatically by report-generator.py -->
```
Without this file, links in the master index are broken wikilinks that Obsidian highlights in red.
### Migration Checklist
Complete checklist when migrating the memory-compiler to a new Mac user:
```
[ ] 1. Clone/copy memory-compiler repo to ~/.claude/memory-compiler
[ ] 2. Run: cd ~/.claude/memory-compiler && uv sync
[ ] 3. Update all hook commands in ~/.claude/settings.json with new username paths
[ ] 4. Add PROJECTS_ROOT=... env var to each obsidian hook command
[ ] 5. Replace all bare `python3` in hook commands with /opt/homebrew/bin/python3
[ ] 6. Verify cc-collector.py _root_prefix() uses hyphens not underscores
[ ] 7. Create wiki/reports/_index.md if missing
[ ] 8. Update projects-overview article count in _master-index.md if it changed
[ ] 9. rsync Fish config, then delete conf.d/*.fish and run `fisher update`
[ ] 10. Run a manual compile to verify pipeline: uv run python scripts/compile.py --dry-run
[ ] 11. Set up launchd jobs for weekly/monthly reports (if /schedule skill unavailable)
[ ] 12. Verify SessionStart hook fires: open a new Claude Code session, check additionalContext
```
### Identifying Old Mac Files via SSH
If config files, plugin caches, or other assets exist on the old Mac under `/Users/aimpress/` and are needed, they can be fetched via SSH:
```bash
# Fetch a specific file
scp aimpress@<old-mac-ip>:/Users/aimpress/.claude/settings.json /tmp/old-settings.json
# Or rsync a directory
rsync -avz aimpress@<old-mac-ip>:/Users/aimpress/.claude/plugins/ ~/.claude/plugins/
```
There is no need to recreate plugin caches manually — they rebuild on first use.
### Verifying the Pipeline After Migration
After completing the migration checklist, verify each layer:
```bash
# 1. Test hooks fire (open Claude Code, look for "Loading knowledge context..." status)
# 2. Test flush works
cd ~/.claude/memory-compiler
echo "test session" > /tmp/test-flush.md
uv run python scripts/flush.py /tmp/test-flush.md
# 3. Test compile works
uv run python scripts/compile.py --dry-run
# 4. Check logs
tail -20 scripts/flush.log
tail -20 scripts/compile.log
```
A successful flush appends a `FLUSH_OK` line or bullet points to `daily/YYYY-MM-DD.md`. A failed flush appends `FLUSH_ERROR: Exception: Command failed with exit code 1`.
## Related Concepts
- [[wiki/concepts/claude-code-schedule-skill-account-type]] — the `/schedule` skill limitation discovered during this migration session; launchd used as fallback
- [[wiki/concepts/macos-python-version-hooks]] — system Python 3.9 vs Homebrew Python issue that breaks hooks using `Path | None` syntax
- [[wiki/concepts/fish-fisher-conf-d-conflict]] — Fisher plugin conflict caused by manually copying conf.d files during migration
- [[wiki/claude-code/overview]] — Claude Code hook system overview including SessionStart, PreCompact, SessionEnd
- [[wiki/obsidian-rag/_index]] — the Karpathy LLM wiki method that the memory-compiler implements
## Sources
- [[daily/2026-04-24.md]] — Mac migration session (/Users/aimpress/ → /Users/ai_leed/): 3 hooks missing PROJECTS_ROOT env var (all fixed); cc-collector.py _root_prefix() underscore→hyphen bug found and fixed; wiki/reports/_index.md created; projects-overview count updated 36→37; 6 daily logs (Apr 1924) compiled manually after migration
- [[daily/2026-04-22.md]] — Continuing migration on ai_leed@192.168.1.44: Fisher showed 2/9 plugins (conf.d conflict fixed); rsync transferred 45 projects / 2.6 GB; time_tracker.py fixed (xlsxwriter + hardcoded path); hooks silently failing due to system Python 3.9; all hooks updated to use /opt/homebrew/bin/python3