AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Dsh Plugin Development

skill-rayyeung1989-dsh-plugin-development-dsh-plugin-development · by RayYeung1989

Use when developing, modifying, debugging, installing, or verifying a dsh plugin (DeepSeek Harness plugin / dsh插件 / DSH插件) — a Cordis plugin package that runs inside DeepSeek Harness profiles (web / headless / custom). Triggers include "开发dsh插件", "写个dsh插件", "给DSH写插件", "deepseek-harness插件", extending the DeepSeek Harness WebUI (theme, sidebar, settings pages, tool cards, chat UI), hooking host beh…

No reviews yet
0 installs
21 views
0.0% view→install

Install

$ agentstack add skill-rayyeung1989-dsh-plugin-development-dsh-plugin-development

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-rayyeung1989-dsh-plugin-development-dsh-plugin-development)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Dsh Plugin Development? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Develop DeepSeek Harness (dsh) Plugins

Build, install, and debug dsh plugins: npm packages whose Cordis plugin entries extend a DeepSeek Harness profile. This skill works from any agent runtime (Claude Code, Codex, Hermes, OpenClaw, …) using only file + shell tools — it does not assume DSH-internal tools.

Ground truth first (golden rule)

Never invent the API. Before writing code, read the real interfaces:

  • Installed packages: .d.ts files under the dsh installation. Find it with node -p "require.resolve('@deepseek-ai/dsh/package.json')" — if that throws MODULE_NOT_FOUND (global install not on the resolution path), use readlink -f "$(which dsh)" and walk up to the @deepseek-ai/dsh package dir, or npm root -g. The whole @deepseek-ai/* surface lives in that package's node_modules. Read lib/types/**/*.d.ts of the exact package (e.g. @deepseek-ai/dsh-session, @deepseek-ai/dsh-llm) for the service/event surface of the installed version.
  • Composed profile tree: dsh web --dump-config (with the user layer) and dsh web --dump-default-config (bundle layers only). Note: dumps rewrite the profile's cordis.yml, so on a read-only $DSH_HOME they fail with EROFS — then read the profile files and installed patch files directly.
  • CLI surface: dsh --help, dsh --version, dsh web --help.
  • Source repo: . Every package's package.jsonrepository.directory points to its source dir (e.g. apps/cli, packages/bundle/base, packages/session/...).

Architecture in one screen

  • DSH is a Cordis plugin framework. A profile (e.g. web) is $DSH_HOME/profiles/ whose package.json declares dsh.profile.bundles — an ordered list of plugin-bundle layers (web = @deepseek-ai/dsh-base + @deepseek-ai/dsh-web-app).
  • Each bundle contributes a patch (cordis.patch.yml). The composed tree is: bundle patches in bundles order → profile cordis.patch.yml$DSH_HOME/cordis.patch.yml--patch overlays.
  • Rows are addressed by id; the last write wins per row; a patch replaces the row's whole config (no merging). - id: addresses an existing row; - insert: adds new rows.
  • A dsh plugin is any npm package a patch row's name: points at. It has a host half (Node: services, events, tools, side effects) and optionally a browser half (Web UI/theme) declared with dsh.client in its package.json.

