clamicro

by laosji

3 通知与集成github未核验到 manifest 含安装期脚本 1收录于 08-16

在手机上审批 Claude Code 、DeepSeek Harness 的操作。局域网直连,零依赖。

安装

dsh plugin --profile web add github:laosji/clamicro

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

安装与环境配置指引、插件开发教程见 DSH 中文社区文档 ↗

安装即在你的机器上以你的权限运行第三方代码——它可读写文件、使用凭据、访问网络,DSH 的工具审批不会为插件代码加沙箱。「检测到 manifest」仅代表发现 dsh.bundle / dsh.plugin 清单,不构成兼容性或安全审查;安装前请审阅源码,不熟悉的插件先在不含密钥的环境试用。

README

目录

English

在手机上看 Claude Code 的状态、审批它要执行的操作。

跑任务时不用一直盯着终端——需要授权时 Mac 会弹通知,在手机上打开页面,看清命令和一句摘要,滑动批准或拒绝,Claude Code 随即继续。

运行中 有事等你 做决定

截图是真实界面,不是效果图。刘海那张是 Mac 上实拍的屏幕截图。

先说清楚默认行为,免得你以为它在拦一切:

等多久 到点怎么办 会不会提醒你
普通操作 10 秒 自动通过 会
高风险(rm -rf、force push、动 ~/.ssh) 3 分钟 自动拒绝 会

也就是说:日常操作它是「告诉你」,高危操作它才是「拦住你」。 两档的等待时长和到点行为都能在设置页改——普通操作的 10 秒改成 0 就是每条都等你;高风险的 3 分钟最长可设到 570 秒(再长就会撞上 hook 的系统超时,审批反而失效)。

零依赖:只需要 Node ≥ 18 和 curl(macOS 自带)。运行时不含任何 node_modules。

仅支持 macOS + iPhone。服务用到 macOS 专有能力(scutil、osascript、Bonjour),界面是按 iOS Safari 做的。


安装

npx clamicro install

两步走完:

  1. 终端里:检查环境 → 展示将要对 ~/.claude/settings.json 做的改动 → 你确认 → 自动备份并写入 → 确认信任当前网络 → 启动服务 → 打印一个网址(不是二维码,理由见下)
  2. 手机打开那个网址(同一 Wi-Fi):进到配对页,点「在 Mac 上显示二维码」。码只出现在 Mac 屏幕上,用手机相机扫它。
  3. 回到 Mac 确认:会弹出一个框问你要不要放这台设备进来,并显示这个请求从哪来。不按「允许」就不会发出任何凭证。

配对完走一遍内置演示:它会造一条假审批,让你在还没有任何真实风险的时候先滑一次。走完这遍就算装好了。

为什么给网址不给二维码? 终端里的二维码必须携带凭证,而终端恰恰是东西会被留下来的地方——回滚缓冲、录屏、投屏、旁边那位的手机镜头。更早的版本在这里印的是永久主令牌;后来那版印的是 60 秒的一次性配对券,安全没问题,但通常在你掏出手机之前就过期了。网址不带任何凭证、也不会过期;凭证是你在手机上点了按钮之后才生成的,而且只出现在 Mac 屏幕上。

装完即可用:需要审批时 Mac 会弹通知并响一声,终端状态栏显示 ⏳ N 条待审批,手机网页随时能看和批。

没有远程推送:提醒只有 Mac 本地通知这一条,完全不联网。离开电脑后不会有东西叫你——高风险操作会等到超时被自动拒绝。详见下方「近场只用 Wi-Fi」。

安装程序只追加不替换。你已有的 hook 配置会完整保留,statusLine 若已被别的工具占用则不覆盖、只提示。改动前自动备份。

卸载:

npx clamicro uninstall

只摘掉自己加的东西,实测与安装前的配置逐字节一致。配置和历史保留在 ~/.claude/clamicro/,可手动删除。

运行时装在哪

npm 包只是安装器。运行时文件会被复制到 ~/.claude/clamicro/app/,hooks 指向那里。

这不是多此一举:hooks 里写的是绝对路径,而 npx 每次跑在会变的缓存目录、全局安装路径又随 node 版本 / nvm / homebrew 变化。指向 npm 包意味着某天路径失效,所有 hook 会静默失败——你不会看到任何报错,只是再也收不到通知。实测删掉 node_modules 后服务与 hook 照常工作。

