PIXEL_CLAUDE_CODE_OAUTH_SETUP.md 11.2 KB

Pixel + Termux 复用 Mac OAuth Token 跑 Claude Code

在 Pixel 10 Pro Fold(Android 16)的 Termux + Ubuntu proot 容器里运行 claude-run,复用 Mac 上同款 Anthropic OAuth Token,完全替换原来的 Kimi 反代方案。


1. 背景

  • 设备:Pixel 10 Pro Fold(代号 rango)/ Android 16,bootloader 已解锁,Magisk root
  • 原方案:claude-code 通过 Kimi Coding Plan 反代(https://api.kimi.com/coding/),用 Kimi token 走所有请求
  • 新目标:直连 api.anthropic.com,复用 Mac 上 ~/.zshrc 里的 CLAUDE_CODE_OAUTH_TOKEN,使用真正的 Claude Opus 4.7
  • 动机:Frida 在 Android 16 无法跑(ptrace/CFI/SELinux 多重限制),后续工作转向 LSPosed + 真 Claude 模型,需要 Pixel 端本地也能跑 claude-code

2. 架构总览

┌─────────────────────────────────────────────────────────────┐
│ Termux (Android shell, user u0_a327)                        │
│                                                              │
│  ~/.bashrc                                                   │
│   └─ export CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-...         │
│                                                              │
│  /usr/bin/claude-run  ←─ wrapper                             │
│   └─ proot-distro login --shared-home ubuntu                 │
│      -- env CLAUDE_CODE_OAUTH_TOKEN="..." claude "$@"        │
│                                                              │
│        ▼                                                     │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ Ubuntu proot container                                │   │
│  │  /root  ←(--shared-home)─→  /data/data/com.termux/.../home│
│  │   ├─ .claude.json          ← claude 主配置            │   │
│  │   └─ .claude/settings.json ← per-user settings        │   │
│  │                                                       │   │
│  │  claude (ELF/glibc, Node.js)                          │   │
│  │   └─→ HTTPS api.anthropic.com                         │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

关键点:

  • Claude Code 是 ELF/glibc 编译,Android Bionic 跑不了 → 必须 proot 跑 Ubuntu
  • --shared-home 把 Termux home 绑定为容器 /root,配置文件可以从 Termux 端直接编辑
  • Token 通过 env KEY=VAL claude 在容器内瞬时注入,不进容器 shell 环境

3. Claude Code 的双重认证闸门

这是整个迁移最关键的认知 —— claude-code 启动时有两道独立闸门:

闸门 检查内容 headless (claude -p) 交互模式 (claude)
① Token 闸门 CLAUDE_CODE_OAUTH_TOKEN env 或 ~/.claude/.credentials.json 任一存在 必须过 必须过
② Onboarding 闸门 ~/.claude.json 的 hasCompletedOnboarding === true 跳过 必须过

Kimi 反代为什么"屏蔽"了 Onboarding 闸门:它的 .env 块在启动时被 claude-code 注入进进程,等价于一直在用 API key 模式,OAuth onboarding 检查被旁路掉了。一旦切回官方 Anthropic,闸门被激活,于是裸 claude-run 弹出 OAuth URL。


4. 完整改动清单

按依赖顺序(缺一不可):

4.1 改 wrapper:注入 OAuth Token

文件:/data/data/com.termux/files/usr/bin/claude-run

#!/data/data/com.termux/files/usr/bin/sh
# Claude Code via proot-distro with shared home + Mac OAuth token
exec proot-distro login --shared-home ubuntu -- env CLAUDE_CODE_OAUTH_TOKEN="sk-ant-oat01-<...>" claude "$@"

权限:chmod 711(owner 可读,其他 app 不可读),owner u0_a327:u0_a327。

Token 直接 inline 到 wrapper,避免依赖 shell 启动文件。Android 沙箱保证其他 app 读不到 /data/data/com.termux/ 下的文件。

4.2 写 settings.json:清理 Kimi 痕迹

文件:/data/data/com.termux/files/home/.claude/settings.json

{
  "env": {},
  "model": "opus",
  "skipDangerousModePermissionPrompt": true,
  "theme": "dark"
}

权限:chmod 600。

env 必须为空 {} —— 之前 Kimi 配置在这里塞了 ANTHROPIC_BASE_URL / ANTHROPIC_API_KEY 等,会覆盖 wrapper 注入的 token。

4.3 清理 ~/.claude.json 的 env 块(最容易漏的一步)

文件:/data/data/com.termux/files/home/.claude.json

claude-code 的"主配置文件",顶层有个 env 字段会在进程启动时被 setenv 进去,优先级高于 wrapper 传入的 env。

操作(用 jq 在 Mac 端处理后 push 回去):

jq 'del(.env)
    | .customApiKeyResponses.rejected = []
    | .model = "opus"
    | .hasCompletedOnboarding = true
    | .lastOnboardingVersion = "2.1.144"' \
   ~/.claude.json.backup > ~/.claude.json.cleaned

需要保证:

  • .env 字段被删除(不是设为空,是整个 key 不存在)
  • .hasCompletedOnboarding = true ← 过 Onboarding 闸门
  • .lastOnboardingVersion = "2.1.144" ← 与当前 claude-code 版本对齐
  • .model = "opus"(之前 Kimi 用的 "opus[1m]" 在官方 API 不存在)
  • .customApiKeyResponses.rejected = [](清掉之前 reject 过的 Kimi key 历史)

权限:chmod 600,owner u0_a327:u0_a327。


5. 完整执行脚本(从 Mac 端一键执行)

#!/usr/bin/env bash
set -euo pipefail

# 1. 从 Mac ~/.zshrc 提取 token
TOKEN=$(awk -F= '/^export CLAUDE_CODE_OAUTH_TOKEN=/{sub(/^export CLAUDE_CODE_OAUTH_TOKEN=/, ""); print; exit}' ~/.zshrc)
[ -z "$TOKEN" ] && { echo "ERROR: token not found in ~/.zshrc"; exit 1; }

# 2. 构造文件
mkdir -p /tmp/claude-pixel
cat > /tmp/claude-pixel/claude-run <<EOF
#!/data/data/com.termux/files/usr/bin/sh
exec proot-distro login --shared-home ubuntu -- env CLAUDE_CODE_OAUTH_TOKEN="$TOKEN" claude "\$@"
EOF
chmod 711 /tmp/claude-pixel/claude-run

cat > /tmp/claude-pixel/settings.json <<'EOF'
{
  "env": {},
  "model": "opus",
  "skipDangerousModePermissionPrompt": true,
  "theme": "dark"
}
EOF

# 3. 处理 .claude.json(先 pull,patch,push)
adb shell "su -c 'cp /data/data/com.termux/files/home/.claude.json /sdcard/cc.json && chmod 644 /sdcard/cc.json'"
adb pull /sdcard/cc.json /tmp/claude-pixel/cc.json
adb shell "su -c 'rm /sdcard/cc.json'"
jq 'del(.env)
    | .customApiKeyResponses.rejected = []
    | .model = "opus"
    | .hasCompletedOnboarding = true
    | .lastOnboardingVersion = "2.1.144"' \
   /tmp/claude-pixel/cc.json > /tmp/claude-pixel/cc.patched.json

# 4. push & 安装
adb push /tmp/claude-pixel/claude-run /sdcard/claude-run.new
adb push /tmp/claude-pixel/settings.json /sdcard/settings.json.new
adb push /tmp/claude-pixel/cc.patched.json /sdcard/cc.json

adb shell "su -c '
WRAPPER=/data/data/com.termux/files/usr/bin/claude-run
SETTINGS=/data/data/com.termux/files/home/.claude/settings.json
MAIN=/data/data/com.termux/files/home/.claude.json

# 备份原版(只备份一次)
[ ! -f \$WRAPPER.prekimi ] && cp \$WRAPPER \$WRAPPER.prekimi
[ ! -f \$MAIN.prekimi ] && cp \$MAIN \$MAIN.prekimi

# 安装新版
cp /sdcard/claude-run.new \$WRAPPER
chown u0_a327:u0_a327 \$WRAPPER && chmod 711 \$WRAPPER

mkdir -p \$(dirname \$SETTINGS)
cp /sdcard/settings.json.new \$SETTINGS
chown u0_a327:u0_a327 \$SETTINGS && chmod 600 \$SETTINGS

cp /sdcard/cc.json \$MAIN
chown u0_a327:u0_a327 \$MAIN && chmod 600 \$MAIN

# 清理
rm /sdcard/claude-run.new /sdcard/settings.json.new /sdcard/cc.json
echo done
'"

# 5. 清理 Mac 临时文件
rm -rf /tmp/claude-pixel

6. 验证

6.1 headless 模式

adb shell 'su u0_a327 -c "
export HOME=/data/data/com.termux/files/home
export PATH=/data/data/com.termux/files/usr/bin:\$PATH
cd \$HOME
claude-run -p \"reply with just OK\" < /dev/null
"'

期望输出:OK(前面有几行 proot warning: can't sanitize binding /proc/self/fd/... 是 adb 非 tty 模式的良性警告,无视)。

6.2 交互模式(用户在 Termux 里直接跑)

$ claude-run

期望:直接进入 Claude Code TUI 界面,不弹出 OAuth URL。

6.3 排错检查清单

症状 检查
报错指向 kimi.com/code/console ~/.claude.json 的 env 块没删干净
弹出 OAuth 登录 URL ~/.claude.json 的 hasCompletedOnboarding 不是 true
Failed to authenticate. 401 Mac 那边的 token 已失效,去 Mac 重新登录刷新
Warning: no stdin data received in 3s headless 模式没加 < /dev/null,等 3 秒后会继续,不是错误
which claude-run 指向其他路径 PATH 优先级问题 / 装了 alias

7. 回滚

之前的版本都备份在 .prekimi 后缀文件里:

adb shell "su -c '
cp /data/data/com.termux/files/usr/bin/claude-run.prekimi /data/data/com.termux/files/usr/bin/claude-run
cp /data/data/com.termux/files/home/.claude.json.prekimi /data/data/com.termux/files/home/.claude.json
echo rolled back to Kimi config
'"

8. 安全注意

  • Wrapper 里 inline 的 OAuth token 是个长效凭证,泄露等于账号被借用
  • 文件权限:wrapper 711(不可读其他 app),.claude.json 600
  • Android 沙箱保证其他 app 无法访问 /data/data/com.termux/ 下的文件
  • 如果手机丢失或共享,Mac 端立刻去 Anthropic console 撤销该 token(一撤销 Mac/Pixel 同时失效,需要重新登录刷新)

9. 已知限制

  1. 网络出口:直连 api.anthropic.com 需要稳定国际网络。Pixel 在 4G 蜂窝下不一定通,建议挂代理或走 Wi-Fi
  2. 计费归属:使用 Mac 同一个 Anthropic 账号配额,Pixel 跑多了会消耗 Mac 同账号的 quota
  3. Token 刷新:OAuth access token 有效期约 1 年,过期后需要在 Mac 端重新执行 OAuth 流程刷新,然后把新 token 同步到 Pixel wrapper
  4. 多设备 token 复用合规性:Anthropic ToS 允许同一账号在多设备使用,但禁止把 token 分享给第三方

10. 相关文件索引

路径 作用
/data/data/com.termux/files/usr/bin/claude-run wrapper(inline token)
/data/data/com.termux/files/usr/bin/claude-run.prekimi 旧版备份
/data/data/com.termux/files/home/.claude.json claude-code 主配置
/data/data/com.termux/files/home/.claude.json.prekimi 主配置备份(含 Kimi)
/data/data/com.termux/files/home/.claude/settings.json per-user settings
/data/data/com.termux/files/usr/var/lib/proot-distro/containers/ubuntu/rootfs Ubuntu 容器 rootfs

Mac 端: | 路径 | 作用 | |------|------| | ~/.zshrc 里的 CLAUDE_CODE_OAUTH_TOKEN | Token 来源 | | ~/.claude.json | Mac 上对应的主配置(参照对比用) |