1644 字
8 分钟
Claude Code 配置多机同步:哪些该同步、哪些是坑

用了两台 Mac 跑 Claude Code 之后,配置漂移是必然的:主力机上的 CLAUDE.md 改了十几版,rules 目录加了新规则,另一台机器还停留在几个月前的状态。这次把同步这件事做完整,记录一下边界怎么划、踩了哪些坑。

同步范围:~/.claude 不能整个搬#

第一反应可能是 rsync -a ~/.claude/ remote:~/.claude/ 一把梭。不行。这个目录里配置和状态混在一起,先看清里面有什么:

Terminal window
ls ~/.claude/
# CLAUDE.md settings.json rules/ skills/ scripts/ plugins/ ← 配置,该同步
# .credentials.json history.jsonl projects/ sessions/ tasks/ ← 状态/凭据,绝不同步
# file-history/ shell-snapshots/ session-env/ paste-cache/ ← 会话产物,同步了纯属污染

划分标准就一条:这个文件描述”我希望 Claude 怎么工作”,还是记录”Claude 在这台机器上干过什么”? 前者同步,后者留在本机。

最终的同步集:

  • CLAUDE.mdsettings.json —— 全局指令和设置
  • rules/skills/scripts/ —— 规则、技能、hook 引用的脚本
  • plugins/ 的配置 json + marketplaces/ + cache/ —— 插件要能在对面机器直接加载

绝对不碰的:.credentials.json(凭据,每台机器各自登录)、projects/(含 memory 和会话历史)、history.jsonlsessions/tasks/。社区的通行做法也是只同步 CLAUDE.md / settings / agents / skills / rules 这一层,凭据类每台机器重新认证。

settings.json 同步前先看一眼 env 段#

settings.json 里有个 env 字段,有人会往里塞 API key。同步前用 jq 只看键名、不看值:

Terminal window
jq '.env | keys' ~/.claude/settings.json
# ["CLAUDE_CODE_DISABLE_TERMINAL_TITLE", "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS", ...]

确认全是无害开关才能同步。如果里面有密钥,要么挪去 shell 环境变量,要么这个文件就不能进同步集。

另一个容易忽略的:settings.json 里的 hooks 和 statusLine 经常引用绝对路径。我的配置里就有两处:

/Users/user/.claude/scripts/bark-notify.sh
jq -r '.statusLine, (.hooks | tostring)' ~/.claude/settings.json | grep -oE '/Users/[^" ]+'
# /Users/user/.open-island/bin/open-island-statusline

settings 同步过去了,这些脚本没跟着过去,hook 就会静默失败。所以依赖也要进同步集——scripts/ 目录、statusline 脚本、插件市场引用的本地目录,一个都不能少。同步完在远端实际执行一次验证:

Terminal window
ssh remote 'echo "{}" | ~/.open-island/bin/open-island-statusline'
# [Claude] 0% context ← 能跑

SSOT 不等于无脑镜像#

用户视角的规则是”本地是 single source of truth”。但落到 rsync 参数上要分两种情况:

  • rules/--delete 镜像——规则就该完全一致;
  • skills/ 不带 --delete——先对比两边目录,发现远端有几个本机独有的 skill(对方机器上自己长出来的工作流文档)。同名的以本地覆盖,独有的保留。

无脑 --delete 会把对方机器积累的本地产物直接删没。SSOT 解决的是冲突时听谁的,不是对方多出来的东西该不该存在

覆盖前照例打包备份,出问题能整体回滚:

Terminal window
ssh remote 'tar czf ~/.claude/backups/config-sync-bak-$(date +%Y%m%d%H%M%S).tar.gz \
-C ~ .claude/settings.json .claude/CLAUDE.md .claude/rules .claude/skills'

还有一个并发细节:动手前发现远端的 settings.json 几分钟前刚被改过——那台机器上有个活跃的 Claude Code session 也在写配置。这种情况备份就不只是仪式了。同步过去的新配置对已在跑的 session 不生效,只影响新启动的。

环境清单跨机误导:每台机器自己描述自己#

我的 rules/ 里有一份 cli-tools.md——本机装了哪些 CLI 工具的清单,让 Claude 不用每次现探测。镜像同步之后马上意识到一个问题:这份清单描述的是主力机,现在躺在另一台机器的 rules 里。对面那台是极简环境,清单里的 rg / fd / pandoc / psql 一个都没有。Claude 在那台机器上读到这份清单,会理直气壮地调用不存在的工具。

解法:清单不同步,每台机器实扫生成自己的版本。扫的时候先踩了个经典坑——

Terminal window
ssh remote 'brew list --formula | wc -l'
# 0 ← 看起来没装 brew?
ssh remote 'claude --version'
# command not found ← 看起来没装 claude?

都是假的。非交互 SSH 不加载交互 shell 的 PATH,/opt/homebrew/bin~/.local/bin 都不在里面。补上 PATH 再扫,90 个 formulae 好好地在那:

Terminal window
ssh remote 'export PATH="/opt/homebrew/bin:$HOME/.local/bin:$PATH"; brew list --formula | wc -l'
# 90

这个教训直接写进了那台机器的清单开头:探测前先补 PATH。顺带发现一个冷知识:那台机器上 jq/usr/bin/jq——从 macOS Sequoia 起系统就自带 jq 了,不再需要 brew 装。

两台机器的清单最后长成了不同的样子:主力机版本详尽罗列十几个分类;极简机版本开头是一段”与主力机的关键差异”速查——没有 conda/nvm/rbenv、没有容器工具、常用文本工具基本缺席——先告诉 Claude 不能假设什么,比罗列有什么更防错

顺带把主力机的清单重扫了一遍#

清单自带的快照日期是两个半月前。重扫发现漂移比预期大得多:

  • miniconda 整个没了——zshrc 里的 conda shim 还在,但 ~/miniconda3 已删除,原 conda base 里的整套 ML 栈跟着蒸发,Jupyter 一族现在由 brew 提供。如果不重扫,Claude 会继续以为 conda activate 可用;
  • brew formulae 从 191 涨到 232;
  • LM Studio、Antigravity 卸了,VS Code、yt-dlp、一套嵌入式工具链(esptool/platformio)装上了。

这类环境清单文件的正确姿势是开头写死一行”快照日期 + drift expected + 用前 command -v 复核”,并且在文末附上”怎么正确重扫”的步骤——这次重扫就是直接照着清单自己写的步骤执行的,包括用 zsh -ic 探测 lazy-loaded 的 nvm/conda 这种细节。文档教会未来的自己(和未来的 Claude)怎么更新它自己,这个闭环比文档内容本身更值钱。

总结#

  • ~/.claude 是配置和状态的混合体,同步前先分类:描述”怎么工作”的同步,记录”干过什么”的留下,凭据永远不碰;
  • settings.json 同步 = settings.json + 它引用的所有绝对路径依赖,缺一个 hook 就静默失败,同步完要在远端实测;
  • SSOT 管冲突仲裁,不管存在性——对方机器独有的产物保留,别用 --delete 一刀切;
  • 描述单台机器事实的文件(环境清单)不进同步集,每台机器实扫自描述;
  • 非交互 SSH 的 PATH 不含 brew 和用户 bin,跨机探测”command not found”先怀疑 PATH 再怀疑没装;
  • 快照类文档要自带生成方法和过期声明,否则过期比没有更糟。
Claude Code 配置多机同步:哪些该同步、哪些是坑
https://blog.lishuyu.app/posts/claude-code配置多机同步/
作者
猫猫魔女
发布于
2026-07-11
许可协议
CC BY-NC-SA 4.0