DSH plugin profiles and bundles in DeepSeek Harness
DeepSeek Harness records a named assembly in a profile, which holds cordis.patch.yml; a bundle is the distribution format of "Cordis config entries + mount code", declared through dsh.bundle in package.json (source). The two words are often mixed up: one is the list of "which layers to install", the other is the format for "how a layer is packaged and distributed". Tell them apart and you can read "what actually loaded at startup" and "which file to edit for a config change". This piece covers only what these two concepts are and how they relate; how to create a profile, see how to create a custom DeepSeek Harness profile, how to publish a bundle, see how to ship a dsh plugin bundle, and the whole tree, see DeepSeek Harness architecture explained.
What a DeepSeek Harness profile is: a name plus an assembly
A DeepSeek Harness profile is one named assembly that records which DSH plugin layers to load at startup and their individual overrides; it lives in the Harness home and contains a cordis.patch.yml (source). Unpack the three things in the name:
- "Named" means one profile per name: names such as
webandheadlesseach correspond to a definite list of layers. Startup picks one by name, so "switching profile" is really switching a list — hence switching a tree. - "Assembly" means it implements no capability: a profile contains no tools and no model adapter, only a list and overrides; the layers it mounts are the ones that do the work.
- "Persistent" means it lives on disk: a profile sits in the Harness home, so the changes you make and plugins you install are still there next launch — which is why it is not the same thing as a one-off command argument.
Once this is clear, several things follow: why does the same dsh behave differently under different profiles? Because their lists differ. Why does switching profile feel like switching software? Because you switched how the whole plugin tree is assembled.
What a profile holds: an override list and a dependency record
The core of a profile is an override list — cordis.patch.yml; it also holds the assembly's dependency record, kept in the profile directory's package.json and node_modules (source). The two kinds of content cover different things:
cordis.patch.ymlhandles overrides: it does not redefine plugins, only patches and tunes already-declared entries — so to adjust the behaviour of a profile it is usually enough to edit here, without touching the source of any DSH plugin.- The dependency record tracks "what was installed": plugins you add to this profile stay as dependencies in the profile directory, and that is exactly what
dsh plugin listreports — not the repository'sdevDependencies. - Together they decide the tree: the list (with overrides) decides which layers load and how each is configured; the dependency record decides where those layers' content comes from and which versions they run on.
- They can be derived:
webandheadlessare starting points, not ceilings — you can derive your own profile on top of them and preload favourite plugins and settings.
To build your own assembly by hand, follow how to create a custom DeepSeek Harness profile; how the concepts relate is in five concepts to know before installing plugins.
What a bundle is: config entries plus mount code
A bundle is a DeepSeek Harness distribution format whose content is "Cordis config entries + mount code", declaring its identity through the dsh.bundle field in package.json (source). Four sentences separate it from an ordinary plugin:
- An ordinary DSH plugin provides capability: it implements concrete tools, commands or services and, once mounted by a profile, adds a capability layer to the tree; it cares about "what to do".
- A bundle provides one assembled layer: it packages a group of config and mounting logic, caring about "how to put these capabilities together and with which parameters to mount them".
- The declaration differs: a bundle declares its identity with
package.json'sdsh.bundle; a package without that field is just an ordinary dependency and does not activate as a whole layer. Adjacent to it is thedsh.profilefield, which ties a package to a specific profile. - A bundle can organise several plugins: capabilities come from plugins, layer organisation comes from bundles, and the two jobs differ — which is why "the plugin is installed" does not mean "it is active", since it also depends on whether it entered the list as a bundle.
To add a layer to a profile, find a ready-made package under Settings → Plugin Market, which is DSH Plugin Hub; for how to publish a bundle, see how to ship a dsh plugin bundle.
How profile and bundle work together
In DeepSeek Harness the two cooperate as "the profile names them, the bundle supplies them": the profile's list decides which layers are wanted, and bundles decide how those layers' content is organised and mounted. Trace it as a sequence:
- First there is a profile: you pick or create one, and it gives the list of entries to mount.
- A bundle extends the list: installing a package that declares
dsh.bundleappends it to the profile's bundle list, joining startup as a whole layer. - The override list fine-tunes: before startup,
cordis.patch.ymloverrides each entry, finally fixing each layer's actual parameters. - Together they grow the tree: only after the three stack do you get the tree you see at runtime — which explains why "installing a plugin" involves the profile, the bundle and the override list at once.
Profile templates shipped with DeepSeek Harness
DeepSeek Harness ships several profile templates, commonly web, headless, sdk and sdk-minimal, plus acp (source). Their scenarios:
web: includes the graphical UI, for everyday interactive use; all Web GUI layers live in this tree.headless: no UI, for scripts and automation; it loads no UI-related layers, so startup is lighter.sdk: for embedding and calling from a program, treating dsh as a programmable runtime.sdk-minimal: a leaner embed, for enabling capabilities on demand instead of pulling up every layer at once.acp: a run mode aimed at protocol access.- Templates can be derived: these are starting points, not ceilings; deriving your own profile on top of them is the usual way to preload favourite plugins and settings.
Notes on profiles and bundles
Treat the profile as an "assembly list" and the bundle as a "reusable layer" and the two concepts will not blur.
- profile ≠ plugin: a profile is a list with overrides and implements no capability by itself.
- Check
cordis.patch.ymlfirst for behaviour: most tuning happens at the override layer, without editing plugin source. - bundle ≠ feature package: it organises config and mounting; the plugins it brings in do the work.
dsh.bundledecides identity: without that field a package is only an ordinary dependency and does not activate as a whole layer.- Read dependencies at the profile layer: the repository's
devDependenciesare irrelevant to you; the record in the profile directory is what takes effect. - Templates can be derived:
web/headless/sdk/sdk-minimal/acpare the starting points that ship with the release. - Installing a plugin is adding an entry: if you cannot tell where a plugin went, look at the current profile's list and dependency record.
Source: DeepSeek Harness docs - architecture overview, docs - Python SDK guide.
FAQ
**A DeepSeek Harness profile is one named assembly that records which DSH plugin layers to load at startup along with their overrides.** It lives in the Harness home and contains a cordis.patch.yml, so the profile itself implements no capability; the plugins it mounts do the actual work.
**A bundle in DeepSeek Harness is a distribution format made of Cordis config entries plus mount code, identified by the dsh.bundle field in package.json.** A package without that field is just an ordinary dependency and does not activate as a whole layer; a package declaring it is appended to the profile's bundle list at install time.
**A profile is the list of which layers to install, while a bundle is the reusable recipe for how one layer is configured and mounted.** DeepSeek Harness uses the profile to name one assembly and the bundle to distribute that assembly's content, so the two answer different questions and work together.
**DeepSeek Harness ships profile templates such as web, headless, sdk and sdk-minimal, plus acp.** web launches the graphical UI, headless runs without a UI for scripts, sdk embeds dsh as a programmable runtime, sdk-minimal is a leaner embed, and acp targets protocol access.
**To change a DeepSeek Harness profile's behaviour, edit cordis.patch.yml rather than any plugin's source.** The override list patches and tunes already-declared entries, so most adjustments happen at the override layer; the dependency record in the profile directory decides which versions those entries run on.
Related Terms
- profile
- A profile is one named assembly in DeepSeek Harness that decides which DSH plugin layers load at startup; it lives in the Harness home and contains cordis.patch.yml.— DeepSeek Harness docs - architecture overview
- bundle
- A bundle is DeepSeek Harness's distribution format of Cordis config entries plus mount code, declared through dsh.bundle in package.json, deciding how a layer joins startup.— DeepSeek Harness docs - architecture overview
- cordis.patch.yml
- cordis.patch.yml is a profile's override list in DeepSeek Harness. It does not redefine plugins but patches and tunes already-declared entries, so tuning a profile usually means editing this file.— DeepSeek Harness docs - architecture overview
- dsh.bundle
- dsh.bundle is the marker a package declares in package.json to be treated as a bundle; when installed, DeepSeek Harness appends it to the profile's bundle list so it joins startup as a whole layer.— DeepSeek Harness docs - architecture overview
Sources
- DeepSeek Harness docs - architecture overview· deepseek-harness
- DeepSeek Harness docs - Python SDK guide· deepseek-harness