Cordis: Turning a Running Application into a Reversible Plugin Tree
Follow cordis.yml, Loader, and Context to see how Cordis composes, replaces, and safely tears down runtime capabilities in DeepSeek Harness.
The short answer: Cordis separates three runtime responsibilities: Loader composes, Context connects, and Fiber owns and reverses a plugin’s side effects.
Keep the header image as the mental model: one row in cordis.yml passes through Loader and Context and becomes a Fiber that can run, be replaced, and be removed. The four source-grounded diagrams below explain that path without turning the article into a wall of prose.
01 / How one configuration row enters the runtime
The flow comes from the Cordis tutorial launcher: it creates a root Context, Loader reads cordis.yml from the current directory, and configured modules are mounted into the runtime. Configuration chooses composition, the plugin contributes behavior, and Fiber records ownership of that mount.
- id: hello
name: './hello.ts'The plugin only needs to provide its entrypoint:
import type { Context } from '@deepseek-ai/cordis'
export function apply(ctx: Context) {
console.log('hello from my first plugin')
}02 / The three problems the plugin tree solves
| Need | Cordis action | Runtime result |
|---|---|---|
| Add a capability | Add a plugin row to composition | The central bootstrap stays unchanged |
| Replace an implementation | Consumers depend on service names, not files | A provider can change |
| Remove side effects | Fiber runs disposers during unload | Listeners, registrations, and resources do not linger |
The point is not the word “plugin”. It is explicit runtime ownership. Finding a module is only the first step; the runtime must also know when dependencies are ready and who cleans up resources.
03 / Context is the connection layer, not a global variable
Context provides service access and plugin registration. In DSH, ctx.tools, ctx.llm, ctx.agents, and ctx.sessions are named capabilities; a consumer does not need to import a provider’s implementation class.
When a plugin declares a service with inject, Cordis keeps it PENDING until the dependency is available and then moves it into LOADING. Readiness comes from the dependency graph, not accidental configuration order.
04 / Swap the provider, keep the consumer
The consumer declares only the capability name:
- id: terminal-tool
name: './terminal-tool.ts'
inject: ['shell']Composition can point shell to a local implementation or an E2B implementation. The consumer still depends on the same service name. This is one foundation for DSH profiles.
05 / HMR works because Fiber is reversible
HMR is not importing the file again. It unloads the old Fiber before mounting the new Fiber. Cordis defines PENDING, LOADING, ACTIVE, FAILED, UNLOADING, and DISPOSED; each state names an observable runtime phase.
External resources attach to Fiber through an effect:
ctx.effect(() => {
const timer = setInterval(() => console.log('tick'), 200)
return () => clearInterval(timer)
})The body creates the resource; the returned disposer reverses it during unload. ctx.on(), ctx.plugin(), and service registration follow the same reversible relationship.
06 / This is how DSH is organized
In DeepSeek Harness, model adapters, tools, sessions, agent management, and the agent loop enter the runtime as plugins. Reduce the model to four verbs:
- Composition selects: a profile decides which plugins load.
- Context connects: Service Definition, Provider, and Consumer roles cooperate by name.
- Fiber owns: every mount has its own lifecycle.
- Effects reverse: unload is a runtime action, not a cleanup promise.
“Everything is a plugin” therefore means that replacement points and resource ownership stay visible.
Where to go next
- Your first plugin: hello.ts + cordis.yml
- Lifecycle and effects
- Services and inject
- Composition and HMR
Implementation references: Loader launcher, Context, Plugin registry, Fiber lifecycle, and the Cordis primer.
Author
Categories
Newsletter
Join the community
Subscribe to our newsletter for the latest news and updates