a4phone
Discovered★ 4DSH(DeepSeek Harness)/ Claude Code / Codex 远程手机交互包。通过 ntfy.sh 在手机上接收任务完成通知(含 AI 最后输出),对 AI 提问与权限请求进行远程点选或文字作答,并可从手机直接继续对话。

a4phone
DSH(DeepSeek Harness)/ Claude Code / Codex / ZCode 远程手机交互包。通过 ntfy.sh 在手机上接收任务完成通知(含 AI 最后输出),对 AI 提问与权限请求进行远程点选或文字作答,并可从手机直接继续对话。
功能
- 任务完成通知:
Stop事件(DSH 为turn/end)→ 电脑弹窗 + 手机推送,包含 AI 最后输出的一段话 - AI 提问交互:
AskUserQuestion(Codex 为request_user_input,DSH 为ask_user_question)→ 手机显示选项按钮点选,也可直接发送文字自由作答 - 权限请求交互:
PermissionRequest→ 手机 Approve/Deny/Always Approve - DSH 一键挂载:
a4p setup自动把内置dsh-hook插件挂到 DSH 全部已装 profile(web / tui / dsh-tui 等),守护进程周期扫描、新装 profile 自动补挂,让 DeepSeek Harness 同样具备手机交互 - 远程续聊:守护进程监听主话题,手机发文字即可与当前会话交流,形成完整远程对话闭环(DSH / Claude Code / Codex / ZCode)
- DSH 远程续聊:手机发文字直接注入 DSH 正在运行的会话(
agent.followup),手机消息与 AI 回复实时出现在桌面端会话里,无需另起进程、无会话锁冲突 - 后台守护进程:
a4p listen无窗口后台运行,日志写入文件 - 桌面弹窗守护进程代发:提问 / 权限请求 / 任务完成的电脑弹窗统一由常驻守护进程弹出(hook 进程——尤其 ZCode——退出时会被执行端口杀掉整棵进程树,hook 内直接弹来不及显示;守护进程在进程树之外,稳定可靠且不增加 hook 延迟)
- 自动更新提醒:守护进程周期检查 npm 新版本并推送手机提醒;其他命令发现新版本时终端提示 + 手机推送(默认开启,可在配置关闭)
- 双模式:外出模式(手机优先)/ 终端优先模式,一键切换
- 零第三方依赖:仅依赖 ntfy.sh 免费服务,无 Google 服务依赖
安装
npm install -g a4phone
使用
a4p setup # 安装引导:生成话题、注册 Hook、启动守护进程、注册开机自启、显示二维码
a4p out # 外出模式(手机优先)
a4p home # 终端优先模式(默认)
a4p status # 查看当前模式
a4p listen # 后台运行续聊守护进程(无窗口)
a4p listen --stop # 停止守护进程
a4p listen --status # 查看守护进程状态
a4p autostart # 查看开机自启状态(--on 开启 / --off 关闭)
a4p resume # 手动续聊最近会话:a4p resume 要追加的内容
a4p last # 查看最近会话记录
a4p test # 发送测试通知
a4p uninstall # 移除 Hook 和配置
a4p --version # 查看版本号
a4p help # 显示帮助
安装引导
a4p setup 自动完成:
- 生成独一无二的话题名称(如
a4p-xxxx),写入~/.a4phone/config.json - 在
~/.claude/settings.json注册三个 Hook(Stop / AskUserQuestion / PermissionRequest),同时写入~/.codex/config.toml的 Codex Hook(见下文 Codex 一节)与~/.zcode/cli/config.json的 ZCode Hook(见下文 ZCode 一节) - 检测到 DSH 环境时,把内置
dsh-hook插件挂载到~/.dsh/profiles/下所有 profile 的cordis.patch.yml(web / tui / dsh-tui 等;守护进程后续每 10 分钟重扫,新装 profile 自动补挂,见下文 DSH 一节) - 默认启动续聊守护进程(
a4p listen后台运行) - 默认注册开机自启(Windows 启动文件夹写入隐藏 VBS,登录时自动运行守护进程)
- 在终端显示二维码
然后用手机 ntfy App 扫描二维码或输入话题名称订阅;DSH 插件热生效无需重启,重启 Claude Code / Codex / ZCode 会话后 Hook 生效。
开机自启无需管理员权限(当前用户启动文件夹),可用
a4p autostart --off关闭、--on重新开启;a4p uninstall会一并移除。WSL/Linux 暂不支持自动注册,可手动用 tmux / systemd 常驻。
模式切换
a4p out # 外出模式:提问/权限请求优先推送手机,超时终端兜底
a4p home # 终端优先模式(默认):直接走终端,手机不参与
a4p status # 查看当前模式
切换即时生效,无需重启会话。
桌面弹窗
AI 提问、权限请求、任务完成时的电脑弹窗统一由常驻续聊守护进程(a4p listen)代发:
- hook / DSH 插件触发时,把通知请求原子写入
~/.a4phone/notify-queue/(而不是 hook 进程里直接弹窗) - 守护进程每 2 秒扫描队列,逐条弹出后删除请求文件;守护进程停运期间积压超过 60 秒的请求自动丢弃,避免恢复后批量轰炸
- 守护进程不在运行时回退为直接弹窗(Claude Code / Codex / DSH 的宿主进程常驻,直接弹可正常显示)
这样做的原因:ZCode 的执行端口会在 hook 命令退出时杀掉整棵进程树,hook 内 fire-and-forget 的气泡来不及渲染(已实测:hook 进程存活时气泡可见、一退出即被掐断);改由 hook 进程树之外的守护进程弹出则稳定可靠,且不增加 hook 延迟(对 Claude Code / Codex 也无副作用)。
AI 最后输出
Stop 事件触发时,a4phone 读取会话记录(transcript),把 AI 最后输出的一段话(截断到 1000 字符)连同目录、会话 ID 一起推送手机,让你离开电脑也能看到任务的实际结果。
手机自由文本作答
AskUserQuestion 提问推送手机后,除了点选选项按钮,还可以直接向响应话题 {topic}-response 发送文字作为答案,自由回答不受选项限制。ntfy 单条推送最多 3 个按钮,选项超过 3 个时自动降级为编号列表,回复对应编号即可选中选项。
远程续聊
在手机端直接向主话题 {topic} 发送文字,即可与最近会话(DSH / Claude Code / Codex)继续对话——无需额外的续聊话题,你订阅的通知话题就是对话通道。
-
启动续聊守护进程(后台无窗口运行):
a4p listen # 后台运行 a4p listen --status # 查看状态 a4p listen --stop # 停止日志写入
~/.a4phone/daemon.log。 -
手机 ntfy App 已订阅主话题
{topic}(a4p setup生成,扫描二维码即可),向该话题发送任意文字即可。 -
守护进程收到手机消息后,按最近会话的 agent 执行续聊(DSH:经文件队列交给
dsh web进程内的插件直接followup到当前 live 会话;Claude Code:claude --resume <会话> --continue -p;Codex:codex exec resume <会话> -o <临时文件> -,-o捕获最后一条回复;ZCode:headless 调zcode.cjs --prompt <消息> --resume <会话> --json,从 JSON 的response字段取回复)。均为 headless,捕获回复后推回手机。Codex 会话若被窗口占用(thread-store conflict),a4phone 会自动把它 fork 成新线程续聊——不需要关闭原窗口,原会话原样保留,手机对话在 fork 上继续。 -
无需守护进程时,也可在电脑上手动续聊:
a4p resume 帮我总结一下刚才的改动 -
查看最近会话记录:
a4p last
续聊完全 headless 运行(无需窗口标题匹配、前台焦点或剪贴板,也不依赖你当前是否开着终端),支持 DSH、Claude Code、Codex 与 ZCode 会话(按最近会话的 agent 自动选择续聊方式)。续聊回合内若再次触发提问/权限请求,仍会推送手机,形成完整的远程对话闭环。
ZCode 续聊的模型跟随:ZCode 的模型/provider 由桌面 app 管理(
~/.zcode/v2/config.json),headless 续聊需要~/.zcode/cli/config.json里有显式模型配置。a4phone 在每次续聊前从该会话的 rollout 记录读取会话实际使用的模型,并自动同步到~/.zcode/cli/config.json—— 你在桌面端切换模型后,续聊自动跟随切换后的模型(a4p setup会先写入一个默认配置)。积压合并:一轮续聊最长可达
resumeTimeout(默认 30 分钟),期间手机连续发来的消息会自动合并为一个批次一次性续聊(不再逐条排队、每条一个独立轮次),保证手机内容一定能送达 AI;积压批次持久化到~/.a4phone/pending-batch.json,守护进程重启/崩溃后自动恢复,不丢消息。
Codex
a4p setup 会同时自动配置 Claude Code 和 Codex。Codex 配置追加到 ~/.codex/config.toml 末尾(保留原有设置),结构如下:
[features]
hooks = true
[[hooks.Stop]]
[[hooks.Stop.hooks]]
type = "command"
command = "a4p hook codex"
[[hooks.PreToolUse]]
matcher = "request_user_input"
[[hooks.PreToolUse.hooks]]
type = "command"
command = "a4p hook codex"
[[hooks.PermissionRequest]]
[[hooks.PermissionRequest.hooks]]
type = "command"
command = "a4p hook codex"
注意:启用项必须放在
[features]表内([features] hooks = true),不能写成根级别的裸hooks = true,否则与[[hooks.*]]冲突导致 TOML 解析错误。Codex 会话中需运行/hooks并手动信任新 Hook。Codex 的提问工具叫
request_user_input(不是AskUserQuestion),PreToolUse 的 matcher 必须匹配该名称 hook 才会触发。Codex 端无法像 Claude Code 那样用updatedInput注入答案,a4phone 采用"阻断工具调用、把手机答案写进阻断原因"的方式,让模型看到答案后直接采用继续。
ZCode
a4p setup 会同时自动配置 ZCode。Hook 写入 ~/.zcode/cli/config.json(保留原有 MCP、插件等设置)。与 Claude Code 不同,ZCode 的事件块挂在 hooks.events 下,且配置文件 Hook 默认禁用,必须 hooks.enabled: true 才会运行(a4phone 写入时自动补上):
{
"hooks": {
"enabled": true,
"events": {
"Stop": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "a4p hook zcode" } ] } ],
"PreToolUse": [ { "matcher": "AskUserQuestion", "hooks": [ { "type": "command", "command": "a4p hook zcode" } ] } ],
"PermissionRequest": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "a4p hook zcode" } ] } ]
}
}
}
ZCode 支持的事件与 Claude Code 一致(Stop / PreToolUse / PermissionRequest),提问工具也叫 AskUserQuestion。与 Claude Code 有两个关键差异:
- 提问触发两次 hook:ZCode 对一次
AskUserQuestion会同时触发PreToolUse和PermissionRequest两个 hook。a4phone 只在PreToolUse分支弹「有提问需要处理」提醒(PermissionRequest分支对提问跳过弹窗,避免重复通知和误导性的「有权限请求需要处理」文案);外出模式下两者配合完成手机作答——提问走 asku 注入答案(updatedInput.answers),权限请求自动放行(decision.behavior: "allow"),与 ZCode 的 hook 输出 schema 兼容。 - 桌面弹窗需守护进程代发:ZCode 的执行端口会在 hook 命令退出时杀掉整棵进程树,hook 内直接弹窗来不及渲染。因此桌面弹窗统一由常驻守护进程从
~/.a4phone/notify-queue/队列代发(见 桌面弹窗),ZCode 的桌面提醒依赖守护进程在运行(a4p setup默认启动并注册开机自启;a4p listen --status可随时查看状态)。
重启 ZCode 会话后 Hook 生效。提问与权限请求的桌面弹窗在 home / out 模式下均会触发;手机点选仅外出模式参与。远程续聊已支持 ZCode 会话(headless 调 zcode CLI,见 远程续聊);
a4p uninstall会一并移除 ZCode Hook。
DSH(DeepSeek Harness)
a4p setup 检测到 DSH 环境(~/.dsh/profiles/ 存在)时,会扫描全部 profile(web / tui / dsh-tui 及后续新装的变体),把内置的 dsh-hook 插件挂载到每个 profile 的 cordis.patch.yml,让 DeepSeek Harness 同样具备手机远程交互。插件复用同一 a4phone 话题与模式,手机端无需额外订阅。
| Hook | 触发事件 | 桌面通知 | 手机交互(外出模式) |
|------|---------|---------|---------------------|
| 任务完成 | turn/end 且 reason.kind === 'completed' | ✔ 电脑弹窗 | 手机推送(含 AI 最后输出) |
| 提问 | ask_user_question 工具调用 | ✔ 电脑弹窗「有提问需要处理」 | 手机点选选项 / 文字自由作答 |
| 权限请求 | approval/request | ✔ 电脑弹窗「有权限请求需要处理」 | 手机 Approve / Deny |
| 远程续聊 | 文件队列 ~/.a4phone/dsh-jobs/(a4p 写请求,插件回复) | — | 手机发文字 → agent.followup 注入当前会话 → 回复推回手机 |
- 插件位于本包
dsh/目录(Cordis 插件,监听 DSH 的session/event、tools/execute、approval/request事件),a4p setup以 insert 形式写入 patch,幂等可重复执行 - 若检测到旧版手动挂载(指向
C:\ProgramMine\dsh-hook的id: dsh-hook),a4p setup会自动替换为本包路径 cordis.patch.yml被 DSH 热监视(watchUserPatches),挂载即时生效;若插件代码有更新,建议重启dsh web(可参考restart-dsh-web.ps1的思路)- 模式切换复用同一套:
a4p out(手机优先)/a4p home(终端优先);Hook 日志写入~/.a4phone/dsh-logs/ - 多 profile 自动发现:profile 身份文件为子目录下的
cordis.yml;除setup全量扫描外,续聊守护进程每 10 分钟重扫一次,新装 profile 无需重跑 setup 即可自动补挂 - 提问与权限请求的桌面弹窗在 home/out 模式下均会触发;手机点选仅外出模式参与
a4p uninstall会同时移除所有 profile 的挂载
DSH 远程续聊
手机向主话题发文字即可继续 DSH 会话,机制与 Claude Code / Codex 的续聊不同:
- 记录最近会话:插件在每次顶层会话
turn/end(completed)时写入~/.a4phone/last.json(agent: "DSH"),与 Claude Code / Codex 的 Stop Hook 一致 - 文件队列协议:
a4p resume/a4p listen把手机消息原子写入~/.a4phone/dsh-jobs/req-<id>.json;插件每秒扫描,处理后写resp-<id>.json,a4p 轮询取回并推回手机;插件同时刷新~/.a4phone/dsh-heartbeat.json心跳,a4p 据此快速判断dsh web是否在运行(未运行会快速失败而非干等超时) - 注入到桌面会话:插件用
agent.followup()把手机文字作为普通user/message写入桌面上正在运行的同一个会话(ctx.agents解析:优先last.json记录的会话,兜底最近顶层会话),await agent.whenIdle()等待轮次结束,提取最后一条 assistant 文本回推——手机消息与 AI 回复都会实时出现在桌面端会话里,桌面与手机看到同一段对话 - 无会话锁冲突:不另起进程,所以不存在 Claude Code
--resume式的独占锁问题;续聊轮次内若触发提问/审批,仍走手机交互,形成完整闭环 - 续聊轮次的"任务完成"推送已自动去重(回复由 a4p 推回,插件不再重复通知)
前提:
dsh web正在运行且已挂载新版dsh-hook插件(a4p setup自动挂载,插件代码更新后需重启dsh web)。未检测到dsh web时续聊会快速失败并给出提示。
⚠️ 待办:DSH workspace 记账归组缺陷(临时外部方案,关注 DSH 官方修复)
背景:DSH 存在一个已知缺陷——workspace 注册表的会话记账只在"首次启动"时用 header 归组历史目录,此后产生的会话(旧版 TUI、dsh headless、部分启动入口等)只写会话日志、不主动记账,于是永久落在"未分组"。该行为官方 README 正文有陈述("Later cwd-only sessions remain Ungrouped.",v0.1.1-rc.2 启动引导段),但并未列入 "Known Limitations and Deferred Work" 一节(该节仅列"会话删除能力缺失""header 索引刷新时机"两条),官方 GitHub(deepseek-ai/deepseek-harness)也无对应 issue;0.1.2-rc.1 起官方将其改写为设计契约——"sessions created afterwards join a workspace only through attachSession",且注明 "current package constraints, not a task backlog"——官方视角是无修复计划的既定行为,并非待办缺陷。(核实:2026-09-03,基于 npm next 0.1.2-rc.1 / GitHub master)
a4phone 的临时方案:在 DSH 插件(dsh/lib/index.js)中加入"孤儿会话自愈",在每次插件启动时把已持久化但未记账的会话按 header.cwd 归入对应项目(必要时自动新建 workspace 记录)。该方案:
- 幂等:只处理未记账的会话,重复运行不重复归组;
- 安全:失败只记日志,不影响插件启动与其他功能;
- 临时:仅作为 DSH 官方修复记账 bug 之前的过渡措施。
迭代检查项(每次功能迭代 / 代码提交前):
- 检查 DSH 官方(
@deepseek-ai/dsh-workspace)是否已修复 workspace 记账归组; - 若已修复,评估并移除本插件中的"孤儿会话自愈"模块(
config.healWorkspaces开关可先关闭再删代码)——它是与 a4phone 核心功能无关的冗余设计,不应长期保留; - 若未修复,保留本方案,并在核实时更新上文对官方态度的描述(截至 0.1.2-rc.1:官方仍无启动期对账,视为设计契约、无修复计划)。
责任划分:根因是 DSH 核心 workspace 记账缺陷(DSH 官方应修;注:截至 0.1.2-rc.1 官方将其视为设计契约,未见修复计划);dsh-tui / 旧入口只是"不主动记账"的设计使然,非其锅;a4phone 是体验受损方而非制造者。
原理
DSH 插件与 Hook(Claude Code / Codex / ZCode)拦截事件后,通过 ntfy.sh 推送带按钮的通知到手机;手机点选或发送文字后,决策经响应话题回传并注入会话。Stop 事件同时把 AI 最后输出从会话记录中抽取出来推送手机。电脑弹窗则由常驻守护进程从 ~/.a4phone/notify-queue/ 队列代发(见 桌面弹窗)。
AI助手触发事件 → a4p hook → ntfy.sh 推送手机 → 手机点选/文字作答 → 决策回传 → 注入会话
远程续聊的闭环:
手机向 {topic} 发文字 → 守护进程 a4p listen
→ 或 DSH:a4p 写 req 文件 → dsh web 进程内插件 agent.followup 注入会话
→ whenIdle 等待轮次结束 → 提取回复写 resp 文件 → a4p 轮询取回
→ 或 claude --resume <会话> --continue -p(headless,stdin 作为消息)
→ 或 codex exec resume <会话> -o <临时文件> -(Codex,-o 捕获最后一条回复)
→ 或 node zcode.cjs --prompt <消息> --resume <会话> --json(ZCode,续聊前自动同步会话模型)
→ AI 回复写入会话并回推手机
→(DSH 续聊直接发生在桌面正在运行的会话上,手机与桌面看到同一段对话)
→(Codex 会话被窗口占用时自动 fork 新线程续聊,无需关闭原窗口)
Hook 输出格式
- 提问(PreToolUse):Claude Code 为
hookEventName: "PreToolUse"+permissionDecision: "allow"+updatedInput.answers(改写工具输入);Codex 为permissionDecision: "deny"+permissionDecisionReason写入手机答案(阻断request_user_input调用,让模型直接采用答案继续) - 权限请求(PermissionRequest):
hookEventName: "PermissionRequest"+decision.behavior
注意事项
- 需 Node.js 18+,手机端安装 ntfy App
- 手机订阅后,请在订阅设置中开启"即时交付",否则消息需手动刷新才能收到
- 续聊支持 DSH、Claude Code、Codex 与 ZCode 会话(按最近会话的 agent 自动选择方式);DSH 续聊需
dsh web正在运行且已挂载新版插件;Codex 续聊通过codex exec resume执行,需 Codex CLI 已登录、hook 已信任;ZCode 续聊需 ZCode 桌面端已安装(自动探测zcode.cjs路径),续聊前自动同步会话模型到~/.zcode/cli/config.json - DSH 支持任务完成通知 / 提问作答 / 权限审批 / 远程续聊(经内置
dsh-hook插件) - 续聊期间守护进程会自动临时切换为外出模式,结束后恢复原模式
- Claude Code 会话同一时间只能被一个进程占用,
--resume续聊前请先结束终端里仍在运行的原会话;Codex 会话被占用时 a4phone 会自动 fork 新线程续聊(复制会话为新线程 ID,原窗口不受影响,手机对话在 fork 上继续) - 续聊守护进程默认随
a4p setup启动并注册开机自启(Windows 登录时自动运行);也可手动a4p listen,WSL/Linux 可用 tmux 或 systemd - ntfy.sh 免费托管服务有发布速率/消息保留限制:短时间高频测试可能触发
limited提示,建议降低推送频率(续聊结果已去重推送,不再重复通知) - ntfy.sh 公共话题可被知晓话题名的人读写,重要场景建议自建 ntfy 服务或使用访问令牌
- ntfy.sh 为国外服务,国内网络下长连接可能不稳定
- 自动更新提醒:默认开启(
checkUpdates: true)。守护进程(a4p listen)启动时及每updateIntervalHours小时(默认 6)检查一次 npm registry(npmmirror 优先、官方兜底),发现新版本推送手机提醒;其他命令(a4p status/a4p resume等)发现新版本时终端提示 + 手机推送(与守护进程共用去重缓存,同一版本只提醒一次)。查询失败静默跳过,不影响正常功能;可在~/.a4phone/config.json设checkUpdates: false关闭 - 配置存储于
~/.a4phone/config.json,最近会话存储于~/.a4phone/last.json,模式存储于~/.a4phone/mode.json,守护进程信息存储于~/.a4phone/daemon.json,日志写入~/.a4phone/daemon.log;DSH Hook 日志写入~/.a4phone/dsh-logs/,DSH 续聊队列位于~/.a4phone/dsh-jobs/,心跳位于~/.a4phone/dsh-heartbeat.json,桌面通知队列位于~/.a4phone/notify-queue/,更新检查缓存位于~/.a4phone/update-cache.json
开发
npm install # 安装依赖
node bin/a4p.mjs setup # 本地调试
开源协议
Comments
Loading…
Similar plugins
by Hyna-hla
DSH Remote 手机遥控端:把电脑上的 DeepSeek Harness 装进口袋。手机连上就能给 AI 派活、看实时回复、批审批;支持局域网/内网穿透、扫码连接、审批通知、会话管理、多主题换装,还能解锁加密保险库。第三方社区作品,开源免费。
★ 12
MIT
Kotlin
Aug 31, 2026
dsh plugin --profile web add dsh-remote-accessby UNLINEARITY
Claude-Code-style TUI bundle for DeepSeek Harness. 充分结合 DSH 的核心机制和高级特性与Codex CLI 、Claude Code 等主流交互机制,打造的 DSH-Code. (对齐DSH官方上游最新版本!持续更新中!支持DSH 特殊模式,插件系统,模型管理,子代理管理,切换模型特殊动画)注:自 DSH-Code 1.0.0起,代码由DSH
★ 34
MIT
TypeScript
Sep 17, 2026
dsh plugin --profile web add dsh-codeby saya-ch
DeepSeek Harness 的 Android App 与安全远程访问插件,支持局域网/远程连接和高度自定义的移动界面与扩展能力。
★ 273
↓ 2.2k/wk
Apache-2.0
TypeScript
Sep 18, 2026
dsh plugin --profile web add dsh-mobileby zexadev
Mobile client for the DeepSeek Harness — use the dsh on your dev machine from your Android or iOS phone, remotely across networks, peer-to-peer over iroh with no server to set up (falls back to a rela
★ 45
MIT
Rust
Sep 9, 2026
dsh plugin --profile web add dsh-plugin-tetherby FYL1025
DeepSeek Harness (DSH) 远程工作区插件:通过 SSH 连接一台或多台服务器,直接在 DSH 的 Web 界面里浏览文件、编辑代码、执行命令——体验类似 VS Code Remote-SSH,无需离开对话。
★ 3
MIT
JavaScript
Aug 16, 2026
dsh plugin --profile web add dsh-remote-workspaceby omdsh-dev
在 DeepSeek Harness 与 Codex、Claude Code、Pi、Reasonix、OpenCode 之间双向迁移对话记录,支持 CLI 与 Web UI
★ 3
MIT
TypeScript
Aug 14, 2026
dsh plugin --profile web add @deepseek-ai/dsh-shuttle