这活得开电脑。是半年前的事。
后来我把整套东西搬进了手机。不是为了炫技,是因为那次在高铁上改一个 CSS,硬等了三小时到站。
先说清楚:下面每一个数字、每一行输出,都是这台手机上当场跑出来的。环境、日志、依赖版本、文件大小,没有一项是回忆着写的。
它不是聊天软件
你说话,它干活。干活的地方就是这台手机本身:敲命令、改文件、截图、认图、开摄像头、点屏幕。
面板跑在 127.0.0.1:9900。这个地址只在本机,外面连不进来。你的对话、你的文件、你的模型 Key,都留在这台机器上。
电脑上那套基本都在:插件、记忆、多模型、任务队列。
先看清这台手机
装之前得知道自己手里是什么。这一步别跳,后面每一个坑都跟这几个数字有关。

GFY-AL00,Android 12,SDK 31,aarch64,8 核,7646 MB 内存,可用空间 26G。
Termux 0.118.3,Python 3.14.8,PHP 8.5.12,javac 21.0.13,Gradle 9.8.2。
node 没装。
这几行看着平淡,但每条都能解释后面一个毛病:
aarch64 意味着 x86 的二进制直接跑不了,官方 build-tools 给的就是 x86。
7646 MB 内存意味着编译 Kotlin 的时候得特意把编译器塞进同一个 JVM,不然两个进程一起能把内存吃穿。
node 没装意味着前端构建全走不通,所以面板干脆是纯 HTML,没有打包步骤。
Python 3.14 意味着有几个老包已经编译不过了,这些后面会一个个点出来。
125 MB 的安装包
参数先摆着,免得你下错包:
文件名 7tan-boot-launcher.apk,125.3 MB,131,409,364 字节,更新 2026-11-04,程序包 1.2.9,面板 V1.0.23,系统要 Android 7.0 及以上。
下载地址就一个:www.7tan.com/updates/7tan-boot-launcher.apk
一个 AI 工具 125 MB,很多人第一反应是"这是不是塞了模型"。不是。拆开看:

termux.apk 117,775,723 字节,112.3 MB,占九成。pkg.zip 13,176,471 字节,12.6 MB,那是程序本体。剩下 setup.sh 和 cleanup.sh 加起来不到 45 KB。
那 112 MB 是整个 Termux。不打进去,手机上连 Python 都没有。
所谓"装个 App 就能用",前提是有人把这个前提一起塞进去了。
安装三步:
一,手机浏览器打开 ai-tool 页,点安卓版 APK。
二,安装时系统会弹"未知来源",允许。
三,打开。第一次启动要十几秒,它在起面板。

配置环境:一键脚本到底做了什么
大部分人卡在这一步。App 装上了,点进面板一片空白,因为 Python 依赖还没装。
面板上有个「一键配置」按钮,背后是一个 bash 脚本,跑完要 3 到 10 分钟。它分五段:
阶段 0,打开 Termux 对外命令通道,1 秒。
阶段 1,装系统依赖、换可用软件源,1 到 3 分钟。
阶段 2,拉程序包并解压,10 到 30 秒。
阶段 3,装 Python 依赖,3 到 10 分钟。
阶段 4,写自启脚本、起服务,5 到 20 秒。

