Claude on WholeTech network
home/settings
Sync your Claude fleet

Communicating settings from one Claude to another

When you run Claude Code on more than one machine — a desk PC, a laptop, a Mac in the studio, a Windows box at the shop, a droplet on the side — you want the same allowlists, the same MCP servers, the same custom commands, the same status line, the same hooks. This page is the hub. It covers syncing one user's config across machines; the five deep-dive pages below cover the rest.

Inventory of ~/.claude/, five sync methods ranked, the recommended setup, a worked settings.json for a multi-PC fleet, the permissions, hooks, MCP servers, skills, auto-memory pattern, and pitfalls. For inter-Claude communication, OS-specific behaviour, shell & terminal details, and disaster recovery — see the five sub-pages.

deep dives — five sub-pages

The full network guide

This page (the hub) handles the config-sync question. Each sub-page handles a topic that needs its own real treatment — same depth, same design, all interconnected. Read in any order; they cross-reference each other.

If you only read two: /communication (because it covers the actual problem of getting Claudes to talk) and /recovery (because future-you will thank present-you).
01 — Why bother

The cost of drift

Every Claude session you have on an unconfigured machine costs you something. Every permission prompt is an interruption. Every "I don't have that MCP server here" is a workflow that doesn't run. Every custom slash command you set up on one machine and forgot on the others is muscle memory that fails three times before you remember why. The point of syncing isn't tidiness — it's keeping Claude usefully the same wherever you sit down.

friction

Permission prompts

Every command Claude wants to run that isn't on the allowlist becomes a yes/no interruption. On a configured machine you've already said yes to your common ones — git, gh, ssh, scp, rclone — once.

missing tools

MCP servers

If your Gmail MCP is wired up on the desk PC and not the laptop, the same prompt produces different work. Syncing the server list (not the secrets) keeps the toolset consistent.

muscle memory

Custom commands & skills

/session-close, /ultrareview, your own slash commands — if they only exist on one machine, you'll forget which one and re-implement them somewhere else.

context

Global CLAUDE.md

The "about me" and "things to avoid" instructions Claude reads at the start of every session. Drift here means Claude treats you differently per machine — minor but real.

style

Theme, status line, keybinds

The cosmetic stuff still matters when you're switching machines daily. Same theme = same scanning patterns = faster reading of diffs and logs.

memory

Auto-memory

The single biggest leverage point — if Claude remembers your preferences on one box and not another, "don't phone it in" has to be learned twice. (See §12 — sync this one carefully.)

The principle: sync the things that describe who you are and how you work; keep local the things that describe this machine (auth tokens, session logs, caches, machine-specific paths).
02 — Inventory

What lives in ~/.claude/

On Windows that's C:\Users\<you>\.claude\; on macOS/Linux it's ~/.claude/. Below: every file and directory you're likely to find, what's in it, and — most importantly — whether you should sync it across machines.

