DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
P

phone-tunnel-pool

Phone Tunnel Pool

一键式 Cloudflare 快速隧道池,用于 dsh Web GUI——通过二维码从手机访问,支持自愈式生成机制和 chase service worker。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:iimaguest/phone-tunnel-pool#4cbeedb31a8d3e446d57c6a97864d1e00b5afd89
README兼容性版本
Tunnel pool widget: a phone tunnel enabled with a live pool of generations

兼容性与来源证明

Phone Tunnel Pool 以 phone-tunnel-pool 发布,当前版本为 0.3.35。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/10/2

版本

0.3.35stable
2026/10/2
0.3.34stable
2026/8/29

相关插件

正在加载相关插件…

最新版
0.3.35
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
Apache-2.0
发布源
github
GitHub
★ 7
周下载
0
最近提交
2026/10/2
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 security-access 分类下经过校验的插件。

Experimental Auto Review@deepseek-ai/dsh-experimental-auto-review针对每个工具的 LLM 授权审查,适用于 DeepSeek Harness Auto 权限预设Cc Safety Netcc-safety-net编码代理 CLI 钩子——阻止破坏性命令和访问机密文件Doctor@linxin666/dsh-doctorDSH 配置档案的事务性救援模式,配备受监督的启动器、隔离的恢复容器、确定性修复、健康监控以及本地 Web 恢复控制台Pocketdsh-pocket把 DeepSeek Harness 装进你的口袋:一个包、一个设置页,手机扫码即同步访问电脑上的 DSH(局域网 + 公网,实时同屏)。

README

phone-tunnel-pool — Cloudflare quick-tunnel pool for the dsh web GUI

English | 简体中文

Enable/disable a self-healing Cloudflare quick-tunnel pool for http://127.0.0.1:3080 (the DeepSeek Harness web GUI) from a floating widget with a scannable QR code. One scan from your phone, and the pool keeps itself alive:

  • Generational rotation (12h): a new pair of tunnels spawns on schedule; older generations stay alive while anything is still on them.
  • Chase service worker: every origin your browser touches registers a service worker. Dead or rotated hostnames redirect to a live sibling or the newest primary — the same open tab survives generation changes as long as it stays connected.
  • Prompt-free migrations: the proxy injects credentials only into pages it has already authenticated; before any redirect the watchdog pre-authenticates the target hostname (minting its auth cookie), so migrations land authenticated — no "Authentication required" popups.
  • Usage-based retirement: generations retire only when idle (no tabs / websockets / recent traffic) or at a hard age cap.
  • Respawn with backoff: dead tunnels are replaced with new hostnames; quick-tunnel mint quota (Cloudflare 429) is respected via exponential backoff + a 2-probe dead-grace (DNS propagation).

Extra: the daemon runs detached and adopts across dsh web restarts, so the same URL, password and QR stay valid until you click Disable — no re-scan (an OS reboot still costs one fresh scan; a named tunnel removes even that — see PLAN.md §7).

Install / Uninstall

# install (from this public repo)
dsh plugin --profile web add github:iimaguest/phone-tunnel-pool
dsh web        # the GUI shows a floating 📱 widget (bottom-right)

# uninstall (one command — removes the dependency AND the dsh.profile.bundles layer)
dsh plugin --profile web remove phone-tunnel-pool
dsh web

After install: open the widget → Enable → scan the QR with your phone camera. Install/remove reconcile dsh.profile.bundles against the installed state automatically — never edit ~/.dsh/profiles/web/package.json by hand; a stray bundle entry with no matching dependency is exactly the kind of state that fails profile boot ("cannot resolve profile bundle").

Prerequisites (all of them)

