npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@firefly0621/dsh-remote-control

v0.1.0-rc.14

Published

Host plugin: zero-config outbound relay connection with GUI pairing, inventory and settings commands

Readme

@firefly0621/dsh-remote-control

English | 中文

Host plugin for the remote-control capability: opens an outbound WebSocket connection to a relay server and serves plugin-inventory and settings commands to a paired mobile app. The dsh host needs no public IP and no inbound ports — it dials out, exactly like the OpenClaw/Claw mobile-control pattern.

Install as a profile plugin

dsh plugin --profile web add @firefly0621/dsh-remote-control

The browser pairing panel (@firefly0621/dsh-client-ui-remote-control) is a dependency of this package, so one install brings the host plugin and the 设置 → 远程控制 settings page together.

Connection is explicit: the plugin stays disconnected until you press 连接 in the pairing panel; the QR + 6-digit pairing code appear only after the connection succeeds (the relay mints the code over the live link). 断开连接 drops it and clears the code. Start a relay locally (@firefly0621/dsh-remote-relay, default ws://127.0.0.1:8787) or point at your own — the plugin defaults to ws://127.0.0.1:8787, auto-generates a deviceId/deviceSecret (persisted in the settings namespace remote-control, secret redacted on every wire surface), and the relay address is editable live in the panel. A phone scans the QR (or types the code) once and stays paired — the app resumes with its stored token afterwards.

Production just configures the relay:

# ~/.dsh/profiles/web/cordis.patch.yml
- update:
    - id: remote-control
      config:
        relayUrl: wss://relay.example.com

Configuration

| Key | Type | Meaning | |---|---|---| | relayUrl | string | Public relay WSS URL, e.g. wss://relay.example.com; absent defaults to ws://127.0.0.1:8787 (a locally running relay). Also editable live from the pairing panel (设置 → 远程控制); the panel-persisted value wins over cordis.yml. | | deviceId | string | Stable device id; auto-generated and persisted when absent. | | deviceSecret | string | Long-lived secret; auto-generated and persisted when absent. |

Behavior

  • Connection is explicit: the relay-address field's 连接 button persists the address and starts the outbound client, 断开连接 stops it and clears the code. On connect the plugin authenticates with hello { deviceSecret }; the relay mints a 6-digit pairing code and sends it back via pairing.issue. The web GUI panel shows the code plus a QR encoding relay=<url>&code=<6位码> once paired (with a 刷新 re-read), and connection failures surface as an error status with the reason.
  • Commands over the wire:
    • plugin.list → current non-group Loader entries (id, module, enabled, fiber phase).
    • settings.describe → every registered settings namespace via ctx.settings.describe({ redactSecrets: true }) — secret fields never leave the host.
    • settings.mutate → path-level edits with optimistic concurrency (ctx.settings.mutate(ns, ops, expectedRevision)), persisted by the settings provider.
    • sessions.list → the host's sessions: live-agent ones with their title (the session-title service's LLM/fallback title when mounted, else the first user message) plus persisted cold sessions, most recent first.
    • sessions.create → a new session on the default workspace and preset; the plugin owns the handle so the phone can delete it.
    • sessions.delete → deletes a session the plugin created (web-created sessions are refused).
    • chat.history → the projected conversation of one session (live or cold): user/assistant text plus tool rows with a truncated result summary and failure marker.
    • chat.stats → whole-log figures of one live session (turns, steps, LLM/tool/ttft/decode wall times, output tokens) from the sessionStats projection; null when that unit is absent or the session is cold.
    • chat.send → submits one message to a chosen sessionId (or the most recent active session when absent), resuming a persisted cold session under its stored preset first; the assistant reply streams back to the app as event pushes (chat/start / chat/chunk / chat/done / chat/error).
    • models.list → the available provider/model catalog plus the host default selection.
    • models.set → sets the model selection of one live session (takes effect from the next message).
  • Device-originated relay commands: sessions.list / sessions.revoke power the GUI's bound-device list and removal; resetIdentity regenerates the identity and reconnects, orphaning every bound session.
  • Connection management: 30s heartbeats, exponential-backoff reconnect (1s → 60s cap with jitter), full teardown on fiber disposal.

Relay

The relay is @firefly0621/dsh-remote-relay (standalone Node service, also published to npm). Its deployment env: PORT, NODE_ENV=production (requires TLS), TLS_CERT/TLS_KEY, DSH_RELAY_DEVICE_SECRETS, optional DSH_RELAY_ALLOW_AUTO_REGISTER=1 (first hello for an unknown random deviceId binds it — the zero-config mode), and optional DSH_RELAY_DATA_DIR (durable session storage so a paired phone resumes after a relay restart). See the dsh-remote-relay repo.

Model Experience

None, as this plugin serves host state to an app; it registers no prompt, tool, or provider request.

KV Cache effect

None; the plugin never assembles or sends a model request.

Known Limitations and Deferred Work

  • No enable/disable/install/uninstall — the Loader is the sole lifecycle authority and exposes no mutation path; inventory is read-only and settings edits only touch the user-settings document.
  • Pairing code is relay-minted — the device displays but does not generate codes; rotating codes requires a relay-side change (the device can force one by reconnecting).
  • Relay sessions persist only with DSH_RELAY_DATA_DIR — without it a relay restart clears sessions and phones must re-pair.