PathWhat it isSync?
settings.jsonUser-level config: theme, model, permissions, hooks, MCP servers, environment, status line.✓ yes
CLAUDE.mdPersonal global instructions. Read at the start of every session as "user's private global instructions for all projects".✓ yes
keybindings.jsonYour custom keyboard shortcuts and chord bindings.✓ yes
commands/Your own slash commands. Each .md file becomes /<name>.✓ yes
agents/Custom subagents you've authored — each one a markdown file with frontmatter describing when to use it.✓ yes
skills/Skill bundles you've created or pulled in. Folder per skill, with SKILL.md and supporting files.✓ yes
plugins/Installed plugin bundles. Synced if you want the same plugins everywhere.~ usually
output-styles/Custom response-style presets (terse, narrative, code-only, etc.).✓ yes
statusline-config.jsonStatus-line layout you've configured (cwd, model, branch, token count, etc.).✓ yes
auth.jsonAnthropic authentication credential. Tied to a single browser sign-in. Recreate per machine.✗ never
.credentials.jsonEncrypted local secrets (API keys you've stored). Machine-bound.✗ never
mcp-needs-auth-cache.jsonPer-machine cache of which MCP servers need (re-)authentication.✗ no
sessions/Log of every chat you've had on this machine. Often hundreds of MB.✗ no
shell-snapshots/Cached snapshots of the shell environment Claude ran in.✗ no
session-env/Environment variable snapshots from open sessions.✗ no
cache/Local cache directory for downloaded artefacts.✗ no
telemetry/Local usage data. Machine-specific.✗ no
file-history/Edit history for files Claude has touched on this machine.✗ no
paste-cache/Recent paste buffer cache.✗ no
tasks/In-flight task records for the harness.✗ no
history.jsonlAppend-only log of all prompts you've ever typed on this machine.✗ no
.claude.jsonCLI state (one level up, in ~/.claude.json): which projects you've opened, recent sessions, last-used directory.✗ no
projects/<slug>/Per-project state: history, memory, settings overrides. The memory/ subfolder is the high-value piece (see §12).~ memory only
backups/Automatic backups of changed config files. Machine-local.✗ no
downloads/Files Claude has downloaded into this machine's working area.✗ no
Roughly: sync everything that's a declaration (settings, commands, skills, memory you authored) and skip everything that's a record (sessions, history, caches, auth).
03 — Scopes

The four config scopes

Claude reads config from multiple places and merges them. Knowing the precedence is what lets you sync the right thing at the right level.

1

Enterprise managed /etc/claude-code/managed-settings.json (Linux/macOS)

Set by your organisation's IT. Wins over everything below. If you're a solo or small-team Paul-style operator, you almost never see this. Used for SSO enforcement, deny-lists, audit configuration.

2

Command-line flags --allowed-tools, --add-dir, etc.

Per-invocation overrides you pass on the shell. Useful for one-off "this session, just this once" exceptions. Don't sync — they live in your shell history, not on disk.

3

Project local .claude/settings.local.json

Per-project, gitignored, not shared with collaborators. The right place for personal "yes I trust this repo's npm test" allowlists. Don't sync between machines — each machine has its own working copies.

4

Project shared .claude/settings.json

Per-project, checked into git, shared with the team. Owns team-wide MCP servers, hooks that everyone running on this repo should have, allowed tool lists agreed across the team. Synced naturally via the repo.

5

User global ~/.claude/settings.json

Your defaults across every project on this machine. This is the one you want synced — it carries your identity, your common allowlists, your hooks, your MCP servers, your status line.

Higher numbers lose to lower numbers — enterprise wins over CLI flags, CLI flags win over project-local, project-local wins over project-shared, project-shared wins over user-global. For multi-machine sync the actionable scope is 5 (user global). Everything else either propagates automatically (via git) or shouldn't propagate at all (per-invocation, machine-local).

04 — Five ways

Methods to sync, ranked

Five approaches, in roughly the order I'd recommend trying them. The right answer for most multi-machine setups is some combination of the first two.

1

A git repo for ~/.claude/ recommended

Make ~/.claude/ a git repo. Commit the things worth syncing; gitignore the noise. Push to a private GitHub repo. On every new machine: clone, restore. On every change: commit. Same model devs already use for their dotfiles.

  • Pros: versioned, diffable, rollback works, works on Windows + Mac + Linux + WSL identically, the network already syncs git.
  • Cons: you commit the diff yourself — drift creeps in if you forget to push.
2

A NAS / Dropbox / OneDrive folder good for memory and skills

Point one specific subfolder of ~/.claude/ at a sync service. Works well for the high-churn pieces — your skill library, your auto-memory — where committing to git every time you tweak a memory file is friction. Use a junction/symlink: ~/.claude/skills/C:\Users\<you>\OneDrive\claude-skills\.

  • Pros: zero-friction propagation; works while you're typing.
  • Cons: conflict resolution on a busy Dropbox can corrupt JSON; harder to audit when something changes.
3

rsync / robocopy on a schedule good for one-way mirroring

Pick a primary machine. Nightly scheduled task rsyncs the synced parts of ~/.claude/ to a NAS or to the other machines (one-way). Same pattern as the WholeTech 6-leg push, just for your config.

  • Pros: no merge logic to worry about; the primary is always the truth.
  • Cons: changes you make on a secondary machine get blown away. Not a problem if you respect the "primary" rule.
4

A bootstrap script for fresh-machine setup

Don't sync at all — just keep a script that recreates your config from scratch. Stored in the same dotfiles repo, run once when you set up a new PC. Pairs well with method 1 (clone + run).

  • Pros: idempotent, scrutable, no live sync to break.
  • Cons: doesn't help ongoing drift; you still need a sync method for day-to-day.
5

Manual copy last resort

Just scp / copy-paste files when you need them. Fine for a one-time migration; a recipe for drift if it's your only mechanism. Useful when the other machines are dev machines you barely touch.

06 — Anatomy

settings.json — the file

The single most important file to sync. Every key it accepts, in plain English:

KeyTypeWhat it sets
themestringVisual theme: dark, light, dark-daltonized, etc.
modelstringDefault model alias: opus, sonnet, haiku, or a specific ID.
permissionsobjectallow, deny, ask lists for tool and command patterns. See §8.
hooksobjectShell commands to run on lifecycle events (Stop, UserPromptSubmit, PostToolUse, etc.). See §9.
mcpServersobjectMap of MCP server name → launch config. See §10.
envobjectEnvironment variables Claude should set when launching tool calls. Avoid putting secrets here.
statusLineobjectStatus-line layout. Run /statusline to configure interactively, then commit the resulting JSON.
outputStylestringDefault response style (one of your output-styles/ entries).
additionalDirectoriesstring[]Extra paths Claude is allowed to read/edit beyond the cwd. Use sparingly — every entry is a footgun.
cleanupPeriodDaysnumberHow long to keep session logs locally before deleting.
apiKeyHelperstringShell command that prints an API key to stdout. Use when you don't want the key on disk.
disableAllHooksbooleanEmergency off-switch for every configured hook.

Older versions of Claude Code used mcp_servers (snake case) and a separate mcp.json file; current versions use mcpServers in settings.json. If both exist, the explicit settings.json wins. When you migrate, copy mcp.json into settings.json's mcpServers block and delete the standalone file.

07 — Worked example

A real ~/.claude/settings.json

This is a settings.json tuned for a WholeTech-style operator: multiple Windows PCs, an SSH droplet, MCP servers for Google + Slack, hooks for end-of-task notification, and an allowlist that takes the friction out of git/gh/ssh/scp/curl/rclone. Copy, then strip out anything you don't use.

{
  "theme": "dark",
  "model": "opus",
  "outputStyle": "default",
  "cleanupPeriodDays": 30,

  // === environment ===
  "env": {
    "DROPLET_HOST": "root@wholetech.com",
    "DROPLET_IP":   "143.198.182.180",
    "WEBSITES_ROOT": "C:\\Users\\walhu\\websites",
    "EDITOR":       "code --wait"
  },

  // === permissions ===
  // allow = run without asking; deny = block outright; ask = always confirm
  "permissions": {
    "allow": [
      // git essentials
      "Bash(git status:*)", "Bash(git diff:*)", "Bash(git log:*)",
      "Bash(git add:*)",    "Bash(git commit:*)", "Bash(git push:*)",
      "Bash(git pull:*)",   "Bash(git fetch:*)", "Bash(git branch:*)",
      "Bash(git checkout:*)", "Bash(git stash:*)",

      // GitHub CLI — read-only ops
      "Bash(gh pr view:*)", "Bash(gh pr list:*)", "Bash(gh pr diff:*)",
      "Bash(gh repo view:*)", "Bash(gh issue list:*)",
      "Bash(gh run list:*)", "Bash(gh run view:*)",

      // droplet ops — trust the host you control
      "Bash(ssh root@wholetech.com:*)",
      "Bash(ssh root@143.198.182.180:*)",
      "Bash(scp:*)",
      "Bash(rsync:*)",

      // dns + cert + http
      "Bash(nslookup:*)", "Bash(dig:*)", "Bash(curl.exe:*)",
      "Bash(certbot:*)",

      // package managers — read-only by default
      "Bash(npm ls:*)",      "Bash(npm view:*)",     "Bash(pnpm ls:*)",
      "Bash(npm run:*)",     "Bash(pnpm run:*)",    "Bash(yarn:*)",

      // backup + sync
      "Bash(rclone listremotes:*)", "Bash(rclone ls:*)",
      "Bash(rclone lsd:*)",         "Bash(rclone size:*)",

      // safe read tools
      "Read(*)", "Grep(*)", "Glob(*)", "WebFetch(*)"
    ],

    "deny": [
      // hard blocks — never run these without explicit confirmation
      "Bash(rm -rf /:*)",
      "Bash(rm -rf ~:*)",
      "Bash(git push --force:*)",
      "Bash(git push -f:*)",
      "Bash(git reset --hard:*)",
      "Bash(rclone delete:*)",
      "Bash(rclone purge:*)",
      "Bash(certbot delete:*)",
      "Bash(certbot revoke:*)"
    ],

    "ask": [
      // always confirm — risky but legitimate sometimes
      "Bash(npm publish:*)",
      "Bash(gh release:*)"
    ]
  },

  // === hooks ===
  // see §9 for full hook recipes
  "hooks": {
    "Stop": [{
      "matcher": "",
      "hooks": [{ "type": "command", "command": "powershell -c \"[console]::Beep(880,200)\"" }]
    }]
  },

  // === mcp servers ===
  // each entry is the launch command for an MCP server. Secrets via env, not hardcoded.
  "mcpServers": {
    "filesystem-websites": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "C:\\Users\\walhu\\websites"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${env:GH_PAT}" }
    }
  },

  "statusLine": {
    "format": "{cwd} · {model} · {branch} · {tokens}"
  }
}
Secrets: note the ${env:GH_PAT} indirection — the actual token isn't in the file. Set GH_PAT in your shell profile or in a per-machine .env that isn't in the synced repo. Same pattern for anything you'd be sad to leak.
08 — Permissions

