文章摘要
Agnes AI

我一直希望有一种方式:电脑放在家里运行 AI,人在外面时只拿手机,就能继续发送任务、查看结果,必要时再让 AI 修改代码或执行命令。

一开始我尝试过 Happier,但实际使用效果并不理想。后来我换成了 Happy,才逐渐把这条“手机远程操控电脑端 AI”的工作流跑通。

这里先说明一个容易混淆的地方:我最后使用的工具叫 Happy,不是 Happier。两者是不同的项目,安装包也不同:

Happy 的安装包是 happy,安装命令为:

1
npm install -g happy

安装完成后,实际使用的命令是 happy

我之前尝试过的 Happier 对应的是 @happier-dev/cli。这个包属于 Happier,不是 Happy 的安装包。

Happy 解决的是什么问题

Happy 并不是把一个完整的大模型装进手机,也不是让手机直接读取电脑上的所有文件。它更像是一层远程控制和消息转发服务:

1
2
3
4
5
手机 Happy
<-> Happy 服务端
<-> 电脑上的 Happy 会话
<-> Codex CLI / AI Agent
<-> 电脑文件、终端和开发环境

真正执行任务的仍然是电脑。电脑上的 AI 会话可以访问项目目录、运行终端命令、修改文件和执行构建;手机负责发送消息、接收输出以及查看会话状态。

这和“手机上的聊天机器人”有一个本质区别:手机端不需要复制整个项目,也不需要安装 Node.js、Python 或 CLI。只要电脑在线,并且目标会话仍然运行,手机就可以远程接管它。

安装 Happy

Happy 依赖 Node.js 环境。在 Windows 上,我使用 npm 全局安装:

1
2
npm install -g happy
happy --version

安装后先确认命令能被当前终端找到:

1
Get-Command happy

Windows 如果使用了 nvm,尤其要注意不同 Node.js 版本对应的全局 npm 目录。曾经遇到过这样的情况:旧的 happy.cmd 路径已经不存在,但新的入口实际位于当前 Node.js 版本目录中。此时不要继续使用旧路径,先用 Get-Command happy 找到当前有效入口。

启动一个 Codex 会话

进入需要工作的项目目录,再启动 Happy 的 Codex 会话:

1
2
cd C:\Users\hank.gao\Documents\my-project
happy codex

也可以显式指定工作目录:

1
happy codex -C "C:\Users\hank.gao\Documents\my-project"

启动后,电脑端会创建一条 Happy 会话。完成登录或配对后,这条会话就会出现在手机端的会话列表中。

这里有一个很重要的概念:会话不是窗口本身,而是窗口背后的 AI 工作上下文。

关闭一个外层 cmd 窗口,通常会连带结束它承载的 Happy 会话;而重启 daemon,只是重启后台服务,不等于重新创建一个全新的 AI 对话。

可见模式和静默模式

我在 Windows 上实际用过两种启动方式。可以先用可见模式确认启动正常,再切换到静默模式长期运行。

可见模式会保留一个 cmd 窗口,方便观察日志和处理本地提示。它适合第一次配置或需要调试时使用。

1
cmd /k happy codex -C "C:\Users\hank.gao\Documents\my-project"

/k 表示命令执行后继续保留窗口,所以黑色终端会一直存在。这个窗口可能就是当前会话的宿主,直接关闭它,可能会让手机端对应的会话一起退出。

稳定运行后,我更倾向于使用后台模式,不让桌面上留下可见的黑窗:

1
cmd /c happy codex -C "C:\Users\hank.gao\Documents\my-project"

/c 表示执行命令后退出外层 cmd。Happy 和 Codex 的子进程仍然可以继续运行,但不会保留同样的外层终端窗口。

可见模式适合安装、排错和确认会话是否真的启动成功;静默模式适合电脑长期运行、手机远程使用。

daemon 是什么

Happy daemon 是电脑端的后台守护进程。它负责维持本地会话和 Happy 服务端之间的连接,并让手机能够找到电脑上的活动会话。

常用检查命令如下:

1
2
happy daemon status
happy daemon list

如果 daemon 没有启动,可以尝试:

1
happy daemon start-sync

