把 DeepSeek Harness 装进口袋:电脑上跑 dsh web,手机扫码就能同步访问(局域网 + 公网,实时同屏)
69.6/100
综合分
1,856
GitHub 星标
6,389
npm 周下载
—/5
用户评分
数据截至 2026/10/18 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/shaobeichen/dsh-pocket.git状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
生态插件
可安装,未声明 dsh 能力
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 16 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-pocket @ 2.12.0
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/3 09:16:22
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 60 处,展示前 55 条)
- 读取本地文件lib/index.js:37
return JSON.parse(readFileSync(pkgPath, 'utf8')).version; - 写入本地文件lib/index.js:56
mkdirSync(dirname(p), { recursive: true }); - 写入本地文件lib/index.js:57
writeFileSync(p, fresh, { mode: 0o600 }); - 读取本地文件lib/index.js:63
const existing = readFileSync(p, 'utf8').trim(); - 读取本地文件lib/index.js:197
const raw = JSON.parse(await readFile(restartNoticePath(), 'utf8')); - 写入本地文件lib/index.js:204
return mkdir(dirname(restartNoticePath()), { recursive: true }) - 写入本地文件lib/index.js:205
.then(() => writeFile(restartNoticePath(), JSON.stringify({ at: Date.now(), pid: process.pid }), 'utf8')); - 删除本地文件lib/index.js:214
await rm(restartNoticePath(), { force: true }).catch(() => {}); - 执行外部命令固定命令lib/index.js:236
const child = spawn('dsh', ['plugin', '--profile', profile, 'update', 'dsh-pocket', '--latest', '-w'], { - 读取本地文件lib/index.js:296
const raw = readFileSync(join(process.env.DSH_HOME ?? join(homedir(), '.dsh'), 'settings.yaml'), 'utf8'); - 写入剪贴板client/client.js:496
await navigator.clipboard.writeText(text); - 请求外部主机registry.npmjs.orgclient/client.js:2267
const meta = await (await fetch("https://registry.npmjs.org/dsh-pocket/latest", { cache: "no-store" })).json(); - 发起网络请求client/client.js:2267
const meta = await (await fetch("https://registry.npmjs.org/dsh-pocket/latest", { cache: "no-store" })).json(); - 读取本地文件lib/service.mjs:93
const v = readFileSync('/proc/version', 'utf8').toLowerCase(); - 执行外部命令来自配置/变量lib/service.mjs:129
execFile(candidates[i], [], { timeout: 5000, windowsHide: true }, (err, stdout) => { - 写入本地文件lib/service.mjs:258
await mkdir(dirname(autoStatePath), { recursive: true }); - 写入本地文件lib/service.mjs:259
await writeFile(autoStatePath, JSON.stringify({ at: Date.now() }), 'utf8'); - 删除本地文件lib/service.mjs:267
try { await rm(autoStatePath, { force: true }); } catch { } - 读取本地文件lib/service.mjs:397
const raw = await readFile(autoStatePath, 'utf8'); - 发起网络请求lib/web-rpc.js:71
async fetch(request) { - 发起网络请求lib/web-rpc.js:172
const response = await fetchHandler.fetch(request); - 读取本地文件lib/settings.mjs:28
const raw = JSON.parse(readFileSync(settingsPath(), 'utf8')); - 写入本地文件lib/settings.mjs:36
mkdirSync(dirname(settingsPath()), { recursive: true }); - 写入本地文件lib/settings.mjs:37
writeFileSync(settingsPath(), JSON.stringify(s, null, 2), { mode: 0o600 }); - 删除本地文件lib/settings.mjs:129
rmSync(settingsPath(), { force: true }); - 写入本地文件lib/tunnel.mjs:119
const out = createWriteStream(dest); - 发起网络请求lib/tunnel.mjs:146
try { head = await fetch(url, { method: 'HEAD', signal }); } catch { head = null; } - 发起网络请求lib/tunnel.mjs:152
const res = await fetch(url, { signal }); - 写入本地文件lib/tunnel.mjs:154
await pipeline(Readable.fromWeb(res.body), createWriteStream(dest)); - 发起网络请求lib/tunnel.mjs:162
const probeRes = await fetch(url, { signal, headers: { Range: `bytes=0-${probeBytes - 1}` } }); - 写入本地文件lib/tunnel.mjs:170
const w = createWriteStream(dest); - 发起网络请求lib/tunnel.mjs:176
const restRes = await fetch(url, { signal, headers: { Range: `bytes=${probeBytes}-${len - 1}` } }); - 写入本地文件lib/tunnel.mjs:178
await pipeline(Readable.fromWeb(restRes.body), createWriteStream(dest, { flags: 'a' })); - 删除本地文件lib/tunnel.mjs:182
await rm(dest, { force: true }).catch(() => {}); - 删除本地文件lib/tunnel.mjs:184
await rm(dest, { force: true }).catch(() => {}); - 发起网络请求lib/tunnel.mjs:200
const res = await fetch(url, { signal, headers: { Range: `bytes=${p.start}-${p.end}` } }); - 写入本地文件lib/tunnel.mjs:202
await pipeline(Readable.fromWeb(res.body), createWriteStream(p.file)); - 删除本地文件lib/tunnel.mjs:206
await Promise.all(parts.map((p) => rm(p.file, { force: true }).catch(() => {}))); - 发起网络请求lib/tunnel.mjs:224
res = await fetch(TUNA_BOTTLES, { signal: AbortSignal.timeout(20_000) }); - 读取本地文件lib/tunnel.mjs:281
const st = await stat(tmpFile); - 删除本地文件lib/tunnel.mjs:288
await rm(tmpFile, { force: true }).catch(() => {}); - 写入本地文件lib/tunnel.mjs:306
await rename(tmpFile, extracted).catch(async () => { - 执行外部命令固定命令lib/tunnel.mjs:316
const child = spawn('tar', ['-xzf', tmpFile, '-C', extractDir], { stdio: 'ignore' }); - 读取本地文件lib/tunnel.mjs:332
try { if ((await stat(direct)).isFile()) found = direct; } catch { } - 读取本地文件lib/tunnel.mjs:339
try { if ((await stat(bin)).isFile()) { found = bin; break; } } catch { } - 删除本地文件递归lib/tunnel.mjs:348
await rm(extractDir, { recursive: true, force: true }).catch(() => {}); - 删除本地文件lib/tunnel.mjs:353
await rm(tmpFile, { force: true }).catch(() => {}); - 执行外部命令来自配置/变量lib/tunnel.mjs:360
execSync(process.platform === 'win32' ? 'where cloudflared' : 'command -v cloudflared', { stdio: 'ignore' }); - 读取本地文件lib/tunnel.mjs:384
await access(explicit); - 读取本地文件lib/tunnel.mjs:405
await access(bin); - 执行外部命令来自配置/变量lib/tunnel.mjs:466
const child = spawn(bin, ['--no-autoupdate', 'tunnel', 'run', '--protocol', 'http2'], { - 执行外部命令来自配置/变量lib/tunnel.mjs:556
const child = spawn(bin, ['--no-autoupdate', 'tunnel', '--url', `http://127.0.0.1:${port}`, '--protocol', 'http2'], { - 写入本地文件client/build.mjs:45
await mkdir(dirname(outputPath), { recursive: true }); - 写入本地文件client/build.mjs:46
await writeFile(outputPath, wrapped, 'utf8'); - 写入剪贴板client/mobile/fileGuard.ts:40
await navigator.clipboard.writeText(text)
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
涉及外部主机:registry.npmjs.org
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
界面预览
2 张 · 点击查看大图功能亮点
- 手机扫码同步访问
- 局域网与公网连接
- 实时同屏
README
由 DeepSeek 最新模型翻译生成DSH Pocket
把 DeepSeek Harness 装进你的口袋:一个包、一个设置页,手机扫二维码就实时看到电脑上的同一个界面——人在外面也能用。
⭐ 顺手留颗 Star,作者能高兴一整天 · 行,给你一颗 Star
这是什么
你不在电脑前,也想用电脑上的 DeepSeek Harness。
- 下班路上,智能体在电脑上跑任务,你想掏出手机看看它干到哪了、结果如何
- 出门在外,突然想让电脑上的智能体查点资料、写段代码,但没有远程桌面、没有 SSH
- 电脑在宿舍/办公室,你人在外面,想随时「操控你的 DeepSeek Harness」——发任务、看输出、点审批
DSH Pocket 就是干这个的:装上它,手机扫个码,就能实时看到并操控电脑上的 DeepSeek Harness 界面——人在外面也能用。
展开完整文档(README 剩余 1 节)
DSH Pocket 把 DeepSeek Harness 装进你的口袋:一个包、一个设置页,手机扫二维码就实时看到电脑上的同一个界面——人在外面也能用。 ⭐ 顺手留颗 Star,作者能高兴一整天 · 行,给你一颗 Star 这是什么 你不在电脑前,也想用电脑上的 DeepSeek Harness。 - 下班路上,智能体在电脑上跑任务,你想掏出手机看看它干到哪了、结果如何 - 出门在外,突然想让电脑上的智能体查点资料、写段代码,但没有远程桌面、没有 SSH - 电脑在宿舍/办公室,你人在外面,想随时「操控你的 DeepSeek Harness」——发任务、看输出、点审批 DSH Pocket 就是干这个的:装上它,手机扫个码,就能实时看到并操控电脑上的 DeepSeek Harness 界面——人在外面也能用。 实际效果——手机上的界面就是电脑上的界面,实时同步: ✨ 特性 | 特性 | 说明 | | 📶 局域网扫码 | 装好即用:设置 → 手机访问,打开就有局域网二维码,手机连同一 WiFi 扫码即开(自动识别本机局域网 IP,WSL 环境自动取 Windows 物理网卡 IP) | | 🚪 局域网开关 | 设置页可一键关闭/开启局域网访问(切换时弹窗提醒):关闭后局域网二维码/链接立即失效,仅公网可用 | | 🌐 公网扫码(人在外面) | 点「开启公网访问」→ cloudflared 隧道 → 出公网二维码,4G/任何网络都能访问 | | 🏷️ 公网固定域名 | 可选「命名隧道」模式:填 Cloudflare Tunnel Token + 自己的域名,公网地址固定不变(重启不再变;见下方说明) | | 🔐 访问密码 | 公网链接默认使用 8 位随机密码(每次开启公网自动换新;可自定义固定密码——自定义后不再换新);局域网有独立的默认 8 位随机密码(默认开启,设置页可一键关闭——关闭后局域网扫码直连) | | 🔑 自定义密码 | 公网/局域网密码都可在设置页设成自己固定的 8–64 位密码(英文字母大小写或数字)(自定义后公网不再自动换新) | | 🧘 会话保持 | 手机输一次密码后长期免输(登录状态绑定电脑上的 dsh web 进程:只要它不重启,手机不用再输;dsh web 重启/更新后需重新输入一次) | | ⚡ 实时同步 | 流式输出走 WebSocket 全透传——电脑上在输出,手机上同步在滚,可双向操作;内置心跳保活(防路由器 NAT/省电机制静默断链,断线自动重连) | | 📱 移动端适配 | 窄屏自动变抽屉布局(移植 dsh-web-mobile,MIT):侧栏抽屉、会话全宽、状态栏安全区、触控优化 | | 🧭 可选右边栏 | 手机端显示原生右边栏入口;普通手机可在设置中关闭以保持紧凑,折叠屏展开后可更方便地同时使用终端底栏和右边栏 | | 📁 文件浏览 | 移动端「文件浏览」入口需要宿主提供 explorer 面板(dsh-web-ui 组件);官方 DSH 未内置时入口自动隐藏,不会出现"点了没反应" | | 🗜️ 传输压缩 | 大 JSON 响应自动 gzip/brotli(长会话 17MB → ~1MB,brotli 质量 6:快且省流量),手机加载更快、更省流量 | | 🔁 隧道自动恢复 | DSH 重启后自动重新拉起之前开着的公网隧道,无需手动重开 | | 🧩 零依赖安装 | 一个 npm 包、一个设置页,没有核心/适配器要分开装;无需账号、无需服务器 | 🚀 怎么用 入口在哪:安装完成并重启 dsh web 后,打开 设置,左侧边栏就能看到 「手机访问」 入口(和「通用设置」「模型」同级): 前提:电脑上已装好 DeepSeek Harness。如果终端提示 dsh: command not found(找不到 dsh 命令),先安装: npm install -g @deepseek-ai/dsh # 全局安装;验证:dsh --version 不想全局装?每次命令前加 npx:npx @deepseek-ai/dsh <命令> 1. 装插件(一个包全都有) dsh plugin --profile web add dsh-pocket -w 2. 重启 dsh web npx @deepseek-ai/dsh web 局域网(同一 WiFi) 设置 → 手机访问 → 手机扫「📶 局域网」二维码 → 打开链接输入局域网密码(显示在设置页局域网区块,点「刷新」可换新,或点「自定义」设成自己固定的 8–64 位密码——英文字母大小写或数字)→ 打开的就是电脑上的 DSH,实时同步。 「局域网访问」开关默认开:可一键关闭/开启(切换时弹窗提醒)——关闭后局域网二维码/链接立即失效(手机打不开),公网不受影响;想恢复时再点「开」即可。 局域网密码默认开启(安全优先)。如果只有自己用、嫌每次输密码麻烦,可在设置页局域网区块把「局域网访问密码」切到关——之后局域网扫码直连、无需密码(仅同一局域网设备可访问;公网始终要密码,不受影响)。 手机登录一次后长期免输:只要电脑上的 dsh web 不重启,再次打开手机不用再输入(dsh web 重启/更新后需重新输入一次)。 高级选项:自动识别在 Tailscale/VPN 等场景下可能选不到可达地址。可在「局域网地址」下拉框手动选择已检测到的 IP;一般不需要修改。 公网(人在外面) 同一页点「开启公网访问」→ 每次都会先弹出安全免责声明,勾选「我已知情」后才能开启(公司/涉密网络请先确认合规)→ 等隧道建立(首次会下载 cloudflared,macOS/Linux 走清华镜像秒下)→ 手机扫「🌐 公网」二维码 → 打开链接输入访问密码(密码显示在设置页公网区块,默认是每次开启公网变新的 8 位随机密码,也可点「自定义」设成 8–64 位固定密码——英文字母大小写或数字,自定义后不再换新)→ 人在外面(4G/公司网)也能访问。 更新到新版本:dsh plugin --profile web update dsh-pocket --latest -w(跨大版本时 --latest 是必须的,^0.x 范围不会自动升到 1.x)。 公网固定域名(命名隧道,可选) 默认「快速隧道」的公网地址每次重启都会变(前缀随机)。想要固定公网地址,可用 Cloudflare 命名隧道(需要 Cloudflare 账号 + 自己的域名): 1. 在 Cloudflare Zero Trust → Networks → Tunnels 创建一条 Tunnel,复制 Tunnel Token 2. 在该 Tunnel 的 Public Hostname 里把你的域名(如 pocket.example.com)的 Service 指向 http://127.0.0.1:3081 3. 回到设置页公网区块:模式切到「命名隧道」,粘贴 Tunnel Token、填写固定域名,保存 4. 点「开启公网访问」→ 公网地址固定为你的域名,重启不再变化 注意:命名隧道模式下公网密码不自动轮换(地址固定,重启后密码不变),建议配合「自定义密码」主动管理;Tunnel Token 只存本机($DSH_HOME/dsh-pocket/settings.json,仅本机可读),设置页不回显。 ⚠️ 安全(必读) - DSH 能执行你电脑上的代码。局域网二维码/URL 配上独立 8 位密码才是钥匙(密码默认开启,可关——关闭后局域网扫码直连,仅同一网络设备可访问),请勿把局域网二维码、URL 或密码发给别人 - 开启公网访问前必须阅读并勾选免责声明(每次开启都会弹框;服务端强制校验,无法绕过):公网 = 把能执行代码的 DSH 暴露到互联网,请使用强密码、用完即关、涉密网络勿用 - 公网默认有 8 位随机密码保护:链接随机分配、默认每次开启换新密码、旧链接立即作废——泄露了也进不来,改密码/重开即可作废;自定义密码可设为 8–64 位英文字母或数字,且不再自动换新 - 手机登录状态与电脑上的 dsh web 进程绑定:电脑 dsh web 一直开着就不用重复输入;重启/更新后需重新输入一次 - 登录限速(防暴力破解):同一 IP 连续输错 5 次锁定 60 秒;全局失败超阈值时短暂全锁(防换 IP 分布式扫描);输对密码后计数清零 - 公网 URL 由 cloudflared 随机分配,每次重启会变化(旧链接自动失效,相当于天然轮换);命名隧道固定域名模式下地址不变、密码不自动轮换,请配合自定义密码管理 - 公网判定是 fail closed(issue #66):除本机(loopback)和局域网私网地址外,一切陌生域名(包括你自建隧道/反向代理指向本机端口的固定域名)一律按公网处理、强制公网密码——不存在「换域名绕过密码」的口子 - 局域网模式不暴露公网,只有同一网络内的设备能访问 - 适合个人自用;公网密码存本机 $DSH_HOME/dsh-pocket/token(默认每次开启公网自动换新,自定义后不换),局域网密码存 $DSH_HOME/dsh-pocket/token-lan(设置页手动刷新),开关/自定义标记存 $DSH_HOME/dsh-pocket/settings.json - CLI 模式(命令行直跑 dsh-pocket)也有密码(issue #90 修复前这条路是无认证的):默认随机生成 8 位密码,打印在终端、并已内嵌进二维码(扫码体验不变),手动敲地址时需要填写,本机访问免密。--pin <值> 或 DSH_POCKET_PIN=<值> 自定义(至少 6 位);--no-auth 可关闭,不推荐——那等于把能执行代码的 DSH 裸暴露给任何能连上该端口的人 💻 DSH Desktop(桌面版) - 桌面版里 dsh-pocket 的扫码同屏正常可用;更新/重启由桌面版管理(插件内这两项自动停用) - ⚠️ 桌面端 advanced 模式暂不支持手机访问(该模式禁用网页布局、手机拿不到 layout 服务,会白屏)——请切回 compatibility 模式后重启;advanced 模式下手机打开会看到明确的提示层 🩹 常见问题(别踩的坑) | 现象 | 原因与解决 | | dsh: command not found / 提示 DSH 未定义 | dsh CLI 没装:npm install -g @deepseek-ai/dsh,或命令前加 npx @deepseek-ai/dsh | | ERR_PNPM_ADDING_TO_ROOT | pnpm 9 对 workspace 根的限制:安装/更新命令末尾加 -w(--workspace-root) | | 装完/更新了但界面没变化 | 必须重启 dsh web 才生效;运行中的进程仍加载旧代码 | | listen EADDRINUSE ... :3081 | 旧 dsh-pocket 进程还占着端口:macOS/Linux lsof -ti :3081 \| xargs kill -9;Windows netstat -ano \| findstr :3081(找 LISTENING 的 PID)→ taskkill /PID <PID> /F,后重试 | | 想换端口(issue #70) | 插件模式:在 $DSH_HOME/dsh-pocket/settings.json 写 "proxyPort": 3082 后重启 dsh web。CLI 模式:dsh-pocket --port 3082。端口被占会报 EADDRINUSE,杀掉旧进程或换一个端口 | | 想给访客一个临时密码 | 暂不支持:issue #69 的「临时访问 PIN」功能已在 2.6.x 移除(撤销时会崩)。现在分享访问:把主密码或 ?token=<主密码> 链接发给对方,用完在设置页点「刷新」换掉即可 | | Linux 服务器装不上 cloudflared(issue #45) | 远程 Linux 国内/企业网下所有 CDN 源(GitHub/ghproxy/gh.ddlc/gh-proxy)都连不上时:在服务器上手动装 cloudflared(如 apt install cloudflared、dnf install cloudflared、或下载 tgz 解压到任意目录),然后在 $DSH_HOME/dsh-pocket/settings.json 加 "cloudflaredPath": "/path/to/cloudflared",重启 dsh web 后插件直接调用它,不再走自动下载 | | 版本停在 0.x 升不上去 | ^0.x 范围不允许升到 1.x:更新用 --latest(dsh plugin --profile web update dsh-pocket --latest -w) | | 公网 error 1033 | 见下方「公网隧道常见问题」——多半是本机代理/VPN(Clash 等 TUN 模式)掐断了隧道 | | 点「重启 dsh web」后页面提示进程在后台运行 | 自重启的新进程是 detached 后台进程(不挂终端),是页内更新的标准做法;停止它:macOS/Linux lsof -ti :3080 \| xargs kill -9;Windows netstat -ano \| findstr :3080 → taskkill /PID <PID> /F(日志在 $DSH_HOME 下 dsh-pocket-restart-.log) | ⚠️ 公网隧道常见问题(必读) 现象:点「开启公网访问」后,手机上打开公网地址报 error 1033(Tunnel error)。 最常见原因:本机开着代理/VPN(Clash、Surge、v2ray、sing-box 等,尤其 TUN 模式)。 这类工具会接管全部流量,并常常把 cloudflared 的隧道边缘连接(.argotunnel.com、Cloudflare 边缘 IP)掐断,导致隧道注册成功但数据面连不上。 另一类隐蔽根因:shell 里的 HTTP_PROXY / HTTPS_PROXY 环境变量(指向 127.0.0.1 的本地拦截代理)。 即使你关掉了 TUN 模式、系统级代理也显示关闭,只要终端启动时注入了这些 env 变量, dsh web 启动后 spawn 的 cloudflared 会继承它们,把隧道边缘连接绕进本地代理 → 同样 1033。 v2.11.1 起 pocket 在启动 cloudflared 时会主动剥离这些代理变量,从根上规避;旧版本需手动处理(见下)。 解决(从轻到重,按顺序试): 1. 先只关闭代理的 TUN 模式,不用退出代理软件——多数情况这一步就够: - Clash:设置里关掉「TUN 模式」开关(或右键菜单栏图标 → 取消勾选 TUN 模式) - Surge:关「增强模式」;v2ray/sing-box:关「虚拟网卡/路由接管」 - 然后回设置页重新点「开启公网访问」 2. 仍不行就彻底退出代理软件(不只是关界面:Clash 要右键菜单栏图标 → 退出;若装有后台服务还要在服务管理器里停掉,ps aux | grep clash 确认进程消失),再重试 3. 给代理加直连规则,放行隧道域名与 Cloudflare 边缘(Clash 规则示例): - DOMAIN-SUFFIX,argotunnel.com,DIRECT - DOMAIN-SUFFIX,trycloudflare.com,DIRECT - IP-CIDR,198.41.192.0/24,DIRECT,no-resolve 4. 网络实在不通时,改用局域网模式:手机开热点 → 电脑连手机热点 → 扫局域网码,效果完全一样(人在外面也能用) 其他可能:企业防火墙/校园网拦截出站;此时请让 IT 放行或改用热点。 首次开启时「下载 cloudflared」失败/卡住: - macOS/Linux:优先走清华镜像(实测 ~3MB/s,几秒下完);失败自动回退官方 GitHub + 加速源。 - Windows:无清华镜像(Homebrew 不支持 Windows),走官方直连下载(约 50MB,单线程会慢,属正常,耐心等几分钟;也可挂代理加速)。 - 全部失败时设置页会给出提示。备选方案(任选其一): 1. 手动装好命令行 cloudflared 后重试(装好后 dsh-pocket 直接用 PATH 里的,不再下载): - macOS:brew install cloudflared;Linux:sudo apt install cloudflared 或官网下载 - Windows:winget install cloudflared 或官网下载 - 任何平台:npm i -g cloudflared 2. 挂代理(系统代理/Clash 等)后重新点「开启公网访问」 3. 手动下载二进制放到 $DSH_HOME/dsh-pocket/bin/ 目录($DSH_HOME 一般是 ~/.dsh,Windows 是 %USERPROFILE%\.dsh;文件名用 cloudflared(Windows 加 .exe)或发布资产名均可,插件都认) 🗂 架构(单包) | 文件 | 说明 | | lib/index.js | 插件入口:自动起代理 + 注册 RPC + 访问密码管理(公网 8 位每次开启变新;局域网独立 8 位可手动刷新/开关)+ 局域网访问总开关 + 桌面端环境适配 | | lib/settings.mjs | 设置持久化:局域网访问总开关(默认开启)+ 局域网密码开关(默认开启)存 $DSH_HOME/dsh-pocket/settings.json | | lib/service.mjs | 服务:代理生命周期(端口自适应)、公网隧道(自动恢复)、状态快照(含二维码) | | lib/proxy.mjs | 改头反向代理:Host/Origin → loopback,HTTP + WebSocket 透传 + polyfill 注入 + gzip/brotli 压缩 + 按 Host 区分的访问令牌认证(公网必验;局域网按开关)+ 局域网关闭时拦截局域网 Host | | lib/tunnel.mjs | cloudflared:多镜像源下载(清华优先)/自适应多线程/启动/解析公网 URL(HTTP/2) | | lib/web-rpc.js | loopback RPC:status / tunnel.start / tunnel.stop / lan.setEnabled / version / update / restart | | client/ | 设置页「手机访问」+ 移动端适配(dsh-web-mobile 移植) | | bin/dsh-pocket.mjs | 命令行:局域网/公网模式,打印 URL + 二维码 | 🛠 开发 npm install node client/build.mjs # 改 client/ 后重新打包 npm test # 代理 / 认证 / 压缩 / 隧道 / 服务 / RPC / 设置(109 测试) 改完想在本机先试? 不用发版:把插件换成指向本地仓库的软链,重启 dsh web 就是本地代码。完整步骤(含怎么换回 npm 官方版本)见 LOCAL-DEV.md。 🤝 致谢 - 移动端适配移植自 mexiaosqwq/dsh-web-mobile(MIT) - 公网隧道基于 cloudflared 📄 License GPL-2.0 —— 自由软件许可:可自由使用、修改、分发,但修改版必须同样以 GPL 开源并保留版权声明;商用同样适用。 说明:移动端适配部分移植自 dsh-web-mobile(MIT 许可,兼容 GPL),其版权声明保留在 client/mobile/LICENSE.dsh-web-mobile。 有问题?欢迎反馈:遇到 Bug、有想法、想提需求,请到 GitHub Issues 告诉我们 🙏
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
shaobeichen/dsh-pocket
把 DeepSeek Harness 装进口袋:电脑上跑 dsh web,手机扫码就能同步访问(局域网 + 公网,实时同屏)
相关插件 · 市场 / 管理
插件精选列表awesome-dsh-plugin/awesome-dsh-plugin
DeepSeek Harness(dsh)插件精选列表
★ 22,025未汉化DSH
73.6
新词雷达zhuyansen/new-term-radar
new-term-radar新词雷达
★ 2,049已汉化MCP
72.8
插件生态导航0xsline/awesome-deepseek-harness
安装 贡献指南 DeepSeek Docs 公开插件目录 Issues
★ 1,188已汉化DSH
72.6
技能注册中心iflytek/skillhub
企业级开源智能体技能注册中心——发布、发现并管理组织内可复用的技能包。
★ 5,358已汉化DSH
71.9
插件市场目录imsai-sh/awesome-deepseek-harness-plugins
面向 DeepSeek Harnessdsh生态的社区插件目录,共收录 13938 个插件含 PR 收录与…
★ 350已汉化DSH
71.8
插件精选清单Anil-matcha/awesome-dsh-plugin
DeepSeek Harnessdsh精选指南——DeepSeek…
★ 1,013已汉化DSH
71.7