Allowlist patterns worth standardising

Permissions are the single biggest friction reducer. Every tool/command pair that appears in your day-to-day belongs on the allowlist; every command that's destructive belongs on the deny list. Below: the patterns that pay back in any multi-PC fleet.

Syntax cheatsheet

Patterns match against the full command line. Use :* as the trailing wildcard if you want to allow any arguments. Lists are matched most-specific-deny-winsallowask.

Three tiers, in priority order

deny

Block destructive verbs

The shortlist of things you'd hate Claude to do without asking: rm -rf /, rm -rf ~, git push --force to any branch, git reset --hard, rclone delete, rclone purge, certbot revoke.

ask

Confirm risky-but-legitimate

npm publish, gh release create, terraform apply, anything that produces a public artefact. You want them available without trip-wires, but never silent.

allow

Pre-allow the daily verbs

Everything you'd type ten times a day: git read commands, gh read commands, ssh to your own hosts, scp, curl, nslookup, npm/pnpm run, rclone ls. Less friction, no real risk on systems you own.

The allowlist that earns its keep on Paul-shaped work

// version control — every read, write to your own remotes
"Bash(git *:*)",          // allow everything in git — narrower if you prefer
"Bash(gh pr view:*)",      "Bash(gh pr list:*)",     "Bash(gh pr diff:*)",
"Bash(gh run view:*)",     "Bash(gh run list:*)",    "Bash(gh repo view:*)",

