lyuksovannyy bf99a952fb dsh-remote 0.6.0: other machines' workspaces in the Workspaces list, richer Devices tab
- sidebar: workspaces (+ sessions) of every other device appear inside the stock
  Workspaces list with a server icon and the device name; click folds sessions,
  hover + creates a session there, a session opens as the remote conversation view
  (/r/<device>/#/session/<id>); the viewed device's own rows stay native
- Devices tab: every device with its state (online/offline, last seen, platform,
  workspace/session/running counts), offline and revoked devices included
- deploy/e2e-dom.mjs, e2e-eval.mjs: DOM dump / evaluate-in-page helpers
2026-10-12 09:50:13 +00:00

dsh-remote

Remote control for DeepSeek Harness, in the style of Claude Desktop: one master and any number of slaves.

  • Every session on every device. Sessions run on the machine that created them. From any device you can browse all of them, open them, and chat in them; the work still executes on the owning machine.
  • The full remote UI at /r/<device>/. The whole DSH UI of another device is proxied over the link: HTTP, the Remote WebSocket, SSE, plugin bundles and terminals. Slave→slave goes through the master's relay.
  • Plugin and config sync, master → slaves. Slaves get the master's npm/registry bundles, its local link: plugins (packed and shipped over the link) and its cordis.patch.yml. The config lands in a managed bundle layer, so each slave's own cordis.patch.yml still wins and slave-only plugins stay untouched.
  • Opt-in secrets. A credential (OMNI_API_KEY, …) reaches a slave only if three places agree: the master offers it, the master enables it for that device, and the slave accepts it.
  • Devices UI. A sidebar panel lists every device and its sessions (live running state, filter, "New session on "). A "Remote devices" settings page handles pairing, revocation and per-device sync policy. You get a toast when a session on any device finishes.

No dependencies: the WebSocket, the multiplexer and the proxy are plain Node.

 slave (laptop) ──outbound WebSocket /dsh-remote/link──►  master  ◄── slave (ai-pc)
   own sessions + own local plugins                  plugins, config, relay hub

Install

On every machine, register the plugin in the DSH web profile and restart DSH:

# master (this repo as a link: plugin, e.g. in Beast-Workspace)
#   profile package.json  →  "@local/dsh-remote": "link:/path/to/dsh-remote"  + bundle entry
# or use the helper (also creates the node_modules link and a config block):
node deploy/install-local.mjs --role master --name "Pelican-Node"
node deploy/install-local.mjs --role auto   --name "ai-pc"          # on a slave
systemctl --user restart dsh    # or restart `dsh web` however you run it

deploy/dsh-web.user.service is a ready-made systemd user unit for a rootless dsh web (127.0.0.1:3081).

macOS: one-line slave install

Create a pairing code on the master (Settings → Remote devices → Create pairing code). Then, in Terminal on the Mac:

curl -fsSL https://git.rizzy.dev/DSH-Plugins/dsh-remote/raw/branch/main/deploy/install-mac.sh \
  | bash -s -- --master http://192.168.0.111:3080 --code XXXX-XXXX-XXXX-XXXX --name my-mac

No sudo and no Homebrew. The script:

  • installs Node 22 to ~/.local/opt/node (checksum-verified), and DSH and pnpm to ~/.local;
  • puts dsh-remote in ~/.dsh/plugins/dsh-remote and registers it as a slave that accepts OMNI_API_KEY and FORGE_CREDENTIALS (--accept changes the list);
  • pairs with the code (deploy/pair.mjs, no running DSH needed);
  • installs the LaunchAgent dev.rizzy.dsh-web: dsh web on 127.0.0.1:3081, started at login and restarted if it dies. Logs go to ~/.dsh/logs/.

On first link-up the Mac pulls the master's plugins and config. With sync.restartOnSync: true, set by the script, DSH restarts itself once so new plugins load. It waits until no session is running and restarts at most once per 10 minutes.

Re-running the script updates everything and keeps the pairing. To remove it: launchctl bootout gui/$(id -u)/dev.rizzy.dsh-web, then delete ~/Library/LaunchAgents/dev.rizzy.dsh-web.plist, ~/.dsh and ~/.local/opt/node.

Away from home, point --master at the public URL. If an auth proxy guards it, add the --edge … flags (see Masters behind an auth proxy). Secrets are prompted for on the terminal and never passed on the command line:

curl -fsSL https://git.rizzy.dev/DSH-Plugins/dsh-remote/raw/branch/main/deploy/install-mac.sh \
  | bash -s -- --master https://dsh.rizzy.dev --code XXXX-XXXX-XXXX-XXXX --name my-mac \
               --edge basic --edge-user dsh-remote-mac

Pair a device

First choose what this installation is: Settings → Remote devices → Node.

Setting
Type: Master / Slave Master holds plugins, config and sessions and accepts links. Slave connects to a master and syncs from it. The choice is stored in the plugin state and beats role in the config file. A change applies after a restart (a Restart DSH button appears when DSH runs under systemd / launchd).
Origin Master: the address slaves use to reach it (read-only, taken from publicUrl / lanUrl or the page's own origin). Slave: the master's origin; read-only once paired, to change it re-pair.
Master has an auth middleware On: a non-DSH answer on the link opens the sign-in window (see Masters behind an auth proxy), then the link retries. Off: work as usual.
  1. Master: Settings → Remote devices → Create pairing code (single use, valid 15 min).
  2. Slave: Settings → Remote devices → enter the master URL (e.g. http://192.168.0.111:3080 or https://dsh.rizzy.dev) and the code → Pair. Then restart the slave's DSH once: with role: auto it switches from master to slave.

The slave gets its own device key; the master stores only its hash. Revoke cuts the device off immediately: open links close with code 4401 and later connections are refused with 401.

Use it

  • Workspaces list: the workspaces of every other machine appear in the stock Workspaces list, below your own, with a server icon instead of the folder icon and the device name on the right. Click one to fold its sessions open (newest first, "Show N more" for the rest); hover for + to start a session in that workspace on that device. Clicking a remote session opens it as the usual conversation view, served by that device at /r/<device>/#/session/<id>. A "Remote: · back to local" pill marks the remote view. While you are viewing a device, its own workspaces are the native rows and are not repeated.
  • Sidebar → Devices: every device with its state (online / offline, last seen, platform, counts of workspaces, sessions and running ones), then its workspaces and sessions. The same server icon marks other machines' workspaces. Open DSH ↗ opens a device's whole UI, + New session creates a session in one of its workspaces.
  • Toasts: ": '
S
Description
Claude-Desktop-style remote control for DSH: master/slave link, every device's sessions on every device (/r/<device>/), plugin + config sync with opt-in secrets.
Readme
544 KiB
0 Stars 2 Watchers 0 Forks
Languages
JavaScript 97.1%
Shell 2.9%