dsh-plugin-development
Skill1 starsChanged 3 months agoMITView on GitHub
Design, implement, debug, review, package, and deploy plugins for DeepSeek Harness (DSH) and its Cordis runtime. Use whenever work touches a DSH plugin, Tool, Code Mode call, session replay, client slot, profile/bundle patch, out-of-tree package, dynamic service injection, blank details panel, or a plugin that works in a monorepo but fails after installation. Use it even when the request only says “add a tool”, “show a card”, or “install this plugin”, because those changes cross DSH's runtime, data-projection, and packaging boundaries.
5 other projects use a version of this.
Adopted by
Most recently taken up by
- NanmiCoder/dsh-agent-teamstheir own version, first seen Oct 8, 2026
- GZX2211/dsh-Visual-Workflowtheir own version, first seen Sep 24, 2026
- Practice019/agent-skillstheir own version, first seen Sep 9, 2026
- striveh/dsh-plugin-developmenttheir own version, first seen Aug 21, 2026
- RayYeung1989/dsh-plugin-developmenttheir own version, first seen Aug 14, 2026
Other versions5 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 5
- NanmiCoder/dsh-agent-teams★ 2.8ksame name
- GZX2211/dsh-Visual-Workflow★ 59same name
- RayYeung1989/dsh-plugin-development★ 2same name
- Practice019/agent-skills★ 0same name
- striveh/dsh-plugin-development★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
The file
Show its rules and text
We split this skill into the rules it gives an agent
19 rules. About 0 are common, 17 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈17
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 16
Treat a DSH plugin as a dynamically mounted capability, not as a static module import.
- Distinctive: line 92
Do not call every representation “the Tool result”.
- Very specific: line 121
Treat output.schema as a programmatic API and validate real representative responses against it.
- Very specific: line 123
Keep render bounded. It determines what the model reads.
- Distinctive: line 125
Keep presentation functions pure: no network, clock, randomness, mutation, or hidden process state.
- Distinctive: line 146
keep bounded atomic reads/updates with explicit filters and cursors.
- Distinctive: line 147
put exact aggregation next to authoritative data and tenant filtering.
- Distinctive: line 148
add a high-level Tool owning pagination, joins, limits, capacity, and fallback.
- Distinctive: line 160
Before writing a strict Tool schema, compare:
- Distinctive: line 163
read-only deployed behavior when deployment drift matters.
- Distinctive: line 180
Do not default to a generic object inspector.
- Distinctive: line 187
Use server paging/search and bounded DOM rendering for large collections.
- Distinctive: line 189
Do not let parallel Tool results compete to auto-open one details panel.
- Distinctive: line 192
Verify a keyed details slot through the mounted chain:
- Distinctive: line 238
Run the bundled checker:
- Distinctive: line 254
Verify headless activation and later arrival of optional providers.
- Distinctive: line 257
Verify bounded DOM, paging/search, media, empty/error states, and scope lifetime.
- Distinctive: line 262
Do not claim success from unit tests, SSR, or one direct Tool call alone.
- Distinctive: line 267
Read references/failure-atlas.md when symptoms are confusing.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
DSH Plugin Development
Treat a DSH plugin as a dynamically mounted capability, not as a static module import. Correctness has five independent dimensions:
- capability graph — Cordis can activate, suspend, reload, and dispose it;
- Tool contract — Code Mode receives a lossless typed value;
- projections — the model, UI, and durable log receive purpose-built views;
- product surface — the user sees a decision rather than implementation data;
- installation closure — a clean profile resolves built host and client code.
Most hard DSH failures are mismatches between these dimensions. Diagnose the boundary before changing the symptom.
Inspect the installed architecture first
Locate the actual DSH version and a working plugin from the same version. APIs and UI seams can move between releases.
rg -n 'defineTool|presentationMeta|presentResult|code-dispatch|tool.details|dsh\.client|dsh\.bundle' \
<dsh-checkout> <plugin-root>
dsh --profile <profile> --dump-configEstablish:
- the provider and consumer of every injected service;
- the plugin's activation state and disposer path;
- the canonical output schema, renderer, and UI presenter of every Tool;
- whether calls are top-level or nested inside Code Mode;
- which session event makes an outcome durable and replayable;
- the owner props and keyed slot used by the mounted UI;
- the profile layers, built exports, and runtime peer resolution;
- the real upstream API scope, pagination, and error contract.
Why: a locally plausible implementation may stay pending, disappear on replay, or fail only when installed outside the source workspace.
Model Cordis as a live capability graph
A plugin provides apply(ctx) and may declare inject. ctx is a live graph,
not a service locator initialized once at boot.
export const inject = ['tools']
export function apply(ctx: Context) {
const dispose = ctx.effect(
() => ctx.tools.register(tool),
'register example tool',
)
ctx.inject(['webServer'], httpCtx => {
httpCtx.effect(() => httpCtx.webServer.register(route), 'register route')
})
return async () => dispose()
}injectdeclares a capability requirement. The plugin may remain pending until the provider appears; YAML order alone does not prove activation.- Register routes, listeners, Tools, and child plugins through reversible effect scopes. Unload, failed activation, and HMR should restore the previous graph.
- Dynamically inject optional services. A headless Tool plugin should not fail merely because a browser server is absent.
- Identify the event mode. Around/waterfall hooks call
next()unless replacing downstream behavior intentionally. - Preserve stable identity for configuration rows so reconciliation can update instead of destroy-and-recreate.
Why: DSH can change its provider graph while the process and session remain alive. Startup-only assumptions produce leaks, invisible pending plugins, and HMR behavior that differs from a clean boot.
Design one result and four projections
Do not call every representation “the Tool result”. Write this table before implementation:
| Representation | Consumer | Required property |
canonical value | Code Mode and programs | lossless, typed JSON |
rendered content | model context | bounded and task-relevant |
presentationMeta | top-level live/replayed UI | pure, replayable projection |
| durable nested projection | Code Mode replay/UI | explicit, bounded session event |
Return exactly one canonical value satisfying output.schema. Do not return UI
blocks or explanatory prose as the canonical value.
defineTool({
name: 'example_plan',
parameters: inputSchema,
output: {
schema: outputSchema,
render: (_args, value) => [{
type: 'text',
text: JSON.stringify(toModelProjection(value)),
}],
},
execute: async args => buildCanonicalResult(args),
presentationMeta: (_args, value) => toUiProjection(value),
})- Treat
output.schemaas a programmatic API and validate real representative responses against it. - Keep
renderbounded. It determines what the model reads; it is not the canonical storage format. - Keep presentation functions pure: no network, clock, randomness, mutation, or hidden process state. They also run during replay.
- Bound UI metadata independently from canonical data. Details can fetch pages.
- Assume nested Code Mode calls may skip the top-level presentation path. If the outcome must survive replay or drive UI, project it explicitly through the Code-dispatch logging seam.
- Change generic spill/truncation only after identifying which representation crosses that boundary. A bounded business result often solves the problem before storage does.
Why: programs, model context, session history, and visual presentation have different budgets and lifetimes. One shared JSON/text payload creates schema errors, context growth, replay loss, and blank views.
Keep atomic Tools, add one business operation
Atomic Tools are useful for composition and diagnosis. They should not force the model to become a pagination engine or distributed query planner.
For workflows over many records:
- keep bounded atomic reads/updates with explicit filters and cursors;
- put exact aggregation next to authoritative data and tenant filtering;
- add a high-level Tool owning pagination, joins, limits, capacity, and fallback;
- return business entities, ordered decisions, and gaps—not intermediate cells;
- separate preview from mutation for inventory, money, publishing, or claims.
The model chooses intent and constraints. The high-level Tool executes the data plan. The UI visualizes the decision.
Why: model-driven full scans are expensive and easy to leave incomplete. They also leak infrastructure language into the user's task.
Audit upstream contracts from three sources
Before writing a strict Tool schema, compare:
- the current service implementation and response model;
- read-only deployed behavior when deployment drift matters;
- the consuming product's real ownership and scope semantics.
Resolve disagreements explicitly. Do not infer a production API from a CLI catalog or a neighboring repository type. Credential reuse and capability transport are separate: a plugin can reuse an existing credential store while calling a typed HTTP API directly.
For large lists, require stable pagination metadata. For summaries, prefer a server aggregate whose totals do not change with the display page. Fallback only on a specific compatibility signal; propagate authorization, validation, and server failures.
Why: strict schemas expose drift early only when they describe the real boundary.
Build UI from the user's decision
Do not default to a generic object inspector. Start with the question the user must answer after the Agent finishes.
- The chat card states outcome, scope, and important exceptions.
- Details show the smallest visual object needed to inspect or adjust the result.
- Hide internal Tool names, JSON fields, IDs, pagination, and technical statuses unless the user is debugging.
- Use server paging/search and bounded DOM rendering for large collections.
- Provide a browser-authorized media path, not merely a server-side URL string.
- Do not let parallel Tool results compete to auto-open one details panel. Use an explicit selection action when multiple results can settle out of order.
Verify a keyed details slot through the mounted chain:
card click
→ actual ToolCall owner
→ selection / openDetails
→ shared details layout
→ keyed renderer
→ useful plugin view or generic fallbackPre-session defaults and per-session pinned state have different lifetimes. Put their controls in the corresponding new-conversation and session-header seams.
Why: an isolated component can render correctly while the real shell never passes it a selected owner. DSH UI correctness is composition correctness.
Make replay an execution mode
The durable session log reconstructs model context and UI. “Visible now” does not mean “visible after reload”. Test:
- a direct top-level Tool call;
- the same Tool nested inside Code Mode;
- reload/replay after completion;
- unload/reload or HMR;
- interrupted and failed calls.
Persist bounded business projections without credentials. Replay must not depend on the original network response, in-memory value, clock, or component state.
Why: top-level and nested calls travel through different presentation paths, and replay has access only to durable events.
Package as if the monorepo does not exist
Host and browser client are separate runtime halves:
- host
main/exports point to built Node output; ./clientpoints to built browser output whendsh.clientis declared;- the bundle patch inserts the host plugin in the intended tree;
- client injection lists runtime/UI dependencies;
- peers resolve from the installed plugin/profile, not a source checkout;
- production starts the built DSH CLI rather than a source loader;
--dump-configproves the plugin is mounted where expected.
Run the bundled checker:
node <skill-root>/scripts/check-plugin-closure.mjs <plugin-root>Then pack/install the plugin into a clean temporary profile and boot it without
the monorepo's node_modules on the resolution path.
Why: workspaces hide undeclared peers, missing browser builds, wrong archive roots, and source entrypoints that cannot resolve in production.
Verification ladder
- Typecheck and validate canonical schemas against representative responses.
- Activate and unload under Cordis; verify every registration disappears.
- Verify headless activation and later arrival of optional providers.
- Exercise top-level, Code Mode, replay, failure, and large-result projections.
- Exercise browser click → details → useful non-empty visual output.
- Verify bounded DOM, paging/search, media, empty/error states, and scope lifetime.
- Boot a clean built profile and inspect
--dump-config. - Then verify reverse proxy, authentication boundary, persistent DSH home, and restart behavior in deployment.
Do not claim success from unit tests, SSR, or one direct Tool call alone. Report which execution modes and installation boundaries were actually exercised.
Diagnose by boundary
Read references/failure-atlas.md when symptoms are confusing. It maps field failures to their incorrect mental model and the evidence that distinguishes them.
Handoff
Report:
- capability graph and optional dependencies;
- canonical/model/UI/durable projections;
- upstream scope and pagination evidence;
- atomic Tools versus the high-level business operation;
- direct, Code Mode, replay, and mounted-UI results;
- clean-profile package result and dumped plugin tree;
- remaining host seam or deployment prerequisite.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