// SSH to hosts you control (be specific — don't whitelist ssh:*)
"Bash(ssh root@wholetech.com:*)",
"Bash(ssh root@143.198.182.180:*)",
"Bash(scp:*)",

// HTTP probes & DNS
"Bash(curl.exe -s*)",      "Bash(curl.exe -sI*)",     "Bash(curl.exe -X GET*)",
"Bash(nslookup:*)",        "Bash(dig:*)",            "Bash(host:*)",

// rclone — read-only verbs
"Bash(rclone ls:*)",       "Bash(rclone lsd:*)",      "Bash(rclone size:*)",
"Bash(rclone listremotes:*)", "Bash(rclone check:*)",

// safe Claude built-ins
"Read(*)", "Grep(*)", "Glob(*)", "WebFetch(*)", "WebSearch(*)"
Don't whitelist Bash(ssh:*) globally — that allows ssh to any host. Allowlist each host you own as a separate pattern. Same for Bash(curl:*) — that's a network-write primitive disguised as a read.

Use /fewer-permission-prompts to audit

The bundled skill fewer-permission-prompts scans your transcripts, ranks common read-only commands by frequency, and proposes an allowlist for the project's .claude/settings.json. Run it on the primary PC, copy the suggestions up to ~/.claude/settings.json if they're broadly applicable, and commit.