Standard workflow

  1. Locate install & target profileecho $DSH_HOME, dsh --version, ls $DSH_HOME/profiles. Confirm which profile the plugin targets (web for the GUI, headless for CLI runs).
  2. Inspect the composed treedsh web --dump-config. Find the row id to add or override; copy the shape of a similar existing row.
  3. Decide host vs client (table below). Prefer the side closest to the data owner; a pure-UI plugin keeps its host half a no-op carrier.
  4. Scaffold from templates/ in this skill.
  5. Write code against real surfaces — read the installed .d.ts of every service/event you touch (sessions, llm, timer, theme, slots, …). See references/services-events.md.
  6. Register + install — patch row (- insert: for a new row, - id: to override) + dsh plugin --profile web add (local path, file:, link:, github:user/repo#tag, or registry name).
  7. Verify (loop)dsh web --dump-config shows your row; boot dsh web; client plugins appear as rows in WebUI 设置 → 插件管理; server behavior via a dsh --profile headless "..." smoke run or session logs.
  8. Debug with the failure table below.

Host vs Client

| Want to … | Side | Key services / entry points | | --- | --- | --- | | Files, processes, network, timers, sessions, LLM, dynamic model tools | Host | sessions, llm, agents, skills, subagents, settings, credentials, fs, sandbox, approval, timer | | Hook conversation lifecycle (turn / step / message events) | Host | ctx.on('turn/end' | 'user/message' | 'assistant/message' | 'step/start' | …) | | Page theme, layout, sidebar, settings pages, tool cards, chat UI | Client | theme, slots, modules, settings, remote | | Host data shown on the client | Both | Host service/event + client slot; RPC via the typert gateway (ctx.remote, see references) |

Plugin anatomy (minimal)

Host-only entry (lib/index.js, ESM — "type": "module"):

import z from '@deepseek-ai/schemastery'

export const name = 'example-turn-logger'
export const inject = ['timer']                 // hard dependencies only
export const Config = z.object({                // validated against the patch `config:`
  greeting: z.string().default('hi'),
})

export function apply(ctx, config) {
  ctx.on('turn/end', (payload) => {
    // verified payload (dsh 0.1.0-rc.6): { turn: number, reason: TurnEndReason }
    // re-check the installed @deepseek-ai/dsh-session/lib/types/types.d.ts first
    console.log(config.greeting, payload.turn, payload.reason.kind)
  })
  ctx.effect(() => ctx.interval(() => console.log('tick'), 60_000))
}

The Loader also accepts a default-export function/class (a class constructed with (ctx, config) and calling super(ctx, '') publishes a Service) or a default-export object { apply, name?, inject?, Config? }.

Client half (lib/client.js, plain JS — no import/JSX/TS) plus the manifest in package.json:

"dsh": { "client": { "platform": "web", "inject": ["@deepseek-ai/dsh-client-ui-theme"], "immediately": true } },
"exports": { "./client": "./lib/client.js" }
window.__ModuleLoader__.load({
  id: 'example-client',
  factory: (require) => {
    var module = { exports: {} }
    var exports = module.exports
    exports.apply = (ctx) => {
      const theme = ctx.get('theme')
      if (theme !== undefined) {
        ctx.effect(() => theme.overrideTokens('example', {
          '--dsw-alias-brand-primary': { light: '#c96442', dark: '#d97757' },
        }))
      }
    }
    return module.exports
  },
})

Rules (violations fail at load or render)

  • ESM only on the host; plain JS only in the browser half (no import, JSX, TypeScript, decorators). Browser UI must use React.createElement (React arrives via require('react')).
  • Optional services: ctx.get('x') with an absence check. Declare inject: ['x'] only for hard dependencies, or you get service "x" is not declared / cannot get property "timer" without inject.
  • Every listener, subscription, timer, and token override must be disposable and owned inside apply (ctx.on(...), ctx.effect(() => disposer), retained disposers). No module-scope side effects, no process/page-wide globals.
  • Host↔client values must be JSON-safe. Never JSON.stringify/structuredClone live Service / Session / Event / Slot objects — extract the scalar leaves you need.
  • A patch config: replaces the whole row config; use !!js expressions for dynamic values (!!js process.env.X, !!js ctx.webStartup.port ?? 3080, !!js dshHomePath('sessions')).
  • Client plugins need a full page reload after install. HMR auto-reload only exists while the pnpm run dev:web watcher rebuilds client bundles.
  • Install client-only and dual-half packages with the dsh.client manifest and a ./client export, or the browser half is never served.

Common failures

| Symptom | Check first | | --- | --- | | Row missing / plugin not loaded | dsh web --dump-config; row id/name correct; package resolvable (two-anchor resolution: profile node_modules, then the flat fallback $DSH_HOME/profiles/node_modules) | | service "x" is not declared | ctx.x used without inject; switch to ctx.get('x') or declare the hard dependency | | cannot get property "timer" without inject | Timers are a Service, not a global: declare inject: ['timer'] | | Config validation error at boot | schemastery Config vs patch config mismatch; --dump-config shows the composed value | | Client half never appears | dsh.client malformed (platform string, inject string[], immediately boolean), missing ./client export, or no page reload | | Client render error | Browser console; JSX/TS/import/Node globals in lib/client.js | | Plugin loads but has no effect | Event names / payloads drift per DSH version — re-read the installed .d.ts | | Dependency resolution error | The import isn't resolvable from the profile; either it is not an in-box package (declare it in dependencies, pnpm installs it) or the package is not installed |

Installing this skill into an agent runtime

Copy this folder into the runtime's skills directory:

  • Cross-runtime (Codex, Copilot CLI, Gemini CLI, and DSH itself scan it): ~/.agents/skills/dsh-plugin-development/
  • Claude Code: ~/.claude/skills/dsh-plugin-development/
  • DSH home: $DSH_HOME/skills/dsh-plugin-development/
  • Hermes / OpenClaw / others: drop the folder wherever that tool scans for SKILL.md (e.g. Hermes plugin dirs, OpenClaw skill dirs).

References & templates

  • references/plugin-package.md — full package / entry / manifest / patch / CLI contract, verified against dsh 0.1.0-rc.6.
  • references/services-events.md — service & event surface and how to enumerate it at runtime.
  • templates/server-plugin/ — host-only starter (Config + events + timer).
  • templates/client-plugin/ — browser-only starter (theme token override + CSS, theme-proven pattern).
  • templates/dual-half-plugin/ — host service + browser UI starter with RPC notes.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.