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

手机遥控台 rururunu/DSHC

DeepSeek Harness
rururunu59 天前有提交已提供中文文档扫描:含敏感能力

用手机远程操控 PC 上运行的 dsh 智能体

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

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add rururunu/DSHC
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么[目录]—
dsh 原生插件 · other
暂无时间戳·判据 →
装得上吗[实装验证]!
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
数据截至 2026/10/02·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 59 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

⚠︎ 实装验证未通过(unknown · 2026/10/2) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 39 处,展示前 39 条)
  • 发起网络请求
    server/lib/index.js:167
    const fetchHandler = (request) => sharedApi.fetch(request);
  • 读取本地文件
    server/lib/share.js:66
    stats = await stat(path);
  • 读取本地文件
    server/lib/share.js:126
    if (!existsSync(file))
  • 读取本地文件
    server/lib/share.js:129
    const parsed = JSON.parse(readFileSync(file, 'utf8'));
  • 写入本地文件
    server/lib/share.js:143
    mkdirSync(dirname(file), { recursive: true });
  • 写入本地文件
    server/lib/share.js:145
    writeFileSync(tmp, `${JSON.stringify({ offers }, null, 2)}\n`, 'utf8');
  • 写入本地文件
    server/lib/share.js:146
    renameSync(tmp, file);
  • 读取本地文件
    server/lib/share.js:191
    size = statSync(offer.path).size;
  • 读取本地文件
    server/lib/share.js:211
    createReadStream(offer.path).on('error', () => res.destroy()).pipe(res);
  • 读取本地文件
    server/lib/share.js:229
    createReadStream(offer.path, { start, end }).on('error', () => res.destroy()).pipe(res);
  • 读取本地文件
    server/lib/state.js:4
    if (!existsSync(file))
  • 读取本地文件
    server/lib/state.js:7
    const parsed = JSON.parse(readFileSync(file, 'utf8'));
  • 写入本地文件
    server/lib/state.js:17
    mkdirSync(dirname(file), { recursive: true });
  • 写入本地文件
    server/lib/state.js:19
    writeFileSync(tmp, `${JSON.stringify(state, null, 2)}\n`, 'utf8');
  • 写入本地文件
    server/lib/state.js:20
    renameSync(tmp, file);
  • 执行外部命令来自配置/变量
    server/lib/tunnel.js:35
    const spawned = spawn(publicCfg.bin, args, {
  • 读取本地文件
    server/lib/workspace-files.js:39
    if (!existsSync(root) || !statSync(root).isDirectory()) {
  • 读取本地文件
    server/lib/workspace-files.js:39
    if (!existsSync(root) || !statSync(root).isDirectory()) {
  • 读取本地文件
    server/lib/workspace-files.js:51
    entries = await readdir(dir, { withFileTypes: true });
  • 发起网络请求
    server/src/index.ts:184
    const fetchHandler = (request: Request): Promise<Response> => sharedApi.fetch(request)
  • 读取本地文件
    server/src/share.ts:83
    stats = await stat(path)
  • 读取本地文件
    server/src/share.ts:134
    if (!existsSync(file)) return []
  • 读取本地文件
    server/src/share.ts:136
    const parsed = JSON.parse(readFileSync(file, 'utf8')) as { offers?: FileOffer[] }
  • 写入本地文件
    server/src/share.ts:153
    mkdirSync(dirname(file), { recursive: true })
  • 写入本地文件
    server/src/share.ts:155
    writeFileSync(tmp, `${JSON.stringify({ offers }, null, 2)}\n`, 'utf8')
  • 写入本地文件
    server/src/share.ts:156
    renameSync(tmp, file)
  • 读取本地文件
    server/src/share.ts:203
    size = statSync(offer.path).size
  • 读取本地文件
    server/src/share.ts:222
    createReadStream(offer.path).on('error', () => res.destroy()).pipe(res)
  • 读取本地文件
    server/src/share.ts:240
    createReadStream(offer.path, { start, end }).on('error', () => res.destroy()).pipe(res)
  • 读取本地文件
    server/src/state.ts:6
    if (!existsSync(file)) return {}
  • 读取本地文件
    server/src/state.ts:8
    const parsed = JSON.parse(readFileSync(file, 'utf8')) as GatewayState
  • 写入本地文件
    server/src/state.ts:17
    mkdirSync(dirname(file), { recursive: true })
  • 写入本地文件
    server/src/state.ts:19
    writeFileSync(tmp, `${JSON.stringify(state, null, 2)}\n`, 'utf8')
  • 写入本地文件
    server/src/state.ts:20
    renameSync(tmp, file)
  • 执行外部命令来自配置/变量
    server/src/tunnel.ts:63
    const spawned = spawn(publicCfg.bin, args, {
  • 发起网络请求
    server/src/types.ts:50
    fetch(request: Request): Promise<Response>
  • 读取本地文件
    server/src/workspace-files.ts:49
    if (!existsSync(root) || !statSync(root).isDirectory()) {
  • 读取本地文件
    server/src/workspace-files.ts:49
    if (!existsSync(root) || !statSync(root).isDirectory()) {
  • 读取本地文件
    server/src/workspace-files.ts:61
    entries = await readdir(dir, { withFileTypes: true })
扫描于 2026/11/4(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 手机远程操控
  • 操控PC智能体

在手机上也能远程操控 DeepSeek Harness

README

由 DeepSeek 最新模型翻译生成
DSHC 简体中文 · English DSHC 是 DeepSeek Harness(dsh)的 Android 遥控台。Agent 仍在 PC 上跑。手机是控制台:走 dsh web 同一套 /api,默认局域网,可选公网。 两块: | 插件 dsh-companion-gateway 0.1.5 | dsh web 里的 Cordis carrier | 绑 0.0.0.0:3081,Bearer,可选 cloudflared。不改 dsh 源码。 | | DSHC ai.dsh.companion 0.1.3 | Android 8+ | HTTP RPC + 一条 remote.mux WebSocket(Typert Remote)。不调模型服务商。
展开完整文档(README 剩余 1 节)
DSHC

简体中文 · English

DSHC 是 DeepSeek Harness(dsh)的 Android 遥控台。Agent 仍在 PC 上跑。手机是控制台:走 dsh web 同一套 /api,默认局域网,可选公网。

两块:

| 插件 dsh-companion-gateway 0.1.5 | dsh web 里的 Cordis carrier | 绑 0.0.0.0:3081,Bearer,可选 cloudflared。不改 dsh 源码。 |
| DSHC ai.dsh.companion 0.1.3 | Android 8+ | HTTP RPC + 一条 remote.mux WebSocket(Typert Remote)。不调模型服务商。 |

flowchart LR
Phone[DSHC] -->|"Bearer HTTP + WS"| GW["插件 :3081"]
GW --> Proxy[dsh-host-apiproxy]
Proxy --> Agent[PC 上的 dsh]
Phone -.->|"同网优先"| LAN[局域网 IP] Phone -.->|"外出"| CF["https://host:443"]
CF --> Tunnel[cloudflared]
Tunnel --> GW

npm:dsh-companion-gateway。路由和故障表:server/README.md。模块:android/docs/ARCHITECTURE.md。协议:docs/dsh-wire-protocol.md。

1. 插件

必须挂在 web profile。装完 / 更新完都要重新跑一次 dsh web,新代码才进进程。token 在 ~/.dsh/profiles/web/companion-gateway.json,更新和卸载都不会清掉(再装会接着用)。

dsh plugin --profile web … 转发给该 profile 里的 pnpm,所以 add / update / remove 都能用。

安装

默认拉 npm 最新:

dsh plugin --profile web add dsh-companion-gateway
dsh web

需要钉死某一版时才加 @版本,例如 dsh-companion-gateway@0.1.5。

成功:日志出现 [companion-gateway] listening on http://0.0.0.0:3081 — bearer token required。

然后 dsh web →「手机网关」:

- 开关局域网。关掉只 unbind :3081,dsh web 继续跑。
- 首次 listen 把 Bearer token 写进 companion-gateway.json。不要写进 cordis.yml / 发布包。
- 手机扫二维码,或从局域网折叠项抄 host / port / token。

手机「添加 → 文件」需要插件 ≥ 0.1.2(GET /api/companion/workspace-files)。

能 ping 通 PC 但 :3081 超时 → 防火墙:

netsh advfirewall firewall add rule name="dsh-companion-gateway" dir=in action=allow protocol=TCP localport=3081 profile=private

本仓库开发(旁边要有 deepseek-harness):

pnpm dsh plugin --profile web add file:C:/My/code/DshCompanion/DshCompanion/server
pnpm dsh web
或:cd server; .\setup.ps1

更新

拉 npm 上的最新版(--latest 不受 package.json 里 semver 范围限制):

dsh plugin --profile web update dsh-companion-gateway --latest
停掉正在跑的 dsh web(Ctrl+C),再:
dsh web

本地 file: 安装:改完源码再 add file:… 一次,然后重启。

卸载

dsh plugin --profile web remove dsh-companion-gateway

只卸插件,不删 companion-gateway.json。局域网端口会在下次 dsh web 时不再监听 :3081。

2. 公网

默认走局域网。隧道可选,保存即生效,不用重启 dsh web。

「手机网关」→ 公网隧道:

| 模式 | 填什么 | cloudflared | 手机 |
| quick | 启用 + 二进制(默认 cloudflared) | tunnel --url http://127.0.0.1:3081 | .trycloudflare.com:443 / https。每次桌面重启域名会变,要重新扫码。 |
| named | 启用 + 公网 hostname + Cloudflare token | tunnel run --token … | hostname:443 / https。稳定。 |

Bearer 与局域网相同。没有 token 不会开隧道(先把局域网网关打开一次)。页上状态:启动中 / 已就绪+URL / 失败+原因。

PATH 里没有 cloudflared:winget install Cloudflare.cloudflared,或在表单里填绝对路径。

隧道就绪后刷新二维码。payload 走公网 host/port/scheme;仍带 lanHost,同 Wi-Fi 时手机优先局域网。

cordis.yml 的 public. 只是启动兜底。GUI 上次写进 companion-gateway.json 的为准。

谁知道 Quick Tunnel URL 谁就能打到网关,门只有 Bearer。空/弱 token 不要开公网。不要把 dsh web 本身 bind 到 0.0.0.0——GUI 路由能读出明文 token。

3. DSHC

构建(Android Studio JBR 在 PATH 里):

$env:JAVA_HOME='C:\Users\GuoLv\AppData\Local\Programs\Android Studio\jbr'
$env:GRADLE_USER_HOME='C:\Users\GuoLv\.gradle'
cd android
.\gradlew.bat --no-daemon assembleDebug

安装 android/app/build/outputs/apk/debug/app-debug.apk。minSdk 26。相机可选(仍可手动填)。Debug 包名 ai.dsh.companion.debug。

远程更新

支持。设置 → 关于 DSHC → 检测更新。有新版本会从 GitHub Releases 下 APK(先读 latest.json,没有则退到最新 Release 的 .apk),下完点安装。进前台也会后台检查,关于项会打红点。

需要系统允许「安装未知应用」。这条通道只覆盖 同一签名、同一包名 的正式包(ai.dsh.companion)。自己打的 debug(ai.dsh.companion.debug)装不上 GitHub 正式包,继续侧载 debug APK。

发版步骤:android/docs/release.md。

配对

1. 插件已在听(第 1 步)。同一 Wi-Fi,或公网隧道已就绪(第 2 步)。
2. 手机扫码,或连接页点「扫描二维码」。
3. 确认。DSHC 把主机写进名册(显示名、token、可选 lanHost)。

不扫码就手动填:

| | 局域网 | 公网 |
| 主机 | PC 局域网 IP(192.168.x.x) | 隧道域名 |
| 端口 | 3081 | 443 |
| 协议 | http | https |
| Token |「手机网关」局域网折叠项 / companion-gateway.json | 同一个 token |

Deep link:dshc://pair?v=1&host=&port=&scheme=&token=&code=(code TTL 10 分钟)。

connect() = ping /healthz + host.describe + 打开 /api/remote.mux WebSocket(Typert 流:$events / session/control / workspace/follow,每个打开的会话另有 session/follow)。mux 断开、空闲超时、心跳失败或默认网卡变了 → nudge() 全部逻辑流一起重建(每个流以 baseline/ready/snapshot 开头,自动补齐断线缺口)。每 20s 打 /healthz,避免 NAT / Cloudflare / 手机无线电把闲置对话掐掉。

DSHC 做什么

手机投影桌面状态,并发送把 PC 解冻的 RPC。Agent 一份,审批闸门一道,屏幕两块。

| 界面 | |
| 会话 | session/list / 改名。界面上的删除 = workspace/archiveSession(dsh 没有 session-delete)。 |
| 工作区 | workspace/。列表来自 workspace/follow 流 baseline;按 sessionIds 分组(session/list 没有 workspaceId),文件树退到会话 cwd。 |
| 聊天 | session/prompt + assistant/chunk。历史与直播都来自 session/follow 流(快照 + 事件);顶栏:模型(session/modelCatalog / selectModel)和权限预设。 |
| 添加 | 输入框 + → 分页 消息(/compact /goal /plan)/ 文件(工作区树 → @路径)。附件:选择图片(内联上传,PNG/JPEG/WebP/GIF,HEIC/超大图自动转码)。文件附件需 dsh ≥ 0.1.3(/api/session/uploadFileBinary);在 0.1.2-rc.1 上会返回明确错误。 |
| 提问 / 审批 | $events 流的 approval/request、user-questions/request waterfall → POST /api/$events/result。工具闸门只有 允许一次 / 拒绝。 |
| 回传文件 | 桌面 share_to_companion → 卡片 → Range GET /api/companion/files/(上限 500MB)。path 不出 PC。 |

dsh 没有、因此 DSHC 也没有:会话级工具授权、skills/MCP 目录、第二套 Agent。
DSHC 基于 Typert Remote 协议(dsh ≥ 0.1.2-rc.1);文件附件需 dsh ≥ 0.1.3。历史消息里的图片缩略图与工具产图回显暂未实现。

布局

DshCompanion/
├── server/ dsh-companion-gateway(index apply + http / tunnel / pairing / gui / share) ├── android/ app + feature: + core:{model,domain,network,data,designsystem} └── docs/ dsh-wire-protocol.md, img/

改网关:server/src/{http,tunnel,pairing,gui}.ts。改连接/会话/审批/工作区:android/core/data/.../repository/。改气泡/输入框/面板:android/feature/chat/。

限制

- dsh 是 developer preview;DSHC 钉当前 checkout。
- Quick Tunnel 域名随桌面重启变——对该主机重新配对。
- 空 token:不 bind 非 loopback,不开隧道。

致谢

DSHC 是 DeepSeek Harness 的 Android 伴侣:Agent 仍在 PC 上跑,手机只是控制台。感谢 DeepSeek 开源 dsh 以及「Everything is a Plugin」这套机制。

协议

MIT
预览分享卡片长什么样 ↓rururunu/DSHC
分享 · DeepSeek Harness Hub
rururunu/DSHC

用手机远程操控 PC 上运行的 dsh 智能体

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部