Context
Claude Code stores its config under ~/.claude/. The dotfiles currently handle this via apps/claude/install.zsh, which copies CLAUDE.md and skills/ from the repo on first setup and never touches them again (previous symlink-based approach was explicitly migrated to copies).
This works for a single machine but creates friction when syncing config between my Mac Studio and Mac Air laptop.
What lives in ~/.claude/
| Path |
Contents |
Currently managed? |
CLAUDE.md |
Global user instructions (master prompt) |
Seeded once from apps/claude/CLAUDE.md, never re-synced |
skills/ |
User-defined skills |
Seeded once from apps/claude/skills/, never re-synced |
settings.json |
Hooks, permissions, env vars, enabled plugins |
Not managed at all |
plugins/ |
Plugins installed via claude plugin install |
Re-installed on every dot run |
projects/, sessions/, history.jsonl, todos/, tasks/, cache/, debug/ |
Per-machine session state, transcripts, memory |
Should stay local |
Problem
- No round-trip: edits to
~/.claude/CLAUDE.md on the Studio don't flow back to the repo, so the Air never sees them.
- Source drift: if I improve
apps/claude/CLAUDE.md in the repo, machines that already ran install.zsh don't pick it up.
settings.json is unmanaged: enabled plugins, hooks, and permission preferences live only on whichever machine I set them on.
- Skills: same issue as CLAUDE.md — personal edits don't sync.
Things to decide
- What's shared vs per-machine?
- Shared:
CLAUDE.md, skills/, settings.json (probably)
- Per-machine: session state, history, caches, plugin cache, logs
- Sync strategy options:
- Symlink approach (revert to pre-migration behaviour): live files point to the repo, edits are committed. Risk: Claude Code may write to some of these files (e.g. memory), causing noisy git diffs.
- Copy + manual sync: keep copies, add a
dot claude-sync command to push local changes back to the repo for committing.
- Two-way sync via iCloud / Dropbox: mount
~/.claude/CLAUDE.md etc. from shared storage. Simpler but opaque to git history.
- Hybrid: symlink static files (
CLAUDE.md, skills/, settings.json), keep dynamic ones (projects/, history.jsonl) local.
- Memory files: auto-memory writes to
~/.claude/projects/*/memory/. These are per-project and per-machine — probably should stay local, but worth confirming.
- Plugins: currently re-installed every
dot run — is that the intended behaviour, or should we track installed plugins in a manifest file checked into the repo?
Proposed next step
Before implementing anything, agree on the scope:
- Which files sync across machines?
- Symlinks vs copy+sync script vs hybrid?
- Does
settings.json need secrets handling (it currently doesn't contain any, but future hooks might)?
Related
apps/claude/install.zsh — current setup logic
apps/claude/CLAUDE.md — repo source-of-truth for global prompt
apps/claude/skills/ — repo source-of-truth for skills
Context
Claude Code stores its config under
~/.claude/. The dotfiles currently handle this viaapps/claude/install.zsh, which copiesCLAUDE.mdandskills/from the repo on first setup and never touches them again (previous symlink-based approach was explicitly migrated to copies).This works for a single machine but creates friction when syncing config between my Mac Studio and Mac Air laptop.
What lives in
~/.claude/CLAUDE.mdapps/claude/CLAUDE.md, never re-syncedskills/apps/claude/skills/, never re-syncedsettings.jsonplugins/claude plugin installdotrunprojects/,sessions/,history.jsonl,todos/,tasks/,cache/,debug/Problem
~/.claude/CLAUDE.mdon the Studio don't flow back to the repo, so the Air never sees them.apps/claude/CLAUDE.mdin the repo, machines that already raninstall.zshdon't pick it up.settings.jsonis unmanaged: enabled plugins, hooks, and permission preferences live only on whichever machine I set them on.Things to decide
CLAUDE.md,skills/,settings.json(probably)dot claude-synccommand to push local changes back to the repo for committing.~/.claude/CLAUDE.mdetc. from shared storage. Simpler but opaque to git history.CLAUDE.md,skills/,settings.json), keep dynamic ones (projects/,history.jsonl) local.~/.claude/projects/*/memory/. These are per-project and per-machine — probably should stay local, but worth confirming.dotrun — is that the intended behaviour, or should we track installed plugins in a manifest file checked into the repo?Proposed next step
Before implementing anything, agree on the scope:
settings.jsonneed secrets handling (it currently doesn't contain any, but future hooks might)?Related
apps/claude/install.zsh— current setup logicapps/claude/CLAUDE.md— repo source-of-truth for global promptapps/claude/skills/— repo source-of-truth for skills