본문으로 건너뛰기
A

dsh-dispatch

alextangson/dsh-dispatch

Command your DeepSeek Harness machines from your phone: approval push, remote dispatch, session board. Built on DeepSeek Harness.

설치

dsh plugin --profile web add github:alextangson/dsh-dispatch

README

dsh-dispatch

Dispatch tasks to DeepSeek Harness from your phone. Approve tool calls with one tap. Command every machine you own.

从手机给 DeepSeek Harness (dsh) 派任务、审批一键批、一部手机指挥所有机器。中文说明 →

CI npm license

Like Claude Code's Dispatch + Remote Control, but for dsh — open source, end-to-end encrypted, self-hostable.

Why this exists

dsh web binds to 127.0.0.1 with no auth — by design. Every existing remote tool wraps that web page in a WebView. dsh-dispatch is not a mirror. It is a command center:

WebView mirrorsdsh-dispatch
See sessions from the couch
Dispatch a new task from your phone✅ into an isolated git worktree
Approval push notifications, tap to allow/deny✅ for every session, even desk-started ones
Many machines on one screen❌ one tunnel each✅ one board
Relay can read your trafficusuallynever — zero-knowledge, E2E encrypted
  • 📤 Dispatch — type a prompt on your phone; the machine creates a git worktree, spins up a fresh dsh session, and reports the final answer back with a push notification.
  • Approvals on your lock screen — the plugin joins dsh's approval/request waterfall. Phone and desktop race; first decision wins; nothing is ever auto-approved.
  • Questions forwardedask_user_question choices show up on your phone; answer from anywhere and the session continues (also rescues the upstream no-answerer hang).
  • 💬 Keep talking — a finished session is not a dead end: reply from the card and the machine picks the same session back up.
  • 👀 See what it's doing — the card names the tool running right now, so three minutes of "running" is not indistinguishable from a hang.
  • 📁 Pick the directory, don't type it — the machine publishes the roots it allows and the phone offers them as a choice; no absolute path recalled from memory, no rejection after you hit send.
  • Optional full-access tier — dispatch under dsh's danger-full-access to skip approvals for fully-trusted tasks; off by default, machine-gated, permanent red badge on every such session.
  • 🌏 English or Chinese — switch in Settings, including the sentences the machine writes.
  • 🖥️ Multi-machine — one phone, N machines, one board with live session states.
  • 🔒 Zero-knowledge relay — routes ciphertext it cannot read. The 32-byte pairing secret travels only inside the QR code. Self-host the relay with one command.

How it works

┌────────────┐  E2E encrypted   ┌───────┐  E2E encrypted   ┌──────────┐
│ dsh plugin │ ───── wss ─────► │ relay │ ◄──── wss ────── │ PWA      │
│ (machine)  │                  │ (dumb │                  │ (phone)  │
│            │                  │ pipe) │                  │          │
└────────────┘                  └───────┘                  └──────────┘
  approval/request waterfall      sees only                approve / dispatch
  ctx.agents.create + worktree    ciphertext               web push alerts
packagenpmwhat it is
dsh-dispatchnpmthe dsh plugin — event-bus listener, approval race, worktree dispatch
dsh-dispatch-relaynpmstateless ciphertext router + Web Push, Docker/npx one-liner
@dsh-dispatch/pwainstallable phone app (PWA) — no app store needed

Quickstart

On the machine that runs dsh:

# 1. Run a relay — yours, or any you trust (it can't read your traffic)
npx dsh-dispatch-relay            # listens on :8787

# 2. Install the plugin into your dsh profile
dsh plugin --profile web add dsh-dispatch
# 3. Configure it — ~/.dsh/profiles/web/cordis.patch.yml
- id: dsh-dispatch
  config:
    relay: 'ws://localhost:8787/ws'          # wss:// for anything non-local
    allowedRoots: ['/path/you/allow']        # dispatch stays OFF until you set this
    pwaUrl: 'https://alextangson.github.io/dsh-dispatch'   # where the pairing link points
# 4. Boot dsh, then run /dispatch-pair and open the printed link on your phone
dsh web

The phone app is hosted at https://alextangson.github.io/dsh-dispatch — no install, no app store; add it to your Home Screen so Web Push can reach the lock screen. It is a static page that talks only to the relay you configured, so self-host it from packages/pwa if you would rather not load it from GitHub Pages.

Your phone reaches the relay directly, so a relay on localhost only works from the same machine. For a real phone, put the relay somewhere reachable over wss:// — a $5 VPS, or a tunnel in front of it.

Approval forwarding works immediately after pairing; dispatch activates once allowedRoots is set. Relay self-hosting (Docker, VAPID push keys) and every config key: see packages/relay and packages/plugin.