下面按阶段拆开。这些细节不写出来,你下次重装还是会在同一个地方卡住。
阶段 0:一行配置,决定服务能不能被静默拉起
配置目录里的 termux.properties 要写 allow-external-apps=true。
这个文件全新安装时不存在,默认 false。它必须由 Termux 自己写,因为 /data/data/com.termux 这个目录,安装器 App 没有权限。
没有这一行,面板只能让你手动切到 Termux 里敲命令。有了它,安装器能在后台把服务拉起来。
阶段 1:判断软件源能不能用,看的不是网速
这一步踩过最久的一个坑。
mirrors.krnk.org 那个源,网络是通的,apt-get update 也照样返回,但索引文件大小对不上:
File has unexpected size 588514 != 591194
apt 直接拒绝这份索引。之后所有包都报 Unable to locate package,连 python 都装不上。现象看起来像网络问题,其实是源坏了。
所以脚本里换源的判据只有一个:apt-cache policy python 有没有 Candidate。
$ apt-cache policy python | head -3 python: Installed: 3.14.8 Candidate: 3.14.8
有 Candidate,源就能用。没有,换下一个。
还有一个必须做的动作:换源之前得先清空 apt 的索引目录(PREFIX/var/lib/apt/lists)。上一轮留下的旧索引会让 apt-cache 依然查得到 python,于是一个坏源也会被判成可用。这条是实测踩出来的。
脚本里排了六个备用源,逐个试到能用为止:packages-cf.termux.dev、packages.termux.dev、mirror.mwt.me、中科大、北外、清华。
装包那行带了 -o Dpkg::Options::=--force-confnew。不加这个,遇到 conffile 会停下来问一句 openssl.cnf 要保留还是覆盖,一键脚本就卡死在那了。
阶段 1 后半段:编译型依赖必须走 apt,不能走 pip
这一批包是 apt 装的:
python unzip curl openssl-tool libxml2 libxslt python-lxml python-pillow python-cryptography python-greenlet
后四个是重点。lxml、Pillow、cryptography、greenlet 都是 C 扩展,Termux 官方给了预编译包,名字前面加 python-。
如果用 pip 装同名的那几个,pip 会下源码、现场编译。在 ARM 手机上编译 lxml,十分钟起步。失败率还高,报错位置往往看不出跟 lxml 有关系。
所以顺序很重要:先 apt 装好这四个,pip 阶段再 import 时它们已经在了,根本不会去碰源码编译。
阶段 2:解压前先把聊天记录挪走
程序包 12 MB 左右,解开是 671 个文件。真实日志里那两行:
[2/5] 下载程序包并解压
已下载 12 MB
解压完成:671 个文件这里有个保护:程序包里不含 data/games.db。直接覆盖会把你所有聊天记录清空。
脚本的做法是先把 data 目录挪走,解压完看新目录里没有库文件,再放回来。
还有一个我自己踩过的坑,值得单独说清楚。
安装器里写了一个版本戳 .7tan_pkg_ver。当初只改了前端 CSS、打了个新 APK,用户装上新包、点一键配置,阶段 2 因为状态文件里标记了「已完成」被整段跳过,解压出来的还是旧程序。界面纹丝不动,看起来就像打包没生效。
现在每次都比对版本戳,不一致就强制只重跑阶段 2,阶段 3 往后的依赖和服务保持不动。
顺带说一个更隐蔽的坑。状态文件早期把「正在做」和「已完成」混用一个值,一进阶段就写状态,等于宣告完成。结果阶段 1 apt 装包失败,用户重跑脚本,这一阶段被直接跳过,报错也就再也修不好了。
现在拆成两个文件:一个只给界面显示进度,另一个才判定要不要跳过。
阶段 3:Python 依赖,这里错了七个地方
这是整段最长的,也是最容易一装就崩的。
先装镜像。默认 pypi.org 在国内拉十几个包,平均每个包超时一次。脚本里写死阿里云:
PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/ PIP_TRUSTED_HOST=mirrors.aliyun.com pypi.org mirrors.ustc.edu.cn
然后有七个必须钉死的地方。全是实际撞出来的,不是预防性写的。
第一,pip 不能自升级。 Termux 的 python-pip 包把 pip 的自升级锁了,执行 pip install --upgrade pip 会直接报 Installing pip is forbidden (termux)。
第二,pydantic 只能用 1.x。 pydantic 2 的核心 pydantic-core 是 Rust 写的。PyPI 上只有 manylinux、musllinux、win、mac 四种预编译包,Termux 的平台标签是 android + bionic,一个都匹配不上。pip 只能下源码现场编译,而机器上没装 rust,必然失败。
所以降到 pydantic 1.10.27,纯 Python,不用编译。
第三,fastapi 必须加 --no-deps。 否则 pip 会顺手把 pydantic 升到 2.x,前面的工作全推翻。
--no-deps 又会漏掉 anyio(starlette 的硬依赖)。实测缺它时 import fastapi 直接 ModuleNotFoundError。所以 anyio 单独先装。
第四,pyyaml 需要 C 编译器。 它只发 sdist,得现场编译。阶段 1 的包列表里没放 clang,因为装它要连带 llvm,好几百兆。所以改成按需补:import 失败才装 clang,装完再编 pyyaml。
不装它的后果是整个服务起不来,因为 config/loader.py 在顶层就 import yaml。
第五,apscheduler 必须钉 3.x。 4.x 依赖 pydantic 2,会把上面定下的 1.x 方案整个推翻。而它又是 scheduler.py 的硬 import,缺了整个 web 服务在 import 阶段就崩。
实测现象只有一行 ModuleNotFoundError: apscheduler,看不出是版本问题。
第六,openai 钉 1.35.0。 更高版本依赖 jiter,那玩意也是 Rust 写的,和 pydantic-core 一样的死法。1.35.0 的依赖全是纯 Python。
第七,httpx 必须小于 0.28。 这条最坑,因为它报的错跟版本毫无关系。
openai 1.35.0 建客户端时传的是 httpx.Client(proxies=...),而 httpx 0.28 把这个参数删了。构造即 TypeError。
现象是每聊一句都回一句:
AI 调用失败: Client.__init__() got an unexpected keyword argument 'proxies'
脚本里兜了一道:启动前检查 httpx 版本,不小于 0.28 就降到 0.27.2。

