Skip to main content
All posts
Guide

DeepSeek-Harness Architecture: What "Everything Is a Plugin" Means

How DeepSeek-Harness implements tools, commands, skills, MCP, hooks, and permissions as one mechanism, with the capability-seam pattern and packages panorama.

DeepSeek-Harness's tagline is "everything is a plugin," and it's a testable claim, not marketing: every product feature — tools, slash commands, skills, MCP bridging, hooks, model adapters, permissions, background jobs, subagent delegation — is implemented by a plugin registering against a Cordis Context, with no parallel manifest format for any of them. This guide walks the actual feature-to-mechanism map and the packages/ tree that backs it.

The claim, made checkable

dsh's own developer cookbook documents a feature → mechanism table, mapping each product capability to exactly how a plugin implements it:

CapabilityImplemented as
Toolctx.tools.register(); schema is auto-assembled into the model prompt
Command (human command, /xxx)ctx.commands registration; never becomes a model message
SkillRegisters a prompt section plus a tool; content is injected into context when invoked
MCPOne plugin per MCP server: discovers its tools, then calls ctx.tools.register() (see our MCP guide)
HookListens on lifecycle extension points (agent/session-start, agent/pre-step, tools/pre-execute, session/event); see our hooks and commands guide
Model adapter (LLM)An LlmAdapter subclass registered via ctx.llm.registerAdapter()
UI / Web Client nodeListens on session/event, or registers a ConversationNodeDefinition to add a node to the built-in Web UI
Permissions / sandboxReturns allow/deny/ask from tools/pre-execute; backed by ctx.sandbox
Background/scheduled jobRegistered on ctx.jobs; timers fire a followup(..., {source: {kind: 'cron'}})
Subagent delegationRegistered on ctx.subagents, a named provider registry (see our subagents guide)

The point of this table isn't trivia — it's that Skill, Command, Hook, and MCP bridging, which have separate manifest formats and directory conventions in some other harnesses, are all the same mechanism used differently in dsh. There's no independent classification system or registration file schema per capability type.

Capability seams: the atomic unit underneath the table

Each row above is a capability seam — the naming dsh's glossary gives to a complete, replaceable unit made of a Service Definition, one or more Service Providers, and one or more Consumers. packages/shell is the canonical worked example:

  • Service Definition: dsh-shell defines the ShellExecutor abstraction as a Cordis Service.
  • Service Providers: dsh-bash-local and dsh-bash-sandbox are two interchangeable concrete implementations — one runs commands directly, the other inside a sandbox.
  • Consumer: dsh-tool-bash injects the service and exposes it to the model as a tool.

Swap the provider (local vs sandboxed execution) and every consumer built against the seam keeps working unmodified, because they only depend on the abstract ShellExecutor interface, not a specific implementation. This pattern — define an abstract service, register interchangeable providers, let consumers inject without caring which provider is active — repeats across essentially every capability in the table above. For the Cordis primitives (Context, Service, inject, Fiber lifecycle) that make this pattern work mechanically, see Cordis explained.

A tour of the packages/ tree

dsh's packages/ directory has roughly 150 sub-packages. Grouped by capability domain, the major ones:

