nianchen8/dsh-skill-panel
DeepSeek Harness Web 应用的技能管理面板
项目介绍Project Overview
dsh-skill-panel 是 DeepSeek Harness 网页端的技能管理插件,可在设置页或侧边栏浏览、搜索、筛选技能,切换模型/用户调用、禁用启用、卸载,并创建技能分组。它基于官方插件接口,读取当前会话技能目录,写入会改写 SKILL.md 前置元数据或删除目录。适用于集中管理多来源技能;注意卸载会删除技能目录,内置技能受保护,需 Harness 0.1.0-rc.6+。
dsh-skill-panel is a skill-management plugin for the DeepSeek Harness web app. It adds a settings page and sidebar panel for browsing, searching, filtering, enabling or disabling, uninstalling, and grouping agent skills, with model/user invocation switches. It uses the public plugin surface and session-scoped skill catalog; writes rewrite SKILL.md frontmatter or delete skill directories. Use it to manage skills centrally; note uninstall deletes directories, bundled skills are protected, and Harness 0.1.0-rc.6+ is required.
请帮我了解并安装插件:【dsh-skill-panel】【https://github.com/nianchen8/dsh-skill-panel】
把上面这条消息直接发给当前会话里的 DSH,让它帮你了解并安装。安装命令不一定准确,发给 DSH 更稳。Send this message to DSH in your current session. CLI install commands may not be accurate across systems — DSH will figure it out for you.
或使用命令行安装(适合开发者)Or use CLI install (for developers)
命令行安装CLI Install
dsh plugin --profile web add dsh-skill-panel
把 nianchen8/dsh-skill-panel 加入你的 DSH 配置(web profile)即可启用。
READMEREADME
dsh-skill-panel
A skill management panel for the DeepSeek Harness web app: browse, search, filter, enable/disable, and uninstall your agent skills from the settings page or the sidebar.
Built entirely on the harness's public plugin surface — a Typert Remote service on the host half, slot-registered React UI on the browser half. No forks, no internal APIs, no build step (pure JS); runtime imports are limited to the harness-provided @deepseek-ai/dsh-storage-domain and zod (declared as dependencies).
Features
- Skill list with name, description, source label, and per-source counts
- Search and source filtering (user
.agents, user.dsh, project roots, custom, bundled) - Model / User invocation switches (rewrites the SKILL.md frontmatter; unspecified switches are preserved)
- Disable / Enable button — fully disables a skill while remembering its previous state, and restores exactly that state on enable
- Uninstall with two-step confirm (deletes the skill directory, bundled skills are protected)
- Detail view with
whenToUse, on-disk path, and the SKILL.md body - Skill groups — create / rename / delete groups, manage membership per group (add / remove skills), browse skills grouped; persisted through the official
ctx.storageDomain(no self-made storage files) - All reads are session-scoped — the panel shows exactly the catalog your current session serves
- Writes invalidate discovery synchronously, and the slash-menu cache is refreshed through the official forwarded events
Requirements
- DeepSeek Harness
0.1.0-rc.6+(web profile) - pnpm available (
corepack enableprovides it)
Install
corepack enable # once per machine
dsh plugin --profile web add dsh-skill-panel # from npm
# or: dsh plugin --profile web add github:nianchen8/dsh-skill-panel
dsh web # restart to load the package
The panel then appears under Settings → Skills and the sidebar's Skills button.
How it works
SKILL.md files (project / user / bundled roots)
│ discovery (skill-filesystem providers, layered per scope)
▼
host skill registry ── snapshot({cwd, scope: agent}) ──► SkillPanelService (Typert Remote)
▲ │ /api/skillPanel/*
│ fs/observed invalidation ▼
└── frontmatter writes / deletions browser client (fetch RPC)
│ slots.register
▼
Settings page · sidebar button · overlay
- Host half (
index.js): aTypertRemoteServicewith twelve Remote endpoints —getConfig,listDetailed,getDetail,setInvocation,setDisabled,uninstall, plus the group CRUDgroupList,groupCreate,groupUpdate,groupDelete,groupAddSkill,groupRemoveSkill. Reads resolve the session-scoped skill view (same catalog the model sees); writes rewrite SKILL.md frontmatter or delete the skill directory, then emitfs/observedfor synchronous discovery invalidation and replayagent-preset/selectedso the official slash menu drops its cached catalog. Groups live in actx.storageDomaindomain (skill_groups), opened lazily and closed on unload; when storage is unavailable the panel degrades to a read-only group view. - Browser half (
client.js): plain React via the platform module table, registered intosidebar.footer.action,shell.overlay, andsettings.section. All data crosses the standard API gateway over/api/skillPanel/<method>.
Placement configuration
The three UI entries (sidebar button, overlay, settings page) default to the tail of their slot: at registration the browser half reads the slot's live entries and places itself after the largest existing order, so a fresh deployment always lands at the bottom of the list regardless of how many entries already occupy the slot.
Arrival semantics (why same-strategy plugins don't fight): the tail order is computed once at registration — the browser half never re-registers after it arrives. Each registration is an atomic read→compute→register, so the next arrival always sees the previous one and appends strictly after it (max + 1, no ties). Once an entry lands, its position is fixed; if it later unloads and comes back (fiber restart), it re-appends at the tail again. Two plugins using this identical strategy therefore coexist as A(0), B(1), C(2), … with the latest arrival always last — no chasing, no livelock.
Each entry can be individually overridden through the loader entry's config in the profile composition (profiles/<name>/cordis.patch.yml):
- id: skill-panel
config:
entries:
sidebar:
enabled: true # show the sidebar button (default true)
order: 5 # explicit position; omit = dynamic tail
# slot: conversation.session.header.actions # optional relocation
overlay:
enabled: true
order: 10
settings:
enabled: false # hide the settings page
enabled— whether the entry registers at all.order— exact ascending position in the slot; absent means dynamic tail (max existing order + 1at registration time).slot— target slot key; omit for the built-in seats above. When relocating, the component degrades gracefully to the props the new slot provides (useSessions/wideare optional in the panel code).
The resolved placement is exposed to the browser through skillPanel/getConfig; if the endpoint is unavailable (e.g. before a restart), the browser half falls back to the defaults above.
Development
The package is pure JavaScript; edit index.js / client.js, then restart dsh web (the client bundle is rescanned at boot).
node --check index.js client.js
npx oxlint --deny-warnings index.js client.js
License
MIT
nexu-io/open-design
freestylefly/awesome-gpt-image-2
anywhere-labs/dsh-desktop
walkinglabs/learn-harness-engineering
awesome-dsh-plugin/awesome-dsh-plugin
MemTensor/MemOS