最后一步是逐个 import 复核:fastapi、uvicorn、pydantic、loguru、httpx、sqlalchemy、aiosqlite、websockets、yaml、apscheduler、slugify。少一个就直接报错停下。
pip 的返回值不可全信,它经常装完了但那个包 import 不了。以 import 结果为准。
阶段 4:自启、唤醒锁、以及「服务已就绪」那一秒
最后一段写自启脚本,再启动服务。
真实日志的结尾是这样:
[4/5] 写入自启脚本并启动服务
~/7tan_autostart.sh 已写入
~/.bashrc 兜底已写入
服务已就绪(1 秒)
[5/5] 配置完成,可以开始使用
检查 AI 密钥是否可用…
AI 服务连通 ✓(deepseek/deepseek-flash)「服务已就绪(1 秒)」这个数字不是写死的,是真的等端口起来才打印。前面那段 3 到 10 分钟花在装依赖上,服务本身起来只要一秒。
这里有个东西必须提:唤醒锁。
Termux 在锁屏、切后台时会停止终端视图重绘。进程还在跑,屏幕却定格不动。脚本开头会调一次 termux-wake-lock,等于在通知栏点亮那个「ACQUIRE WAKELOCK」。
不点这个锁,长任务跑到一半会被系统挂起。跑完之后记得关掉,它一直在耗电。
环境配好之后,这东西的真实成本
三步装包加一键配置,顺利的话 5 分钟。不顺利的话,上面每一个坑都能吃掉你一晚上。
我把这台机器的实际数字摆出来:apk 125.3 MB,解压 671 个文件,apt 装掉二百多个包,pip 装十几轮,磁盘占掉约 1.6G。
值得吗。
看你怎么用。我一天里绝大多数改动都是改文案、调颜色、补一页说明,这些用不着电脑。
真要搭一个 Android 工程、编一个原生 App、或者处理几万条数据,还是回去用电脑。
它解决的问题不是「手机能替代电脑」。是有那么几个小时你手上只有手机,而活不会等你。
APK 是怎么编出来的
这一段跟日常使用无关,写给好奇的人。
没用 Gradle。这个 App 没有第三方依赖,用 SDK 自带的 aapt2、javac、d8、zipalign、apksigner 直接构建,全程离线,也避免 Gradle 拉 AGP 卡住。