升级就是重跑一次 npx clamicro install。


它做了什么

你在手机上看到 来自
会话状态、子状态(Thinking/Searching/Editing) hooks 事件流
5 小时 / 7 天用量、上下文占用、本次花费 statusLine
待审批操作 + 一句人话摘要 + 影响面标签 PermissionRequest
任务完成 / 出错通知 Stop / StopFailure
事件时间线(每个会话的完整流水) 全部 hooks
暂停 / 恢复 / 取消本轮 PreToolUse 拦截点
额度接近上限预警 statusLine

这张表说的是 Claude Code。接了别的后端时,能做什么由那个后端的能力决定—— 见下面「不止 Claude Code」。


不止 Claude Code

2.14.0 起,同一块看板可以同时盯着多个后端。目前支持 Claude Code 和 DeepSeek Harness(DSH)。

首页按模型分区:每个模型一个标题,下面是它自己的状态、履历和用量。 顺序按「谁先连上」固定,不会因为谁刚有动静就换位置。

待审批不分区,永远在最上面、跨后端一起显示——它有倒计时,被分进某个 区块意味着你得先找到那个区块才看得见,而漏看一条等于一次静默的自动决策。

不同后端能做的事不一样

Claude Code DeepSeek Harness
手机审批 ✓ ✓
暂停 / 恢复 ✓ —
取消本轮 ✓ —(协议支持,尚未接)
从手机发消息 ✓ —(协议支持,尚未接)
用量 5h / 7d 滚动窗口 累计 token

界面按能力渲染:某个后端不支持的操作,入口直接不给。留一个点了没反应的 按钮比没有按钮更糟——你会以为暂停成功了,然后走开。

DSH 的用量只报 token、不折算金额:DSH 自己不算钱,折算需要一张按模型分档的 价目表,而它会在你不知情时过期,然后手机上安静地显示一个错的金额。

接 DSH

npx clamicro install 探测到 ~/.dsh 就会问一句要不要接上,同意后自动装桥接插件 和那只像素猫(点一下直接打开手机看板;没配对过的话那一页就是二维码入口)。

它写的是别人家的配置(~/.dsh/profiles),所以一定会先问,--yes 也不会 替你答应。卸载时会一并摘除。手动接法和三条硬约束见 plugins/。

手势

审批卡片左滑拒绝、右滑批准,详情页和首页列表都支持。批准有 3 秒撤销窗口。 高风险操作(rm -rf、git push --force、密钥文件、越界写入)在详情页需要划得更远, 在列表里则完全不能滑动批准——列表是快速分诊的地方,真要放行危险操作得点进去看清楚。

暂停的真实语义

Claude Code 没有「运行时暂停」原语,没法在任意时刻冻结它。「暂停」实际是 在下一个工具调用前把它挂住,当前这一步仍会跑完。UI 上有明确提示, 免得你以为点了没反应。取消同理,也是在下一个拦截点返回 {continue:false}。

审批链路:

Claude Code 要执行需授权的操作
  → PermissionRequest hook(HTTP,timeout 600)
  → 服务建审批记录,Mac 弹通知,然后阻塞住
  → 你在手机上批准 / 拒绝
  → hook 返回 decision → Claude Code 继续或被拒

安全

这是一个把 Claude Code 的执行权限交到手机上的工具,值得把边界写清楚。

网络信任闸门

服务只在你显式信任过的网络里暴露到局域网。换到陌生网络(咖啡厅、机场、酒店)时自动只绑回环,手机连不上,同时 Mac 弹通知让你确认。

npx clamicro networks   # 看当前网络和已信任列表
npx clamicro trust      # 信任当前网络
npx clamicro untrust    # 撤销:不带参数撤当前网络,也可 untrust <id前缀> / untrust all

信任是可撤销的。误信任一个网络(比如在咖啡厅手滑点了「是」)不该是不可逆的——那个网络会永久留在列表里,下次再连上就自动暴露。

网络指纹用网关 IP + 网关 MAC + 网段 + SSID + DHCP 服务器 + 搜索域 + DNS 列表。

前三项不够:SSID 在新版 macOS 需要定位权限、走有线时根本没有;而 00:00:5e:00:01:xx 是 VRRP 虚拟 MAC,企业网里并不唯一。实测过一种会碰撞的组合——两个不同公司都用 192.168.1.0/24、网关都是 192.168.1.1、网关 MAC 都是 VRRP、又都拿不到 SSID,四个字段完全一样,于是 A 公司信任过之后 B 公司的网络被当成已信任。后面那三个信号来自 DHCP,不需要任何权限,在不同组织之间几乎不会全部相同。

已实现的防护

防护 挡住什么
Host 头白名单 DNS rebinding。恶意站点把域名重绑到你的局域网 IP 后浏览器视为同源,CORS 完全失效,能读看板、命令原文并批准操作——且攻击者不需要在你的 Wi-Fi 上
hooks / statusLine 仅回环 同网段的人伪造 hook 事件:刷审批通知、注入假时间线、伪造额度
/api/pair 要求自定义头 CSRF。跨站「简单请求」浏览器会照发,副作用已发生——等于你访问的任何网站都能让这台 Mac 弹二维码
hooks / statusLine / pair-new 只认本机 同网段的人伪造 hook 事件:刷审批通知、往时间线注入假记录、伪造额度读数——更要命的是给自己造一张配对券。「本机」是三件事同时成立:回环来源 且 回环 Host 且 没有代理转发头。只看来源地址不够:开着 Cloudflare 隧道时,公网流量正是从 127.0.0.1 进来的
配对要在 Mac 上确认 只是「看到」二维码的人——屏幕共享、投屏、旁边那位的镜头、拿到隧道 URL 的人——拿到设备令牌。看见码不再够用,得有人坐在 Mac 前面按一下。那个对话框出任何问题(超时、拿不到图形会话、崩了)一律算拒绝
终端里不出现任何形似凭证的东西 安装器印的是纯网址,不带令牌也不会过期,所以回滚缓冲、录屏、肩窥都拿不到东西。凭证在你点了手机上那个按钮之后才生成,且只在 Mac 屏幕上渲染
CSP frame-ancestors 'none' 点击劫持:恶意页面把审批页嵌进 iframe 诱导你滑动
常数时间比较 token 与审批 key 的时间侧信道
SameSite=Lax + HttpOnly CSRF;同时保证从别的 App 点链接进来仍是登录态(Strict 会导致每次都要重新扫码)
单条审批专属 key 拿到一条深链只能决定那一条;审批结束后 2 分钟失效(留这一小段是因为你点完之后结果页还要用它拉一次)

说人话:配过对的手机等于你 Mac 的钥匙

设备令牌 = 批准任意操作的权限,包括 rm -rf、sudo、读你的 ~/.ssh/id_rsa。请像对待钥匙一样对待那台手机:

  • 二维码本身已经不足以配对:它一次性、60 秒过期,而且还要在 Mac 上按「允许」。 拍到码的人没有你按那一下也配不上。话虽如此,还是别把它留在屏幕上
  • 怀疑泄露了就立刻换发:npx clamicro rotate-token。所有设备上的登录当场失效, 对运行中的服务即刻生效,不用重启;之后手机需要重新扫码配对。 只想吊销某一台就用 npx clamicro forget <id>,其他设备不受影响
  • 登录 cookie 30 天过期,到期重新扫一次

剩下的风险:HTTP 明文

局域网内是明文。同网络的被动嗅探者能拿到你的 token,进而获得完整控制权,包括批准 rm -rf。命令原文同样是明文。

这在保持「扫码即用」的前提下无解——自签证书会让 Safari 报警并破坏整个体验。网络信任闸门把它从「你得记得别在咖啡厅用」变成了「陌生网络默认就用不了」,但如果你确实需要在不可信网络上用:

装 Tailscale。 WireGuard 端到端加密,没有任何第三方看到明文,且不限于同一 Wi-Fi。服务会自动识别 100.64/10 地址并绑上去,且不受网络信任闸门限制——覆盖网自带加密,不关心底下是什么物理网络。

另一条路是内网穿透(clamicro tunnel on),但穿透服务终结 TLS,技术上看得到命令原文——所以它是应急选项,不是默认。


近场只用 Wi-Fi

控制面不出局域网。命令原文、审批指令、时间线、额度全部走 http://<局域网IP>:8765 直连。

按"人在哪儿"分两层,两层都不出局域网:

场景 提醒方式 联网范围
① 人在电脑边 macOS 本地通知 + 提示音 完全不联网
② 离开电脑 没有提醒 —

