A friendly walk-through of every file Claude Code looks at, where it lives, how layers stack, and what wins on conflict. Every claim cites the official Anthropic doc URL or the NotebookLM notebook it came from. Use the buttons in the top-right to switch theme or export your notes.
CLAUDE.md (project instructions), .mcp.json (MCP servers), and .env (secrets โ note: Claude Code itself doesn't read this, your tools do). settings.json is also project-level but optional; defaults work fine. Everything else โ skills, rules, agents, hooks, plans, custom commands โ is opt-in. Almost everything exists at both levels: a personal copy at ~/.claude/ for stuff that follows you across all projects, and a project copy at <project>/.claude/ for stuff that ships with one repo. When the same thing exists in both places, more-specific usually wins โ but skills flip the rule (personal > project), and that's the one trap to remember.
| Thing | User-global | Project | Project-local (gitignored) | On conflict |
|---|---|---|---|---|
CLAUDE.md |
~/.claude/CLAUDE.md |
./CLAUDE.md or ./.claude/CLAUDE.md |
./CLAUDE.local.md |
Concatenated โ all loaded, project-most-specific last (highest attention) |
settings.json |
~/.claude/settings.json |
.claude/settings.json |
.claude/settings.local.json |
Local > Project > User; arrays merge; scalars replace |
| Skills | ~/.claude/skills/ |
.claude/skills/ |
โ | Personal > Project โ ๏ธ (the trap) |
| Rules | ~/.claude/rules/ |
.claude/rules/ |
โ | Project > User |
| Agents (subagents) | ~/.claude/agents/ |
.claude/agents/ |
โ | Project > User |
| Hooks | inside ~/.claude/settings.json |
inside .claude/settings.json |
inside .claude/settings.local.json |
All fire in parallel, merged + deduplicated13 |
| Custom commands (legacy) | ~/.claude/commands/ |
.claude/commands/ |
โ | Skill of same name wins; otherwise more-specific wins13 |
| Plans (plan-mode files) | ~/.claude/plans/ (default) |
customizable via plansDirectory setting |
โ | Single location at a time (configured by setting, not layered)13 |
| MCP servers | ~/.claude.json (User scope) |
.mcp.json at project root (Project scope) |
~/.claude.json (Local scope, project-keyed) |
Local > Project > User |
.env (Claude Code itself) |
Not read by Claude Code at all โ your tools do9 | โ | ||
~/.claude/ on Mac, /home/dev/.claude/ on VPS. Follows you across every project..claude/ folder. Goes in version control so the team gets it.CLAUDE.local.md and .claude/settings.local.json. Auto-gitignored.CLAUDE.md, then the parent, then the grandparent, all the way to the filesystem root. Every match it finds gets concatenated โ they don't override each other.1CLAUDE.md you can write @path/to/other.md to pull another file in. Works with @~/path for home. Max 5 hops deep. First-time imports of files outside the project show an approval dialog.1"model": "opus"). Most specific wins.permissions.allow) โ concatenated and deduplicated.2--- lines. Skills, agents, and path-scoped rules use it for metadata.3. (like .claude/). Hidden from Finder by default. Tools use them so they don't visually clutter your home directory.claude from. Walk-up starts here.plugin-name:skill-name namespace so they can't collide with your own.3Two homes. Color coded:
~/.claude/plans/)
โ
โโโ .claude.json USER-GLOBAL โ MCP servers (local + user scopes)
โ
โโโ .gemini/ .codex/ .config/opencode/ other CLIs' homes (peers, no overlap with Claude)
โ
โโโ projects/ where your code lives (just a folder)
โ
โโโ my-project/ PROJECT-SCOPED โ checked into git
โโโ CLAUDE.md team-shared instructions (or .claude/CLAUDE.md, both work)
โโโ CLAUDE.local.md your personal notes (auto-gitignored)
โโโ .mcp.json MCP servers shared with the team
โโโ .env secrets โ read by your tools, not by Claude Code itself
โโโ .gitignore standard git stuff
โโโ .claude/ project's Claude config root
โโโ settings.json team-shared settings (committed)
โโโ settings.local.json YOUR personal overrides (auto-gitignored)
โโโ skills/ project skills
โโโ agents/ project subagents
โโโ rules/ project rules (path-scoped or always-on)
โโโ commands/ legacy โ same as skills
The two-tree mental model. Pretty much every Claude Code config file has this same shape: a personal copy at ~/.claude/, a team copy at <project>/.claude/, and sometimes a .local.-suffixed personal-on-this-project copy. The interesting part is what happens when both copies exist โ see "Layering rules" below.
Click any row to expand. Required vs optional, locations, tiny example.
CLAUDE.md — persistent instructionsWhat it is. A markdown file with rules and context that Claude reads at the start of every session.1 Loaded as a user message after the system prompt โ strong influence, not absolute enforcement.
Locations (highest scope to lowest):
/Library/Application Support/ClaudeCode/CLAUDE.md on macOS ยท /etc/claude-code/CLAUDE.md on Linux./CLAUDE.md or ./.claude/CLAUDE.md (both honored)~/.claude/CLAUDE.md./CLAUDE.local.md (auto-gitignored)Required? No โ but if you skip it, Claude has zero project context.
Minimal example:
# My project
- Always use 2-space indent
- API handlers live in `src/api/handlers/`
- Run `npm test` before committing
Gotcha. Claude Code reads CLAUDE.md, NOT AGENTS.md.1 If your repo uses AGENTS.md for other agents, add a one-line CLAUDE.md that does @AGENTS.md.
settings.json — behavior configWhat it is. JSON file that controls model, permissions, hooks, and most other Claude Code behavior.2
Locations:
~/.claude/settings.json.claude/settings.json (committed).claude/settings.local.json (auto-gitignored on creation)2Required? No.
Minimal example:
{
"permissions": { "allow": ["Bash(npm test)"] },
"model": "opus"
}
settings.local.json — your personal overrides for this projectWhat it is. Same JSON shape as settings.json, but personal-to-this-machine. Auto-gitignored.2 Use it for sandbox URLs, experimental flags, or to disable a noisy team-wide hook just for you.
Location: always .claude/settings.local.json at the project root.
.mcp.json — MCP servers shared with the teamWhat it is. The only file-based MCP config. Lives at the project root and gets committed so your teammates have the same MCP servers.5
Locations: project root only โ ./.mcp.json.
But there are also user-scope and local-scope MCP servers โ those don't live in .mcp.json. They live in ~/.claude.json (your home directory). The CLI manages them via claude mcp add --scope user|local|project.5
Approval flow: First time you open a project with a .mcp.json, Claude asks you to approve each server. Reset with claude mcp reset-project-choices.
~/.claude.json — the user-level config (different from ~/.claude/settings.json!)Easy to miss. This is a single JSON file at ~/.claude.json โ not inside the ~/.claude/ folder. It stores both user-scope MCP servers (available across all projects) and local-scope MCP servers (per-project, but private to you).5
Different from ~/.claude/settings.json, which is your user-level settings. The two coexist.
.env — secretsWhat it is. Plain-text key=value pairs. Claude Code itself does not read .env โ your tools do (the apps you're building, helpers like get-secret, etc.). Some other CLIs (Gemini CLI) do read project .env directly.9
Locations: wherever your tools expect them. Common: project root, ~/.env.
Required? Only if you're using credentials.
Always gitignore secrets. No exceptions.
.gitignore — standard gitskills/ — reusable playbooksWhat it is. Each skill is a folder with a SKILL.md file. The folder name becomes /skill-name. Used for repeatable playbooks (deploy, commit, fix-issue, etc.).3
Locations:
~/.claude/skills/<name>/SKILL.md.claude/skills/<name>/SKILL.md<plugin>/skills/<name>/SKILL.md (namespaced as plugin:skill)Trap. Personal beats project for skills. (Yes, that's the opposite of agents โ see Layering rules.)3
Minimal SKILL.md:
---
description: Deploy the app to production. Use when user says deploy.
disable-model-invocation: true
---
1. Run tests
2. Build
3. Push to deploy target
agents/ — specialized subagentsWhat it is. Markdown files with YAML frontmatter that define a subagent (its system prompt, tools, model). Claude delegates tasks to them.4
Locations (priority โ lower number wins):
.claude/agents/<name>.md~/.claude/agents/<name>.mdTrap. For agents, project beats user โ opposite of skills. Memorize this.4
rules/ — modular instructions, optionally path-scopedWhat it is. Markdown files in .claude/rules/ that load alongside CLAUDE.md. With YAML frontmatter (paths:), they only load when matching files are touched.1
Locations: ~/.claude/rules/ (user) and .claude/rules/ (project). User loads before project, so project wins on conflict.1
Cool feature: the .claude/rules/ directory supports symlinks, so you can share rule sets across projects.1
Path-scoped example:
---
paths:
- "src/api/**/*.ts"
---
# API rules
- All endpoints validate input
- Use the standard error format
commands/ — legacy slash commands (now part of skills)Status: A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way.3 Existing commands keep working; new ones should be skills (skills support supporting files, frontmatter controls, etc).
hooks — NOT a folder, just a key in settings.jsonWhat it is. Lifecycle scripts triggered by events (pre/post tool use, session start, etc.). Configured under the "hooks" key inside any settings.json at any scope.6
There is no ~/.claude/hooks/ folder. If you see one in your file tree, it's not Anthropic-recognized.
Plugins are the exception โ plugins can ship a hooks/hooks.json file.6
Minimal example (in ~/.claude/settings.json):
{
"hooks": {
"Notification": [{
"matcher": "",
"hooks": [{ "type": "command", "command": "osascript -e 'display notification ...'" }]
}]
}
}
~/.claude/projects/ — internal session storageThis is NOT where your work goes. It's Claude Code's internal storage for session transcripts (JSONL files) and auto-memory.1
Each project gets a directory keyed off the git repo: ~/.claude/projects/<key>/. Inside:
memory/MEMORY.md โ auto-memory index (loaded into every session, first 200 lines / 25KB)memory/<topic>.md โ auto-memory topic files (loaded on demand)<session>.jsonl โ full session transcriptsDon't hand-edit these unless you know what you're doing. Use /memory from inside a session to view & edit safely.1
plans/ — plan-mode files (officially documented)What it is. Plan-mode writes plan files here. There's an official plansDirectory setting that controls the location.13
Default location: ~/.claude/plans/. Override per-project with plansDirectory in .claude/settings.json:
{
"plansDirectory": ".claude/plans"
}
Layering: plans live in ONE place at a time โ whichever plansDirectory wins on standard settings precedence (Local > Project > User). They don't merge across scopes the way CLAUDE.md does.
This is the hot zone. Different mechanisms have different rules. The quick-reference matrix:
| Mechanism | Loads how | Wins on conflict | Surprise level |
|---|---|---|---|
CLAUDE.md | Walks UP, concatenated | All loaded; project-most-specific has highest attention | Standard |
@import | Inline expansion, max 5 hops | Imported text inserted at the import point | Standard |
settings.json | Fixed 5-layer scopes (NO walk-up) | Local > Project > User; arrays merge, scalars replace | โ ๏ธ Doesn't walk up like CLAUDE.md |
| Skills | Discovered at session start (lazy body) | Personal > Project | โ ๏ธ Opposite of "more-specific wins" |
| Agents | Discovered at session start | Project > User | โ ๏ธ Opposite of skills |
| Rules | Always-on or path-scoped | Project > User | Standard |
| MCP servers | Three named scopes | Local > Project > User | โ ๏ธ Local + User both in ~/.claude.json |
| Hooks | Configured in settings.json at any scope | All fire in parallel (merge + dedup) | โ ๏ธ Don't override each other |
Plans (plansDirectory) | Single dir at a time | Highest-precedence settings.json wins | Standard |
| Custom commands | Lazy | Skill of same name wins; else more-specific | Standard |
.env | Not read by Claude Code | Your tools decide | โ ๏ธ Other CLIs DO read it |
Full details for each row below.
Rule: All of these are concatenated, not overridden. Order in context: filesystem root โ CWD (most specific last). Most-specific instructions get higher attention because they're nearest the conversation.1
Conflict? Claude may pick one arbitrarily. Manage it by writing more-specific instructions in deeper-scoped files.
@import โ relative paths, max 5 hops@~/path works.CLAUDE.md walks UP the directory tree: if you start Claude in ~/projects/myapp/src/api/, it looks for CLAUDE.md in src/api/, then myapp/, then projects/, then ~/, and concatenates everything it finds.1 settings.json does NOT do that.13 It only looks at the five fixed scopes above โ your home (~/.claude/), this project's .claude/, and managed/CLI. It will not pick up a stray settings.json sitting in some parent folder. If you put one there, Claude Code ignores it.
Merge rule:2
permissions.allow) โ concatenated and deduplicated. Lower-priority scopes can ADD without overriding."model": "opus") โ highest-priority scope wins. Lower-priority value is ignored.If a skill name exists in both ~/.claude/skills/ and .claude/skills/, the personal one wins. This is the opposite of "more-specific wins."3
For agents, more-specific (project) wins.4 Standard intuition. But again โ opposite direction from skills.
User-level rules (~/.claude/rules/) load before project rules (.claude/rules/), giving project rules higher priority on conflict.1 Same direction as agents.
Three scopes; matched by name (or by endpoint URL for plugins/connectors). Local is the default when you run claude mcp add without --scope.5
The trap: Local AND User scope MCP servers both live in ~/.claude.json (your home), not in .claude/. Only Project-scope lives in .mcp.json.
Hooks live inside settings.json, so they technically inherit settings layering. But the way hooks combine is different from how scalar settings combine.
Rule: when the same hook event has handlers at multiple levels (user, project, local, managed, plus plugin and skill/agent frontmatter), all matching hooks fire in parallel. They merge rather than override. Identical hook commands are auto-deduplicated.13
What this means in practice: if you've got a notification hook on Stop in your user settings, and a teammate added a different Stop hook to the project's .claude/settings.json, both fire when Claude stops. Project hooks ADD to user hooks; they don't replace them.
plansDirectory) โ single location, configurablePlan-mode files save to a single directory at a time. Default: ~/.claude/plans/.13 You change it with the plansDirectory setting in any settings.json (so the standard 5-layer settings precedence picks the winner โ no walk-up, no concatenation across multiple plan directories).
~/.claude/commands/ or .claude/commands/)Still fully supported. Live at user-global OR project. New work should be skills, but old commands keep working.3
Conflict rule: if both a command and a skill share the same name, skill wins.13 Otherwise, more-specific (project) wins over user-global for same-name commands.
.env loading โ varies by tool, not by ClaudeClaude Code itself does NOT auto-read any .env file. The ~/.env convention you use (with get-secret) is a community/safety pattern, not a Claude Code feature. Some other CLIs (Gemini CLI specifically) DO read project-level .env directly.9
Walk-throughs so the abstract rules become muscle memory.
GROK_API_KEY in ~/.env and <project>/.envSetup. You have GROK_API_KEY=xK1... in ~/.env (your global) and a different value GROK_API_KEY=xK2... in this project's .env.
.env.9curl -H "Authorization: Bearer $GROK_API_KEY" ....$GROK_API_KEY depends on YOUR shell environment. If your shell sourced ~/.env at startup, that's what's set. If you also exported the project value via your shell's hooks or a direnv tool, the project value wins because it was set later.get-secret GROK_API_KEY ./project/.env (the explicit path argument) so it's deterministic.secret-scan in both scopesSetup. You have ~/.claude/skills/secret-scan/SKILL.md with your generic patterns. The project also has .claude/skills/secret-scan/SKILL.md with team-specific extra patterns.
~/.claude/skills/secret-scan/ SKILL.md becomes /secret-scan. The project copy is shadowed and never invoked.project-secret-scan) or reference the project file from your personal skill.CLAUDE.md filesSetup. ~/.claude/CLAUDE.md says "Always use OAuth for new auth flows." Project CLAUDE.md says "Use Cloudflare service tokens for new auth flows โ OAuth is forbidden in this codebase."
.claude/rules/auth.md."If you run multiple CLIs side-by-side, here's the cross-reference.9
| Feature | Claude Code | Gemini CLI | Codex CLI | OpenCode |
|---|---|---|---|---|
| User-global config | ~/.claude/settings.json+ ~/.claude.json |
~/.gemini/settings.json |
~/.codex/config.toml |
~/.config/opencode/opencode.json |
| Project config | .claude/settings.json (+.local.json) |
.gemini/settings.json |
.codex/config.toml (trusted projects) |
opencode.json at project root |
| Project context file | CLAUDE.md |
GEMINI.md |
AGENTS.md (or codex.md) |
AGENTS.md |
| Context walks up? | Yes (CWD โ root) | Yes โ AND down (subdirs to depth 200)14 | Yes โ top-down (project root โ CWD)15 | Yes (CWD up to nearest .git)16 |
| Agents folder | ~/.claude/agents/ ยท .claude/agents/ |
~/.gemini/agents/ ยท .gemini/agents/14 |
~/.codex/agents/ |
~/.config/opencode/agents/ ยท .opencode/agents/ |
| Skills folder | ~/.claude/skills/ ยท .claude/skills/ |
~/.gemini/skills/ ยท .gemini/skills/+ ~/.agents/skills/ ยท .agents/skills/14 |
~/.codex/skills/+ ~/.agents/skills/ ยท .agents/skills/15 |
~/.config/opencode/skills/ ยท .opencode/skills/+ flexible (loads from .agents/ too)16 |
Reads .env? |
No (your tools do) | Yes โ walks up CWD โ home; also ~/.gemini/.env14 |
Yes โ project root .env15 |
Yes โ project .env16 |
| MCP config | .mcp.json (project) +~/.claude.json (user/local) |
Inside settings.json at mcpServers (all scopes merged)14 |
Inside config.toml at [mcp_servers.*]15 |
Inside opencode.json "mcp" block16 |
~/.agents/skills/ |
Not recognized natively (would need symlink) | Officially recognized14 | Officially recognized15 | Recognized (flexible scanning)16 |
~/.agents/skills/ is OFFICIAL for three of the four CLIs. Earlier research treated it as community/orchestrator-only convention. The dedicated CLI notebooks confirm Gemini, Codex, and OpenCode all load skills from ~/.agents/skills/ (and .agents/skills/ walked up from CWD) natively. Only Claude Code doesn't โ but you can symlink or use the orchestrator approach to bridge.141516
Other walk-up surprises:
GEMINI.md walks UP and DOWN. CWD up to project root, plus subdirectories down to depth 200. Claude Code only walks up.14.git. So your repo boundary is automatic.16If you want one source of truth for project context:
AGENTS.md as a universal context file โ adopted natively by OpenCode and Codex. Claude Code does NOT auto-read it,1 but you can @AGENTS.md from your CLAUDE.md and Gemini's @-import in GEMINI.md to share the same source.The parity table above lays out what each CLI looks for. This section answers: can I write something once and have all four CLIs use it? Short version โ natively, no. The CLIs do not share directories.9 But there are five well-traveled bridge patterns.
Pick one CLI's skill directory as canonical, then symlink the others into it.9
# Make Claude's skills the canonical home
mkdir -p ~/.claude/skills
ln -s ~/.claude/skills ~/.gemini/skills
ln -s ~/.claude/skills ~/.codex/skills
Now every skill you author at ~/.claude/skills/<name>/SKILL.md appears in all three CLIs. Same trick works for agents/, rules/ (where the CLI has an equivalent), and any custom config folder.
Caveat: the YAML frontmatter fields differ between CLIs. disable-model-invocation is Claude-specific. A skill that uses Claude-only fields will work in Claude but be partly ignored elsewhere. Keep skills written to the lowest-common-denominator frontmatter (name, description, body) for portability.
~/.agents/skills/ as the universal home (officially recognized by 3 of 4 CLIs)Updated finding: earlier research called this a community-only convention. Per the dedicated Gemini, Codex, and OpenCode notebooks, all three CLIs natively load skills from ~/.agents/skills/ and walk up to find .agents/skills/ in your project tree.141516 Only Claude Code doesn't โ that's the gap.
Setup: drop a skill at ~/.agents/skills/<name>/SKILL.md. It's instantly visible to Gemini, Codex, and OpenCode. To make Claude see it too, symlink:
ln -s ~/.agents/skills ~/.claude/skills/_shared
Now Claude sees a _shared namespace whose contents are the universal skill set; the other CLIs see them at the canonical ~/.agents/skills/ path.
Trade-off: still need that one symlink for Claude. Frontmatter compatibility caveat from Pattern 1 still applies โ Claude-only frontmatter fields are ignored when the same skill loads in Gemini/Codex.
AGENTS.md as universal context (the cleanest bootstrap)Write your shared rules in AGENTS.md at the project root. Then have every CLI's specific file import it.9
# In AGENTS.md (the universal source of truth)
- Use 2-space indentation
- API handlers live in src/api/handlers/
- Never commit .env files
# In CLAUDE.md
@AGENTS.md
# Claude-specific instructions below
- Use plan mode for changes under src/billing/
# In GEMINI.md (Gemini reads its own file by default โ point it at AGENTS.md)
@AGENTS.md
OpenCode and Codex already use AGENTS.md natively. Claude's @import syntax pulls it into CLAUDE.md.1 Gemini supports its own @ imports in GEMINI.md. One file, four CLIs.
All four major CLIs support MCP.9 Instead of writing CLI-specific skills, connect every CLI to the same MCP servers. The capabilities you build live in the MCP server (any language), not in the CLI's skill folder.
.mcp.json or ~/.claude.json~/.gemini/settings.json under mcpServers~/.codex/config.toml under [mcp_servers.*]opencode.json under "mcp"This is the most portable option for tool-shaped capabilities (database queries, API calls, search). Skills are good for prompts and playbooks; MCP is good for tools.
Wrap one CLI inside an MCP server so another CLI can call it.9 Example: run a tiny gemini_mcp_server.py that exposes a consult_gemini tool, then add it to Claude's MCP. Now Claude can ask Gemini for a second opinion mid-task.
Useful for: validation passes, multi-model voting, model-shopping. Heavier setup than the other patterns but doesn't require you to translate skills across formats.
ov sling <task> --runtime claude|gemini|codex dispatches the same task definition into different CLI runtimes inside isolated git worktrees.9bifrost cli --harness codex launches the Codex CLI but routes its API traffic to Anthropic or Google instead of OpenAI.9 Useful for keeping the CLI you like but using whichever model is cheapest/best for the task.| Goal | Best pattern | Why |
|---|---|---|
| Same skills/playbooks across all CLIs | 1 (symlinks) or 2 (~/.agents/skills/ + orchestrator) |
Direct file-level sharing with zero translation |
| Same project context across all CLIs | 3 (AGENTS.md + per-CLI @import) |
Cleanest bootstrap โ works without any extra tools |
| Same TOOLS (database, APIs, search) across all CLIs | 4 (universal MCP) | MCP is the official cross-CLI tool protocol; build once, connect anywhere |
| Have one CLI consult another mid-task | 5 (CLI-as-MCP) | Lets Claude call Gemini for a second opinion, or vice versa |
| Hot-swap CLI runtimes per task | Overstory | Use the right model for each subtask without juggling configs |
.mcp.json servers are equally reachable from any CLI configured to point at them.AGENTS.md + @import) is the cleanest fit for the shared/ folder you've been planning (soul.md, user.md, priorities.md). Keep them as plain markdown, then @import from CLAUDE.md and GEMINI.md. Codex and OpenCode already read AGENTS.md natively โ give them an AGENTS.md with @-imports of the shared files.~/.agents/skills/) just got upgraded โ it's now the recommended universal home, not a community workaround. Drop a skill there and three of four CLIs see it natively. Only Claude needs a symlink. If you write skills you want everywhere, this is the path.141516~/.claude/skills/ to be the source of truth and have other CLIs follow.Your VPS at /home/dev/ mirrors your Mac home. Same shape, different absolute paths. The relative-to-home structure is what matters for muscle memory and scripts.
Heads up โ this section is being reworked. P-3's "exact mirror at ~/" assumed each machine's home stays clean enough that "skip OS clutter" is a workable sync rule. The VPS dotfolder reality (24+ folders, mostly machine-specific) disproves that assumption. P-9 proposes a wrapper folder (working name workspace/) as the sync boundary. Tree below shows the P-9 shape; the P-3-flat shape was simpler but doesn't survive contact with real machine state. See D2 above for the full discussion.
Two different ways to be "the same":
/Users/coach โ /home/dev.~/workspace/projects/n8n/ on Mac matches ~/workspace/projects/n8n/ on VPS โ different absolute paths, same shape.We chose shape parity. Scripts using ~/workspace/... work on both machines. Scripts using /home/dev/workspace/... only work on VPS.
(Originally locked under P-3 as "exact mirror at ~/" with no wrapper. P-9 reopens this โ see D2. The shape-parity principle is unchanged regardless of which option lands.)
.claude/settings.local.json โ different per machine by design.claude.json โ local-scope MCP servers track project paths and per-machine state; do not sync~/.claude/projects/<key>/<session>.jsonl โ session transcripts; per-machine (but see below โ they CAN be mirrored read-only)osascript on Mac) โ needs a Linux equivalent on VPSGoal: each machine should be aware of the other's CC sessions. VPS Claude should be able to comb through Mac sessions, and vice versa. Plus a session-browser web app indexes BOTH + claude.ai web sessions, with filterable tags.
~/.claude/projects/. Each project key has its own auto-memory MEMORY.md โ both machines writing to the same project key will conflict and corrupt each other's notes.
| Source | Location | Sync |
|---|---|---|
| VPS sessions | /home/dev/.claude/projects/... | native (already on VPS) |
| Mac sessions | /Users/coach/.claude/projects/... | periodic rsync Mac โ VPS into /home/dev/imported-sessions/mac/ |
| claude.ai web sessions | cloud | API pull (or manual export until API ships) |
The session-browser web app indexer scans all three sources and tags each session by:
cwd field, normalized so /Users/coach/X and /home/dev/X map to the same projectEven before sync runs, you can drop a line in each machine's ~/.claude/CLAUDE.md:
# Cross-machine session awareness
The other machine's Claude Code sessions are mirrored read-only at:
Mac sessions on VPS: /home/dev/imported-sessions/mac/
VPS sessions on Mac: ~/.claude-vps-mirror/ (TBD)
Session-browser web app: https://<your-app>/sessions
Now Claude can find remote sessions on demand (via SSH or local read), even before the indexer is built.
dev, switch to root, or rename?Keep dev. Don't run as root. Don't rename to coach.
The "[DEV] Claude Code on VPS" notebook is unambiguous: run Claude Code as a non-root named user with sudo. Running as root gives the AI "master keys" โ catastrophic if it hallucinates a destructive command or interacts with malicious code.8
This isn't just advice. Claude Code actively refuses to run with --dangerously-skip-permissions if it detects the root user.8 That flag is core to autonomous remote operation, so root literally breaks the use case.
coach/home/dev/.~/projects/n8n/ works on both machines regardless of the absolute path. Renaming gives you path parity but at high cost โ and ~/ already does the same thing more cleanly.~/ or $HOME.None. Current setup already keeps dev. No new candidate revision needed.
dev/, work/, or code/?Four shapes were on the table:
| Shape | Mac | VPS | Trade-off |
|---|---|---|---|
| None โ projects at home | ~/projects/, ~/handoffs/, โฆ |
/home/dev/projects/, โฆ |
Cleanest. Mac mixes with macOS clutter (Documents/, Library/). |
dev/ wrapper, Mac only |
~/dev/projects/, โฆ |
/home/dev/projects/, โฆ |
Mac stays tidy. Asymmetric: Mac has one extra level. |
dev/ wrapper, both |
~/dev/projects/, โฆ |
/home/dev/dev/projects/, โฆ |
Symmetric. Recursive name on VPS (user dev has folder dev) โ awkward. |
work/ wrapper, both |
~/work/projects/, โฆ |
/home/dev/work/projects/, โฆ |
Symmetric. No recursion. One name discipline applied to both. |
P-3 Option A is being reconsidered. A new wrapper folder (working name: workspace/) is on the table to make sync rules dramatically simpler. Awaiting reviewer pass.
v1 said "P-3 Option A holds: no extra wrapper above ~/projects/." That was based on an assumption that has since broken: you can sync everything in home and just skip OS clutter. New evidence โ Jonah's actual VPS state โ shows that's not realistic.
Jonah's /home/dev/ right now has 24+ dotfolders, almost all machine-specific:
.pm2/, .dispatch/, .ccgram/, .notebooklm/ (running on VPS), .n8n-mcp/, .copilot/, .gnupg/, .bun/, .dotnet/, .cache/, .local/, .config/, etc..claude/, .gemini/, .codex/, .opencode/, .agents/.Documents/, Library/, Music/, Pictures/ โ never sync.P-3 Option A's sync rule becomes: "sync these visible folders + these dotfolders; skip these other dotfolders + Mac clutter." Two maintenance lists, both growing every time you install a tool.
Move all sync targets into one wrapper. Sync rule collapses to: "sync the wrapper + this small CLI dotfolder allowlist." One growing list, one stable list.
| Rank | Name | Notes |
|---|---|---|
| 1 | workspace/ | Verbose but unambiguous. Covers code + ideas + knowledge + handoffs equally. Web-search corroborated as a real dev convention. |
| 2 | homebase/ | Warmest. Late addition; just as clear as workspace. |
| 3 | lab/ | Three letters. Experiments + production. |
| 4 | _workspace/ | Top-sortable variant. Matches _dev0, _resources pattern. |
| 5 | studio/ | Vibes-forward. |
| 6 | basecamp/ | Climbing metaphor. |
| 7 | hq/ | Three letters, lowercase, immediate meaning. |
| 8 | launchpad/ | Sci-fi flavor. |
| โ | dev/ ยท code/ ยท work/ ยท forge/ | Rejected (recursion / too narrow / not encompassing / disliked) |
Every successful creator surveyed uses some wrapper โ only the name varies:10
| Creator | Wrapper name |
|---|---|
| Nate Herk | agentic workflows |
| Jono Catliff | Claude |
| Adam Goodyer | repositories |
| Nick Saraev | business/ + personal/ |
| Network Chuck | (no local convention โ VPS-as-forever-terminal) |
| Web-search corroboration | Real-world devs converge on workspace/, dev/, src/, repo/, Developer/17 |
P-9 candidate written in pending-revisions.md. architecture-decisions.md NOT edited per the no-silent-rewrites rule. Reviewers asked to weigh in on the wrapper name; everything else in P-9 has solid evidence behind it.
Pure teaching content. No decision to make โ just demystifies the question of "what's already here, where am I allowed to put stuff."
Documents/, Library/, Music/, Pictures/ by default โ it's just dotfiles. But it doesn't stay clean: every CLI you install drops a dotfolder (.claude/, .gemini/, .codex/, .pm2/, .notebooklm/, .bun/, etc.) plus visible folders for tool data. After a few months it's just as cluttered as a Mac home โ see Jonah's actual VPS at 24+ dotfolders. Both machines need a sync strategy that doesn't rely on home staying clean./ is NOT your home. /etc/, /opt/, /var/ are system folders managed by the OS and package manager. Don't put your work there. Don't fight them.CLAUDE.md, .mcp.json, .env. Everything else is opt-in.
Common things that look mandatory but aren't:
plans/ โ only if you use Plan Mode. Plan Mode itself is opt-in (Shift+Tab cycles to it)./simplify, /loop, /debug, etc.) ship with Claude Code. You don't need any of your own to start.Explore, Plan, general-purpose) cover the common cases.Notification hook is nice; everything else is for power users..claude/rules/ โ only if your CLAUDE.md is getting too big or you have file-type-specific rules.~/.agents/skills/ โ only if you're running multiple CLIs. Gemini, Codex, and OpenCode load skills natively from here; Claude Code doesn't (needs a symlink). If you're CC-only, skip it./memory.)https://code.claude.com/docs/en/memory (retrieved 2026-04-30). Walk-up rule, @import syntax, CLAUDE.md scopes, AGENTS.md note, .claude/rules/, auto-memory storage location, plan-mode plans/ folder reference.https://code.claude.com/docs/en/settings. 5-layer precedence (Managed โ CLI โ Local โ Project โ User), arrays-merge / scalars-replace / objects-deep-merge, settings.local.json auto-gitignore.https://code.claude.com/docs/en/skills. Skill folder layout, Enterprise > Personal > Project > Plugin precedence, frontmatter reference, custom-commands-merged-into-skills.https://code.claude.com/docs/en/sub-agents. Agent precedence (Project priority 3 > User priority 4 > Plugin priority 5), .claude/agents/ walk-up.https://code.claude.com/docs/en/mcp. Three scopes (Local / Project / User), ~/.claude.json as the home for Local + User scope, .mcp.json as project-only file-based config, approval flow.https://code.claude.com/docs/en/hooks. Hooks live in settings.json (any scope), event types, plugin hooks/hooks.json.https://code.claude.com/docs/en/common-workflows. Plan mode, --worktree flag, .claude/worktrees/ directory.7db6ea97, retrieved 2026-04-30). Non-root recommendation, --dangerously-skip-permissions root refusal, ~/projects/ structure, worktree project--feature naming convention.c4acbd14, retrieved 2026-04-30). Side-by-side parity table, .env handling per CLI, AGENTS.md as cross-CLI convention.42f55c2a, retrieved 2026-04-30). Wrapper-folder recommendation (repositories/, projects/, business/), settings precedence walk-through._dev0/migration/review/research/conventions/03-community-patterns.md. Pattern A "Simple Hierarchical" universal across 50+ public repos, Boris Cherny "vanilla setup" quote._dev0/migration/review/research/conventions/00b-prior-chat-jsonl-mined.md L146-177. ~/.agents/skills/ as community/orchestrator universal registry (later confirmed officially recognized by Gemini, Codex, OpenCode โ see citations 14-16).e5664a62, retrieved 2026-04-30). settings.json does NOT walk up (fixed scopes only); skills/agents have intentionally opposite precedence; hooks fire in parallel with dedup; plans is officially documented via plansDirectory setting (default ~/.claude/plans/); custom commands still supported, skill wins on name collision.fa8eb9c4, retrieved 2026-04-30). GEMINI.md walks up AND down (subdirs to depth 200); reads .env (CWD up + ~/.env + ~/.gemini/.env); MCP in settings.json at all hierarchy levels merged; skills at ~/.gemini/skills/, .gemini/skills/, AND ~/.agents/skills/, .agents/skills/; agents at ~/.gemini/agents/, .gemini/agents/.81d2e6cb, retrieved 2026-04-30). AGENTS.md walks TOP-DOWN (project root โ CWD); reads .env; MCP in ~/.codex/config.toml + .codex/config.toml (trusted projects); skills at ~/.codex/skills/ + ~/.agents/skills/ + project .agents/skills/ walked up.cbd59533, retrieved 2026-04-30). AGENTS.md at project root or global; OpenCode walks up to nearest .git; reads .env; MCP in opencode.json "mcp" block; skills at ~/.config/opencode/skills/, .opencode/skills/, plus flexible scanning that picks up .agents/skills/.~/dev/, ~/workspace/, ~/src/, ~/repo/, ~/Developer/.Verification log with full claim โ source mapping: _dev0/migration/review/research/conventions/07-verification-log.md. Contradictions resolved: 06-contradictions.md.