实际使用时,daemon start 刚返回并不一定代表它已经完全可用。启动后最好稍等片刻,再运行 happy daemon statushappy daemon list。我曾经遇到过查询时机太早,命令暂时超时,但几秒后 daemon 已经正常连接服务端的情况。

判断 daemon 是否真正可用,至少要同时看状态、会话列表和日志。只看到一个存活的进程,不代表控制接口一定健康。

可以把几个对象这样理解:

对象作用
Happy 客户端手机端查看会话和发送消息
Happy 会话一条具体的 AI 工作上下文
Happy daemon电脑端的后台连接和会话管理服务
Codex CLI实际运行 AI 编程任务的本地进程

不要用新会话代替恢复会话

远程工作最怕上下文丢失。电脑重启、daemon 重启或窗口异常退出之后,如果直接再次运行 happy codex,通常会得到一条新的会话。新会话并不知道旧会话里已经讨论过什么。

如果原来的会话记录还在,应优先使用恢复命令:

1
happy resume <sessionId>

例如:

1
happy resume cms6yzrlisfnkwc0u6ghma7zo

这里的 <sessionId> 可以从手机端会话信息、电脑端日志或本地 Happy 会话记录中找到。

我后来遇到过一个很隐蔽的问题:sessions.json 里明明还有旧会话,但 daemon 启动时没有把它们全部加载。进一步排查后发现,Happy 会忽略超过一段时间没有更新的持久化会话。于是“记录还在”并不等于“会话已经恢复到运行态”。

这时需要区分三种状态:

1
2
3
会话记录存在
!= daemon 已加载
!= Codex 进程正在运行

检查时不能只看 sessions.json,还要结合 happy daemon list、daemon 日志和实际进程一起判断。

会话记录存在不等于daemon 已加载,也不等于Codex 进程正在运行

我实际遇到的 Windows 踩坑

npm 路径变化

使用 nvm 切换 Node.js 后,全局 npm 包的路径可能改变。旧的 happy.cmd 可能已经失效,而当前版本的入口在另一个 Node.js 目录。

建议每次切换 Node.js 后重新确认:

1
2
3
node --version
npm --version
Get-Command happy

后台脚本里也不要永久写死已经失效的 Node.js 路径。

Codex CLI 不在 Happy 的 PATH 中

Happy daemon 能够在线,不代表它一定能启动 Codex。Windows 商店版或特殊安装位置的 Codex CLI,有时不会被 Happy 子进程正确发现。

这种情况下常见的现象是:

  • daemon 状态正常
  • 手机能看到电脑
  • happy resume 却没有产生 Codex 子进程
  • 日志提示找不到 Codex CLI,或者进程启动后立即退出

排查时要分别确认 Happy 和 Codex:

1
2
3
Get-Command happy
Get-Command codex
codex --version

如果当前 Codex 只能通过 WindowsApps 等特殊路径启动,就要让 Happy 启动时能够继承到正确的 PATH,或者安装一个对普通命令行环境可见的 Codex CLI。

先确认当前终端能找到两个命令:

1
2
Get-Command happy
Get-Command codex

这通常说明 daemon 已连接,但 Happy 启动 Codex 时使用的 PATH 不完整。检查 codex --version,再核对 Happy daemon 的启动环境。

切换 Node.js 版本后重新确认 npm 全局包入口:

1
2
3
node --version
npm --version
Get-Command happy

把 Claude 会话误当成 Codex 会话

Happy 可以管理不同类型的本地 Agent。会话记录里会保存 flavor 信息。如果一条本来应该运行 Codex 的会话被记录成 claude,恢复时可能会走错启动流程。

我曾经遇到过这样的日志:Happy 进入了 Claude 本地模式,然后去寻找 .claude/projects/ 下的会话文件。文件不存在后,进程以错误码 1 退出,手机端最终显示:

1
Process exited unexpectedly

看到这个提示时,不要只检查网络,也要检查会话类型、工作目录和实际启动的 CLI。

Process exited unexpectedly 是结果,不是原因。需要继续查看会话的 flavor、工作目录、启动命令和对应日志。

daemon 存活但控制接口异常

还有一种情况是:进程列表里能看到 daemon,状态文件也存在,但 happy daemon statushappy daemon list 长时间超时。