② 为什么没有提醒:锁屏可达的通知只能走 APNs,那必然经过第三方服务器。

先后试过两条并都删掉了:ntfy 双 topic 中转(能在锁屏通知里直接点按钮批准,等于把控制面交给第三方)、Bark(只发一句「有个审批」,控制面留在局域网)。后者已经克制到极限,但它换来的仍然只是「离开电脑时能被叫一下」——而这个工具的前提本来就是你人在附近。为了这个把「有操作在等你审批」这个事实持续告诉一台外部服务器,不划算。

代价要说清楚:离开电脑后没有任何东西会叫你,高风险操作会等到超时(默认 3 分钟)被自动拒绝,那一轮任务失败。这是有意的默认——人不在就不该放行 rm -rf。想主动看的话,手机浏览器随时能打开看板。


设计要点

hook 必须先回包再提醒。 async: true 只对 command 类型有效,HTTP hook 一律阻塞等响应。所以所有端点立即返回 {},推送在响应之后异步发出。

自超时上限 570 秒。 不能走到系统 600s 超时——那会被当成「非阻塞错误」放行到正常权限流程,人不在电脑边时终端会空挂着等一个没人看的弹框。

四种终态:allowed / denied / expired(超时自动拒绝)/ abandoned(终端自己批了,或会话被 Ctrl-C)。同一条审批被多路重复决策时,第一个写入的赢,后到的返回当前真实状态而不报错。

Stop 的提醒阈值。 Stop 在每一轮回复结束时都触发,包括两秒就结束的对话。默认只有 turn ≥ 30s 才推送。turn_started_at 未知时(服务中途启动)按「要推」处理——宁可多推一次,也别漏掉一次任务完成。

状态栏由服务端渲染。 bin/statusline.sh 不解析 JSON,直接把载荷 POST 给服务,服务返回渲染好的文本。因此不依赖 jq,也不用付 Node 的 ~115ms 启动开销(实测 15ms)。有待审批时状态栏会显示 ⏳ N 条待审批。

子状态是推导的。 Claude Code 没有 Thinking/Searching/Editing 事件,全部从 PreToolUse.tool_name 推导;PostToolUse 到下一个 PreToolUse 之间视为 Thinking。

服务挂了不拖累 Claude Code。 回环端口拒绝连接是即时的,hook 拿到非阻塞错误后照常继续,只是收不到通知。而且 SessionStart 是个 command hook,会先把服务拉起来再转发事件——打开 Claude Code 就等于服务可用。

地址用 Bonjour 主机名而不是 IP。 macOS 已经在广播 <LocalHostName>.local,用它做基址,DHCP 换 IP 后旧链接依然有效,不必重新扫码。极少数路由器屏蔽组播,那种情况把 hostMode 改成 "ip"。

登录 cookie 必须是 SameSite=Lax 不能是 Strict。 从别的 App 点链接进 Safari(备忘录里存的地址、Mac 上弹的二维码)属于跨站导航,Strict 的 cookie 不会被带上,表现是每次都像没登录过。

额度是账号级的,不按会话存。 按会话存会出现旧会话的陈旧数字把最新数字顶掉。只认最新一次观测,并在界面上标出更新时间和来源会话。

审批与事件落盘。 ~/.claude/clamicro/history.json,防抖写入 + 临时文件原子替换。重启时仍挂起的审批一律转 abandoned——那些 hook 的连接早断了,再显示成「待审批」是在骗人。

hooks 是热加载的,statusLine 不是。 改完 hooks 当前会话立刻生效;statusLine 要新开会话。

吊销是即刻的,不用重启。 forget / rotate-token / untrust 都是独立的 CLI 进程,只改磁盘;而服务只在启动时读过一次配置。所以 2.14.0 之前这三条命令重启前全部无效——forget 却打印着「这些设备上的登录立即失效」。现在服务监听配置文件热加载 token / 设备簿 / 信任网络,那句话才是真的。

配置和 settings.json 都是原子写。 先写同目录临时文件再 rename。非原子写有两条会踩到的路径:热加载正好读到写了一半的 JSON;以及进程被打断时文件永久半截——config.json 半截等于令牌和已配对设备全没,settings.json 半截等于 Claude Code 起不来。权限也在 rename 之前设好,不留「文件已就位但还是 0644」的窗口。

