Commit 85a1571a7c3b239810e6cc550ceed506c7915391
1 parent
98be58b0
docs(hermes-agent): Pixel 编译安装 hermes-agent + 配置 Kimi Coding Plan 文档
新增 HERMES_AGENT_PIXEL_SETUP.md,记录从 Mac 经 adb 把 NousResearch hermes-agent 装到 Pixel Termux 的完整流程及两个坑(bootstrap 过期导致 node openssl 符号缺失需先 apt upgrade;wrapper /usr/bin/env shebang 在 su -c 下失效需改绝对路径),以及 Kimi Coding Plan 的原生配法(kimi-coding provider + api.kimi.com/coding,运行时自动切 anthropic 协议 + claude-code UA)。 - README.md 目录清单登记新文档 + 补登 PIXEL_CLAUDE_CODE_OAUTH_SETUP.md - API key 用占位符,未写真实凭证 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Showing
3 changed files
with
442 additions
and
0 deletions
wechat_plain/scripts/local-testkit/docs/HERMES_AGENT_PIXEL_SETUP.md
0 → 100644
| 1 | +# 在 Pixel 上编译安装 hermes-agent + 配置 Kimi Coding Plan | ||
| 2 | + | ||
| 3 | +> 目标设备:Pixel 8 Pro (husky),Android 16,已 root(Magisk)+ Termux。 | ||
| 4 | +> hermes-agent = **NousResearch 的自改进 AI agent**(github.com/NousResearch/hermes-agent,Python 3.11+/Node),提供 `hermes` CLI(`hermes` 聊天 / `hermes gateway` 消息网关 / `hermes setup` 配置)。本文记录从 Mac 经 adb 把它装到 Pixel Termux,并接 Kimi Coding Plan 作为 LLM 后端的完整流程。 | ||
| 5 | +> | ||
| 6 | +> 相关记忆:`~/.claude/.../memory/hermes-agent-termux-install.md`、`magisk-su-android-inet-group.md`、`termux-path-convention.md`。 | ||
| 7 | + | ||
| 8 | +--- | ||
| 9 | + | ||
| 10 | +## 0. 前置 | ||
| 11 | + | ||
| 12 | +- 设备已 root,Termux 已装(GitHub/F-Droid 版,非 Play 商店)。Termux 重装/设备 restore 后 **uid 会变**,先取当前 uid: | ||
| 13 | + ```bash | ||
| 14 | + adb shell 'su -c "stat -c %u /data/data/com.termux"' # 例:10302(low3 = 302) | ||
| 15 | + ``` | ||
| 16 | +- 所有「以 Termux 用户身份联网」的命令必须带 inet 等 supplementary group,否则 DNS/网络全断。统一模板(uid=10302 为例): | ||
| 17 | + ``` | ||
| 18 | + su -g 10302 -G 3003 -G 9997 -G 20302 -G 50302 10302 -c "<cmd>" | ||
| 19 | + ``` | ||
| 20 | + 其中 `3003=inet 9997=everybody 20<low3>=cache 50<low3>=all_aN`。详见 memory `magisk-su-android-inet-group`。 | ||
| 21 | +- Termux 环境变量(脚本里统一 export): | ||
| 22 | + ```bash | ||
| 23 | + export PREFIX=/data/data/com.termux/files/usr | ||
| 24 | + export HOME=/data/data/com.termux/files/home | ||
| 25 | + export PATH=$PREFIX/bin:$PATH | ||
| 26 | + export LD_LIBRARY_PATH=$PREFIX/lib | ||
| 27 | + export TMPDIR=$PREFIX/tmp | ||
| 28 | + export TERMUX_VERSION=0.118.3 | ||
| 29 | + ``` | ||
| 30 | + | ||
| 31 | +--- | ||
| 32 | + | ||
| 33 | +## 1. 编译安装 hermes-agent | ||
| 34 | + | ||
| 35 | +官方安装器原生支持 Termux:检测到 Termux 后用 stdlib venv+pip(不用 uv),自动 `pkg install` python/git/nodejs/clang/rust/ffmpeg/ripgrep,从源码编译 native wheel(maturin / pydantic-core / jiter…),装到 `~/.hermes/hermes-agent/venv`,并在 `$PREFIX/bin/hermes` 建 wrapper。**整机编译约 25–30 分钟**。 | ||
| 36 | + | ||
| 37 | +### 1.1 ⚠️ 必做:先升级 Termux 全量包(否则 node 坏) | ||
| 38 | + | ||
| 39 | +全新 bootstrap 过期时,`pkg install nodejs` 装上的 node 链不上旧 openssl: | ||
| 40 | +``` | ||
| 41 | +node: CANNOT LINK EXECUTABLE "node": cannot locate symbol "OSSL_PROVIDER_add_conf_parameter" | ||
| 42 | +``` | ||
| 43 | +install.sh 因 `set -e` 在 Node 步骤 `rc=1` 退出。**先升级再装**: | ||
| 44 | +```bash | ||
| 45 | +export DEBIAN_FRONTEND=noninteractive | ||
| 46 | +apt-get update -y | ||
| 47 | +apt-get upgrade -y -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef | ||
| 48 | +node --version # 应能正常打印版本(不再 CANNOT LINK) | ||
| 49 | +``` | ||
| 50 | + | ||
| 51 | +### 1.2 跑安装器(脱离 + 日志,扛 adb 掉线/doze) | ||
| 52 | + | ||
| 53 | +把下面脚本 push 到 `/sdcard`,再以 Termux 用户 `setsid nohup` 脱离运行: | ||
| 54 | + | ||
| 55 | +```bash | ||
| 56 | +#!/data/data/com.termux/files/usr/bin/bash | ||
| 57 | +# 见上方 export 块…… | ||
| 58 | +export DEBIAN_FRONTEND=noninteractive | ||
| 59 | +cd "$HOME"; termux-wake-lock 2>/dev/null || true | ||
| 60 | +echo "=== UPGRADE START $(date) ===" | ||
| 61 | +apt-get update -y; apt-get upgrade -y -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef | ||
| 62 | +node --version || { echo "NODE BROKEN"; exit 2; } | ||
| 63 | +echo "=== HERMES INSTALL $(date) ===" | ||
| 64 | +curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash -s -- --non-interactive | ||
| 65 | +echo "=== HERMES INSTALL END rc=$? $(date) ===" | ||
| 66 | +``` | ||
| 67 | +```bash | ||
| 68 | +adb push install.sh /sdcard/install.sh | ||
| 69 | +LOG=/data/data/com.termux/files/home/hermes-install.log | ||
| 70 | +adb shell "su -g 10302 -G 3003 -G 9997 -G 20302 -G 50302 10302 -c \ | ||
| 71 | + 'setsid nohup /data/data/com.termux/files/usr/bin/bash /sdcard/install.sh >$LOG 2>&1 </dev/null & echo pid \$!'" | ||
| 72 | +# 轮询:grep 'HERMES INSTALL END rc=0' $LOG | ||
| 73 | +``` | ||
| 74 | +`--non-interactive` 跳过 setup 向导(无 TTY 也能跑)。 | ||
| 75 | + | ||
| 76 | +### 1.3 ⚠️ 必做:修 wrapper shebang | ||
| 77 | + | ||
| 78 | +installer 生成的 `$PREFIX/bin/hermes` 首行是 `#!/usr/bin/env bash`。Termux 没 `/usr/bin/env`,交互会话靠 termux-exec 动态改写,但用 `su -c` 驱动(无 termux-exec)会报 `No such file or directory`(指解释器)。改成绝对路径(以 Termux 用户改,保留属主): | ||
| 79 | +```bash | ||
| 80 | +adb shell "su 10302 -c 'sed -i \"1s|#!/usr/bin/env bash|#!/data/data/com.termux/files/usr/bin/bash|\" /data/data/com.termux/files/usr/bin/hermes'" | ||
| 81 | +``` | ||
| 82 | +> 注意:`hermes update` 会重新生成 wrapper、把 shebang 改回 `/usr/bin/env`,**每次更新后需重修**。 | ||
| 83 | +> `venv/bin/hermes` 的 shebang 是绝对 venv python,本就没问题,可用它绕过 wrapper 验证。 | ||
| 84 | + | ||
| 85 | +### 1.4 验证 | ||
| 86 | + | ||
| 87 | +```bash | ||
| 88 | +adb shell 'su -g 10302 -G 3003 -G 9997 -G 20302 -G 50302 10302 -c " | ||
| 89 | + export PREFIX=/data/data/com.termux/files/usr HOME=/data/data/com.termux/files/home | ||
| 90 | + export PATH=\$PREFIX/bin:\$PATH LD_LIBRARY_PATH=\$PREFIX/lib TMPDIR=\$PREFIX/tmp | ||
| 91 | + hermes --version"' | ||
| 92 | +# → Hermes Agent v0.15.1 (2026.5.29) · Python 3.13.13 | ||
| 93 | +``` | ||
| 94 | +产物位置:代码 `~/.hermes/hermes-agent/`,配置 `~/.hermes/config.yaml` + `~/.hermes/.env`,skills `~/.hermes/skills/`。 | ||
| 95 | + | ||
| 96 | +--- | ||
| 97 | + | ||
| 98 | +## 2. 配置 Kimi Coding Plan(sk-kimi- key) | ||
| 99 | + | ||
| 100 | +hermes **原生支持** Kimi Coding Plan,**不要**用 `provider=anthropic`+`ANTHROPIC_BASE_URL` 绕路。 | ||
| 101 | + | ||
| 102 | +### 2.1 源码逻辑(为什么这么配) | ||
| 103 | + | ||
| 104 | +| 文件 | 逻辑 | | ||
| 105 | +|---|---| | ||
| 106 | +| `hermes_cli/auth.py:248` | `kimi-coding` provider:`api_key_env_vars=("KIMI_API_KEY","KIMI_CODING_API_KEY")` | | ||
| 107 | +| `hermes_cli/auth.py:515` | `KIMI_CODE_BASE_URL = "https://api.kimi.com/coding"`;`_resolve_kimi_base_url()` 把 `sk-kimi-` 前缀 key 自动重定向到这里 | | ||
| 108 | +| `agent/anthropic_adapter.py:385` | `_is_kimi_coding_endpoint(base_url)` 检测到 `api.kimi.com/coding` → **自动切 Anthropic Messages 协议 + 注入 claude-code User-Agent** | | ||
| 109 | +| `hermes_cli/main.py` `_model_flow_kimi()` | setup 向导:写 `model.provider/base_url/default`,清空 `KIMI_BASE_URL` override | | ||
| 110 | + | ||
| 111 | +**关键坑**:Kimi `/coding` 端点的 OpenAI 路径 `/coding/v1/chat/completions` 返回 **403** `access_terminated_error`("only available for Coding Agents such as Kimi CLI, Claude Code, Roo Code…");只有 Anthropic 路径 `/coding/v1/messages` 通(200)。hermes 通过上面的 UA 伪装自动绕过,所以**必须走 kimi-coding provider(anthropic 协议),不能用 OpenAI 协议**。 | ||
| 112 | + | ||
| 113 | +### 2.2 落地配置(等价于 `hermes model` 选 Kimi) | ||
| 114 | + | ||
| 115 | +**`~/.hermes/.env`**:只放 key,**不要**设 `KIMI_BASE_URL`,也别留 `ANTHROPIC_*`(否则 `provider: auto` 会误判): | ||
| 116 | +``` | ||
| 117 | +KIMI_API_KEY=sk-kimi-XXXXXXXX... | ||
| 118 | +``` | ||
| 119 | +> 用 `cat /sdcard/x >> .env`(root 追加不改属主)或 `su <uid> -c 'sed ...'`(Termux 用户改,保属主)避免把 key 写进命令行/ps。 | ||
| 120 | + | ||
| 121 | +**`~/.hermes/config.yaml`**(用 CLI 设,非交互): | ||
| 122 | +```bash | ||
| 123 | +hermes config set model.provider kimi-coding | ||
| 124 | +hermes config set model.base_url https://api.kimi.com/coding | ||
| 125 | +hermes config set model.default kimi-for-coding | ||
| 126 | +``` | ||
| 127 | +可用模型:`kimi-k2.6 / kimi-k2.5 / kimi-for-coding / kimi-k2-thinking / kimi-k2-thinking-turbo`。 | ||
| 128 | + | ||
| 129 | +### 2.3 验证 | ||
| 130 | + | ||
| 131 | +```bash | ||
| 132 | +# -z/--oneshot = 一次性 prompt,免 TTY | ||
| 133 | +hermes -z "用中文只回答一个数字: 1+1=?" | ||
| 134 | +# → 2 | ||
| 135 | +``` | ||
| 136 | +裸 `hermes`(不带 `-m/--provider`)直接走 Kimi 即配置成功。 | ||
| 137 | + | ||
| 138 | +### 2.4 排错速查 | ||
| 139 | + | ||
| 140 | +| 现象 | 原因 / 处理 | | ||
| 141 | +|---|---| | ||
| 142 | +| `HTTP 404 resource not found` | base_url 漏了协议路径或用了 `provider=anthropic`+错 base;改用 `kimi-coding` + `https://api.kimi.com/coding` | | ||
| 143 | +| `HTTP 403 access_terminated_error` | 走了 OpenAI `/chat/completions` 路径;必须 kimi-coding(anthropic 协议,hermes 自动加 claude-code UA) | | ||
| 144 | +| `no final response was produced` | config 残留错的 `model.base_url`(如 openrouter)或 provider 不对;按 2.2 重设三项 | | ||
| 145 | +| `curl: Could not resolve host` | `su` 切 uid 时漏了 `-G 3003`(inet 组) | | ||
| 146 | + | ||
| 147 | +--- | ||
| 148 | + | ||
| 149 | +## 附:一次性自检脚本 | ||
| 150 | + | ||
| 151 | +```bash | ||
| 152 | +adb shell 'su -g 10302 -G 3003 -G 9997 -G 20302 -G 50302 10302 -c " | ||
| 153 | + export PREFIX=/data/data/com.termux/files/usr HOME=/data/data/com.termux/files/home | ||
| 154 | + export PATH=\$PREFIX/bin:\$PATH LD_LIBRARY_PATH=\$PREFIX/lib TMPDIR=\$PREFIX/tmp | ||
| 155 | + hermes --version | ||
| 156 | + hermes config show | grep -iE \"provider|default|base_url\" | ||
| 157 | + hermes -z \"ping, reply PONG\" | ||
| 158 | +"' | ||
| 159 | +``` |
wechat_plain/scripts/local-testkit/docs/PIXEL_CLAUDE_CODE_OAUTH_SETUP.md
0 → 100644
| 1 | +# Pixel + Termux 复用 Mac OAuth Token 跑 Claude Code | ||
| 2 | + | ||
| 3 | +> 在 Pixel 10 Pro Fold(Android 16)的 Termux + Ubuntu proot 容器里运行 `claude-run`,复用 Mac 上同款 Anthropic OAuth Token,**完全替换原来的 Kimi 反代方案**。 | ||
| 4 | + | ||
| 5 | +--- | ||
| 6 | + | ||
| 7 | +## 1. 背景 | ||
| 8 | + | ||
| 9 | +- **设备**:Pixel 10 Pro Fold(代号 `rango`)/ Android 16,bootloader 已解锁,Magisk root | ||
| 10 | +- **原方案**:claude-code 通过 Kimi Coding Plan 反代(`https://api.kimi.com/coding/`),用 Kimi token 走所有请求 | ||
| 11 | +- **新目标**:直连 `api.anthropic.com`,复用 Mac 上 `~/.zshrc` 里的 `CLAUDE_CODE_OAUTH_TOKEN`,使用真正的 Claude Opus 4.7 | ||
| 12 | +- **动机**:Frida 在 Android 16 无法跑(ptrace/CFI/SELinux 多重限制),后续工作转向 LSPosed + 真 Claude 模型,需要 Pixel 端本地也能跑 claude-code | ||
| 13 | + | ||
| 14 | +--- | ||
| 15 | + | ||
| 16 | +## 2. 架构总览 | ||
| 17 | + | ||
| 18 | +``` | ||
| 19 | +┌─────────────────────────────────────────────────────────────┐ | ||
| 20 | +│ Termux (Android shell, user u0_a327) │ | ||
| 21 | +│ │ | ||
| 22 | +│ ~/.bashrc │ | ||
| 23 | +│ └─ export CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-... │ | ||
| 24 | +│ │ | ||
| 25 | +│ /usr/bin/claude-run ←─ wrapper │ | ||
| 26 | +│ └─ proot-distro login --shared-home ubuntu │ | ||
| 27 | +│ -- env CLAUDE_CODE_OAUTH_TOKEN="..." claude "$@" │ | ||
| 28 | +│ │ | ||
| 29 | +│ ▼ │ | ||
| 30 | +│ ┌──────────────────────────────────────────────────────┐ │ | ||
| 31 | +│ │ Ubuntu proot container │ │ | ||
| 32 | +│ │ /root ←(--shared-home)─→ /data/data/com.termux/.../home│ | ||
| 33 | +│ │ ├─ .claude.json ← claude 主配置 │ │ | ||
| 34 | +│ │ └─ .claude/settings.json ← per-user settings │ │ | ||
| 35 | +│ │ │ │ | ||
| 36 | +│ │ claude (ELF/glibc, Node.js) │ │ | ||
| 37 | +│ │ └─→ HTTPS api.anthropic.com │ │ | ||
| 38 | +│ └──────────────────────────────────────────────────────┘ │ | ||
| 39 | +└─────────────────────────────────────────────────────────────┘ | ||
| 40 | +``` | ||
| 41 | + | ||
| 42 | +**关键点**: | ||
| 43 | +- Claude Code 是 ELF/glibc 编译,Android Bionic 跑不了 → 必须 proot 跑 Ubuntu | ||
| 44 | +- `--shared-home` 把 Termux home 绑定为容器 `/root`,配置文件可以从 Termux 端直接编辑 | ||
| 45 | +- Token 通过 `env KEY=VAL claude` 在容器内瞬时注入,不进容器 shell 环境 | ||
| 46 | + | ||
| 47 | +--- | ||
| 48 | + | ||
| 49 | +## 3. Claude Code 的双重认证闸门 | ||
| 50 | + | ||
| 51 | +这是整个迁移最关键的认知 —— claude-code 启动时有两道**独立**闸门: | ||
| 52 | + | ||
| 53 | +| 闸门 | 检查内容 | headless (`claude -p`) | 交互模式 (`claude`) | | ||
| 54 | +|------|---------|----------------------|---------------------| | ||
| 55 | +| ① Token 闸门 | `CLAUDE_CODE_OAUTH_TOKEN` env 或 `~/.claude/.credentials.json` 任一存在 | 必须过 | 必须过 | | ||
| 56 | +| ② Onboarding 闸门 | `~/.claude.json` 的 `hasCompletedOnboarding === true` | **跳过** | **必须过** | | ||
| 57 | + | ||
| 58 | +**Kimi 反代为什么"屏蔽"了 Onboarding 闸门**:它的 `.env` 块在启动时被 claude-code 注入进进程,等价于一直在用 API key 模式,OAuth onboarding 检查被旁路掉了。一旦切回官方 Anthropic,闸门被激活,于是裸 `claude-run` 弹出 OAuth URL。 | ||
| 59 | + | ||
| 60 | +--- | ||
| 61 | + | ||
| 62 | +## 4. 完整改动清单 | ||
| 63 | + | ||
| 64 | +按依赖顺序(缺一不可): | ||
| 65 | + | ||
| 66 | +### 4.1 改 wrapper:注入 OAuth Token | ||
| 67 | + | ||
| 68 | +**文件**:`/data/data/com.termux/files/usr/bin/claude-run` | ||
| 69 | + | ||
| 70 | +```sh | ||
| 71 | +#!/data/data/com.termux/files/usr/bin/sh | ||
| 72 | +# Claude Code via proot-distro with shared home + Mac OAuth token | ||
| 73 | +exec proot-distro login --shared-home ubuntu -- env CLAUDE_CODE_OAUTH_TOKEN="sk-ant-oat01-<...>" claude "$@" | ||
| 74 | +``` | ||
| 75 | + | ||
| 76 | +权限:`chmod 711`(owner 可读,其他 app 不可读),owner `u0_a327:u0_a327`。 | ||
| 77 | + | ||
| 78 | +> Token 直接 inline 到 wrapper,避免依赖 shell 启动文件。Android 沙箱保证其他 app 读不到 `/data/data/com.termux/` 下的文件。 | ||
| 79 | + | ||
| 80 | +### 4.2 写 settings.json:清理 Kimi 痕迹 | ||
| 81 | + | ||
| 82 | +**文件**:`/data/data/com.termux/files/home/.claude/settings.json` | ||
| 83 | + | ||
| 84 | +```json | ||
| 85 | +{ | ||
| 86 | + "env": {}, | ||
| 87 | + "model": "opus", | ||
| 88 | + "skipDangerousModePermissionPrompt": true, | ||
| 89 | + "theme": "dark" | ||
| 90 | +} | ||
| 91 | +``` | ||
| 92 | + | ||
| 93 | +权限:`chmod 600`。 | ||
| 94 | + | ||
| 95 | +> **`env` 必须为空 `{}`** —— 之前 Kimi 配置在这里塞了 `ANTHROPIC_BASE_URL` / `ANTHROPIC_API_KEY` 等,会覆盖 wrapper 注入的 token。 | ||
| 96 | + | ||
| 97 | +### 4.3 清理 `~/.claude.json` 的 env 块(最容易漏的一步) | ||
| 98 | + | ||
| 99 | +**文件**:`/data/data/com.termux/files/home/.claude.json` | ||
| 100 | + | ||
| 101 | +claude-code 的"主配置文件",顶层有个 `env` 字段会在进程启动时被 setenv 进去,**优先级高于 wrapper 传入的 env**。 | ||
| 102 | + | ||
| 103 | +操作(用 jq 在 Mac 端处理后 push 回去): | ||
| 104 | + | ||
| 105 | +```bash | ||
| 106 | +jq 'del(.env) | ||
| 107 | + | .customApiKeyResponses.rejected = [] | ||
| 108 | + | .model = "opus" | ||
| 109 | + | .hasCompletedOnboarding = true | ||
| 110 | + | .lastOnboardingVersion = "2.1.144"' \ | ||
| 111 | + ~/.claude.json.backup > ~/.claude.json.cleaned | ||
| 112 | +``` | ||
| 113 | + | ||
| 114 | +需要保证: | ||
| 115 | +- `.env` 字段被**删除**(不是设为空,是整个 key 不存在) | ||
| 116 | +- `.hasCompletedOnboarding = true` ← **过 Onboarding 闸门** | ||
| 117 | +- `.lastOnboardingVersion = "2.1.144"` ← 与当前 claude-code 版本对齐 | ||
| 118 | +- `.model = "opus"`(之前 Kimi 用的 `"opus[1m]"` 在官方 API 不存在) | ||
| 119 | +- `.customApiKeyResponses.rejected = []`(清掉之前 reject 过的 Kimi key 历史) | ||
| 120 | + | ||
| 121 | +权限:`chmod 600`,owner `u0_a327:u0_a327`。 | ||
| 122 | + | ||
| 123 | +--- | ||
| 124 | + | ||
| 125 | +## 5. 完整执行脚本(从 Mac 端一键执行) | ||
| 126 | + | ||
| 127 | +```bash | ||
| 128 | +#!/usr/bin/env bash | ||
| 129 | +set -euo pipefail | ||
| 130 | + | ||
| 131 | +# 1. 从 Mac ~/.zshrc 提取 token | ||
| 132 | +TOKEN=$(awk -F= '/^export CLAUDE_CODE_OAUTH_TOKEN=/{sub(/^export CLAUDE_CODE_OAUTH_TOKEN=/, ""); print; exit}' ~/.zshrc) | ||
| 133 | +[ -z "$TOKEN" ] && { echo "ERROR: token not found in ~/.zshrc"; exit 1; } | ||
| 134 | + | ||
| 135 | +# 2. 构造文件 | ||
| 136 | +mkdir -p /tmp/claude-pixel | ||
| 137 | +cat > /tmp/claude-pixel/claude-run <<EOF | ||
| 138 | +#!/data/data/com.termux/files/usr/bin/sh | ||
| 139 | +exec proot-distro login --shared-home ubuntu -- env CLAUDE_CODE_OAUTH_TOKEN="$TOKEN" claude "\$@" | ||
| 140 | +EOF | ||
| 141 | +chmod 711 /tmp/claude-pixel/claude-run | ||
| 142 | + | ||
| 143 | +cat > /tmp/claude-pixel/settings.json <<'EOF' | ||
| 144 | +{ | ||
| 145 | + "env": {}, | ||
| 146 | + "model": "opus", | ||
| 147 | + "skipDangerousModePermissionPrompt": true, | ||
| 148 | + "theme": "dark" | ||
| 149 | +} | ||
| 150 | +EOF | ||
| 151 | + | ||
| 152 | +# 3. 处理 .claude.json(先 pull,patch,push) | ||
| 153 | +adb shell "su -c 'cp /data/data/com.termux/files/home/.claude.json /sdcard/cc.json && chmod 644 /sdcard/cc.json'" | ||
| 154 | +adb pull /sdcard/cc.json /tmp/claude-pixel/cc.json | ||
| 155 | +adb shell "su -c 'rm /sdcard/cc.json'" | ||
| 156 | +jq 'del(.env) | ||
| 157 | + | .customApiKeyResponses.rejected = [] | ||
| 158 | + | .model = "opus" | ||
| 159 | + | .hasCompletedOnboarding = true | ||
| 160 | + | .lastOnboardingVersion = "2.1.144"' \ | ||
| 161 | + /tmp/claude-pixel/cc.json > /tmp/claude-pixel/cc.patched.json | ||
| 162 | + | ||
| 163 | +# 4. push & 安装 | ||
| 164 | +adb push /tmp/claude-pixel/claude-run /sdcard/claude-run.new | ||
| 165 | +adb push /tmp/claude-pixel/settings.json /sdcard/settings.json.new | ||
| 166 | +adb push /tmp/claude-pixel/cc.patched.json /sdcard/cc.json | ||
| 167 | + | ||
| 168 | +adb shell "su -c ' | ||
| 169 | +WRAPPER=/data/data/com.termux/files/usr/bin/claude-run | ||
| 170 | +SETTINGS=/data/data/com.termux/files/home/.claude/settings.json | ||
| 171 | +MAIN=/data/data/com.termux/files/home/.claude.json | ||
| 172 | + | ||
| 173 | +# 备份原版(只备份一次) | ||
| 174 | +[ ! -f \$WRAPPER.prekimi ] && cp \$WRAPPER \$WRAPPER.prekimi | ||
| 175 | +[ ! -f \$MAIN.prekimi ] && cp \$MAIN \$MAIN.prekimi | ||
| 176 | + | ||
| 177 | +# 安装新版 | ||
| 178 | +cp /sdcard/claude-run.new \$WRAPPER | ||
| 179 | +chown u0_a327:u0_a327 \$WRAPPER && chmod 711 \$WRAPPER | ||
| 180 | + | ||
| 181 | +mkdir -p \$(dirname \$SETTINGS) | ||
| 182 | +cp /sdcard/settings.json.new \$SETTINGS | ||
| 183 | +chown u0_a327:u0_a327 \$SETTINGS && chmod 600 \$SETTINGS | ||
| 184 | + | ||
| 185 | +cp /sdcard/cc.json \$MAIN | ||
| 186 | +chown u0_a327:u0_a327 \$MAIN && chmod 600 \$MAIN | ||
| 187 | + | ||
| 188 | +# 清理 | ||
| 189 | +rm /sdcard/claude-run.new /sdcard/settings.json.new /sdcard/cc.json | ||
| 190 | +echo done | ||
| 191 | +'" | ||
| 192 | + | ||
| 193 | +# 5. 清理 Mac 临时文件 | ||
| 194 | +rm -rf /tmp/claude-pixel | ||
| 195 | +``` | ||
| 196 | + | ||
| 197 | +--- | ||
| 198 | + | ||
| 199 | +## 6. 验证 | ||
| 200 | + | ||
| 201 | +### 6.1 headless 模式 | ||
| 202 | + | ||
| 203 | +```bash | ||
| 204 | +adb shell 'su u0_a327 -c " | ||
| 205 | +export HOME=/data/data/com.termux/files/home | ||
| 206 | +export PATH=/data/data/com.termux/files/usr/bin:\$PATH | ||
| 207 | +cd \$HOME | ||
| 208 | +claude-run -p \"reply with just OK\" < /dev/null | ||
| 209 | +"' | ||
| 210 | +``` | ||
| 211 | + | ||
| 212 | +期望输出:`OK`(前面有几行 `proot warning: can't sanitize binding /proc/self/fd/...` 是 adb 非 tty 模式的良性警告,无视)。 | ||
| 213 | + | ||
| 214 | +### 6.2 交互模式(用户在 Termux 里直接跑) | ||
| 215 | + | ||
| 216 | +``` | ||
| 217 | +$ claude-run | ||
| 218 | +``` | ||
| 219 | + | ||
| 220 | +期望:直接进入 Claude Code TUI 界面,**不**弹出 OAuth URL。 | ||
| 221 | + | ||
| 222 | +### 6.3 排错检查清单 | ||
| 223 | + | ||
| 224 | +| 症状 | 检查 | | ||
| 225 | +|------|------| | ||
| 226 | +| 报错指向 `kimi.com/code/console` | `~/.claude.json` 的 `env` 块没删干净 | | ||
| 227 | +| 弹出 OAuth 登录 URL | `~/.claude.json` 的 `hasCompletedOnboarding` 不是 `true` | | ||
| 228 | +| `Failed to authenticate. 401` | Mac 那边的 token 已失效,去 Mac 重新登录刷新 | | ||
| 229 | +| `Warning: no stdin data received in 3s` | headless 模式没加 `< /dev/null`,等 3 秒后会继续,不是错误 | | ||
| 230 | +| `which claude-run` 指向其他路径 | PATH 优先级问题 / 装了 alias | | ||
| 231 | + | ||
| 232 | +--- | ||
| 233 | + | ||
| 234 | +## 7. 回滚 | ||
| 235 | + | ||
| 236 | +之前的版本都备份在 `.prekimi` 后缀文件里: | ||
| 237 | + | ||
| 238 | +```bash | ||
| 239 | +adb shell "su -c ' | ||
| 240 | +cp /data/data/com.termux/files/usr/bin/claude-run.prekimi /data/data/com.termux/files/usr/bin/claude-run | ||
| 241 | +cp /data/data/com.termux/files/home/.claude.json.prekimi /data/data/com.termux/files/home/.claude.json | ||
| 242 | +echo rolled back to Kimi config | ||
| 243 | +'" | ||
| 244 | +``` | ||
| 245 | + | ||
| 246 | +--- | ||
| 247 | + | ||
| 248 | +## 8. 安全注意 | ||
| 249 | + | ||
| 250 | +- Wrapper 里 inline 的 OAuth token 是个**长效凭证**,泄露等于账号被借用 | ||
| 251 | +- 文件权限:wrapper `711`(不可读其他 app),`.claude.json` `600` | ||
| 252 | +- Android 沙箱保证其他 app 无法访问 `/data/data/com.termux/` 下的文件 | ||
| 253 | +- 如果手机丢失或共享,**Mac 端立刻去 Anthropic console 撤销该 token**(一撤销 Mac/Pixel 同时失效,需要重新登录刷新) | ||
| 254 | + | ||
| 255 | +--- | ||
| 256 | + | ||
| 257 | +## 9. 已知限制 | ||
| 258 | + | ||
| 259 | +1. **网络出口**:直连 `api.anthropic.com` 需要稳定国际网络。Pixel 在 4G 蜂窝下不一定通,建议挂代理或走 Wi-Fi | ||
| 260 | +2. **计费归属**:使用 Mac 同一个 Anthropic 账号配额,Pixel 跑多了会消耗 Mac 同账号的 quota | ||
| 261 | +3. **Token 刷新**:OAuth access token 有效期约 1 年,过期后需要在 Mac 端重新执行 OAuth 流程刷新,然后把新 token 同步到 Pixel wrapper | ||
| 262 | +4. **多设备 token 复用合规性**:Anthropic ToS 允许同一账号在多设备使用,但禁止把 token 分享给第三方 | ||
| 263 | + | ||
| 264 | +--- | ||
| 265 | + | ||
| 266 | +## 10. 相关文件索引 | ||
| 267 | + | ||
| 268 | +| 路径 | 作用 | | ||
| 269 | +|------|------| | ||
| 270 | +| `/data/data/com.termux/files/usr/bin/claude-run` | wrapper(inline token) | | ||
| 271 | +| `/data/data/com.termux/files/usr/bin/claude-run.prekimi` | 旧版备份 | | ||
| 272 | +| `/data/data/com.termux/files/home/.claude.json` | claude-code 主配置 | | ||
| 273 | +| `/data/data/com.termux/files/home/.claude.json.prekimi` | 主配置备份(含 Kimi) | | ||
| 274 | +| `/data/data/com.termux/files/home/.claude/settings.json` | per-user settings | | ||
| 275 | +| `/data/data/com.termux/files/usr/var/lib/proot-distro/containers/ubuntu/rootfs` | Ubuntu 容器 rootfs | | ||
| 276 | + | ||
| 277 | +Mac 端: | ||
| 278 | +| 路径 | 作用 | | ||
| 279 | +|------|------| | ||
| 280 | +| `~/.zshrc` 里的 `CLAUDE_CODE_OAUTH_TOKEN` | Token 来源 | | ||
| 281 | +| `~/.claude.json` | Mac 上对应的主配置(参照对比用) | |
wechat_plain/scripts/local-testkit/docs/README.md
| @@ -302,6 +302,8 @@ local-testkit/ | @@ -302,6 +302,8 @@ local-testkit/ | ||
| 302 | ├── HERMES_WECHAT_ARCHITECTURE.md | 302 | ├── HERMES_WECHAT_ARCHITECTURE.md |
| 303 | ├── REVERSE_ENGINEERING_LOG.md | 303 | ├── REVERSE_ENGINEERING_LOG.md |
| 304 | ├── NOTIFICATION_STRATEGY.md | 304 | ├── NOTIFICATION_STRATEGY.md |
| 305 | + ├── PIXEL_CLAUDE_CODE_OAUTH_SETUP.md # Pixel 上 claude-run 复用 Mac OAuth | ||
| 306 | + ├── HERMES_AGENT_PIXEL_SETUP.md # 在 Pixel 编译装 NousResearch hermes-agent + 配 Kimi Coding Plan | ||
| 305 | └── plan.md | 307 | └── plan.md |
| 306 | 308 | ||
| 307 | server/services/wechat/ # 主 plugin(Node.js) | 309 | server/services/wechat/ # 主 plugin(Node.js) |