上周我在老家电脑上打开终端,敲下claude,回车。等我的不是一个熟悉的项目上下文,而是一个全新欢迎页。那一刻我意识到,之前那台工作机上攒的 skills、CLAUDE.md、命令别名、权限白名单、第三方模型配置,全部像没存在过一样。我在办公室里花了三个下午调好的 Claude Code 环境,换台电脑就归零了。
这事不是个例。Claude Code 这类终端 AI 编程工具的配置几乎全在本地,账号登录只能保住你的订阅和额度,本地目录里的会话、技能、配置统统不会跟着账号走。尤其是像我这种需要在台式机、办公笔记本、家里轻薄本、客厅 Linux 小主机之间来回切换的人,如果不在同步上花点心思,每次换机都是一次“失忆”。
这篇就是把我的四机同步方案完整拆开讲一遍:哪些文件该同步、哪些文件碰都不要碰、怎么用一条命令让新机器恢复成老机器、以及不同平台之间那堆防不胜防的小坑。内容偏实操,适合已经在用 Claude Code、且不止一台设备的开发者。看完你可以直接照抄,也可以根据这套思路魔改成自己的版本。
1. 换台电脑,Claude Code 为什么像被格式化过
1.1 我的“失忆现场”
我那天原本的计划很简单:回老家之后,继续在公司没写完的一个内部工具项目。项目代码已经推到远端仓库了,我以为把仓库 clone 下来就万事大吉。
结果claude一启动,它既不记得我项目里的背景约束,也不再认识我之前给它装的技能。更尴尬的是,它连基本的行为习惯都丢了——我在公司机器上早就配好了权限白名单,哪些命令可以直接执行、哪些文件允许读写,都是从踩坑里一点点放开的。换到老家这台机器之后,Claude Code 又变回了那个“每走一步都要问我一次”的新手状态。
我当时第一反应是:这东西不是有账号体系吗?登录同一个账号,怎么配置不跟着走?
后来把~/.claude目录翻了个底朝天,才彻底搞明白——账号归账号,配置归配置。Claude Code 的设计里,账号负责认证和计费,剩下的几乎全部是本地的。你在项目里写过的那句“所有日志文件放在 logs/ 下,不要动 public/assets”,存在CLAUDE.md里;你通过技能的安装目录,存在~/.claude/skills下;你授权过的工具清单,写在settings.json里。这些文件才是 Claude Code 真正“认识你”的基础。
1.2 真相:账号管的是额度,不是配置
想明白这一点之后,我又去翻了一圈相关资料,确认了 Claude Code 的同步边界:它能跟着账号走的,只有一个合法的登录态和订阅身份;本地的一切运行状态,都是机器专属的。
这个概念其实和很多开发工具是一致的,但 Claude Code 特别容易让人误以为它有云同步能力。因为它是一个 AI 编程工具,给人的直觉是“AI 应该记住我”。可它的记忆分两层:
- 第一层是模型上下文里的记忆,也就是对话过程中模型看到的项目文件、历史消息,这些是临时的、按会话存在的;
- 第二层是本机的持久化记忆,包括你的
CLAUDE.md、skills、commands、settings、会话历史,这些全都落在本地文件系统。
想清楚这两层之后,问题就转化了:我需要的不是让 Anthropic 帮我记住什么,而是自己想办法把第二层“本机文件”在不同设备之间搬运和同步。
尤其是现在不少人还会给 Claude Code 接第三方模型,比如 DeepSeek、GLM,或者用社区工具做多模型切换。这些配置通常写在环境变量或settings.json里,同样只存在本机。环境变量还能在 shell 配置文件里找回来,但settings.json里的各种模型参数、系统提示词、工具权限,一旦换机就是全部重来。
所以“换台电脑 Claude Code 全没了”这个问题的本质,不是一个 bug,而是本地优先架构下的必然结果。解决思路也很朴素:像管理 dotfiles 一样去管理.claude目录。
2. 同步之前,先搞清 Claude Code 到底在你机器上放了什么
2.1 ~/.claude 全家桶拆解
要制定同步方案,第一步不是急着建仓库,而是把你机器上的~/.claude目录拆开看一遍。我之后清理了大量教程类文章,也看了自己目录里实际的文件,最终把 Claude Code 在本地的数据分成以下几类。
以我目前的版本为例,~/.claude下面常见的内容包括:
| 路径 | 内容 | 同步价值 |
|---|---|---|
~/.claude/CLAUDE.md | 用户级全局记忆文件,跨项目的通用约束 | 高 |
~/.claude/settings.json | 用户级配置,模型、权限、行为开关 | 高(需脱敏) |
~/.claude/commands/ | 自定义斜杠命令,比如/review、/deploy | 高 |
~/.claude/skills/ | 技能目录,社区安装的各种 skills | 高 |
~/.claude/agents/ | 自定义 agent 定义 | 高 |
~/.claude/todos/ | 任务清单,跨会话维护 | 中 |
~/.claude/projects/ | 按项目路径编码的会话记录,JSONL 格式 | 低(按需) |
~/.claude/history.jsonl | 全局会话历史索引 | 低 |
~/.claude/shell-snapshots/ | 终端会话快照,用于恢复 shell 状态 | 低,且含敏感信息 |
~/.claude/.statsig/ | 实验开关等临时状态 | 忽略 |
~/.claude/.credentials.json | 登录凭据或密钥 | 忽略并保护 |
项目级的CLAUDE.md不在这个目录里,它跟着项目仓库走。所以如果项目代码存在 Git 仓库里,项目级记忆天然就已经在同步了。真正容易被忽略的是用户级的~/.claude/CLAUDE.md,以及上面这些全局配置。
这里说一个很多人不知道的点:projects/目录下的会话文件,文件名是用项目路径编码过的。比如你/home/me/work/app下的项目,会生成一个类似-home-me-work-app.jsonl的文件。也就是说,Claude Code 判断“这是哪个项目的会话”靠的是绝对路径,而不是 Git remote。这也是为什么换机器之后,即使你把项目 clone 到同一个仓库,它也不会自动关联之前的会话——因为在新机器上项目路径可能完全不一样。
2.2 哪些必须同步,哪些同步反而会出事
我一开始脑子一热,想过干脆把整个~/.claude目录塞进云盘,一了百了。后来发现这是最蠢的方案,原因有四个:
第一,shell-snapshots/目录里可能有终端里的明文信息。Claude Code 为了恢复 shell 状态会把环境变量、历史命令之类的东西记录下来。这东西同步到别的机器,既没有价值,还有泄露风险。
第二,projects/目录大且敏感。我用了两个月后,这个目录已经有三四百 MB。里面是完整对话记录,包含粘贴过的代码、API 请求、错误日志,甚至可能包含密钥片段。把它塞进同步仓库,仓库很快会爆炸,而且等于把机密文件复制到所有设备上。
第三,.statsig、日志文件这类临时状态同步过去毫无意义。Claude Code 在每台机器上会自己重建这些内容,你强行同步只会制造冲突。
第四,settings.json里很可能有你不该提交的密钥。很多教程会让你在settings.json里直接写apiKey或者第三方服务的 token。如果你不做脱敏处理就拉进同步仓库,等于把密钥广播给所有 clone 这个仓库的人。
所以我的原则是:配置和技能要同步,数据和秘密不硬同步。
具体到文件级别,我最终选择同步的是这些:
CLAUDE.mdsettings.json(脱敏后,敏感字段用环境变量替代)commands/skills/agents/todos/(可选,因为更新频繁,容易产生冲突)
所有这些加起来,实际体积还不到 10MB,非常适合放进一个 Git 私有仓库。
3. 四机同步方案的整体设计与目录策略
3.1 为什么选 Git 私有仓库做“配置主源”
确定要同步的内容之后,接下来一个问题:用什么做同步通道?
市面上无非三种选择:网盘(iCloud、OneDrive、坚果云)、P2P 同步工具(Syncthing)、Git 私有仓库。我四台机器分别是 Windows、macOS、Linux 混着用,网盘客户端在这三个平台上的行为差异很大,而且在后台实时同步文件时,很容易把我正在写的settings.json同步到一半,导致配置损坏。
Syncthing 整套方案我也试过,后文会详细讲。这里先说我放弃它做主力通道的直接原因:它倾向于“设备之间自由同步”,一旦一台机器离线,另一台机器改了配置,等它上线后很容易因为双向同步产生冲突文件,而且冲突解决逻辑不透明,对于文本配置来说并不友好。
Git 私有仓库最大的优势是同步逻辑是人类可读的:改了什么、什么时候改的、在哪台机器上改的,全都有迹可循。就算两台机器同时改同一个文件,Git 也能明确告诉你冲突了,而不是静悄悄地把文件覆盖掉。
我最终选的方案就是:一个私有 Git 仓库当“配置主源”,每台机器都只和这个仓库保持同步,机器之间不直接对话。
仓库结构大致是这样的:
claude-code-sync/ ├── CLAUDE.md ├── settings.json ├── commands/ │ ├── review.md │ └── deploy.md ├── skills/ │ └── ... ├── agents/ │ └── ... ├── scripts/ │ └── bootstrap.sh ├── scripts/ │ └── bootstrap.ps1 └── .env.example这里有两个关键设计:一是settings.json里不写真实密钥,统一用${env:XXX}或${env:XXX}这类方式读取环境变量,每台机器各自维护一份.env;二是保留一份.env.example作为新机器的配置清单,告诉你在哪里填哪些 key。
3.2 用符号链接把真实配置“接”进仓库
仓库建好之后,怎么让 Claude Code 用它?
最粗暴的做法是:每台机器 clone 仓库之后,复制文件到~/.claude。问题是,复制过去之后,仓库和实际使用目录就是两份文件。你在这台机器上改配置时,到底改的是哪一份?很容易分心,然后忘记提交。
更好的做法是符号链接(symlink)。我把~/.claude里的settings.json、commands、skills、agents、CLAUDE.md分别做成符号链接,指向仓库里的对应文件或目录。这样 Claude Code 在运行时实际读到的就是仓库里的文件,本机改配置等于直接改仓库,然后整个流程就变成“改仓库、提交、push”。
这里有一个容易翻车的细节:不能把整个~/.claude目录做成软链。因为.claude目录里还有大量不需要同步的内容,比如.statsig、shell-snapshots、projects。如果整目录软链,你就得把它们全部纳入 Git 管理,不然新机器上会缺目录,导致 Claude Code 启动异常。
我采用的方式是分项目录软链。以 macOS/Linux 为例:
mkdir -p ~/.claude ln -sfn ~/code/claude-code-sync/CLAUDE.md ~/.claude/CLAUDE.md ln -sfn ~/code/claude-code-sync/settings.json ~/.claude/settings.json ln -sfn ~/code/claude-code-sync/commands ~/.claude/commands ln -sfn ~/code/claude-code-sync/skills ~/.claude/skills ln -sfn ~/code/claude-code-sync/agents ~/.claude/agents注意,skills、commands、agents这几个目录在第一次安装 Claude Code 时不一定存在。如果不存在,软链会失败或者行为奇怪。我的脚本里会先检查,如果原来没有这些目录,就直接创建目录,然后把仓库里的内容链接过去。如果原来已经有目录了,但里面没有需要保留的本地数据,直接rm -rf再链也不亏。
这样做的收益很明显:任何一台机器上安装了新 skill,或者改了一条 command,它直接落在仓库里,其它机器只要git pull就自动生效,不需要再拷贝一次。
4. 落地执行:同步仓库、bootstrap 脚本与跨平台处理
4.1 初始化仓库与筛选文件
先别急着在每台机器上配软链,第一件事是初始化主仓库。
我在Github上建了一个名为claude-code-sync的私有仓库,然后在第一台机器上把它 clone 到~/code/claude-code-sync。接着把需要同步的文件复制进去。注意,settings.json先复制过去之后,要立刻打开它,把里面的敏感字段改成环境变量引用。比如原先是:
{ "apiKeyHelper": "...", "model": "claude-sonnet-4-20250514" }我会改成:
{ "model": "claude-sonnet-4-20250514", "apiKeyHelper": "env:ANTHROPIC_API_KEY" }不同版本对apiKeyHelper的写法可能不一样,但原理是一样的:不要在配置文件里留下明文密钥。如果你是通过ANTHROPIC_BASE_URL接第三方模型,也是同样的处理方式,把 URL 和 key 都挪到环境变量里。
然后我添加了一个.gitignore,明确忽略不该进仓库的东西:
.env *.log .DS_Store再强行补一条目录排除规则,防止有人误把整个projects目录拖进来:
projects/ shell-snapshots/ .statsig/ credentials*关于todos/,我一开始是同步的,后来发现它更新太频繁,两台机器同时工作时会产生不少无意义的提交记录。最终我把它从仓库移除了,只在主力机器上保留。如果你也用 Git 管理,建议先忍住不要同步todos/,等确实有跨设备待办需求再加回来。
4.2 bootstrap 脚本:从零到能跑的三步
仓库有了,接下来是让新机器快速接入。我写了两个脚本,一个给 bash/zsh(macOS、Linux、WSL 都能用),一个给 PowerShell(Windows)。
bash 脚本核心逻辑:
#!/usr/bin/env bash set -euo pipefail REPO_DIR="$HOME/code/claude-code-sync" CLAUDE_DIR="$HOME/.claude" if [ ! -d "$REPO_DIR" ]; then echo "仓库不存在,请先 clone 到 $REPO_DIR" exit 1 fi mkdir -p "$CLAUDE_DIR" link_item() { local name="$1" local target="$REPO_DIR/$name" local link_path="$CLAUDE_DIR/$name" if [ -e "$link_path" ] && [ ! -L "$link_path" ]; then mv "$link_path" "$link_path.bak.$(date +%s)" echo "备份原有 $name 到 $link_path.bak.*" fi ln -sfn "$target" "$link_path" echo "已链接 $name" } link_item "CLAUDE.md" link_item "settings.json" link_item "commands" link_item "skills" link_item "agents"这段脚本有几个细节值得说明:
set -euo pipefail保证中间任何一步失败都会停下,不会留下半成品。- 遇到已有文件但又不是符号链接的情况,我没有直接删,而是先备份。这个非常重要,因为新机器上如果已经跑过一次 Claude Code,它可能已经生成了自带的
settings.json,直接删掉会导致你丢东西。 ln -sfn里的-f是为了强制替换,-n是防止目标是一个目录时把链接创建到目录内部去。
PowerShell 版本的思路一样,只是符号链接命令不同:
New-Item -ItemType SymbolicLink -Path "$env:USERPROFILE\.claude\skills" -Target "$env:USERPROFILE\code\claude-code-sync\skills"Windows 上创建符号链接有几个前置条件,后面单独讲。
接入新机器的完整流程被我压缩成了三句话:
- 装好 Claude Code 本体,跑过一次让目录结构生成;
- clone 我的同步仓库到
~/code/claude-code-sync; - 运行 bootstrap 脚本,然后配置
.env环境变量。
整个流程熟练之后只需要两三分钟,新机器就能拥有和老机器几乎一致的 Claude Code 环境。
4.3 Windows、macOS、Linux 三端差异处理
这套方案真正的难点不在脚本本身,而在平台差异。我在四台机器上踩了一圈,总结出下面几个高频坑。
第一个坑:Windows 上的符号链接权限。
默认情况下,普通用户在 Windows 上执行New-Item -ItemType SymbolicLink会报错,提示“你没有足够的权限执行此操作”。这不是 PowerShell 的问题,而是 Windows 的安全策略。解决办法有两个:
- 打开“开发者模式”:设置 → 隐私和安全性 → 开发者选项 → 打开“开发人员模式”。开启后,普通用户就能创建符号链接。
- 或者用管理员身份的终端执行脚本。
我最终选择开启开发者模式,因为这样不用每次都以管理员身份运行。
第二个坑:Windows 下的 PowerShell 执行策略。
运行我的bootstrap.ps1脚本可能被系统拦下来。你可以用Set-ExecutionPolicy -Scope CurrentUser RemoteSigned放宽本用户的执行限制,但要注意这是有安全影响的。如果只是临时跑一次,我建议直接在当前 PowerShell 窗口里复制脚本逐行执行。
第三个坑:macOS 和 Linux 的~/展开差异。
bash 脚本里我用了$HOME而不是~,就是为了避免在脚本里因为引号问题导致~不展开。这个坑在写 cron 任务时尤其明显,交互式 shell 里正常,脚本里就翻车。
第四个坑:换行符。
Windows 上如果用了 Git 默认配置,checkout 仓库时可能会把settings.json的换行符转成 CRLF。Claude Code 读 JSON 一般不受影响,但CLAUDE.md是纯文本,如果换行符变了,在最坏情况下会导致 markdown 格式错乱。我的解决方式是:在同步仓库根目录添加.gitattributes:
* text=auto *.json text eol=lf *.md text eol=lf *.sh text eol=lf这样无论在哪台机器上 checkout,关键的 JSON 和 Markdown 文件都会保持 LF 换行。
第五个坑:环境变量怎么跨平台统一。
不同平台的 shell 配置不一样。macOS 和 Linux 我写在~/.zshrc或~/.bashrc,Windows 上我写在 PowerShell$PROFILE里。内容基本一致:
export ANTHROPIC_MODEL="claude-sonnet-4-20250514" export ANTHROPIC_API_KEY="sk-ant-..." # 如果你用第三方模型,再加 export ANTHROPIC_BASE_URL="https://api.example.com"然后把.env.example放进同步仓库,每一台机器 clone 之后照着填一遍。注意.env本身不进仓库,每台机器的 key 可以不同,这样反而更安全——比如家用机用一个限制更严格的 key,服务器上用另一个。
5. 会话历史与私有数据的取舍:我不建议全量同步
5.1 让 git 承载全部会话?这是坑
写完基础同步方案之后,我第一个想解决的问题就是:新机器上没有之前的对话记录,Claude Code 对我的项目一无所知。
于是我想过把~/.claude/projects/目录也纳入同步。结果试了两天,立即放弃了。
首先是体积问题。一次完整会话的 JSONL 文件可能是几十 KB 到几 MB,我用了两个月之后整个projects/目录已经有几百 MB。Git 仓库就算压缩,也会变得越来越大,每次push都卡顿,何况里面还有大量重复的代码片段。
其次是隐私问题。projects/里的 JSONL 是对话全文,里面经常包含我不小心粘贴进去的密码、内部 API 的完整请求、客户数据字段。把这些内容同步到我所有设备上的仓库里,等于扩大了敏感信息的暴露面。我的原则是:敏感数据能少复制一份就少复制一份。
第三是路径匹配问题,这是最隐蔽的坑。前面说过,Claude Code 的会话记录按项目绝对路径编码。你在公司机器的/Users/me/work/app下工作,会话文件叫-Users-me-work-app.jsonl。到了家里,项目如果放在/Users/me/Documents/work/app,即使你把同一个项目 clone 下来,Claude Code 也会认为这是一个完全不同的项目,原来的会话记录根本对不上。
所以,即使我把projects/全量同步过去,只要两台机器项目路径不一样,那些会话在新机器上依然是“不存在”的。
5.2 按需迁移会话,而不是硬同步
既然不是继续全量同步,那我怎么在换机后继续之前的工作?
我的方案分两步。
第一步,统一项目路径。我在所有机器上都约定项目放在同一个位置的同一个目录名下面,比如统一放在~/work/<project-name>。这样虽然不同系统的$HOME路径前缀不一样,但项目内相对路径一致。至少在有需要时,我可以手工迁移一条会话。
第二步,按需手工迁移。如果我在公司电脑上处理到一半的任务,回家还想继续,我不会同步整个projects/,而是只导出那一个项目的 JSONL 文件。具体操作:
- 在源机器上找到对应的会话文件,比如
~/.claude/projects/-Users-me-work-app.jsonl; - 把它安全复制到新机器上同样的
~/.claude/projects/目录下; - 启动
claude,用--continue或者--resume找到最近的会话。
这样做的好处是:我只复制了必要的那一条会话,体积小、暴露面小,而且因为项目路径一致,Claude Code 能正确识别。如果项目路径不一致,我宁可在新机器上重新开一个会话,把项目的CLAUDE.md和关键 README 丢给它,让它快速重新进入状态。
要补充的是,CLAUDE.md才是跨机器“记忆”的正主。只要项目里的CLAUDE.md写得够好,新机器重新开会话的成本是很低的。我后来刻意花时间把项目的CLAUDE.md写得更细,同步需求自然就降下来了。
6. 多机日常协作与冲突处理
6.1 同时改配置的 Git 冲突怎么解决
方案跑起来之后,真正会咬人的是冲突。
我手里的四台机器并不是一台闲置一台用,而是可能同时开着。比如我在办公电脑上装了一个新 skill,晚上回家,看到家里电脑上正好也改了一个自定义 command。两台机器都还没来得及push,于是第二天办公电脑pull的时候,冲突就来了。
Git 的冲突处理对于文本配置来说,不算难,但要有流程。
我自己的习惯是:
- 每次准备提交前,先
git pull --rebase,把远端提交拉到本地再变基,避免出现 merge commit 把历史搅乱。 - 如果真冲突了,
git status看是哪个文件冲突。settings.json冲突最常见,因为它是单文件。 - 打开冲突文件,把两边的修改手动合并。如果只是某一行模型名不一样,选最新的那个就行;如果是权限列表冲突,我会把两边的
allow数组都合并进来。 - 合并完
git add、git rebase --continue,然后git push。
这里我要说一个反直觉的结论:冲突并不完全是坏事。因为配置文件的冲突不会影响代码运行,它反而会逼着你去想“我在其他机器上到底改了些什么”,很多时候能发现自己重复安装了两个相似技能的冗余。
为了减少冲突频率,我还用了另一个策略:为settings.json配置一个自定义 merge driver。简单来说,就是让 Git 在合并这个文件时,不要逐行 diff,而是以“一方优先、另一方丢弃”的方式处理。但自定义 merge driver 的配置有点繁琐,且不一定适合所有人,我这里不展开。对大多数单人或双人使用场景,手动处理冲突已经足够了。
6.2 日常同步流程和验证清单
把同步流程变成一个肌肉记忆,我的做法是把它压缩成一条命令。在 shell 配置里加了一个 alias:
alias csync='cd ~/code/claude-code-sync && git pull --rebase && git add -A && git commit -m "sync $(date)" && git push'每次在一台机器上改完配置、装完 skill、调完命令,退出 Claude Code 之后,顺手敲一句csync,配置就会被兜住。这个 alias 很糙,但对个人使用场景来说非常够用。
到了另一台机器,直接csync一次,然后重启 Claude Code,一切就同步了。
这里要特别提醒一点:Claude Code 在运行状态中可能会缓存配置。如果你在一台机器上修改了settings.json,推到另一台机器后,那台机器正开着的 Claude Code 不会立刻感知到。需要退出重进。如果是改了CLAUDE.md,通常新的会话会自动读取,但正在进行的会话不会更新。
新机器跑完 bootstrap 之后,我建议按下面这个清单验证一遍:
| 验证项 | 方法 | 预期结果 |
|---|---|---|
| 全局配置生效 | 在任意目录执行claude,观察启动行为 | 模型、权限、问候语与旧机器一致 |
| 技能同步成功 | 进入对话后输入/help或触发技能安装列表 | 能看到仓库里同步过来的 skills |
| 自定义命令可用 | 输入/review或其他自定义斜杠命令 | 正常执行 |
| 全局 CLAUDE.md 生效 | 新建一个临时项目,问它“我们的项目有哪些约定” | 能复述出 CLAUDE.md 中的关键约束 |
| 环境变量正确 | 通过对话或日志确认模型接入正常 | 第三方模型能正常响应 |
这套验证看起来繁琐,其实两分钟就能跑完。我后来已经熟练到只要看启动时的模型名和能自动补全的命令列表,就知道同步成没成功。
7. 这套方案的边界与替代方案
7.1 四个最容易被忽略的坑
方案讲了这么多,说几个我自己踩过、但网上很少被提到的坑。
坑一:settings.json可能被工具本身改写。
Claude Code 更新版本之后,有时会往settings.json里写入新的配置项。如果你的settings.json是一个符号链接,这没问题,它会直接在仓库文件里写。但如果新版本在升级时“好心”地备份了一下旧配置,它会复制出一个.bak文件,而这个文件如果被 Git 跟踪了,目录里就会出现大量奇怪的历史快照。我的处理是:.gitignore里把*.bak*全局忽略掉。
坑二:Windows 上杀毒软件可能拦截符号链接。
Windows Defender 或者其他安全软件有时会把符号链接当成可疑行为。尤其当你的开发目录和配置目录不在同一个盘符时,创建链接偶尔会被拦截。我没有找到完美的解决方案,只能说尽量让仓库路径固定,少换位置。如果一个链接建立失败,优先检查是不是杀毒软件拦截了New-Item。
坑三:不要把.env.example和真实.env放混。
我有一次在同步仓库里误提交了真实的.env文件,虽然仓库是私有的,但这也是一次典型的安全失守。后来我在.gitignore里同时忽略了.env和.env.*,但随后发现连.env.example也被忽略了。改成了这样:
.env .env.* !.env.example又把.env.example强制保留。这个细节看起来不起眼,但能防止把示例文件弄丢。
坑四:多机同时操作同一个项目时要格外小心。
配置同步没问题,但如果我在两台机器上同时改同一个代码项目,Claude Code 的会话状态会非常混乱。它基于本地文件目录工作,不会知道另一台机器上发生了什么。最后合并代码倒不怕,怕的是它会用旧的代码状态给你生成修改建议。所以我现在给自己定了一条规矩:**同一个项目,同一时间只在一台机器上做 AI 辅助开发。**另一台机器可以看代码、写代码,但不跑 Claude Code。
7.2 不满足的场景怎么办:云盘、Syncthing 等备选
Git + 符号链接这套方案不是银弹。它主要的短板是:**同步是手动的,不实时。**如果你只有一台主力机、一台备用机,手动push/pull完全够用。如果你需要两台机器近乎实时地共享同一个配置状态,或者你不想维护 Git 仓库,可以考虑另外两种方案。
云盘同步:把~/.claude下面需要同步的目录放进 iCloud、OneDrive、坚果云这类网盘的同步目录里,再用符号链接指过去。优点是没有 Git 的学习成本,缺点同样明显——网盘客户端在后台同步时可能在你写入配置的半途锁文件,导致配置损坏;而且如果你不小心把整个.claude目录放进去,等它同步几个 GB 的会话记录时会让你怀疑人生。真要这么用,建议只放CLAUDE.md和skills/这种低变更目录。
Syncthing:在自建设备之间做近实时同步,不经过第三方服务器。它比网盘可控,也比 Git 实时。我之前试过用 Syncthing 同步~/.claude,跑了一周,最终败给了冲突文件。Syncthing 在遇到双端同时修改时,会保留一个*.sync-conflict-*文件,配置目录里到处都是这种文件,Claude Code 虽然不理会它们,但看着很难受。
所以我的结论是:如果你很懒,只想同步 skills 和 CLAUDE.md,用 Syncthing 也能将就。如果你想完整复刻我的方案、且能接受手动同步,Git 私有仓库是最稳的。
回到开头那个场景。现在我回老家,只需要花两分钟跑一遍 bootstrap,然后csync一下,整个 Claude Code 就恢复了我在公司电脑上的样子。skills 全在,CLAUDE.md 全在,权限白名单全在,第三方模型的接入也不用手动配。这个过程里,真正让我觉得有价值的不只是同步本身,而是我被迫把自己的配置“显式化”了——以前那些零散写在某个角落的配置,现在都变成了仓库里看得见、管得住的文本文件。
最后再分享一个小经验:**先别追求完美,从只同步CLAUDE.md和skills开始。**把这一小步跑通之后,你自然会理解哪些配置值得同步、哪些数据需要单独处理。等你想明白这一点,再上 Git 仓库、再写 bootstrap 脚本,效率和满意度都会比一上来就折腾全套高得多。