🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

手机遥控台 eogee/a4phone

DeepSeek Harnessv1.7.1
eogee27 天前有提交已提供中文文档扫描:含敏感能力

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

36.5/100
综合分
5
GitHub 星标
34
npm 周下载
—/5
用户评分

数据截至 2026/10/7 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add a4phone
npm 源 · a4phone 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · ui
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功(非静态推断);本次验证针对插件 v1.7.2,当前版本为 v1.7.1
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 27 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包a4phone @ 1.7.1
✓Node 引擎要求 >=18 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/31 04:50:22

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 11 处,展示前 11 条)
  • 写入本地文件
    dsh/lib/index.js:64
    mkdirSync(logDir, { recursive: true });
  • 写入本地文件
    dsh/lib/index.js:65
    appendFileSync(path.join(logDir, HOOK_LOG_FILE[hook] ?? 'hooks.jsonl'), line + '\n');
  • 执行外部命令来自配置/变量
    src/daemon.mjs:39
    const child = spawn(process.execPath, [scriptPath, 'listen', '--daemon-child'], {
  • 执行外部命令固定命令
    src/daemon.mjs:73
    spawn('taskkill', ['/pid', String(pid), '/f', '/t'], { stdio: 'ignore' }).on('error', () => {});
  • 发起网络请求
    src/listen.mjs:166
    const res = await fetch(`${url}?${since}`);
  • 执行外部命令来自配置/变量
    src/notify.mjs:50
    const child = spawn(cmd, args, opts);
  • 发起网络请求
    src/ntfy.mjs:23
    const res = await fetch(server, {
  • 发起网络请求
    src/ntfy.mjs:42
    const res = await fetch(url, { signal: controller.signal });
  • 执行外部命令来自配置/变量
    src/resume.mjs:189
    child = spawn(cmd, cmdArgs, { cwd, shell: false, env });
  • 执行外部命令来自配置/变量
    src/resume.mjs:201
    spawn(taskkill, ['/pid', String(child.pid), '/f', '/t']).on('error', () => child.kill());
  • 发起网络请求
    src/update-check.mjs:85
    const res = await fetch(`${base}/a4phone/latest`, { signal: controller.signal });
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

1 张 · 点击查看大图

功能亮点

  • 接收任务完成通知
  • 远程点选或文字作答
  • 手机继续对话

README

由 DeepSeek 最新模型翻译生成
a4phone a4phone DSH(DeepSeek Harness)/ Claude Code / Codex / ZCode / Qoder / WorkBuddy 六个 AI 阵营的远程手机交互包。通过 ntfy.sh 在手机上接收任务完成通知(含 AI 最后输出),对 AI 提问与权限请求进行远程点选或文字作答,并可从手机直接继续对话(WorkBuddy 除外,见 WorkBuddy)。 功能 - 任务完成通知: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 同样具备手机交互
展开完整文档(README 剩余 1 节)
a4phone

a4phone

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

功能

- 任务完成通知: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 / Qoder)
- 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 自动完成:

1. 生成独一无二的话题名称(如 a4p-xxxx),写入 ~/.a4phone/config.json
2. 在 ~/.claude/settings.json 注册三个 Hook(Stop / AskUserQuestion / PermissionRequest),同时写入 ~/.codex/config.toml 的 Codex Hook(见下文 Codex 一节)、~/.zcode/cli/config.json 的 ZCode Hook(见下文 ZCode 一节)、~/.qoder/settings.json 的 Qoder Hook(见下文 Qoder 一节)与 ~/.workbuddy/settings.json 的 WorkBuddy Hook(见下文 WorkBuddy 一节)
3. 检测到 DSH 环境时,把内置 dsh-hook 插件挂载到 ~/.dsh/profiles/ 下所有 profile 的 cordis.patch.yml(web / tui / dsh-tui 等;守护进程后续每 10 分钟重扫,新装 profile 自动补挂,见下文 DSH 一节)
4. 默认启动续聊守护进程(a4p listen 后台运行)
5. 默认注册开机自启(Windows 启动文件夹写入隐藏 VBS,登录时自动运行守护进程)
6. 在终端显示二维码

然后用手机 ntfy App 扫描二维码或输入话题名称订阅;DSH 插件与 Qoder / WorkBuddy Hook 热生效无需重启,重启 Claude Code / Codex / ZCode 会话后 Hook 生效。

开机自启无需管理员权限(当前用户启动文件夹),可用 a4p autostart --off 关闭、--on 重新开启;a4p uninstall 会一并移除。WSL/Linux 暂不支持自动注册,可手动用 tmux / systemd 常驻。

模式切换

a4p out # 外出模式:提问/权限请求优先推送手机,超时终端兜底 a4p home # 终端优先模式(默认):直接走终端,手机不参与 a4p status # 查看当前模式

模式切换即时生效,无需重启会话。

桌面弹窗

AI 提问、权限请求、任务完成时的电脑弹窗统一由常驻续聊守护进程(a4p listen)代发:

1. hook / DSH 插件触发时,把通知请求原子写入 ~/.a4phone/notify-queue/(而不是 hook 进程里直接弹窗)
2. 守护进程每 2 秒扫描队列,逐条弹出后删除请求文件;守护进程停运期间积压超过 60 秒的请求自动丢弃,避免恢复后批量轰炸
3. 守护进程不在运行时回退为直接弹窗(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)继续对话——无需额外的续聊话题,你订阅的通知话题就是对话通道。

1. 启动续聊守护进程(后台无窗口运行):

a4p listen # 后台运行 a4p listen --status # 查看状态 a4p listen --stop # 停止

日志写入 ~/.a4phone/daemon.log。

2. 手机 ntfy App 已订阅主话题 {topic}(a4p setup 生成,扫描二维码即可),向该话题发送任意文字即可。

3. 守护进程收到手机消息后,按最近会话的 agent 执行续聊(DSH:经文件队列交给 dsh web 进程内的插件直接 followup 到当前 live 会话;Claude Code:claude --resume <会话> --continue -p;Qoder:qoder --resume <会话> --fork-session --session-id <新会话ID> -p(Qoder 没有会话锁,续聊一律 fork 到新会话,原会话不受影响,新会话自动记回 last.json 保持手机多轮连续);Codex:codex exec resume <会话> -o <临时文件> -,-o 捕获最后一条回复;ZCode:headless 调 zcode.cjs --prompt <消息> --resume <会话> --json,从 JSON 的 response 字段取回复)。均为 headless,捕获回复后推回手机。Codex 会话若被窗口占用(thread-store conflict),a4phone 会自动把它 fork 成新线程续聊——不需要关闭原窗口,原会话原样保留,手机对话在 fork 上继续。

4. 无需守护进程时,也可在电脑上手动续聊:

a4p resume 帮我总结一下刚才的改动

5. 查看最近会话记录:

a4p last

续聊完全 headless 运行(无需窗口标题匹配、前台焦点或剪贴板,也不依赖你当前是否开着终端),支持 DSH、Claude Code、Codex、Qoder 与 ZCode 会话(按最近会话的 agent 自动选择续聊方式)。续聊回合内若再次触发提问/权限请求,仍会推送手机,形成完整的远程对话闭环。

WorkBuddy 不在此列——其凭据只在桌面进程内存中,内置 CLI 需交互式登录,无法 headless 续聊(详见 WorkBuddy)。手机向话题发文字时会收到明确提示而非静默失败。

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。

Qoder

a4p setup 会把 Qoder 的 Hook 写入 ~/.qoder/settings.json(保留你原有的插件、Hook 等其他设置)。Qoder CLI 的 Hook 协议与 Claude Code 同构,因此三个事件块、Hook 输出格式、AskUserQuestion 提问工具都与 Claude Code 走同一套代码路径,只是 Hook 命令带 qoder 标识、写入路径不同:

{
"hooks": {
"Stop": [ { "matcher": "", "hooks": [ { "type": "command", "command": "a4p hook qoder" } ] } ],
"PreToolUse": [ { "matcher": "AskUserQuestion", "hooks": [ { "type": "command", "command": "a4p hook qoder" } ] } ],
"PermissionRequest": [ { "matcher": "", "hooks": [ { "type": "command", "command": "a4p hook qoder" } ] } ]
}
}

与已支持宿主的差异(均经本机 Qoder CLI 1.1.64 实测确认):

- Hook 热生效:写入 ~/.qoder/settings.json 后无需重启会话,下一次工具调用即触发(实测与 DSH 插件一样即时生效)
- 无需额外开关:既没有 ZCode 的 hooks.enabled,也没有 Codex 的 Hook 手动信任步骤;disableAllHooks 默认关闭,Hook 注册即可用
- Stop 载荷直送 AI 输出:载荷含 session_id / transcript_path / cwd / hook_event_name / last_assistant_message,任务完成通知直接取该字段;会话记录位于 ~/.qoder/projects/<项目>/<会话ID>.jsonl,格式与 Claude Code 一致
- Hook 执行环境:Windows 下由 Git Bash 执行、工作目录已是项目根,因此 a4p 需在 PATH 上(npm install -g a4phone 即满足) 远程续聊需要独立的 Qoder CLI 并已登录:安装 npm install -g @qoder-ai/qodercli@latest,再执行 qoder login(CLI 的登录态与桌面端各自独立)。Qoder 没有会话锁:直接 --resume 一个仍活跃的会话并不会报错,而是往同一份会话记录续写、继续那个会话的任务,因此 a4phone 的 Qoder 续聊一律 --fork-session 到新会话(实测原会话完全不被改动,手机侧多轮上下文自动衔接);另注意 --resume 不能与 --continue 并用。只装桌面端未装 CLI 时,通知/提问作答/权限审批照常可用,仅续聊会提示无法启动。a4p uninstall 会一并移除 Qoder Hook。

WorkBuddy

a4p setup 会把 WorkBuddy 的 Hook 写入 ~/.workbuddy/settings.json(保留你原有的所有设置)。WorkBuddy 与 Claude Code 同源,Hook 协议完全同构,因此三个事件块、Hook 输出格式、AskUserQuestion 提问工具都与 Claude Code 走同一套代码路径,只是 Hook 命令带 workbuddy 标识、写入路径不同:

{
"hooks": {
"Stop": [ { "matcher": "", "hooks": [ { "type": "command", "command": "a4p hook workbuddy" } ] } ],
"PreToolUse": [ { "matcher": "AskUserQuestion", "hooks": [ { "type": "command", "command": "a4p hook workbuddy" } ] } ],
"PermissionRequest": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "a4p hook workbuddy" } ] } ]
}
}

