Introduction¶
The philosophy of DeepSeek Harness (hereinafter referred to as DSH) is “Everything is a plugin”: Tools, Configs, Services, Events, and middleware must ultimately be integrated as plugins. For those new to plugin development, the difficulty usually isn’t a lack of documentation, but a lack of a minimal example that connects the concepts, runs within a profile, and provides observable output at every step.
Below is an introduction to dsh-plugin-practice. It breaks down the core concepts of plugin development into six progressive lessons. The code accumulates lesson by lesson and is itself a standard DSH Bundle, which can be installed and uninstalled using official commands.
What is this¶
dsh-plugin-practice is maintained by Ri0n72Y and is positioned as a minimal practice repository for learning DeepSeek Harness / Cordis plugin development, version 0.1.0. It is a TypeScript package built from src/ to lib/ using tsdown via the prepare script.
The specific problem it solves is: every concept is implemented as runnable code, providing a complete command chain from building, installing, starting to verification; each lesson has corresponding Agent test statements and expected output, allowing for self-verification after learning.
The repository contains two patch files corresponding to two loading methods: cordis.patch.yml for official Bundles; cordis.dev.patch.yml for overlay mode to load local TypeScript source code directly.
Course Content¶
The current content covers six lessons:
| Lesson | File | Core Concept |
|---|---|---|
| 1 | src/plugin.ts |
apply(ctx), ctx.effect(), disposer, plugin lifecycle |
| 2 | src/workspace-info.ts |
inject = ['tools'], defineTool(), arguments and canonical output |
| 3 | src/configurable-greet.ts |
Config interface, Schemastery, defaults, runtime configuration validation |
| 4 | src/workspace-name-service.ts + src/workspace-name-tool.ts |
Service Provider, Context declaration merging, Consumer / inject |
| 5 | src/workspace-event-* |
typed Events, ctx.emit(), ctx.on(), loosely coupled broadcast |
| 6 | src/workspace-transform-* |
ctx.waterfall(), next(), around middleware, short-circuit |
A few notes:
- Lesson 1’s plugin outputs
[practice-lifecycle] heartbeatevery 5 seconds at runtime, and outputsdisposedupon uninstallation, used to observe the timing of side effects registered byctx.effect()and the cleanup of the disposer. - Lesson 3’s
configured_greettool usesgreeting: Hifrom the Bundle patch, corresponding to Config defaults and runtime configuration validation. - Lesson 4 uses Context declaration merging to customize the
ctx.workspaceNameService. The Provider and Consumer belong to two separate files. - Lesson 6 simultaneously demonstrates the wrapping of around middleware and the short-circuiting of block middleware: input
helloreturnsHELLOafter being uppercased; inputblocked wordsshort-circuits the default handling in the block middleware, ultimately resulting in** BLOCKED **.
Environment Requirements¶
- Node.js
^22.19.0 || >=24.0.0; - pnpm (repository declares
pnpm@11.7.0); dshCLI installed and executable locally.
First run the following command to confirm the CLI is available, then proceed with the subsequent steps:
dsh --help
Local Development and One-Click Deployment¶
Clone the repository and install dependencies:
git clone https://github.com/Ri0n72Y/dsh-plugin-practice.git
cd dsh-plugin-practice
pnpm install
After finishing daily development, execute:
pnpm deploy
deploy is defined in package.json as:
{
"scripts": {
"deploy": "pnpm run prepare && dsh plugin --profile practice add ."
}
}
That is, first build lib/ from src/ using tsdown, then install or update the current checkout into the practice profile. Then start DSH:
dsh --profile practice
If you want to check the final combined configuration first:
dsh --profile practice --dump-config
The default development profile is fixed to practice. Change the name directly by adjusting the deploy script in package.json.
Installing with Official Commands¶
pnpm deploy merely connects the build and official installation commands; plugin installation and profile management are still handled by DSH. You can also skip the local steps and install the Git repository directly:
dsh plugin --profile practice add github:Ri0n72Y/dsh-plugin-practice
This repository is a TypeScript package, and package.json provides a prepare script, so lib/ will be built from src/ automatically after installing via Git. Note that for pnpm 10+, when installing Git dependencies for the first time, you may need to authorize build scripts in the profile’s pnpm-workspace.yaml via allowBuilds.
It can be installed this way because package.json declares the Bundle manifest according to official conventions:
{
"dsh": {
"bundle": {
"patch": "./cordis.patch.yml"
}
}
}
The installation chain is: dsh plugin add reads dsh.bundle pointing to cordis.patch.yml, and the patch then loads the built lib/*.js via package export paths.
Source Development / Overlay Mode¶
If you don’t want to build every time you modify the source code, you can use overlay mode to load .ts files directly. First, replace /ABSOLUTE/PATH/TO/dsh-plugin-practice in cordis.dev.patch.yml with the repository’s actual absolute path, then run:
dsh web --patch /ABSOLUTE/PATH/TO/dsh-plugin-practice/cordis.dev.patch.yml
If running the CLI from the DeepSeek Harness source repository, use:
pnpm dsh web --patch /ABSOLUTE/PATH/TO/dsh-plugin-practice/cordis.dev.patch.yml
Testing After Installation¶
After deploying and starting through the steps above, test the Agent line by line:
Use the workspace_info tool and tell me the current workspace.
Use configured_greet to greet Ada.
Use workspace_name and return only the workspace name.
Use announce_workspace to announce the current workspace.
Use waterfall_demo with input "hello".
Use waterfall_demo with input "blocked words".
Expected behavior:
workspace_inforeturns the current DSH Node process’scwdand directory name.configured_greetusesgreeting: Hifrom the patch, e.g., returnsHi, Ada!.workspace_namegets the directory name via the customizedctx.workspaceNameService.announce_workspaceemits thepractice/workspace-announcedevent, and the listening plugin outputs[workspace-event] announced: <name>in the terminal.waterfall_demo("hello")returnsHELLO;waterfall_demo("blocked words")returns** BLOCKED **.- In the background,
[practice-lifecycle] heartbeatis output every 5 seconds, anddisposedis output upon uninstallation.
The runtime behaviors corresponding to the six lessons can all be observed directly.
Uninstallation and Common Commands¶
Uninstall the plugin:
dsh plugin --profile practice remove dsh-plugin-practice
Common development commands:
pnpm run typecheck
pnpm run build
pnpm run check
pnpm deploy
dsh --profile practice --dump-config
dsh --profile practice
Applicable Scenarios and Notes¶
Suitable for developers who want to get started with DSH / Cordis plugin development, especially those who wish to go through the concepts in the order of lifecycle → Tool → Config → Service → Event → middleware. The repository is small in size, with main dependencies being @deepseek-ai/cordis ^4.0.1、@deepseek-ai/dsh-tools ^0.1.0-rc.5、@deepseek-ai/schemastery ^3.18.1, making it suitable for reading the source code directly.
Notes before use:
- Plugins run with the permissions of the current dsh process. You should check the source code before installing any third-party plugins; the license for this repository is not explicitly declared in the collected materials (the
LICENSEfile is listed in thefilesofpackage.json), and the actual content of the repository shall prevail. - DSH is still in a rapid iteration stage; if there are breaking changes to the API, you should refer to the official development documentation and the current TypeScript interfaces for adjustment, and do not assume the repository code will always be usable.
- The commands in this article use the
practiceprofile uniformly; if there is a conflict with existing profiles or isolation is required, adjust the correspondingdeployscript and the--profileparameter in the installation command.
Conclusion¶
The value of dsh-plugin-practice lies in “runnability”: every concept corresponds to a piece of source code, a test statement, and an expected output, forming a closed learning loop. If you are looking for your first hands-on project for DSH plugin development, you can start here.
- Community Directory Page (independent site, no official affiliation with DeepSeek / Fang Fang): https://www.skillhub.cn/plugins/Ri0n72Y/dsh-plugin-practice
- GitHub Repository: https://github.com/Ri0n72Y/dsh-plugin-practice