---
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 19–24) 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
