dsh-skill-picker-english
v0.2.0
Published
DSH Web GUI skill picker: a button beside the composer opens a searchable list of installed skills; picking one inserts the official `/skill-name` gesture into the input box, so the skill loads with your message (WorkBuddy-style skill invocation for DeepS
Readme
dsh-skill-picker-english
Can't remember skill names? The official
/completion relies on prefix memory — who can remember them all once you have dozens installed? This plugin makes skills visible, searchable, and quick to pick — click ⚡ and every skill with its description is laid out in front of you: search, click, insert, and it loads automatically with your message.
A skill picker for the DSH Web GUI: a button in the composer's right tool row opens a searchable list of installed skills; picking one inserts the official /skill-name gesture into the draft, so DSH's native mechanism loads the skill and executes it with your message. WorkBuddy-style "write the skill into the message box" interaction, recreated for DeepSeek Harness.
Why use it (vs the official / completion)
The official / skill completion is built in, but it's memory-driven — you have to remember the skill name first, then type / plus a prefix to filter it out. Once you have many skills, that falls apart:
| | Official / completion | dsh-skill-picker-english |
|---|---|---|
| Trigger | Type / in the input box | ⚡ button beside the input box |
| Discovery | Prefix memory-driven — forgotten names are unfindable | Full-list browsing + keyword search — you can browse even if you forgot the name |
| Sorting | Fixed | Recently used on top, frequent ones first |
| Description | Truncated | Full description at a glance |
Know the name? Use the official one. Forgot it? Use this plugin — the two complement each other and can be used together.
Features
- ⚡ One click pops up every skill (lightning icon, instantly understandable)
/completion: typing a slash lists all skills, with fuzzy search (any match on name + description) + frequent-first ordering (v0.2.0)- 🔍 Real-time search (searches both skill names and descriptions)
- 🧠 Smart ordering: recently used on top, frequent ones first (same as WorkBuddy)
- 📋 Uses the official host skills API (same data source as DSH's built-in
/completion; automatically covers user-level + project-level skills) - 🧩 Inserts the official
/skill-namegesture; loading/execution go through DSH's native mechanism — zero agent-side changes - 🎨 Follows the Web UI theme (CSS variables), light/dark adaptive
- 📦 Pure client + host dual-half plugin, no third-party runtime dependencies
Installation
# Method 1: GitHub clone + link (recommended; no npm publishing needed)
git clone https://github.com/a735624258/dsh-skill-picker-english.git
dsh plugin --profile web add link:/path/to/dsh-skill-picker-english
# Method 2: Install directly from Git
dsh plugin --profile web add "github:a735624258/dsh-skill-picker-english"
# Method 3: After publishing to npm (prebuilt install, best experience)
dsh plugin --profile web add dsh-skill-picker-englishNote: not yet published to npm (
npm view dsh-skill-picker-englishwill 404) — use method 1 or 2. If thedshcommand is blocked by the PowerShell execution policy (File ... cannot be loaded), use:powershell -ExecutionPolicy Bypass -Command "dsh plugin --profile web add link:C:\path\to\dsh-skill-picker-english"
Takes effect after restarting dsh web (or refreshing the page to load the new bundle).
Usage
- Open any session and find the ⚡ button on the right side of the input box's tool row
- Click it to pop up the skill list (you can type keywords to filter)
- Click a skill →
/skill-nameappears in the draft automatically - Continue typing your message and send — DSH recognizes the
/skill-namegesture, automatically loads the skill, and executes its instructions
Example: after picking review-multiple-choice, the draft becomes /review-multiple-choice grade these multiple-choice answers, and the skill loads automatically when sent.
How it works
DSH's dsh-tool-skill scans user messages for the /kebab-case-name gesture (SKILL_GESTURE regex) during the agent/pre-step phase; on a hit it injects the matching skill content into the conversation as a skill-invocation — i.e. "writing /skill-name in the user message auto-loads the skill" is an official, existing capability; it just has no UI.
This plugin only adds the UI layer:
[client] ⚡ button → fetch('/dsh-skill-picker-english/skills')
↓
[host] scans user-level $DSH_HOME/skills + project-level <cwd>/.dsh/skills etc. → skill catalog (name + description)
↓
[client] pick → inputActions.setDraft(draft + '/skill-name ')
↓
[DSH] agent/pre-step recognizes the gesture → auto-loads the skill → executes- Client half: registers into the official
conversation.input.rightslot (the control seat in the composer tool row, left of the send button); the skill list prefers the official host skills API (connection.api.skills.list— same source as DSH's built-in/completion, session-scoped, automatically includes user-level/project-level skills), falling back to the host scan route on failure; inserted text goes through the framework input machine'sinputActions.setDraft(a single path — undo/draft persistence handled automatically); recent/frequent ordering is stored in localStorage
Relationship with the official / completion
DSH already ships built-in skill completion: typing / in the input box pops up a skill menu filtered by prefix (e.g. /sk lists skills starting with "skill"). This plugin doesn't replace it — it fills in the gaps of the official approach:
| | Official / completion | dsh-skill-picker-english |
|---|---|---|
| Trigger | Type / in the input box | ⚡ button beside the input box |
| Discovery | Prefix memory-driven — you must remember the name to type it | Full-list browsing + keyword search — you can browse even if you forgot the name |
| Sorting | Fixed order | Recently used on top, frequent ones first (localStorage) |
| Best for | Veterans who remember names | People with many skills, incomplete name recall, or who prefer browsing |
In one sentence: know the name, use the official one; forgot it, use this plugin. They complement each other and can be used together.
Compatibility & notes
- Skill sources: prefers the official host skills API (
connection.api.skills.list— exactly the same data source as DSH's built-in/completion, session-scoped, automatically covering all official directories: user-level~/.dsh/skills, project-level<workspace>/.dsh/skills,<workspace>/.agents/skills, etc.); when the official API is unavailable it automatically falls back to the built-in scan (user-level + project-level directories). Both paths honor theDSH_HOMEenvironment variable. - Not scanned yet:
~/.agents/skillsand custom skill directories (customSkillDirsconfig) — PRs welcome. - Failure protection: the client half uses
ctx.slots.inject(registers only once theconversation.input.rightslot declaration exists; silently skips when the slot is missing, so startup never breaks); the host half wraps its route in try/catch and returns an empty list instead of an error when the scan directory doesn't exist. - Dependency versions: written against the DSH
0.1.0-rc.6API (cordis 4 / web profile standard assembly). If a DSH major-version update changes the API, the plugin's startup log error is the source of truth; uninstall withdsh plugin --profile web remove dsh-skill-picker-englishto roll back.
Development
# Install dependencies (provides esbuild)
npm install
# Build (source src/ → output lib/; client half auto-wraps the __ModuleLoader__ handshake)
npm run build
# Install into the web profile (link mode; source changes take effect immediately)
dsh plugin --profile web add link:$PWD
# Syntax check (the built output)
node --check lib/index.js
node --check lib/client.js⚠️ After changing source code you must
npm run build:lib/client.jsis a build artifact, and the ESM source cannot be loaded directly as a client bundle — the DSH web shell requires client bundles to register in thewindow.__ModuleLoader__.load({ id, factory })CJS handshake format, otherwise startup fails withloaded without registering "dsh-skill-picker-english" via __ModuleLoader__.load. The build script (build.mjs) injects this handshake automatically via esbuild's banner/footer.
Directory structure:
dsh-skill-picker-english/
├── package.json # dsh.bundle.patch + dsh.client declarations + build script
├── cordis.patch.yml # bundle patch: inserts the plugin row into the web profile
├── build.mjs # esbuild build: host ESM + client CJS (__ModuleLoader__ handshake)
├── src/
│ ├── index.js # host half source: /dsh-skill-picker-english/skills route + prompt section
│ └── client/
│ └── index.jsx # client half source: conversation.input.right slot component
├── lib/ # build output (don't hand-edit; generated by `npm run build`)
│ ├── index.js
│ └── client.js
└── README.mdDependencies
- host:
@deepseek-ai/cordis,@deepseek-ai/dsh-host-webserver,@deepseek-ai/dsh-skill,@deepseek-ai/dsh-system-prompt - client:
@deepseek-ai/dsh-client-runtime,@deepseek-ai/dsh-client-ui-slots,react
License
MIT