杀进程之前先确认身份。 stop 和安装流程都会 kill 掉端口上的监听者,而 8765 不是保留端口。判据是 /healthz 回的 service: 'clamicro'(只对回环返回,局域网上的扫描者拿不到),不是匹配命令行——命令行的形状不稳定。不是我们的进程就拒绝并提示换端口,绝不硬抢。

风险判定不看工具名。 判据是「参数里有没有 command」。原来写的是 toolName === 'Bash',而 DSH 的工具名是小写 bash——精确匹配会让整套高危规则一条都不跑,rm -rf / 判普通风险、10 秒自动通过。名字差一个字母,安全核心静默失效且不报任何错。


常用命令

npx clamicro install      # 安装 / 升级
npx clamicro uninstall    # 卸载
npx clamicro qr           # 打印登录二维码
npx clamicro status       # 服务、网络、版本
npx clamicro trust        # 信任当前网络
npx clamicro untrust      # 撤销信任(untrust <id前缀> | untrust all)
npx clamicro networks     # 当前网络 + 已信任列表
npx clamicro rotate-token # 换发访问令牌(令牌可能泄露时)
npx clamicro test-push    # 发一条测试通知(Mac 本地)
npx clamicro logs         # 跟踪日志
npx clamicro stop         # 停止服务

平时不用手动启动——SessionStart hook 会在你打开 Claude Code 时自动把服务拉起来。

配置在 ~/.claude/clamicro/config.json(权限 600,含访问 token)。日常设置改手机网页即可,不用编辑这个文件。

ignoreCwds 里的工作目录不做阻塞审批——开发 clamicro 自身时用,正常使用应留空。


使用教程

第一次用、或者遇到「这是 bug 还是设计如此」的困惑,看 docs/guide.zh-CN.md · English。


维护笔记

踩过的坑和当时的判断依据记在 NOTES.md。


已知限制

  • 需与 Mac 同一 Wi-Fi(或同一 tailnet);公司网络若开启客户端隔离或 VLAN 隔离则不通
  • 局域网内明文传输,不可信网络请用 Tailscale,见上方「安全」
  • 纯 HTTP 非 secure context,拿不到 Service Worker / Web Push
  • 仅 iPhone + macOS
  • Pause 为「下一个可拦截点暂停」,不是运行时冻结
  • 手势为主的界面,VoiceOver 用户目前没有等价入口
  • 审批与事件保留一天、上限 300/3000 条,超出滚动丢弃

原始 README: https://github.com/laosji/clamicro/blob/main/README.zh-CN.md ↗

同类插件

查看全部 →
通知与集成alvinunreal

dsh

将 DeepSeek Harness 的生命周期状态、错误与审批请求,桥接到本地运行的 OpenPets 桌面伙伴。

查看详情
1081github+08-21
通知与集成tencent-connect

dsh-qqbot

让 QQ Bot 接入 DeepSeek Harness(dsh)的官方插件

查看详情
55github+08-17
通知与集成omdsh-dev

dsh-open-in-vscode

从 Web GUI 一键在 VS Code 中打开工作区目录。

查看详情
39github+08-13
通知与集成omdsh-dev

dsh-notification

回合完成桌面通知,按结果分控 + 关键词过滤。

查看详情
38github+08-13
通知与集成THEWOLFWALKER

dsh-notifier

DSH 统一通知推送与远程控制:一个 `notify()` API 打通 25+ 渠道(Telegram / 钉钉 / 飞书 / 企业微信 / QQ 机器人 / WxPusher / PushPlus / Server 酱 / Bark / Discord / Slack / ntfy / webhook 等),timeSensitive / active / passive 分级路由并重试;五通道反向审批(Telegram 按钮 / 飞书卡片 / QQ / WxPusher / 微信 iLink);QQ/钉钉/飞书官方扫码登录;本地 Web 管理台;多 agent 路由;系统桌面通知——以及**手机指挥中心**:在手机上发 `!status` / `!stop` / `!retry` 遥控 agent,通知带可操作按钮(查看结果 / 重试 / 日志,点击回调 agent)。密钥脱敏、工具限流、零运行时依赖。

查看详情
27github+08-16
通知与集成wzj998

chatccc

飞书(Lark)或微信(WeChat)聊天控制 DeepSeek Harness / Claude Code / Cursor / Codex / CCC Agent

查看详情
22github+08-23