WhatNeeded?Who provides it
dsh web running on its default port 3080 (DSH_TARGET_PORT to override)requiredyou (the plugin tunnels to it)
cloudflared binary on PATHrequiredyou — brew install cloudflared (or apt/dnf/Chocolatey, or set DSH_CLOUDFLARED to the existing binary)
Node.js runtimerequireddsh itself — no separate install (the daemon reuses dsh's node)
python3 + qrcode packageoptionalyou — pip install qrcode; without it the widget shows URL + login instead of a scannable QR
caffeinateoptionalmacOS ships it; skipped elsewhere
PowerShelloptionalWindows ships it — used only for process cleanup on Windows (no pkill there)
Outbound networkrequiredcloudflared → Cloudflare edge on 443/7844 (no inbound port needed)

The widget preflights these on dsh web start and shows a yellow warning line (with the exact fix, e.g. brew install cloudflared) before you even click Enable; the daemon also fails fast with a readable error if cloudflared is missing at Enable time, and refresh in the popup re-checks everything — a stale error clears once the prereqs pass.

The feature flag set is version-gated on cloudflared --version: 2024.6+ enables the opt-in post-quantum handshake (DSH_PQ=1), 2024.8+ adds --management-diagnostics=false; older builds (apt/dnf packages) get a reduced, compatible flag set.

Platforms. macOS, Linux and Windows (Windows uses PowerShell for process cleanup; caffeinate is macOS-only and silently skipped elsewhere). The daemon's state file and log live in the per-OS temp directory (os.tmpdir()); the widget settings file (iptunnel-settings.json) lives in ~/.dsh.

Screenshots

dsh web on a phone, reached through the tunnel pool

Tunnel pool widget: a phone tunnel enabled with a live pool of generations

Live hostnames, credentials and the QR are blurred out in these shots.

How it's wired

dsh web GUI  <--  /iptunnel routes  --  auth proxy (127.0.0.1:3090)
                                              │  Basic + session cookie,
                                              │  Host rewrite to 127.0.0.1:3080
                                              │  (the GUI's browser-trust fence)
                                              ▼
cloudflared A ─ to ─ auth proxy ───────────────────────────────────┐
cloudflared B ─ to ─ auth proxy ───────────────────────────────────┤ (tunnel daemon
    ... new generations ...  ──────────────────────────────────   │   manages all)

Files: lib/index.js (host API: enable/disable/adopt, state + QR SVG routes), lib/daemon.mjs (detached pool brain: spawn, probe, rotate, retire, respawn), cf-auth-proxy.mjs (public /iptunnel/* service paths + Basic auth + watchdog injection + credential handoff), iptunnel-sw.js (chase service worker), iptunnel-watchdog.js (open-tab watchdog), lib/client.js (widget), verify.sh (end-to-end audit). PLAN.md = full spec + edge cases; NOTES.md = engineering history.

The dsh 0.2 launch token (why the tunnel 401'd)

dsh 0.2 moved web auth into the connection service: the desktop URL carries a per-process launch token (http://127.0.0.1:3080/?token=<secret>), a valid token exchange mints a signed browser-session cookie, and every request with neither gets 401. The tunnel path is phone → trycloudflare → this proxy → the GUI, and a phone can never learn a token that only exists in the desktop process output — so on 0.2 the tunnel answered 401 all the way down.

The fix (0.3.35): the plugin reads the token through the connection service's public authenticatedUrl() API and hands it to the proxy — via the daemon environment on a fresh enable, and via POST /iptunnel/__ctl/launch-token whenever a surviving daemon outlives a dsh restart (the token is per-process, the daemon is deliberately not). The proxy exchanges the token against the GUI once, holds the resulting session cookie, and stamps it onto every forwarded request and websocket handshake — re-minting on an upstream 401 and on every token push. A phone therefore presents only this proxy's Basic auth, exactly as before, and the launch token never reaches cloudflared's environment, the QR, or the published URL. On a dsh without the gate the token is empty, every new code path no-ops, and forwarding is byte-identical to the pre-0.2 behaviour (test/launch-token.test.mjs pins all of this against a mock origin, including rotation).

Resource footprint (minimal by default)

  • Disabled = zero processes (just the floating pill in the GUI).
  • Enabled = 1 node daemon + 1 auth proxy + 2 cloudflared per live generation. Default ceiling: 4 generations × 2 = 8 tunnels (a busy pool runs all of them; idle generations retire on their own after 60 min).
  • Knobs to shrink further: DSH_MAX_GENS=2 (≤4 tunnels), DSH_IDLE_MS=1200000 (retire after 20 min idle), DSH_PQ — post-quantum handshake is opt-in (DSH_PQ=1) because it costs CPU per connection; without it the tunnel uses the classic handshake.
  • Phone battery: the watchdog backs off 30s → 300s (5 min) while nothing changes.
  • Keep-awake is opt-in: caffeinate (macOS) is off by default; turn it on in the widget ("Keep machine awake while enabled") or via DSH_CAFFEINATE=1 — it applies on the next Enable (and lets the display sleep — -i only, no screen-on drain). Without it, an idle MacBook may sleep and the pool goes quiet until it wakes.
  • Daemon log is capped at 512 KB (keeps the last 128 KB); probes run at 30s.

Security model

  • The password is generated per Enable, held in memory, shown in the widget and embedded in the QR; nothing is committed or published. (The daemon keeps the current credentials in a 0600 state file under the OS temp dir so the tunnel survives a dsh web restart; that file is deleted on disable.)
  • /iptunnel/* service paths (health, sw-config, sw.js, entry, watchdog.js, telemetry, preauth) are public by necessity — browsers fetch service workers without credentials; they carry hostnames and pool liveness only. The credential handoff (/iptunnel/preauth) mints a cookie only for a caller presenting the valid password; it never echoes anything.
  • window.__ptAuth is injected only into HTML the proxy has authenticated.
  • The proxy listens on 127.0.0.1; public network exposure happens only through the tunnel hostnames — the QR/hostname is a bearer secret (anyone who gets it can open the tunnel while enabled): disable when done.
  • Quick tunnels are testing-grade (no uptime SLA, per-IP mint quota). The repo-agnostic sibling package carries the same pattern for any local port; a named tunnel is the lifetime endgame (one stable hostname → no re-scans, no prompts, no quota).

License

Apache-2.0 — see LICENSE. Third-party code: cloudflared (distributed by Cloudflare), the Python qrcode library — used at runtime, not vendored.