09 — Hooks

Hooks worth setting once

A hook is a shell command Claude runs automatically when something happens. Lifecycle events available: UserPromptSubmit, PreToolUse, PostToolUse, Stop, SubagentStop, Notification, SessionStart. Three I'd recommend across every machine:

1. Beep when Claude stops

The single highest-value hook: an audible cue that Claude finished. Lets you walk away during long runs without watching the screen.

"hooks": {
  "Stop": [{
    "matcher": "",
    "hooks": [{
      "type": "command",
      // Windows: PowerShell beep. macOS: 'afplay /System/Library/Sounds/Glass.aiff'. Linux: 'paplay /usr/share/sounds/freedesktop/stereo/complete.oga'
      "command": "powershell -c \"[console]::Beep(880,200)\""
    }]
  }]
}

2. Push notification on long jobs

Pair the beep with a Pushover / ntfy / Slack message so you get notified on your phone. Especially useful when Claude is running a background agent or a cloud task.

"Stop": [{
  "matcher": "",
  "hooks": [{
    "type": "command",
    "command": "curl.exe -s -d \"Claude finished\" ntfy.sh/walhus-claude"
  }]
}]

3. Auto-format after every Edit/Write

Run Prettier/Black/gofmt automatically on files Claude touched. Keeps the diff clean and saves you from "Claude wrote it with the wrong quote style" comments in code review.

"PostToolUse": [{
  "matcher": "Edit|Write|MultiEdit",
  "hooks": [{
    "type": "command",
    // CLAUDE_FILE_PATHS is set by the harness; format only what was touched
    "command": "for f in $CLAUDE_FILE_PATHS; do npx prettier --write \\\"$f\\\" 2>/dev/null || true; done"
  }]
}]

4. Guard against committing to main

A pre-tool gate that intercepts git push to main/master and forces a confirmation.

"PreToolUse": [{
  "matcher": "Bash",
  "hooks": [{
    "type": "command",
    // returns nonzero (= block) if pushing to main
    "command": "powershell -c \"if ($env:CLAUDE_TOOL_INPUT -match 'git push.*\\bmain\\b') { Write-Host 'Refusing to push main — confirm in chat'; exit 2 }\""
  }]
}]
Hooks run with your shell privileges. Don't paste in hook commands from untrusted sources without reading them — they can do anything you can do. The disableAllHooks: true escape hatch exists for a reason.
10 — MCP servers

MCP servers across machines

MCP servers are how Claude reaches outside its sandbox — Gmail, Calendar, Drive, Slack, your own filesystem trees, GitHub, Postgres. The declaration is portable; the auth is not. Sync the declarations, re-auth per machine.

What to put in settings.json

