SponsorLobeHubLobeHubLearn more
dshfind

Lesson 1: What Exactly Is a Plugin?

In one sentence: A DSH plugin is a file that exports an apply function. At startup the framework hands you a universal power strip called ctx; you plug things into it (tools, UI, policies), and everything you plugged in is automatically unplugged when the plugin unloads. That's the whole idea.


1. Start From Plugins You Have Already Met

You have almost certainly used these:

What you've seenWhat it does
Browser extension (ad blocker)Adds a feature to an already-built browser
VSCode plugin (themes, language support)Adds a feature to an already-built editor
A phone appInstalls on top of an already-built phone OS

They share one trait: the body is prebuilt, and the plugin is a patch stuck on the side. A browser extension cannot touch the address bar, the tab strip, or the rendering engine — that is the "core", and it is hardcoded.

DSH is different. There is no untouchable core in DSH.


2. What Makes DSH Different: the Software Itself Is Assembled From Plugins

The first line of the DSH architecture doc reads:

Everything is a plugin, including the loop.

The "loop" is the agent's main loop — the "think a bit → do one thing → think again" cycle. In other frameworks that is the core and cannot be changed. In DSH it is a plugin too, and it can be swapped.

So all of these are plugins, on completely equal footing:

  • Which model you use → a plugin
  • Every tool the model can call → a plugin
  • Where commands run and whether they can touch your files → a plugin
  • Where the chat log is stored → a plugin
  • The web interface you are looking at → dozens of plugins
  • The main loop mentioned above → still a plugin

🎁 Analogy: other frameworks are a finished building — changing the floor plan means knocking down a load-bearing wall. DSH is a box of Lego — any brick can be pulled out and replaced, including the one you thought was the foundation.

That is why DSH plugins can do far more than "browser extensions": you are not decorating a finished product, you are replacing its parts.


3. What a Plugin Looks Like

It really is this small:

import type { Context } from '@deepseek-ai/cordis'

export const name = 'hello-plugin'

export function apply(ctx: Context) {
  console.log('[hello-plugin] plugin loaded!')
}

Three meaningful lines, one at a time:

This lineWhat it says
export const name = ...Names the plugin so you can recognize it in logs when something breaks
export function apply(ctx)The entry point. The framework calls it once when loading you
The ctx parameterYour only channel to the rest of the system — every capability comes from it, every contribution goes onto it

(Source: docs/user/develop/basic/index.zh.md)


4. ctx: a Universal Power Strip

ctx is the one concept you have to remember. Picture a power strip with many sockets, each owning one kind of capability:

ctx一切的入口ctx.llm模型调用ctx.tools工具注册表ctx.sessions会话ctx.skills技能ctx.shell命令执行ctx.sandbox沙箱

ctx.xxx 就是 DSH 的 API 面:所有能力都挂在 ctx 这个入口上

SocketWhat it owns
ctx.toolsTools the model can call
ctx.llmModel adapters (swap models here)
ctx.shellCommand execution
ctx.fsFile reads and writes
ctx.sessionsSession log
ctx.skillsSkills
ctx.sandboxSandbox confinement

Both directions go through ctx:

  • To use someone else's capability → take it off ctx, e.g. ctx.llm.stream(...) to call the model
  • To provide a new capability → hang it on ctx, e.g. ctx.tools.register(...) to register a tool

So "learning to write plugins" is essentially "knowing which socket of ctx your thing plugs into". Chapter 3 Lesson 2 covers ctx in depth, and Chapter 3 Lesson 10 teaches you to reverse-look-up which package a ctx key lives in.


5. The Rule That Matters Most: If It Can Be Installed, It Must Come Off Cleanly

This is the biggest difference between a DSH plugin and an ordinary one, and it is the core of the paper behind it.

Ordinary software plugins usually uninstall only halfway: listeners stay attached, timers keep firing, registered menu items linger. Over time the system gets dirty.

DSH requires registrations to be revertible — everything you hang on ctx is automatically removed by the framework when the plugin unloads:

Anything registered through ctx — event listeners, tools, timers — is cleaned up automatically when the plugin unloads. You do not need to removeListener or clearInterval by hand.

docs/user/develop/basic/index.zh.md

If you opened a resource the framework does not know about (a network connection, say), use ctx.effect() to tell it how to close it:

export function apply(ctx: Context) {
  ctx.effect(() => {
    const timer = setInterval(() => console.log('heartbeat'), 5000)
    // The returned function runs when the plugin unloads.
    return () => clearInterval(timer)
  })
}

Why does this matter so much? Because it makes "reshaping yourself while running" possible — no restart, install a plugin to try it, drop it if it does not fit, and the system returns to exactly where it was. A DSH agent can even install plugins on itself (Chapter 3 Lesson 8 covers this).

💡 One sentence is enough: every registration on ctx returns an undo, and the framework keeps them all and applies them at unload.


6. Don't Mix These Up: Plugin / Skill / Bundle

Newcomers get tangled in these three words. One table settles it:

NameWhat it isWho reads itExample
PluginA piece of code that hangs capabilities on ctxThe frameworkAdds a csv tool
SkillA manual (Markdown) teaching the model how to do somethingThe model"How to write a good commit message"
BundleA manifest listing which plugins to load and in what orderThe launcherdsh-base defines the big default set

In one line: plugins add parts to the system, skills add knowledge to the model, and bundles decide which parts get installed this boot.

Some repositories are both a plugin and a skill (dsh-genui ships code plus a bundled skill). That is common and perfectly fine.


Key Takeaways

  1. A plugin is a file that exports apply; the framework calls it once and hands you ctx.
  2. DSH has no untouchable core — model, tools, UI, and even the main loop are plugins on equal footing.
  3. ctx is the only channel: take capabilities off it, hang new capabilities on it.
  4. Registrations are revertible: whatever you hang on ctx is removed automatically at unload; use ctx.effect() for resources you opened yourself.
  5. Plugin, skill, and bundle are three different things: parts / knowledge / manifest.

🚀 Next lesson: now that you know what it is, let's see what it can do — using 275 real plugins from the ecosystem to map the actual boundaries.

Quiz · What Is a Plugin

Answer each question, then submit to check your result.

1. What is the most fundamental difference between a DSH plugin and a browser extension?
2. What is `ctx` in `apply(ctx)` for?
3. When a plugin unloads, what happens to the listeners and tools it registered through ctx?
4. What is the difference between a "skill" and a "plugin"?