实测确认的差异(WorkBuddy 5.7.6 / Windows)

- Hook 热生效:写入后当前会话下一次工具调用即触发,无需重启会话(实测确认)
- 会话记录结构不同:位于 ~/.workbuddy/projects/<项目slug>/<sessionId>.jsonl,与 Claude Code 同为 JSONL,但消息结构三个字段全不同——顶层 type: "message"(非 assistant)、role 在顶层(非 message.role)、文本块 type: "output_text"(非 text)。transcript.mjs 已加专门分支解析
- Hook 60 秒超时(重要):WorkBuddy hook 脚本超过 60 秒会被宿主直接终止。a4phone 外出模式若等待手机作答恰好到 60s,答案还没注入就被杀掉(手机端已作答但会话无反应)。因此对 WorkBuddy 自动把作答等待上限收窄到 45 秒(src/hook.mjs 的 resolveWaitSeconds),留出写回与传输余量;a4p setup 会提示当前上限。想更长等待需先确认宿主超时可配
- Windows 执行环境:hook 由 Git Bash 执行,a4p 需在 PATH 上(npm install -g a4phone 即满足)

不支持远程续聊(重要限制):WorkBuddy 的任务完成通知 / 提问作答 / 权限审批三项正常,但暂不支持从手机续聊。

