Hermes Agent 在 Termux(Pixel 10 Pro Fold)上的安装记录
记录 2026-06-25 在一台新 root 的 Pixel 10 Pro Fold(codename rango,build CP1A.260405.005)上从源码(/Users/yibo/Documents/lemonAI/hermes-agent,非 git clone)装 Hermes Agent v0.17.0 到 Termux 的完整经验。按踩坑顺序记录,最重要的坑放最前面。
0. 最容易再犯的坑:macOS tar 打包必须排除 AppleDouble 文件
现象:hermes chat / hermes doctor 报 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa3 in position 45,看起来像是 Android 平台兼容性问题,浪费了大量时间去查 locale / 编码环境。
真因:在 Mac 上用 tar -czf src.tar.gz . 打包源码时没设 COPYFILE_DISABLE=1,macOS 的 BSD tar 会把每个文件的 Finder 扩展属性打包成同名的 ._xxx AppleDouble 二进制 sidecar 文件一起塞进 tar 包。推到设备解压后,仓库里混进了 6289 个 ._* 文件。tools/registry.py: discover_builtin_tools() 扫描 tools/*.py 时把 tools/._xxx.py 也当源码用 read_text(encoding="utf-8") 读,二进制 blob 当然解码失败。
修法:
find . -name '._*' -type f -delete # 在已污染的目录里清
# 或者打包时从源头避免:
COPYFILE_DISABLE=1 tar -czf src.tar.gz --exclude='.git' .
教训:以后任何从 macOS 往 Linux/Android 环境传源码(tar/zip 都一样),打包命令前一定先 export COPYFILE_DISABLE=1,或者直接用 git archive(不会带 AppleDouble)。
1. 自动化执行 Termux 命令的方式:adb shell run-as,不是真正打开 App
这台设备 root 后,adb shell run-as com.termux <cmd> 可以直接以 Termux App 自己的 UID 跑命令,不需要打开 Termux 的 Activity/Service,也不需要 RUN_COMMAND intent + allow-external-apps 配置。坑点:
run-as不会加载 Termux 的 profile,必须手动export HOME=/data/data/com.termux/files/home PREFIX=/data/data/com.termux/files/usr PATH=$PREFIX/bin:$PATH。run-as读不到/sdcard(scoped storage 限制),文件要先adb push到/sdcard/Download/,再用 root(su -c) 复制进/data/data/com.termux/files/home/,并且必须手动修正属主和 SELinux context,否则 Termux 进程自己访问不了:bash su -c "cp /sdcard/Download/x /data/data/com.termux/files/home/x" su -c "chown u0_a329:u0_a329 /data/data/com.termux/files/home/x" su -c "chcon u:object_r:app_data_file:s0:c73,c257,c512,c768 /data/data/com.termux/files/home/x" # 类别(category)要跟目录一致,否则 mlsconstrain 拒绝访问 su -c "chmod 700 /data/data/com.termux/files/home/x"- 多层 shell quoting(本机 bash → adb shell → run-as → sh -c)极易出错。稳妥做法:把命令写成脚本文件再推上去执行,不要塞 inline 一长串带引号的命令。
- 设备充电(
AC powered: true)时 Doze 不会触发,息屏不影响后台跑的编译/安装。
2. psutil==7.2.2 在 Android 上无法从源码构建
现象:pip install -e '.[termux]' 卡在 Failed to build 'psutil',报 platform android is not supported。换了 psutil 5.9.8~7.2.2 之间一串版本号都一样报错。
真因:psutil 的 setup.py 按 sys.platform 字符串选择要编译哪份平台相关 C 源码(psutil/_common.py: LINUX = sys.platform.startswith("linux"))。CPython 3.13 在 Termux 上把 sys.platform 正确地报成 'android'(而不是 'linux'),导致 LINUX 判断为 False,落进 psutil 的"不支持"分支退出。
修法:不要试图 patch psutil 源码自己编译。Termux 官方仓库已经维护了预编译的 python-psutil 包,版本恰好对得上:
pkg install -y python-psutil
python -m venv --system-site-packages venv # 关键:让 venv 继承系统 site-packages
--system-site-packages 让 venv 里 import psutil 直接复用系统包,pip 解析依赖时发现已满足 psutil==7.2.2,不会再去源码构建。
附带验证:psutil.cpu_percent() 之类读全局 /proc/stat 的调用在 Android 上会 PermissionError(系统级限制,非 bug),但 hermes 实际只用 psutil.pid_exists() / Process(pid).status() 这类只读自身/子进程的调用,完全正常。
3. jiter(Rust/PyO3 扩展)编译的两个连续坑
jiter 没有 Android wheel,必须现场用 maturin 编译。pyproject.toml 没钉版本但需要联网拉一整棵 Rust 依赖树。
3a. cargo 并行编译的 Text file busy 竞态
现象:error: failed to run custom build command for proc-macro2 → Text file busy (os error 26)。
修法:export CARGO_BUILD_JOBS=1 降并发后重试即可,是构建脚本并发写/执行同一路径的瞬时竞态,跟 Android/交叉编译无关。
3b. 镜像的同步缺口
现象:配置中科大 mirrors.ustc.edu.cn/crates.io-index 镜像后,wasip2/wasip3 两个 WASI 相关小 crate 连续两次下载超时(failed to transfer more than 10 bytes in 30s)。
修法:删掉 ~/.cargo/config.toml 里的镜像配置,直连官方 crates.io(static.crates.io 实测 0.85s 拿到 200,比想象中快很多)。不要想当然认为国内必须用镜像——先测一下直连速度,crates.io/PyPI 的 CDN 在这个网络环境下表现完全不差,镜像反而可能有特定包同步不全的问题。
注意:pip 的清华源(pypi.tuna.tsinghua.edu.cn)全程很稳,没遇到类似问题,只有 cargo 的镜像踩了坑。
关键加速点:pip 的 wheel cache
maturin 自身编译一次要 10+ 分钟(单线程,编译 470+ 个 crate)。pip 成功后会把 maturin 的产物缓存成 wheel(~/.cache/pip/wheels/.../maturin-1.14.1-cp313-cp313-android_24_arm64_v8a.whl),之后每次 pip install 重试都会复用这个 wheel,不会重新编译——所以中途换源/调参数后放心重跑整条 pip install -e '.[termux]' 命令,不会从零开始。
4. ffmpeg 包安装失败:libc++ 符号版本不一致
现象:pkg install ffmpeg 装到一半报 CANNOT LINK EXECUTABLE "ffmpeg": cannot locate symbol "_ZNSt6__ndk1...",是 Termux 仓库里这批包之间 libc++ 版本暂时不同步导致的。
修法:直接 pkg upgrade -y(会顺带升级 70 多个基础包,包括 libc++ 本身),再 dpkg --configure ffmpeg 收尾,问题消失。不是要单独重装 ffmpeg。
5. Kimi Coding Plan key 的配置方法:别跑 hermes setup
hermes setup / hermes model 是 prompt_toolkit 交互式向导(方向键选择 + 文本输入),在没有真实 PTY 的 adb shell run-as 自动化通道里没法驱动。改为直接写配置文件,效果完全等价:
~/.hermes/.env:
KIMI_API_KEY=sk-kimi-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
~/.hermes/config.yaml:
model:
default: "kimi-for-coding"
provider: "kimi-coding"
sk-kimi- 前缀的 key 默认就走 https://api.kimi.com/coding/v1(Kimi Code API / Coding Plan),不需要额外设 KIMI_BASE_URL。只有 platform.moonshot.ai 发的老 key 才需要覆盖 base_url。
验证方法:hermes doctor 的 "Auth Providers" 段会出现 ✓ Kimi / Moonshot 连通性检查;更直接的端到端验证是非交互单次问答:
hermes chat -q "你是谁,用的是哪个模型?"
-q 是一次性查询模式(问完直接退出,不进交互循环),自动化场景测试模型是否真的能跑通就用这个,不要用裸的 hermes chat(会卡在交互式 TUI 里)。
已知的、不影响使用的剩余警告
tirith security scanner enabled but not available—— tirith 试图下载aarch64-unknown-linux-gnu版本的二进制(glibc,不是 Termux 的 Bionic),不会真正可用,hermes 已优雅降级为纯 pattern matching,不阻塞功能。Plugin 'wecom-platform' ... dlopen failed: cannot locate symbol "PyExc_Warning"—— 本地编译的cryptographyRust 扩展在加载某个可选插件时有 C-API 符号问题,8/49 个插件未启用,核心 chat 功能不受影响。Context file AGENTS.md TRUNCATED—— AGENTS.md 超过默认 context 截断阈值,是内容长度问题,跟安装无关。