Security model

  • Pairing = trust. The QR/pairing code contains a 32-byte secret; whoever scans it controls the machine within allowedRoots. Treat it like an SSH key. Rotate anytime with /dispatch-repair.
  • E2E encryption (nacl.secretbox, per-message nonce). The relay stores room presence and push endpoints — never plaintext, never keys.
  • No timeout-approve exists anywhere in this codebase. Unanswered approvals stay pending and re-remind. The one way a tool call runs unreviewed is the full-access tier you switch on yourself, per machine and per dispatch — and every such session carries a permanent red badge.
  • Dispatch is allowlisted. Requests outside allowedRoots are rejected visibly. Worktrees are never auto-deleted.

Status & roadmap

v0.3.0 on npm — developer preview tracking dsh 0.1.x (upstream warns of breaking changes; every harness API touchpoint is isolated in one adapter layer). Everything below is verified end-to-end against dsh 0.1.1-rc.2 with the real DeepSeek API, not in mocks: phone dispatch → worktree session → real tool execution → sandbox-escalation approval pushed to the phone → allow → command runs; a question answered from the phone flows back into the running session; a follow-up typed on the phone reopens a finished session and the card names the tool it runs; a full-access dispatch runs under danger-full-access and writes outside the workspace with no approval prompts.

The hosted PWA tracks main and the plugin is released from it, so the two line up at 0.3.0. A machine still on 0.2.0 degrades visibly rather than silently: the directory step says the plugin is too old and falls back to a text field, and no reply box appears.

dsh-dispatch-relay stays at 0.2.0 — it has not changed since, and a version bump with no diff behind it is a lie about what you are installing.

Known limitations:

  • A full-access session runs under dsh's danger-full-access preset, which sets approval: 'never' — so it raises no approval cards at all. Full access and phone approvals are mutually exclusive per session, by dsh's own preset semantics. That's the trade: speed for no review surface.
  • Web Push works through the relay, but lock-screen delivery has only been verified in desktop browsers so far, not on a physical phone over HTTPS.
  • Each dispatch gets a fresh worktree from the repo's HEAD — files created by a previous dispatch live in that dispatch's own worktree.
  • A pending question doesn't survive a phone reload (no questions.get in the protocol yet); the machine re-reminds until answered.
  • The approval card's three field labels stay Chinese in English mode. A structured copy of the detail would double a field already capped at 10KB inside a 16KB envelope; halving how much of a command you can read before approving it is a bad trade on that particular screen. The tool name, reason and arguments were never translatable anyway.
  • Console diagnostics are Chinese. They are developer output, not UI, and the language switch does not claim them.

Roadmap: real-device push polish → fleet views → session history beyond the live board.

中文

这是什么:dsh 官方没有手机端、没有远程方案。现有第三方全是"把 localhost:3080 套壳进 WebView"。dsh-dispatch 走的是 Claude Code Dispatch 那条路——一个指挥中心

  • 手机派任务:输入一句话,机器自动开独立 git worktree 跑一个新会话,跑完推送结果。目录不用手打——机器把白名单目录报给手机,你点选就行。
  • 审批推送:任何会话(包括你在电脑上开的)的工具审批都会推到手机,锁屏一键允许/拒绝;手机和桌面竞速,先答先赢,永不超时自动批准
  • 提问转发:模型调 ask_user_question 时,选项直接出现在手机上,答完会话继续跑。
  • 接着聊:会话跑完不是终点,在卡片下面直接追问,机器会把同一个会话拉起来继续。
  • 看得见在干嘛:卡片显示此刻正在跑的工具,不用盯着"运行中"猜它是不是卡死了。
  • 多机看板:一部手机管 N 台机器,会话状态实时同屏。
  • 中英双语:设置里一键切换,连机器发来的报错也会跟着翻译。
  • 零知识中继:relay 只转发密文(端到端加密,密钥只存在于配对二维码里),一条命令自托管。

快速开始npx dsh-dispatch-relaydsh plugin --profile web add dsh-dispatch → 在 profile 的 cordis.patch.yml 里配 relayallowedRoots → dsh 里执行 /dispatch-pair,手机打开 https://alextangson.github.io/dsh-dispatch 扫码即配对。手机是直连 relay 的,所以 localhost 上的 relay 只有本机能用;真要用手机,relay 得放在 wss:// 能访问到的地方。

版本:插件与托管 PWA 都在 0.3.0。机器上如果还是 0.2.0,降级是看得见的——目录选择器会提示"这台机器的插件较旧"并退回手填,追问输入框不出现;升级插件即可。

安全:配对码即信任边界(当 SSH 私钥对待,可随时 /dispatch-repair 轮换);派任务只进你白名单的目录;审批永不自动通过(唯一例外是你主动开启的完全访问模式,那类会话在看板上永久标红)。

Contributing

Issues and PRs welcome. The wire protocol is frozen in docs/PROTOCOL.md; product boundaries in docs/PRODUCT.md; every dsh API claim is sourced in docs/dsh-plugin-groundtruth.md.

Keywords: DeepSeek Harness plugin, dsh-plugin, dsh remote control, mobile approvals, phone dispatch, agent remote control, E2E encrypted relay, Claude Code Dispatch alternative, DeepSeek 手机远程控制, 手机审批, 远程派任务.

License

MIT

관련 플러그인