DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

lion231226 /

lion231226/dsh-skill-router

Verified

Search, load, archive and promote DSH skills without paying their context cost · DSH 技能路由器

★ 1 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@9594c152

dsh-skill-router

English | 中文

A DeepSeek Harness plugin for the problem nobody warns you about: the skill catalog is announced in full, every session.

DSH injects a name + description line for every model-invocable skill. That is the right design — the model can only pick a skill it can see — but the cost grows linearly and silently. On one real profile measured here (2026-11-13):

model-invocable skills in the catalog 573
characters per request 161,761 (≈ 43k tokens)
skills actually invoked in 1,557 sessions 32 (5.6 %)
share of catalog characters spent on never-invoked skills 94.2 %

The obvious fix is to mark long-tail skills disable-model-invocation: true. That works — until you discover the two side effects:

  1. The model can no longer see them at all. Nothing tells it that a page-layout skill exists, so it writes the page from scratch.
  2. The built-in skill tool refuses to load them. It requires modelInvocable, and archived skills are not. You get skill "x" is not available for model invocation.

This plugin closes both gaps.

What it does

Tool Behaviour
search_skills(query, limit?) Searches an index of archived skills. Results carry the upstream source when known (owner/repo#ref @sha). Chinese keywords are expanded through a small alias table, so 幻灯片 finds html-ppt.
load_skill(name, max_chars?) Reads any skill body by name, ignoring the invocation policy, so archived skills load exactly like catalog ones.
rebuild_skill_index(include_catalog?) Rescans the local skill roots, records which skills are archived, attributes them to their upstream repository, and rewrites ~/.dsh/skills-INDEX.json + .md. No external script.
archive_skills(names, reason?) Adds disable-model-invocation: true to the frontmatter and writes a ledger entry. Idempotent.
restore_skills(names) Removes that line again — but only if the file still matches the hash recorded at archive time. If you edited the skill afterwards, it refuses instead of overwriting.
promote_skill(name, project_root?) Copies a skill into <project>/.dsh/skills/<name>, where it is announced only inside that project. Refuses if the target exists, or above 2000 files / 50 MB.
demote_skill(name, project_root?) Removes that copy again. It only deletes a directory the ledger says this plugin created.

archive + restore are a pair; promote + demote are a pair. Nothing deletes a skill.

How it works

  • The index only contains skills that are already archived, so it is roughly the long tail and nothing else.
  • load_skill reads SKILL.md directly. It does not go through the tool that enforces the invocation policy — that is the whole point.
  • The ledger lives at ~/.dsh/skill-router/ledger.json and records beforeSha256 for every archive, which is what makes restore safe.
  • Skills shipped by other plugins live inside their packages, have no SKILL.md under a skill root, and therefore cannot be archived. search_skills will not find them either; disable the plugin if you want them gone.

Install

From GitHub:

dsh plugin --profile <profile> add github:lion231226/dsh-skill-router

Or through the app: Settings → Plugins → install from a package / GitHub source.

On DSH Desktop the profile is managed by the app — install it from the app's plugin manager rather than the CLI, which would target a different profile.

Quick start

  1. rebuild_skill_index once, so the index reflects your machine.
  2. archive_skills("html-ppt, card-xiaohongshu, gsap-core") — or archive whatever you never use.
  3. Ask for something those skills cover. The model sees skill-librarian in its catalog, calls search_skills, then load_skill.
  4. If you need one back in the catalog permanently: restore_skills("html-ppt").

Recommended companion: keep one small skill in your catalog whose description states that an index exists and when not to search it (pure arithmetic, common knowledge, one-file edits). Without that line the model has no reason to believe anything is missing. The plugin's own skill-librarian skill is that line.

Safety

  • No deletions. Archive and restore only add or remove one frontmatter line; promote and demote only copy or remove the copy the ledger recorded.
  • Restore refuses on drift. If a skill changed after archiving, restore_skills reports it rather than overwriting your edit.
  • Promote is bounded. 2000 files / 50 MB per skill, and an existing destination is never replaced.
  • No network. Nothing is fetched, no telemetry, no credential access.

Tests

npm test

27 assertions across three files: plugin wiring with a mock context (7 tools register, required parameters normalise correctly, disposers release), index/manage logic in temp directories (iteration, hash-checked restore, tamper refusal, promote/demote, limits, ledger backfill), and search quality against a real 448-entry index.

Compatibility

  • Host: dsh >= 0.2.0-rc.1. Host-only plugin — no browser UI, no client bundle.
  • Reads ~/.dsh/skills-INDEX.json; falls back to ~/.dsh/skills-INDEX.md.
  • @deepseek-ai/dsh-tools is imported at runtime but deliberately not declared as a dependency: declaring it would let pnpm hoist a second copy into the profile, and a stale copy shadowing the host's own is the classic way a DSH plugin breaks an entire profile. The host provides it.

License

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit 9594c152760f

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout