DeepSeek Harness Plugin

liujuntao123/dsh-mobile-keys

Stars ★ 0 Category UI Enhancements Added 2026-11-02 npm dsh-mobile-keys

Adds a mobile hotkey mode to the DSH web composer that auto-detects touch and mobile devices and switches to Ctrl+Enter for send and plain Enter for a newline while leaving the desktop keymap untouched, with a Settings toggle, a /mobilekeys command and a window.__dshMobileKeys console API.

Install

# from npm (prebuilt)

dsh plugin --profile web add dsh-mobile-keys

# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)

dsh plugin --profile web add github:liujuntao123/dsh-mobile-keys

Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).

README

中文 | English

A mobile hotkey mode plugin for DeepSeek Harness (DSH) — a browser-side bundle plugin. It auto-detects mobile devices and switches the send/newline key bindings, fixing the fact that mobile soft keyboards cannot produce Shift+Enter, which makes the composer impossible to wrap lines on. Preferences persist in browser localStorage; no backend needed.

Compatibility: adapted to DSH 0.2.x (composer contract, settings slot and command API verified against 0.2.1-rc.5); still compatible with earlier builds that only expose data-lexical-editor.

⌨️ Key bindings

Mode Send Newline Notes
Desktop (default) Enter Shift+Enter Identical to native DSH; the plugin stays out of the way
Mobile mode Ctrl+Enter Enter Send rides DSH's native accelerated gesture; newline intercepts plain Enter and re-dispatches a synthetic Shift+Enter through DSH's own line-break path

✨ Features

  • 🔍 Auto-detection: defaults to auto mode — classifies the device by UA / touch points / pointer type / viewport width and follows rotation or monitor changes live. Touch-screen laptops and kiosk touch displays are never misclassified.
  • 🎛️ Settings toggle: DSH Settings → General → "Mobile hotkey mode" switch, live status line, one-tap "restore auto-detect" after a manual override.
  • 💬 /mobilekeys command: check status and switch Auto / On / Off right from the composer.
  • 🛠️ Console API: window.__dshMobileKeys.getStatus() / setMode() / getBindings().
  • 🛡️ Zero intrusion elsewhere: IME composition, open overlays (menus/dialogs/command palette), question-card inputs, and anything outside the composer all pass through untouched; in desktop mode the plugin does nothing at all.
  • 💾 No backend: preference stored in localStorage (key dsh.mobilekeys.v1), remembered per device.

🤖 AI install

Hand the following prompt to your AI (DeepSeek / Claude, etc.) and it will install the plugin for you:

Please install the dsh-mobile-keys plugin into the DeepSeek Harness web profile: run dsh plugin --profile web add git+https://github.com/liujuntao123/dsh-mobile-keys.git, then restart dsh web and hard-refresh the browser (Ctrl+F5), then run window.__dshMobileKeys.getStatus() in the browser console to confirm it returns { mode, detected, effective, bindings }, and confirm the "Mobile hotkey mode" toggle appears in Settings → General.

Full AI install instructions (manual method, troubleshooting, verification): AI_INSTALL.md.

📦 Installation

Method 1: install from GitHub (recommended)

dsh plugin --profile web add git+https://github.com/liujuntao123/dsh-mobile-keys.git

DSH will automatically: pnpm-install the git dependency → detect the dsh.bundle declaration → add dsh-mobile-keys to dsh.profile.bundles in package.json.

Requires pnpm. If missing: npm install -g pnpm.

Method 2: manual install

cd ~/.dsh/profiles/web   # Windows PowerShell: cd $env:USERPROFILE\.dsh\profiles\web
pnpm add git+https://github.com/liujuntao123/dsh-mobile-keys.git

Then you must add "dsh-mobile-keys" to the dsh.profile.bundles array in that directory's package.json:

"dsh": {
  "profile": {
    "bundles": [
      "@deepseek-ai/dsh-base",
      "@deepseek-ai/dsh-web-app",
      "dsh-mobile-keys"    // ← required, otherwise it won't load
    ]
  }
}

⚠️ pnpm add does not touch the bundles list; DSH loads plugins from that list, so missing this line means it won't take effect.

Method 3: local clone + link (for development)

git clone https://github.com/liujuntao123/dsh-mobile-keys.git

Point a link dependency at it in the web profile's package.json:

"dependencies": {
  "dsh-mobile-keys": "link:/absolute/path/to/dsh-mobile-keys"
}

and likewise add "dsh-mobile-keys" to bundles.

After installing: restart + hard refresh (all methods)

bash scripts/restart-dsh-web.sh   # if you cloned this repo; otherwise restart dsh web your way

Then hard-refresh the browser with Ctrl+F5.

⚙️ Usage

Modes

store.mode Meaning
auto (default) Detect the device and follow it
on Always mobile bindings (Ctrl+Enter send / Enter newline)
off Always desktop bindings (Enter send / Shift+Enter newline)

Settings panel

DSH sidebar → gear (Settings) → General → "Mobile hotkey mode", with a two-line description:

Current keys: send Ctrl+Enter / newline Enter
Detected device: mobile · Recommended on mobile devices to avoid being unable to insert newlines
  • The switch shows and controls the effective mode; flipping it writes a manual value (on / off).
  • Line 1: the currently effective bindings, live with the mode.
  • Line 2: the device verdict and a recommendation; after a manual override a "restore auto-detect" action appears at the end of this line, clearing the override back to auto.

Command & console

  • Type /mobilekeys in the composer → pick Auto / On / Off.
  • Browser console:
window.__dshMobileKeys.getStatus()      // { mode, detected, effective, bindings }
window.__dshMobileKeys.setMode('on')    // 'auto' | 'on' | 'off'
window.__dshMobileKeys.getBindings()    // { send, newline }

Verification checklist

  1. Settings → General shows the "Mobile hotkey mode" row with a working switch and live status.
  2. /mobilekeys opens the mode menu.
  3. With mobile mode on: Enter inserts a newline, Ctrl+Enter sends; turning it off restores Enter-to-send.
  4. With the command menu open, Enter still selects an item instead of inserting a newline.

🔍 How it works

The DSH composer is a Lexical editor. Enter semantics come from a KEY_ENTER_COMMAND handler registered at CRITICAL priority:

  • event.shiftKey === true → the handler returns false, falling through to @lexical/plain-text's default → line break inserted;
  • otherwise → submit (ctrlKey/metaKey count as an accelerated send).

So this plugin:

  • changes nothing on the send side: mobile mode's Ctrl+Enter is the native accelerated gesture;
  • touches the newline side minimally: only while mobile mode is active, it intercepts a plain Enter inside the composer at the document capture phase (preventDefault + stopImmediatePropagation), then re-dispatches a synthetic keydown with shiftKey: true onto the Lexical root ([data-lexical-editor="true"]), reusing DSH's own line-break path (selection, undo stack, and controlled updates all behave exactly like a real Shift+Enter).

Guard rails:

  • Only key === 'Enter' is considered; Shift/Ctrl/Cmd/Alt+Enter, IME composition (isComposing / keyCode 229), and visible overlays ([role="menu"|"listbox"|"dialog"|…]) always pass through;
  • Targets outside [data-lexical-editor="true"] (buttons, question-card inputs, …) always pass through;
  • Synthetic events carry a __dshMobileKeysSynthetic marker to prevent re-entry.

Mobile detection (auto mode):

mobile ⇐ UA matches Android/iPhone/iPad/iPod/Mobile/Silk
       ⇐ iPadOS 13+ desktop UA (Macintosh + maxTouchPoints > 1)
       ⇐ (pointer: coarse) AND has touch AND (max-width: 820px)

🧪 Development

npm test            # dependency-free Node tests: loads the real lib/client.js in a VM, end to end
node --check lib/client.js

Layout:

lib/index.js       host-side minimal Cordis plugin (mount/unmount shell)
lib/client.js      all browser logic (ModuleLoader bundle, no build step)
tests/             dependency-free Node tests (node --test)
scripts/           restart-dsh-web.sh: restart dsh web with its original command line
cordis.patch.yml   bundle patch: inserts the plugin into a profile composition

No build step — edit lib/client.js, restart dsh web, hard-refresh.

❓ FAQ

Q: Relationship with dsh-hotkeys? A: This plugin borrowed the bundle-plugin shape and conventions from ctenni/dsh-hotkeys but focuses on one thing: automatic per-device key-binding switching. No recording — the device is the switch. The two can coexist.

Q: Phones have no Ctrl key — how do I press Ctrl+Enter? A: Tablets with keyboards and phones with external keyboards work out of the box; soft-keyboard-only users can turn the mobile mode off in Settings, or wait for a future "custom mobile send key".

Q: Does the ask_user_question card input change? A: No. Its Enter means "submit/continue" and is unrelated to the composer; the plugin does not touch it.

Q: I don't see the toggle in Settings. A: Make sure dsh-mobile-keys is listed in dsh.profile.bundles, dsh web was restarted, and the browser was hard-refreshed; window.__dshMobileKeys should resolve in the console.

📄 License

MIT

Content from the project README on GitHub ↗

Links

More in this category

View the whole category →

Community comments

Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.