A minimal Cordis plugin is a TypeScript module that exports apply(ctx). The following path assumes you already have a built DeepSeek Harness source checkout.
Create the directory
mkdir -p scratch-plugin/src
Create scratch-plugin/src/my-plugin.ts:
import type { Context } from '@deepseek-ai/cordis'
export const name = 'hello-plugin'
export function apply(ctx: Context) {
console.log('[hello-plugin] plugin loaded!')
}
Mount it with a patch
Create scratch-plugin/cordis.yml:
- insert:
- id: hello
name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts'
Replace name with the real absolute path. The patch file’s directory does not change the profile’s module-resolution base.
pnpm dsh web --patch ./scratch-plugin/cordis.yml
Expected terminal output:
[hello-plugin] plugin loaded!
Declare service dependencies
Do not rely on entry order in the configuration file. Declare dependencies with inject:
import type { Context } from '@deepseek-ai/cordis'
export const name = 'my-tool-plugin'
export const inject = ['tools']
export function apply(ctx: Context) {
// ctx.tools is ready here.
}
Clean up external resources
Events and tools registered on ctx are revoked when the plugin unloads. Put external resources such as timers and network connections inside ctx.effect() and return a disposer:
import type { Context } from '@deepseek-ai/cordis'
export function apply(ctx: Context) {
ctx.effect(() => {
const timer = setInterval(() => {
console.log('heartbeat')
}, 5000)
return () => clearInterval(timer)
})
}
Plugin code runs inside the Harness process and lifecycle. Do not load unaudited source, and do not treat a GitHub topic as a security endorsement.
Evidence and revision
Primary sources
This guide is intentionally concise; use the official source or documentation below as the authority for commands, behavior, and risk boundaries.