"mcpServers": {
  "filesystem-websites": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", "C:\\Users\\walhu\\websites"]
  },
  "filesystem-secrets": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", "C:\\Users\\walhu\\.secrets"]
  },
  "github": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-github"],
    "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${env:GH_PAT}" }
  },
  "postgres-walhus": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-postgres", "${env:WALHUS_DB_URL}"]
  }
}

Auth lives outside the synced file

The Google MCP servers (Gmail, Calendar, Drive) and Slack auth via OAuth on first use. The browser flow writes a token into ~/.claude/mcp-needs-auth-cache.json and a per-server token file. Don't sync those. Each machine does its own one-time auth.

The pattern Paul already uses

The Google + Slack MCP servers in this fleet (Gmail, Calendar, Drive, Slack — see /integrations) authenticate via claude.ai and don't appear in mcpServers at all — they're managed connectors. The ones that DO live in mcpServers are the local ones: filesystem trees you've granted access to, your GitHub server, your Postgres pointer.

Practical rule: add a new MCP server on the primary PC; commit the settings.json change; pull on the others; let each one do its own auth dance.

11 — Workflows

Skills, agents, commands, plugins

These four are folders of declarations rather than fields in settings.json, so the sync story is even simpler: copy the folder, restart Claude.

WhereWhatSync method
~/.claude/skills/ Skill bundles — folders containing SKILL.md with frontmatter declaring when to use it, plus any scripts/templates it needs. Commit to dotfiles repo. Active set determined by frontmatter; no settings.json entry required.
~/.claude/agents/ Custom subagents. Each is a markdown file with frontmatter (name, description, model, tools). Commit to dotfiles repo. Available to every session on every synced machine.
~/.claude/commands/ Slash commands. my-thing.md becomes /my-thing. Commit to dotfiles repo. Same name on every machine, same behaviour.
~/.claude/plugins/ Installed plugin bundles. Some are vendored (own code), some are pulled from a marketplace at install time. Commit the installed bundles for reproducibility; or commit a manifest and reinstall on each machine.
~/.claude/output-styles/ Named response styles you can switch to with /output-style. Commit to dotfiles repo.

Two skills worth carrying everywhere

The 'plugin' shortcut for distributing your own stuff

If you find yourself maintaining the same five custom commands across machines, bundle them as a plugin and publish it (private repo is fine). Then every machine runs /plugin install <repo> and gets the same set. Updates propagate by running install again. Heavier than git-syncing the commands/ folder, but cleaner if you ever want to share the bundle with someone else.

12 — Memory

Auto-memory — sync, or keep local?

Auto-memory is the file-based memory system at ~/.claude/projects/<project-slug>/memory/. Each memory file is a markdown card with frontmatter; MEMORY.md is the index. This is where Claude remembers who you are, what you're like to work with, and what you've already corrected it on. It's the highest-leverage thing you could sync — and the most context-sensitive.

What's in there (a real example)

The auto-memory for the C--Users-walhu-websites project on this machine currently holds, indexed in MEMORY.md:

That last one is the case for syncing. The rule was established on one machine in one conversation; if it doesn't propagate to the others, Claude on the other machines will phone things in until you re-correct.

The case against syncing

Memory is context-specific. A memory written while configuring a Mac may not apply on Windows. A memory about a specific project's quirks doesn't help another project. And memories that capture in-flight conversation state (rare, but it happens) can mislead.

The compromise that works

Sync the memory directory structure via a symlink/junction to a OneDrive folder, so memories propagate live, but treat the memory index as authoritative and prune aggressively:

  1. Move the memory folder out of ~/.claude/projects/<slug>/ into a sync-able location: ~/OneDrive/claude-memory/<slug>/.
  2. Replace the original folder with a symlink/junction. On Windows: mklink /J "C:\Users\walhu\.claude\projects\<slug>\memory" "C:\Users\walhu\OneDrive\claude-memory\<slug>". On macOS/Linux: ln -s ~/OneDrive/claude-memory/<slug> ~/.claude/projects/<slug>/memory.
  3. Repeat the symlink on every machine — same target, same source. OneDrive does the heavy lifting.
  4. Review MEMORY.md weekly. Prune stale entries. Memories decay; the index is your hygiene tool.