这说明“进程还在”不等于“服务健康”。可以按下面的顺序处理:

  1. 检查是否存在多个 Happy daemon。
  2. 检查是否有旧的 resume 进程或终端宿主残留。
  3. 备份本地会话记录。
  4. 停掉异常 daemon,再启动唯一的一份 daemon。
  5. 逐条恢复需要保留的会话。
  6. daemon list 和日志确认会话确实注册成功。

清理会话文件前一定要先备份。会话 ID、加密密钥和工作目录都可能保存在本地记录里,不能把“看起来旧”的条目直接全部删除后再指望找回上下文。

手机能不能直接读取文件

这是我一开始最容易误解的地方。

Happy 手机端不是一个可以自由浏览电脑或手机文件系统的文件管理器。它不能自动读取手机目录里的 .txt,也不能凭空把手机 QQ 下载目录交给电脑端 Codex。

目前更可靠的方式是:

  • 短文本:直接复制粘贴到 Happy 会话。
  • 图片:使用客户端提供的图片附件入口。
  • 长文本或脚本文件:先通过云盘、同步工具或网页上传到电脑,再让电脑端 AI 读取。

如果工作流是“手机从 QQ 群下载原作者脚本,再由电脑加工发布”,Happy 更适合做控制台,而不是文件传输层。

和自动发布工作流结合

我自己的目标不只是远程聊天,而是完成这样一条链路:

1
2
3
4
5
6
7
QQ群发布原作者 txt
-> 手机下载
-> 文件送到电脑
-> 按规则附加代码
-> 生成我的脚本
-> GitHub commit / push
-> Greasy Fork 同步发布

在这条链路里,Happy 可以负责:

  • 远程查看电脑上的处理进度。
  • 手动让 Codex 重跑一次失败任务。
  • 检查生成的脚本和 Git diff。
  • 修复规则变化导致的解析错误。
  • 确认 Git push 是否成功。

但文件从手机到电脑,最好交给更适合传输的工具,例如坚果云、Syncthing 或一个带认证的网页上传服务。电脑端再用监听脚本观察 incoming 目录,发现新文件后自动运行处理流程。

一个比较实用的目录结构是:

1
2
3
4
incoming/      手机上传的原始文件
processing/ 正在处理的文件
done/ 已成功生成并推送的文件
failed/ 处理失败,等待人工检查的文件

这样,Happy 不需要负责搬运文件,只需要在任务失败或规则变化时提供远程操作入口。

这套方案适合什么场景

Happy 适合下面这类工作:

  • 电脑有完整开发环境,不能搬到手机上。
  • AI 需要访问本地项目和终端。
  • 人在外面,但希望继续推进一个已经开始的任务。
  • 需要保留上下文,而不是每次重新解释背景。
  • 偶尔需要手机发送一句指令或查看结果。

它不适合被当成:

  • 手机本地文件管理器。
  • 完全脱离电脑的云端 Agent。
  • 自动解决所有网络、进程和会话恢复问题的魔法服务。

电脑必须在线,Happy daemon 必须健康,目标会话也必须正确启动。任何一层出问题,手机端都可能只显示一个比较笼统的错误。

我的最终使用方式

经过几轮重启、恢复和清理后,我现在把它分成三层:

1
2
3
手机 Happy:发送任务、查看结果
电脑 Happy:维持远程会话、连接服务端
电脑 Codex:读项目、改文件、跑命令、提交代码

需要长期运行时,优先使用静默启动;首次配置和排错时,使用可见终端。遇到手机端显示异常,先查看电脑端日志和进程,不要立即判断为手机网络问题。遇到上下文丢失,优先找回旧 sessionId 并执行 happy resume,不要直接创建新会话。

结语

Happy 给我的最大价值,不是让我在手机上拥有了一个更小的 AI,而是让我可以把电脑上的 AI 工作环境带在身后。

手机只需要发送一句话,真正复杂的事情仍然在电脑上完成:读取项目、执行命令、修改代码、运行测试,再把结果传回来。

当然,这套方案仍然有边界。Happy 解决的是远程控制和会话接管,不是手机文件同步,也不是完整的无人值守流水线。要实现“人在外面也能自动完成 QQ 脚本加工、GitHub 推送和油叉同步”,还需要把文件投递、目录监听、失败重试和发布验证补齐。

但从实际使用来看,先让手机可靠地接管电脑上的 AI,会是一个很有价值的起点。