DomainRepresentative packagesWhat it covers
LLM adaptersllm-deepseek, llm-pi-ai, llm-retryDeepSeek's official chat-completions adapter, plus a design-validation "twin" adapter and cross-provider retry logic
MCPmcp/mcp-clientClient-role bridging of external MCP servers' Tools
Skillskill, skill-filesystem, skill-badgeThe skill provider registry plus a local-filesystem provider and a built-in "badge" skill
Subagentsubagent, subagent-claude-code, subagent-codex, subagent-acp, subagent-dsh-sdk, subagent-fork-in-process, subagent-spawn-in-processDelegation to in-process sessions, external agents over ACP, or officially to Claude Code / Codex
Hooks bridgehooks-claude-code, hooks-codexReuse existing Claude Code / Codex hooks.json shell-hook configs
Sandboxsandbox-local, sandbox-policy, sandbox-windows-aclLinux bwrap/Landlock, macOS Seatbelt, Windows ACL restricted-token backends
Web accessweb-search-exa, web-search-perplexity, web-search-deepseek, web-fetch-httpPluggable search providers plus an anonymous public HTTP(S) fetch provider
ACPacp/acpAn "automation-only" ACP server for external GUI/orchestration clients
SDKsdk/client, sdk/server, sdk/protocolTypeScript SDK plus the shared stdio JSON-RPC protocol also used by the Python SDK
E2B cloud sandboxe2b/e2b, e2b/fs-e2b, e2b/subprocess-e2bSwaps local execution for E2B's cloud sandbox environment
LSPlsp/lsp, lsp/lsp-stdio, lsp/tool-lspLanguage-server capability seam (ctx.lsp) for definition/references/hover
Terminalterminal/terminal, terminal/tool-terminalPersistent PTY session seam with owner-scoped IDs
Workflowworkflow/workflow, workflow/tool-ralphA general workflow engine plus the Ralph loop tool
Goalgoal/goal, goal/command-goalPersistent completion goals attached to a session
Session persistencesession-persistence-jsonl, session-persistence-sqliteTwo selectable on-disk session formats
Telemetrysession-telemetry, session-telemetry-otelOTLP export, off by default

This isn't an exhaustive list — it's the domains that matter most for understanding what "microkernel" means in practice: the core boot process is small, and essentially every feature you'd recognize as "part of dsh" is one of these ~150 packages loaded as a plugin, not something baked into a monolithic core.

What this buys you

  • One lifecycle for everything. HMR, dependency resolution, and automatic cleanup on unload (via ctx.effect()) apply identically whether you're building a tool, a hook, or a full UI panel — you learn Cordis once and it covers every feature category.
  • No manifest zoo. There's no separate schema to learn for skills vs commands vs hooks vs MCP — one plugin registration pattern covers all of them, which keeps the mental model small once you've internalized it.
  • Swappable implementations by design. The capability-seam pattern (service + interchangeable providers + consumers) means things like sandboxing backend, memory storage, or search provider can be swapped without touching consumer code.

What it costs you

  • Everything looks like the same shape from the outside. A tool registration and a hook registration both start as apply(ctx) { ... } — you need to actually read what's inside to know which capability a given plugin provides, since there's no directory-naming or manifest convention that tells you at a glance (unlike, say, a skills/ folder with SKILL.md files in some other harnesses).
  • You need Cordis literacy for any single feature, not just advanced ones. Because there's no shortcut manifest to skim, understanding even a simple hook requires understanding Context/inject/lifecycle at a basic level — see Cordis explained for the primitives.
  • Coming from a harness with per-capability manifests can feel disorienting at first. If you're used to Claude Code's separate skills/commands/hooks/MCP manifest conventions, dsh's single mechanism takes a bit of relearning — see migrating from Claude Code for a direct mapping.

FAQ

Is "everything is a plugin" just marketing language?

No — it's checkable against the actual feature-to-mechanism table above. Every listed capability genuinely is implemented as a plugin registration against ctx, with no separate manifest format hiding underneath.

What's the smallest unit of "a feature" in dsh's architecture?

The capability seam — one Service Definition, its Provider(s), and its Consumer(s). Individual plugins are usually one of these three roles, not the whole seam by themselves.

Does "everything is a plugin" mean I can remove core features?

In principle, yes for anything implemented as a swappable plugin — that's the point of the design — but base bundles wire in the plugins most profiles need by default, so removing one usually means replacing it with an alternative, not running without it.

How many packages does dsh ship?

Roughly 150 sub-packages under packages/, spanning the domains in the table above — LLM adapters, MCP, skills, subagents, sandboxing, SDKs, and more.

Where do I start if I want to build on this architecture?

Start with a single tool or hook, since both use the same basic Context/apply() pattern — see the plugin development primer and Cordis explained for the primitives underneath.

Next steps

For the framework primitives (Context, Service, inject, Fiber lifecycle) that make this architecture work, read Cordis explained. For how MCP and hooks specifically fit into this same mechanism, see the MCP guide and hooks and commands guide. For terminology, check the glossary, and for how this compares to Claude Code's separate-manifest design, read DeepSeek-Harness vs Claude Code.