Syncing Claude Code Config Across Machines (Mac, Pi, DGX)
The trick to syncing Claude Code across machines is that you never sync all of it. Copy the shared config (agents, commands, hooks) everywhere, and leave the machine-specific settings (model endpoint, API key) exactly where they are. Copy the whole .claude directory across instead, and you get a cryptic 404 Model not found on the machine whose endpoint you just overwrote.
If you're running Claude Code across multiple machines, say a Mac for development, a Raspberry Pi for edge testing, and a DGX box for heavy compute, you've probably hit this. Your carefully crafted agents, slash commands, and hooks get out of sync. Then you fix that by copying configs around, and break authentication on the machines that need different endpoints. This guide shows you how to build a sync system that keeps the shared parts in harmony while respecting machine-specific needs. (If you want the broader Claude Code setup this sits inside, the agents, skills, hooks, and permissions, start with Claude Code Best PracticesshippedAI Development & AgentsApr 20, 2025Claude Code Best Practices: Setup, Commands, and the Defaults Worth ChangingThe Claude Code setup, skills, subagents, and hooks I run in production, plus the defaults worth changing first. Updated for the 2026 feature set..)
Full implementation available on GitHub: BioInfo/claude-code-sync
Quick install:
curl -o ~/sync-claude-config.sh https://raw.githubusercontent.com/BioInfo/claude-code-sync/main/sync-claude-config.sh
chmod +x ~/sync-claude-config.sh
The Problem: Configuration Drift and the 404 Error
Here's what typically happens: you add a new agent on your Mac, customize some hooks, create a slash command. Then you switch to your DGX box and... none of that is there. You try to copy your .claude directory over, and suddenly:
API Error: 404 Model not found
Why? Because one machine talks to Claude through a Bedrock gateway, while another needs direct Anthropic API access.1This is common in enterprise setups: a work laptop routes through a Bedrock or Vertex gateway for governance and billing, while a personal or compute box uses a direct Anthropic API key. The agents and hooks are identical; only the connection differs. The model identifier that works on one machine doesn't exist on the other, so the moment you overwrite it, the next request 404s.
The fix is to be precise about which parts of your config are shared and which are bound to a single machine. Pick a sync strategy below and watch what each one does to the machine-specific settings.
Agents, commands, hooks
the shared config you want everywhere
Synced. This part you do want copied.
Model endpoint
Bedrock ARN vs direct-API model id
API Error: 404. The other machine’s model id doesn’t exist here.
API key
per-machine credential
Auth breaks. The wrong machine’s key lands here.
Session history & logs
todos, shell snapshots, project state
Dragged along. Stale state from another box.
2 machine-specific settings just broke. This is the 404.
Only smart merge keeps the shared parts in sync without touching what each machine needs to stay itself. Switch the strategy and watch the model endpoint.
Copying the entire .claude directory between machines overwrites machine-specific configuration like model endpoints, API keys, and database connections. That breaks authentication and causes the cryptic 404 above.
What Needs to Sync vs. What Needs to Diverge
Should sync across all machines:
- Custom agents (your 18+ specialized agents)
- Slash commands (commit helpers, documentation generators, etc.)
- Skills (like
ai-newsletter) - Hooks (auto-formatting, linting, notifications)
- Status line scripts
- Global
CLAUDE.mdinstructions - Plugin configurations
Must remain machine-specific:
ANTHROPIC_MODEL- Different model identifiers per machineANTHROPIC_BEDROCK_BASE_URL- Only for Bedrock-enabled machinesCLAUDE_CODE_USE_BEDROCK- Feature flag per environmentAWS_REGION- For Bedrock configurationsANTHROPIC_API_KEY- Direct API credentials- MCP server connection strings (database URLs, etc.)
Never sync:
- Session history and todos
- Debug logs and shell snapshots
- File history and project state
The middle list is the one that bites. Those values look like settings you forgot to sync, when they are actually correct because they differ per machine.
Building the Smart Sync System
Architecture Overview
The solution has three key components:
- Machine Profile Detection - Auto-identifies Mac, Pi, or DGX and applies appropriate config template
- Conflict Analysis - Compares local vs remote configs and groups differences
- Smart Merge Engine - Syncs shared configs while preserving machine-specific settings
Prerequisites
First, install a modern bash (macOS ships with ancient bash 3.2):
brew install bash
You'll also need passwordless SSH set up:
# Generate SSH key if you don't have one
ssh-keygen -t ed25519
# Copy to your remote machines
ssh-copy-id bioinfo@raspberrypi.local
ssh-copy-id bioinfo@spark-09e9.local
The Smart Sync Script
Create ~/scripts/sync-claude-config-smart.sh. The script uses associative arrays (bash 4+) to map machine types to configuration profiles:2macOS still ships bash 3.2, the last GPL-2 release Apple will bundle. Associative arrays (declare -A) need bash 4+, which is why the script pins the Homebrew bash path in its shebang and checks the version on startup.
#!/opt/homebrew/bin/bash
# Machine configuration profiles
declare -A MACHINE_PROFILES=(
["mac"]="bedrock-azure"
["pi"]="api-direct"
["dgx"]="api-direct"
)
# Files that need machine-specific handling
MACHINE_SPECIFIC_CONFIGS=(
"settings.json:env.ANTHROPIC_MODEL"
"settings.json:env.ANTHROPIC_BEDROCK_BASE_URL"
"settings.json:env.CLAUDE_CODE_USE_BEDROCK"
".mcp.json:mcpServers.postgresql.env.POSTGRES_CONNECTION_STRING"
)
The key innovation is the merge_configs_preserve_machine_specific() function using Python for JSON manipulation:
def merge_configs_preserve_machine_specific(base, new, machine):
# Merge: new data takes precedence
result = {**base, **new}
# But machine-specific env vars override everything
if 'env' in machine and 'env' in result:
result['env'].update(machine['env'])
return result
While jq is great for simple queries, Python's JSON library handles complex merging logic more elegantly. We embed Python scripts directly in bash using heredocs for a single-file solution.
Workflow Commands
Add these aliases to your .zshrc:
# Setup (run once on each machine)
alias cc-setup='sync-claude-config-smart.sh setup-machine'
# Analysis and merging
alias cc-analyze-pi='sync-claude-config-smart.sh analyze pi'
alias cc-merge-pi='sync-claude-config-smart.sh merge pi'
alias cc-smart-pi='sync-claude-config-smart.sh smart-merge pi'
# Same for DGX
alias cc-analyze-dgx='sync-claude-config-smart.sh analyze dgx'
alias cc-merge-dgx='sync-claude-config-smart.sh merge dgx'
alias cc-smart-dgx='sync-claude-config-smart.sh smart-merge dgx'
# Safety
alias cc-backup='sync-claude-config-smart.sh backup'
Usage Patterns
Initial Setup: Configure Each Machine
Run once on each machine to set up machine-specific configs:
cc-setup
The script auto-detects machine type (Mac, Pi, DGX) and applies the appropriate configuration template. For Pi and DGX, you'll also need to set your API key:
echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.zshrc
source ~/.zshrc
Daily Workflow: Smart Merge
When you've added agents or commands on your Mac and want to sync to other machines:
# Check what's different first
cc-analyze-pi
# Then sync with smart merge
cc-smart-pi
The smart merge:
- Creates automatic backup
- Syncs all agents, commands, skills, plugins
- Merges JSON configs intelligently
- Preserves model settings, API keys, and machine-specific env vars
Interactive Conflict Resolution
For complex scenarios where you want control:
cc-merge-pi
This presents four options:
- Push local - Send your configs to remote (overwrites remote)
- Pull remote - Get configs from remote (overwrites local)
- Smart merge - Auto-merge preserving machine settings
- Review file-by-file - Manually decide for each conflict
Option 4 is powerful. It shows side-by-side diffs (using delta or colordiff if available) and lets you choose per file:
[L] Use Local [R] Use Remote [M] Merge intelligently
[S] Skip [Q] Quit review
Conflict Analysis
Before syncing, always analyze:
cc-analyze-pi
Output:
========================================
Analyzing Conflicts with pi
========================================
CONFLICT: settings.json
Local vs Remote: +12/-8 lines
CONFLICT: agents/python-pro.md
Local vs Remote: +3/-0 lines
Conflict Summary
- settings.json
- agents/python-pro.md
This grouped view helps you understand the scope before making changes.
Machine Configuration Templates
A machine on Bedrock (enterprise gateway)
For setups routing through Bedrock via a corporate gateway:
{
"env": {
"CLAUDE_CODE_USE_BEDROCK": "1",
"ANTHROPIC_BEDROCK_BASE_URL": "https://your-gateway.example.net/bedrock",
"ANTHROPIC_MODEL": "arn:aws:bedrock:us-east-1:123456789:inference-profile/...",
"AWS_REGION": "us-east-1"
}
}
A machine on the direct API (Pi/DGX)
For direct Anthropic API access:
{
"env": {
"ANTHROPIC_MODEL": "claude-sonnet-4-6",
"ANTHROPIC_API_KEY": "${ANTHROPIC_API_KEY}"
}
}
The script automatically applies these templates during cc-setup.
Advanced Features
Automatic Backups
Every sync operation creates a timestamped backup:
~/backups/claude-config/claude-config-20251020-090348.tar.gz
The system keeps the last 10 backups automatically. To restore:
cc-sync list # See available backups
cc-sync restore /path/to/backup.tar.gz
Rsync for Directories
For large directories like agents/ with 18+ files, the script uses rsync instead of scp:
rsync -avz --delete "$CLAUDE_DIR/agents/" "${target_host}:~/.claude/agents/"
This is more efficient and handles deletions properly.3The --delete flag is what keeps a removed agent from lingering on the remote. It also means a mistaken local deletion propagates, so the automatic backup before each sync is the safety net that makes --delete safe to use.
Color-Coded Output
The script uses ANSI color codes for clear visual feedback: green for success, blue for info, yellow for warnings, red for errors, magenta for conflicts. Store the codes in variables at the top of the script (\033[0;32m for green, \033[0m to reset) so the output stays scannable and the script stays maintainable.
Troubleshooting Common Issues
Issue: "404 Model not found" After Sync
Cause: Machine-specific model configuration was overwritten.
Solution:
cc-setup # Reapply machine-specific config
Issue: Configs Keep Getting Overwritten
Cause: Using cc-push-* instead of cc-smart-*.
Solution: Always use smart merge for regular syncing:
cc-smart-pi # Not cc-push-pi
Issue: Want to See Exactly What Will Change
Solution: Use analyze first:
cc-analyze-pi # Shows grouped diffs
Issue: Bash Version Too Old
Error: declare: -A: invalid option
Solution:
brew install bash
# Script checks version and provides this message
Why do I get a 404 after copying my Claude Code config?
Because you overwrote a machine-specific model endpoint. The ANTHROPIC_MODEL value (and the Bedrock or Vertex variables around it) is bound to one machine's gateway and account; the moment you copy another machine's value over it, Claude Code asks the API for a model that does not exist there and gets a 404. The fix is to re-run cc-setup to restore that machine's own endpoint, and to use smart merge instead of a whole-directory copy going forward, so the shared agents and hooks sync while the endpoint stays put.
Real-World Scenarios
Scenario 1: Added New Agent on Mac
You created a new specialized agent database-architect.md:
cc-smart-pi # Sync to Pi
cc-smart-dgx # Sync to DGX
Both remote machines now have the agent, but keep their own model configs.
Scenario 2: Modified Hooks on DGX
You improved auto-formatting hooks on DGX and want them on Mac:
# On Mac
cc-analyze-dgx # See what changed
cc-pull-dgx # Pull the changes
Or use interactive merge if you're unsure:
cc-merge-dgx # Choose option 2 (Pull)
Scenario 3: Complete Standardization
You want all machines to match your Mac setup:
cc-backup # Safety first
cc-smart-pi # Smart merge to Pi
cc-smart-dgx # Smart merge to DGX
Each machine gets your agents, commands, and hooks, but keeps its own connection config.
Best Practices
- Always analyze before syncing -
cc-analyze-*is your friend - Use smart merge by default - Only use push/pull when you're certain
- Run
cc-setuponce per machine - Establishes baseline config - Backups are automatic - But manual backups before experiments don't hurt
- Test on one machine first - Sync to Pi, verify, then DGX
- Document machine differences - Keep notes on why configs diverge
Add cc-backup && cc-smart-pi && cc-smart-dgx to a daily cron job or git hook. Your configs stay synchronized automatically while you work.
Extending the System
Adding New Machines
To add a new machine type:
# In the script
declare -A MACHINES=(
["pi"]="bioinfo@raspberrypi.local"
["dgx"]="bioinfo@spark-09e9.local"
["gpu-rig"]="bioinfo@gpu-server.local" # New
)
declare -A MACHINE_PROFILES=(
["mac"]="bedrock-azure"
["pi"]="api-direct"
["dgx"]="api-direct"
["gpu-rig"]="api-direct" # New
)
Then add aliases:
alias cc-smart-gpu='sync-claude-config-smart.sh smart-merge gpu-rig'
Custom Configuration Templates
Add your own profile types:
get_machine_config_template() {
local machine_type=$1
local profile=${MACHINE_PROFILES[$machine_type]}
case "$profile" in
"bedrock-azure")
# Azure Bedrock config
;;
"api-direct")
# Direct API config
;;
"vertex-ai") # New profile
cat << 'EOF'
{
"ANTHROPIC_MODEL": "claude-sonnet-4-6",
"GOOGLE_CLOUD_PROJECT": "${GCP_PROJECT_ID}",
"VERTEX_AI_ENDPOINT": "us-central1-aiplatform.googleapis.com"
}
EOF
;;
esac
}
Integration with Git
For team environments, you might want to version control parts of your config:
cd ~/.claude
git init
git add agents/ commands/ skills/
git commit -m "Team-shared Claude Code configs"
git remote add origin git@github.com:team/claude-configs.git
git push -u origin main
Then have the sync script pull from git first, then sync to machines.
Performance Considerations
For large configurations:
- Rsync is faster than scp for directories (10x speedup for 18+ files)
- Parallel syncing - Sync to multiple machines concurrently:
cc-smart-pi & cc-smart-dgx & wait
- Compression helps over slow connections - rsync's
-zflag enables this - Exclude patterns prevent syncing unnecessary data:
--exclude='.claude/debug/*' \
--exclude='.claude/history.jsonl'
Conclusion
Syncing Claude Code configs across multiple machines doesn't have to be fragile. By separating shared configurations (agents, commands, hooks) from machine-specific settings (model endpoints, API keys), you can:
- Keep your development workflow consistent
- Avoid cryptic 404 errors from model misconfigurations
- Safely sync without fear of breaking authentication
- Recover quickly with automatic backups
The smart sync approach respects machine boundaries while keeping the good stuff synchronized. Your agents, custom commands, and carefully tuned hooks work everywhere, while each machine maintains its own connection to Claude.
Start with cc-setup on each machine, then use cc-smart-* for day-to-day syncing. Once the harness itself is dialed in (the best-practices guideshippedAI Development & AgentsApr 20, 2025Claude Code Best Practices: Setup, Commands, and the Defaults Worth ChangingThe Claude Code setup, skills, subagents, and hooks I run in production, plus the defaults worth changing first. Updated for the 2026 feature set. covers the agents, skills, and hooks worth building), keeping it consistent across every box is what makes the investment compound.
Clone it: github.com/BioInfo/claude-code-sync. The full script, documentation, and examples are MIT-licensed.
Related Articles
- Claude Code Best Practices: Setup, Skills, Subagents, HooksshippedAI Development & AgentsApr 20, 2025Claude Code Best Practices: Setup, Commands, and the Defaults Worth ChangingThe Claude Code setup, skills, subagents, and hooks I run in production, plus the defaults worth changing first. Updated for the 2026 feature set.
- Making Claude Code More Agentic: Subagents and RoutingshippedAI Development & AgentsJan 9, 2026Making Claude Code More Agentic: Parallel Execution, Model Routing, and Custom AgentsHow to configure Claude Code to use more subagents, run operations in parallel, and behave more like the multi-agent systems we've come to expect from tools like OpenCode.
- Auto-Updating CLI Tools for Claude Code SkillsshippedPractical ApplicationsJan 12, 2026Auto-Updating CLI Tools for Claude Code SkillsBuild an automated system that discovers CLI dependencies from Claude Code skill metadata and keeps them updated weekly via LaunchAgent.
- Debugging Claude Code With ClaudeshippedPractical ApplicationsJan 10, 2026Debugging Claude Code with Claude: A Meta-Optimization JourneyUsing Claude to analyze its own debug logs and session data reveals hidden performance bottlenecks and provides a systematic approach to optimizing AI development tools.
Follow the lab
Get the next experiment
Enjoyed the breakdown on Syncing Claude Code Config Across Machines (Mac, Pi, DGX)? New entries land roughly weekly. No digest, no roundup. Just the next build log, when it ships.
Related experiments
Apparatus
1,940 words · 15 min read
- claude-code
- setup
- development-setup
- bash
- automation
Links to this entry
- Auto-Sync Twitter Bookmarks to Obsidian with Bird CLI
- Claude Code Best Practices: Setup, Commands, and the Defaults Worth Changing
- Claude Skills vs MCP Servers: Why Context Efficiency Matters
- Cline and Roo Code: Quick Start Guide
- Debugging Claude Code with Claude: A Meta-Optimization Journey
- Fixing macOS Window Chaos: How Hammerspoon and Karabiner Solved My Docking Nightmare
- My AI Research Assistant Works the Night Shift (A Claude Code Skill Story)
- My Personal AI Assistant Lives Everywhere: Building with Clawdbot
- When ARIA Crashed the DGX: Building GPU Monitoring in 5 Minutes