An alternative if OneDrive scares you: commit the memory folder to the same git repo as the rest of ~/.claude/. Slightly more friction (you commit on every edit) but versioned, diffable, and you'll see exactly what changed. The skills that author memory automatically already write text-only files, so diffs read cleanly.
13 — Pitfalls

What goes wrong

leak

Committing auth.json or .credentials.json

The number-one accidental leak. auth.json contains your Anthropic session; .credentials.json can contain API keys. Always gitignore both before the first commit. Use git check-ignore -v auth.json to verify.

conflict

Dropbox + JSON = bad day

If two machines edit the same settings.json simultaneously, Dropbox creates conflicted copies with mangled names. Claude reads whichever it finds first. Symptoms: settings randomly revert. Fix: pick one primary, or use git.

path

Hardcoded paths break across OS

C:\Users\walhu\... on Windows isn't /Users/walhu/... on Mac. Either keep separate settings files per OS, or use ${env:HOME} and forward slashes (settings.json is JSON so Windows accepts forward slashes too).

size

Syncing sessions/ by accident

sessions/ can grow to hundreds of MB. If you forget to gitignore it the first commit is huge; if you forget to exclude it from OneDrive, your quota tanks. Both .gitignore and your sync tool's exclude list need to know.

stale

Forgetting to pull on the secondary

You change settings on Machine A, commit, push. Open Machine B a week later — old settings. Wire a git pull into your Machine B startup script, or alias claude to "pull dotfiles, then run".

version

Settings schema drift between Claude Code versions

Schema changes over time — keys get renamed, sections move. If Machine A is on 4.7 and Machine B is on 4.6, a synced settings.json may load partially. Keep all your machines on the same Claude Code version, or scope the sync to keys both versions accept.

14 — Bootstrap

Setting up a new machine

The whole point of doing the sync work is that a new machine is fast. Below: the steps to go from a blank Windows install to a fully-configured Claude in about ten minutes. Adapt freely.

  1. Install Claude Code. npm install -g @anthropic-ai/claude-code (or the equivalent from /newby/).
  2. Authenticate. claude once, sign in via the browser. This creates ~/.claude/ with the auth files but nothing else.
  3. Move that ~/.claude/ aside. mv ~/.claude ~/.claude.bak (or rename in Explorer). Keeps a safety net.
  4. Clone the dotfiles repo. git clone git@github.com:<you>/claude-dotfiles ~/.claude.
  5. Restore the auth bits. Copy auth.json from ~/.claude.bak back into ~/.claude — or just re-run claude login.
  6. Symlink the memory folder to OneDrive (or wherever your shared memory lives). See §12.
  7. Set the machine-local secrets. Drop ~/.secrets/godaddy.env, ~/.secrets/rclone.conf, or whatever per-PC creds you keep out of git.
  8. Open a session. Confirm: theme is right, status line looks right, an allowlisted command runs without prompting, an MCP server is listed, /your-custom-command works.

A scheduled task to keep dotfiles fresh

On Windows, a daily morning task that git -C ~/.claude pull --ff-only means you arrive at work and the latest settings are already there. Same idea as the CC-Mirror-* tasks on the WholeTech fleet.

# Windows Task Scheduler one-liner — registers a daily 09:00 pull
schtasks /create /tn "Claude dotfiles pull" /tr "git -C C:\Users\walhu\.claude pull --ff-only" /sc daily /st 09:00

For the WholeTech fleet specifically

Drop the dotfiles repo into the same 6-leg backup pattern you already run — droplet, B2, GitHub, Drive, HS NAS, CC NAS. Then losing a PC doesn't lose your Claude config; even the secrets you carefully kept out of the repo are independently backed up via your existing scheduled tasks.

related

See also

Live
◐ Theme