Sync your ~/.claude directory across multiple machines via a private GitHub repo. Scripts are available for Windows (PowerShell) and Linux/macOS (Bash).
| Tool | Windows | Linux | macOS |
|---|---|---|---|
| Git | git-scm.com | sudo apt install git |
brew install git |
| GitHub CLI | cli.github.com | install guide | brew install gh |
| jq (Bash only) | — | sudo apt install jq |
brew install jq |
| PowerShell 5.1+ (Windows only) | built-in | — | — |
After installing GitHub CLI, authenticate once:
gh auth loginOn Windows you may also need to allow script execution:
Set-ExecutionPolicy -Scope CurrentUser RemoteSignedIf a required tool is missing, the scripts will print platform-specific install instructions and exit.
Run this once per machine:
# Windows
.\claude-sync-init.ps1# Linux / macOS
bash claude-sync-init.shYou will be prompted for:
- Repo URL — your private GitHub repo (e.g.
https://github.com/you/claude-settings.git) - Subdirectory — an optional path within the repo to sync into (e.g.
claude). Leave blank to use the repo root.
The script clones the repo to ~/.claude-sync/repo/ and writes a local config to ~/.claude-sync/config.json.
If the repo is brand new (empty), run push first. If it already has settings from another machine, run pull first.
Re-running init on a machine that is already configured will prompt before overwriting.
# Windows
.\claude-sync-pull.ps1 [-Force]# Linux / macOS
bash claude-sync-pull.sh [--force]Fetches the latest commits and copies repo contents into ~/.claude. Files in ~/.claude that no longer exist in the repo are removed, making pull a true mirror. If both local and remote have changed the same file since the last sync, you will be asked which version wins.
Use -Force / --force to re-copy all files even when the remote commit matches the last sync (useful if files are missing from ~/.claude without any new commits).
# Windows
.\claude-sync-push.ps1# Linux / macOS
bash claude-sync-push.shCopies ~/.claude into the local repo clone, removes any repo files that no longer exist locally, commits with a timestamp and machine name, and pushes to GitHub. If the remote is ahead of your last sync, you will be warned before proceeding.
# Windows
.\claude-sync-status.ps1 [-Verbose]# Linux / macOS
bash claude-sync-status.sh [--verbose|-v]Read-only. Reports whether there are local changes to push or remote changes to pull since the last sync, and highlights any conflicts. Makes no changes.
By default only counts are shown. Pass -Verbose / --verbose to list each changed file.
~/.claude-sync/
config.json # local config — never synced to GitHub
repo/ # git clone of your settings repo (staging area)
The config is always local to each machine and is never uploaded. The repo/ directory is purely a staging area — your settings live in ~/.claude.
The following are excluded from syncing by default (local/ephemeral data):
*.log .credentials.json cache .tmp ide backups debug downloads
file-history mcp-needs-auth-cache.json plans policy-limits.json
projects sessions shell-snapshots statsig telemetry settings.local.json todos plugins
To customize, edit the exclusions array in ~/.claude-sync/config.json.
Conflicts are detected using the lastSyncCommit recorded after each successful push or pull. If a file changed both locally and on the remote since that commit, you are prompted:
CONFLICT: The following files changed both locally and remotely:
settings.json
Which version wins? [L]ocal / [R]emote:
Choosing Local aborts the pull and leaves your files untouched. Run push to upload your version.
Choosing Remote overwrites your local files with the repo version.
Setting up a new machine:
# Windows
.\claude-sync-init.ps1
.\claude-sync-pull.ps1# Linux / macOS
bash claude-sync-init.sh
bash claude-sync-pull.shAfter making local changes:
# Windows
.\claude-sync-push.ps1# Linux / macOS
bash claude-sync-push.shBefore making changes (to get latest from another machine):
# Windows
.\claude-sync-pull.ps1# Linux / macOS
bash claude-sync-pull.sh