原因(2026-10-07 实测):WorkBuddy 桌面端把登录凭据只保存在桌面进程内存中(CODEBUDDY_CREDENTIALS_IN_MEMORY),并不落盘——sharedDataPath/auth/<id>.info 在未显式登录时不存在。因此从任何外部终端调用其内置 CLI(resources/app.asar.unpacked/cli/bin/codebuddy)都会报 Authentication required. Please use /login command,而 /login 是交互式斜杠命令,无法在 headless 续聊中非交互完成。

另有一道未确认的关卡:即使手动登录成功,CLI 是否能 --resume 续接桌面端的历史会话 ID 仍未验证(有资料称 CLI 只能看到自己在终端创建的会话)。基于这两点,a4phone 选择不提供该功能,而非留一个可能静默失败的开关。

需要续聊时请直接回到 WorkBuddy 桌面端继续对话;a4p resume 遇到 WorkBuddy 会话会给出明确提示,不会静默失败。

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 的续聊不同:

1. 记录最近会话:插件在每次顶层会话 turn/end(completed)时写入 ~/.a4phone/last.json(agent: "DSH"),与 Claude Code / Codex 的 Stop Hook 一致
2. 文件队列协议:a4p resume / a4p listen 把手机消息原子写入 ~/.a4phone/dsh-jobs/req-<id>.json;插件每秒扫描,处理后写 resp-<id>.json,a4p 轮询取回并推回手机;插件同时刷新 ~/.a4phone/dsh-heartbeat.json 心跳,a4p 据此快速判断 dsh web 是否在运行(未运行会快速失败而非干等超时)
3. 注入到桌面会话:插件用 agent.followup() 把手机文字作为普通 user/message 写入桌面上正在运行的同一个会话(ctx.agents 解析:优先 last.json 记录的会话,兜底最近顶层会话),await agent.whenIdle() 等待轮次结束,提取最后一条 assistant 文本回推——手机消息与 AI 回复都会实时出现在桌面端会话里,桌面与手机看到同一段对话
4. 无会话锁冲突:不另起进程,所以不存在 Claude Code --resume 式的独占锁问题;续聊轮次内若触发提问/审批,仍走手机交互,形成完整闭环
5. 续聊轮次的"任务完成"推送已自动去重(回复由 a4p 推回,插件不再重复通知)

