add claude code analysis 20260404
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
# Claude Code 自动回滚机制解析与版本切换指南
|
||||
|
||||
> 日期:2026-03-31
|
||||
|
||||
## 背景
|
||||
|
||||
Claude Code 从 v2.1.88 自动回滚到 v2.1.87,本文记录了完整的排查过程和解决方案。
|
||||
|
||||
## 回滚原因
|
||||
|
||||
**Anthropic 在 npm 做了服务端回滚**,不是本地触发的。
|
||||
|
||||
### npm Registry 状态
|
||||
|
||||
| dist-tag | 版本 |
|
||||
|----------|------|
|
||||
| `stable` | 2.1.81 |
|
||||
| `latest` | 2.1.87 |
|
||||
| `next` | 2.1.89 |
|
||||
|
||||
- v2.1.88 **已被完全从 npm 删除**(registry 中不存在)
|
||||
- `latest` tag 从 2.1.88 退回到 2.1.87
|
||||
|
||||
### 时间线
|
||||
|
||||
| 时间 | 事件 |
|
||||
|------|------|
|
||||
| Mar 28 19:25 | 自动更新下载 v2.1.87 |
|
||||
| Mar 30 18:31 | 自动更新下载 v2.1.88 |
|
||||
| Mar 30 ~ Mar 31 | Anthropic 从 npm 撤掉 v2.1.88,将 `latest` tag 退回 v2.1.87 |
|
||||
| Mar 31 05:59 | 自动更新器检查 npm registry,发现 `latest` 是 2.1.87,将 symlink 切回 |
|
||||
|
||||
## 自动更新机制
|
||||
|
||||
### 核心架构
|
||||
|
||||
```
|
||||
~/.local/bin/claude → symlink → ~/.local/share/claude/versions/{version}
|
||||
```
|
||||
|
||||
- 包名:`@anthropic-ai/claude-code`
|
||||
- 版本二进制存储:`~/.local/share/claude/versions/`
|
||||
- 入口 symlink:`~/.local/bin/claude`
|
||||
|
||||
### AutoUpdater 工作流程
|
||||
|
||||
1. 每次 Claude Code 启动时,AutoUpdater 检查 npm registry 的 `latest` dist-tag
|
||||
2. 如果本地版本与 `latest` 不匹配,下载目标版本二进制到 `versions/` 目录
|
||||
3. 更新 symlink 指向新版本
|
||||
4. 逻辑是**跟随 `latest` tag**,不是单调递增 — 所以 Anthropic 退 tag 就等于回滚
|
||||
|
||||
### 关键发现
|
||||
|
||||
- 二进制是 Bun 编译的 Mach-O arm64 可执行文件
|
||||
- 内部包含 `auto_updater_disabled`、`AutoUpdater`、`autoUpdaterStatus` 等标识
|
||||
- 启动遥测会上报 `auto_updater_disabled` 状态
|
||||
- 并发更新有互斥锁保护("Another instance is currently performing an update")
|
||||
|
||||
## 禁用自动更新的正确方式
|
||||
|
||||
通过逆向二进制中的 `h1H()` / `isAutoUpdaterDisabled` 函数,确认自动更新器的检查逻辑:
|
||||
|
||||
```javascript
|
||||
// 反编译后的禁用检查逻辑(简化)
|
||||
function getAutoUpdaterDisabledReason() {
|
||||
if (process.env.DISABLE_AUTOUPDATER) return { type: "env" };
|
||||
if (config.autoUpdates === false) return { type: "config" };
|
||||
return null; // 未禁用,自动更新正常运行
|
||||
}
|
||||
```
|
||||
|
||||
### 踩坑记录
|
||||
|
||||
`autoUpdaterDisabled: true` 是**错误的 key**,写了不生效,自动更新器仍会在启动时抢先将 symlink 切回 `latest` 指向的版本。
|
||||
|
||||
### 方法 A:环境变量(推荐,最可靠)
|
||||
|
||||
```bash
|
||||
# 加到 ~/.zshrc,每次 shell 启动自动生效
|
||||
echo 'export DISABLE_AUTOUPDATER=1' >> ~/.zshrc
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
### 方法 B:settings.json
|
||||
|
||||
编辑 `~/.claude/settings.json`,注意 key 是 `autoUpdates`:
|
||||
|
||||
```json
|
||||
"autoUpdates": false
|
||||
```
|
||||
|
||||
> 注意:对于 native 安装方式,如果同时设置了 `autoUpdatesProtectedForNative: true`,则 `autoUpdates: false` 会被覆盖,此时只能用环境变量方式。
|
||||
|
||||
## 解决方案:切回 v2.1.88
|
||||
|
||||
### 步骤 1:禁用自动更新
|
||||
|
||||
```bash
|
||||
# 确保环境变量已生效
|
||||
export DISABLE_AUTOUPDATER=1
|
||||
```
|
||||
|
||||
### 步骤 2:切换 symlink
|
||||
|
||||
```bash
|
||||
ln -sf ~/.local/share/claude/versions/2.1.88 ~/.local/bin/claude
|
||||
```
|
||||
|
||||
### 步骤 3:验证
|
||||
|
||||
```bash
|
||||
claude --version
|
||||
# 输出:2.1.88 (Claude Code)
|
||||
```
|
||||
|
||||
### 步骤 4:使用
|
||||
|
||||
```bash
|
||||
claude --dangerously-skip-permissions
|
||||
```
|
||||
|
||||
## 恢复自动更新
|
||||
|
||||
```bash
|
||||
# 1. 从 ~/.zshrc 删掉 export DISABLE_AUTOUPDATER=1
|
||||
# 2. 如果用了方法 B,从 settings.json 删掉 "autoUpdates": false
|
||||
# 3. 重启终端,自动更新器会在下次启动时恢复工作
|
||||
```
|
||||
|
||||
## 其他版本切换方式
|
||||
|
||||
```bash
|
||||
# 切到 next channel (v2.1.89)
|
||||
claude update --channel next
|
||||
|
||||
# 切到 stable channel (v2.1.81)
|
||||
claude update --channel stable
|
||||
|
||||
# 查看本地已有的版本
|
||||
ls ~/.local/share/claude/versions/
|
||||
|
||||
# 手动切换到任意本地版本
|
||||
ln -sf ~/.local/share/claude/versions/<版本号> ~/.local/bin/claude
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- v2.1.88 被 Anthropic 从 npm 删除,可能存在已知问题
|
||||
- 禁用自动更新后不会收到安全修复,需定期手动检查
|
||||
- 本地残留的 v2.1.88 二进制不会被自动清理
|
||||
Reference in New Issue
Block a user