官方 build-tools 只发 linux-x86_64,而我这是 aarch64。aapt2 一跑就崩:
cannot locate symbol _ZNSt6__ndk113__hash_memoryEPKvm
字都认识,意思不懂。查了一阵才弄明白:aapt2 和 adb 都是对着 libc++ 30 编的,仓库里装的是 27c。重装 libc++ 就好,就一行。
还有一个细节:内置资源在 aapt2 链接之后以「不压缩」方式追加进 APK。
为什么不能压缩。因为 AssetManager.openFd() 要直接取到文件描述符做流式读取,压缩过的条目拿不到。那 112 MB 的 termux.apk 就是这么塞进去的,不压缩也不会有额外开销。
速度实测:首次全量约 5 分钟(要拉 Kotlin 编译器和 Compose 全套),改一行代码之后增量 57 秒,assembleRelease 4 分 1 秒。内存峰值 4.3G / 7.5G,没爆。
关键的开关是这一个:
kotlin.compiler.execution.strategy=in-process
让 Kotlin 编译器跑在 Gradle 同一个 JVM 里。不开这个,两个进程一起能把 7.5G 吃穿。
打开之后看到什么
三块,从上往下。
AI 工作台是它想事情的过程。实时控制台是它真敲下去的命令。对话在最下面,那是你打字的地方。
右上角有个下拉,切模型,默认 deepseek。
工作台我平时不看,只在它卡住的时候瞄一眼。能看见它跑到第几轮、调了哪个工具、是不是在瞎猜。
手机上砍掉了四样
源站管理。那张表横着放不下,在手机上改站点纯属受罪。
任务中心。手机不看排队,看的是现在好了没。
Token 输入框。打字填一长串 Key,是折磨。
意识模型。电脑端专属的调试面板。
手机上的正事是一两句话把活交出去,然后等结果。
多出来的两只手
手机版有两样电脑给不了的东西。
一是手。开了无障碍,它能点屏幕、滑列表、往输入框里写字。你让它把这个 App 的每日签到点一下,它真会去点。这是系统级权限,等于把手机交出去一部分,想清楚再开。
二是眼睛。手机立起来对着桌子,问一句这上面有什么,它会拍一张,然后说。

我拿它认过提词器上的字,也让它看过电脑屏幕上的报错。这两件事在电脑上做不到,因为电脑没有手,也没有能转的镜头。
我拿它干过的三件真事
三件都在同一部手机上做完,最长的那件跑了 25 轮,两个半分钟。
第一件,全站换色。原来导航是绿底白字,要改成首页那套白底蓝。它做完之后不是跟我说改好了,是截了图数像素:安卓页绿色 0,百科页绿色 0,主蓝 57,908 个像素。
第二件,加汉堡菜单。手机窄,9 个栏目挤不下,右边那个「版号查询」只剩半个字。它改成点一下弹出来,还顺手算了一遍:面板高 307,可用 369,还有 62 的余量,不会裁。


第三件,写说明书。手机版这一章现在挂在 www.7tan.com/manual.html 上,一个字没在我电脑上敲。

三个坑,提前说
一,息屏就断。锁屏之后它还在跑,但网络会断,长任务容易半路失联。要么把屏幕设成常亮,要么别在锁屏时扔长活。
二,9900 打不开。八成是后台被系统杀了。设置里把它的省电策略改成「无限制」,再打开。
三,APK 解析失败。125.3 MB,下到一半断了就这样。删掉重下,对一下文件大小。

最后一句
它不是那种给你几个模板、帮你写两句文案的手机 AI。
它是一台你能改的机器。改歪了它自己会截图给你看哪歪了,这一条比什么都实在。
配置环境那一段我写得啰嗦,是因为那四十几个坑,每一个我都真金白银地卡过一晚上。你要是在哪一步卡住了,把报错发在评论区,我看着像的就补进下一版。