前提:dsh web 正在运行且已挂载新版 dsh-hook 插件(a4p setup 自动挂载,插件代码更新后需重启 dsh web)。未检测到 dsh web 时续聊会快速失败并给出提示。

DSH workspace 记账归组

DSH 存在 workspace 记账归组缺陷(此后产生的会话永久落在"未分组")。a4phone 在插件中做了"孤儿会话自愈"作为临时过渡措施,该方案与官方修复进展的跟踪记录见 docs/dsh-workspace-accounting.md。

原理

DSH 插件与 Hook(Claude Code / Codex / ZCode / Qoder / WorkBuddy)拦截事件后,通过 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 作为消息) → 或 qoder --resume <会话> --fork-session --session-id <新会话ID> -p(Qoder,headless,每轮 fork 到新会话) → 或 codex exec resume <会话> -o <临时文件> -(Codex,-o 捕获最后一条回复) → 或 node zcode.cjs --prompt <消息> --resume <会话> --json(ZCode,续聊前自动同步会话模型) → AI 回复写入会话并回推手机 →(DSH 续聊直接发生在桌面正在运行的会话上,手机与桌面看到同一段对话) →(Codex 会话被窗口占用时自动 fork 新线程续聊,无需关闭原窗口) →(WorkBuddy 不支持续聊,手机发文字会收到明确提示;请回桌面端继续对话)

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、Qoder 与 ZCode 会话(按最近会话的 agent 自动选择方式);DSH 续聊需 dsh web 正在运行且已挂载新版插件;Codex 续聊通过 codex exec resume 执行,需 Codex CLI 已登录、hook 已信任;ZCode 续聊需 ZCode 桌面端已安装(自动探测 zcode.cjs 路径),续聊前自动同步会话模型到 ~/.zcode/cli/config.json;Qoder 续聊需独立 Qoder CLI(npm install -g @qoder-ai/qodercli@latest)且已 qoder login 登录(CLI 登录态独立于桌面端),仅装桌面端时通知/提问/审批仍可用而续聊会提示未登录
- DSH 支持任务完成通知 / 提问作答 / 权限审批 / 远程续聊(经内置 dsh-hook 插件)
- WorkBuddy 支持任务完成通知 / 提问作答 / 权限审批,但不支持远程续聊(凭据仅存在于桌面进程内存,内置 CLI 需交互式 /login;详见 WorkBuddy 一节)。注意其 hook 有 60s 硬超时,外出模式作答等待已自动收窄至 45s
- 续聊期间守护进程会自动临时切换为外出模式,结束后恢复原模式
- 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 # 本地调试

开源协议

MIT

联系方式

- 官网:<https://eogee.com>
- 使用文档:<https://eogee.com/article/54>
- QQ:3886370035 | 微信:eogee2022
- 问题反馈:邮件 eogee@qq.com,或提 GitHub Issue
预览分享卡片长什么样 ↓eogee/a4phone
分享 · DeepSeek Harness Hub
eogee/a4phone

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

这是你的仓库?认领条目

回到顶部