Skip to main content
All posts
Tutorial

How to Update and Remove DeepSeek Harness Plugins

The exact dsh plugin update, why, and remove commands, how the bundle list stays in sync automatically, and what to check before removing a plugin for good.

To update a DeepSeek Harness (dsh) plugin, run dsh plugin --profile <name> update <package>. To remove one, run dsh plugin --profile <name> remove <package>. Both are plain pnpm commands underneath — dsh has no separate versioning or uninstall system of its own, and it automatically re-syncs your active configuration afterward.

This guide covers exactly what those commands do, how to check why a package is installed before you touch it, and the one thing worth verifying after any update or removal.

There is no dsh-specific version system

If you've read our guide on how to install plugins, you already know that dsh plugin --profile <name> <args...> forwards everything after the profile flag straight to pnpm, run inside that profile's directory. Update and removal work the same way — update, why, and remove are pnpm subcommands, not something dsh invented:

# update every plugin in the profile
dsh plugin --profile demo update

# update one specific plugin
dsh plugin --profile demo update dsh-hello-plugin

# ask why a package is installed at all
dsh plugin --profile demo why dsh-hello-plugin

# remove a plugin
dsh plugin --profile demo remove dsh-hello-plugin

Because it's just pnpm, plugin versioning follows ordinary semver/registry semantics for npm-published packages, and ordinary git-ref semantics for GitHub-sourced ones. dsh doesn't maintain its own changelog, compatibility matrix, or update notification system for plugins.

What why is for, and when to use it

Before removing anything, why tells you whether the package you're about to drop is actually a top-level plugin you installed, or a transitive dependency something else needs:

dsh plugin --profile web why dsh-hello-plugin

This is pnpm's own dependency-tracing output, scoped to the profile directory. It's the fastest way to confirm you're about to remove the right thing before you commit to it — especially useful in a profile that's accumulated a dozen-plus plugins over a few weeks and you no longer remember what pulled in what.

How the bundle list stays in sync

This is the part that's easy to misunderstand coming from other plugin systems: you never hand-edit a list of "active plugins" yourself. After every dsh plugin command, dsh re-scans the profile's actual installed dependencies and reconciles them against dsh.profile.bundles — the ordered list in the profile's own package.json that determines which config patches actually load.

  • Update: if an update pulls in a new version of a package that newly declares a dsh.bundle field (it didn't before), dsh activates it automatically. If a dependency drops its dsh.bundle declaration, dsh deactivates the corresponding patch.
  • Remove: once a package is gone from node_modules, it's gone from the active bundle list. There's no separate "disable but keep installed" state — removed means removed, and its config patch stops applying the next time the profile starts (or immediately, if you're running with hot reload).

Practically, this means the source of truth for "what's active in this profile" is always the actual installed dependency tree, not a config file you maintain by hand. If you want to double-check exactly what's currently active after an update or removal, run:

dsh --profile web --dump-config

This prints the fully composed configuration tree — every bundle patch, in the order it's applied — without starting the process. It's the most reliable way to confirm a removal actually took effect, especially if a plugin you removed had inserted config that another still-installed plugin also touches.

Updating a plugin installed from GitHub

If you installed a plugin with a commit pin (github:owner/repo#<sha>, which we recommend in our GitHub install guide), running update on it will not silently move you to a newer commit unless you change the pin yourself. That's the point of pinning — an update to an unpinned github:owner/repo reference, by contrast, can pull in whatever the upstream branch currently points to, including code you haven't reviewed. If you're updating a GitHub-sourced plugin regularly, it's worth periodically re-reading the diff on the upstream repo rather than trusting update to have only bumped a version number.

Cleaning up after removal

Removing a plugin drops it from the profile's bundle list and node_modules, but a few things worth checking manually:

  • Config it inserted elsewhere. If the removed plugin's patch file used insert to add configuration that another plugin now depends on (via inject), that dependent plugin will fail to load. --dump-config before and after a removal is the fastest way to spot this.
  • Data it wrote to disk. Plugins that persist state (session logs, memory stores, caches) generally don't clean up their own files on removal — dsh's uninstall is a dependency removal, not an application uninstaller. If a plugin's README documents a data directory, check it manually if you want a full cleanup.
  • Credentials it used. If a plugin required an API key stored via $DSH_HOME/.credentials.yaml or an environment variable, removing the plugin doesn't revoke or clean up that credential.

Community tools that help with this

A few plugins in the ecosystem exist specifically to make plugin management easier from inside the Web UI rather than the CLI. dsh-updater-ui adds a self-updater to the Settings page with a one-click check-and-pull flow. dsh-plugin-suite includes an update manager that checks for updates, backs up, and can roll back a plugin. These are ordinary third-party dsh plugins, not part of dsh itself — the same install and trust considerations from our security checklist apply to them as to anything else you'd dsh plugin add.

FAQ

Does dsh plugin remove uninstall a plugin cleanly, like an app uninstaller?

Mostly, but not completely. It removes the package and deactivates its config patch, but any data the plugin wrote to disk (session state, caches, memory stores) is left behind unless the plugin documents and you manually clean up its data directory.

Can I disable a plugin without removing it?

Not through dsh plugin directly — there's no separate "disabled" state distinct from "not installed." Some community plugins (like the ones linked above) add a toggle UI on top, but that's the plugin managing its own internal state, not a dsh-native feature.

What happens if I update a plugin and it breaks something?

There's no built-in rollback in the core CLI. If you installed from GitHub with a commit pin, you can re-pin to the previous known-good commit and reinstall. If you installed from npm, you can specify the previous version explicitly in your add/update command, same as any pnpm-managed dependency.

Do I need to restart dsh after updating or removing a plugin?

If you're running with hot reload enabled (the @deepseek-ai/cordis-plugin-hmr mechanism used for local plugin development), changes can apply without a full restart. Otherwise, restart the profile to be sure the new configuration is loaded.

How do I see what a plugin's dsh.profile.bundles list currently looks like?

Run dsh --profile <name> --dump-config to see the fully composed, currently active configuration — this reflects the real state after any update or removal, not just what's written in a file.

Next steps

If you haven't installed your first plugin yet, start with how to install DeepSeek Harness plugins. For plugins that need a build step, installing from GitHub covers the allowBuilds prompt in detail. If an update or install throws an error you don't recognize, check plugin install errors and fixes or the broader troubleshooting guide.