Introduction¶
When using DSH, plugins are generally installed in the profile directory and managed by the profile’s package.json. As you install more, a problem arises: the same plugin might be declared twice, for example, once from github: and once from a local file:, with the same package name but different sources. This results in multiple copies of the same package in node_modules. This can take up space lightly, or heavily lead to the runtime loading the wrong version, which takes a lot of time to troubleshoot.
dsh-plugin-dedupe solves this issue: it scans the profile before installation and blocks it directly if duplicate declarations are found. Below is an introduction to its features, installation, and usage.
What is it¶
dsh-plugin-dedupe (DSH Plugin Deduplication Guardian) is an open-source plugin maintained by Jiaoyc224, MIT licensed, current version 0.1.0. One-sentence positioning: it prevents installing the same plugin multiple times in a DSH profile.
It works in two ways:
- When loaded as a DSH plugin, it automatically scans the current profile’s
package.jsondependencies and the actual installation status ofnode_modulesduring the startup phase; - As a
pnpm installpreinstall hook, it runs a check script before installation and returns a non-zero exit code upon finding errors to block the installation.
It declares peerDependencies: @deepseek-ai/cordis ^4.0.1 in package.json and is marked as optional.
What it checks¶
The detection logic is divided into two layers: first parsing the dependencies / devDependencies / optionalDependencies / peerDependencies of package.json, and then scanning node_modules to count the actually installed package names. Specific rules are as follows:
| Detection Type | Behavior | Description |
|---|---|---|
| Duplicate declaration of same-named dependencies (different sources) | Error | The same package name appears multiple times in package.json with different sources, e.g., github + file |
| Duplicate declaration of same-named dependencies (same source, multiple fields) | Warning | The same package is declared in both dependencies/devDependencies with the same source protocol |
Multiple same-named packages in node_modules |
Warning | The same-named package appears multiple times in node_modules (different versions/sources coexist) |
dsh-* plugins installed but not declared |
Warning | Likely old remnants or manually copied in |
Only “duplicate declarations with different sources” count as errors and will block installation; other cases downgrade to warnings. The actual blocking output looks roughly like this:
[dsh-plugin-dedupe] Scanning profile: C:\Users\<your-user>\.dsh\profiles\web
❌ Duplicate declaration detected: "dsh-agent-teams" has multiple sources in package.json:
github:NanmiCoder/dsh-agent-teams
file:E:/fake/dsh-agent-teams
[dsh-plugin-dedupe] Detected 1 duplicate plugin error, installation blocked.
Installation¶
Install directly in the DSH profile directory:
cd <your-dsh-profile-dir> # e.g.: C:\Users\<user>\.dsh\profiles\web
pnpm add github:Jiaoyc224/dsh-plugin-dedupe
Or use the dsh plugin command:
dsh plugin --profile web add github:Jiaoyc224/dsh-plugin-dedupe
Enabling the preinstall hook¶
The preinstall hook needs to be added manually. Edit the profile’s package.json and add to scripts:
{
"scripts": {
"preinstall": "node node_modules/dsh-plugin-dedupe/scripts/check-duplicates.mjs"
}
}
This way, every time before running pnpm install, the deduplication check is performed first. If duplicate plugins are found, it returns a non-zero exit code to block the installation.
There is one note about the first installation: after installing the plugin, you need to run pnpm install once first to generate node_modules/dsh-plugin-dedupe; otherwise, subsequent pnpm install calls won’t trigger the preinstall hook. This step can use pnpm install --prefer-offline to avoid an infinite loop.
Running the check independently¶
If you don’t want to hook it, the check script can be run independently:
# In the profile root directory
node node_modules/dsh-plugin-dedupe/scripts/check-duplicates.mjs
# Or specify the profile directory
node node_modules/dsh-plugin-dedupe/scripts/check-duplicates.mjs --profile /path/to/profile
The plugin’s bin field also provides the dsh-dedupe command, pointing to the same check script.
Environment Variables¶
The plugin supports two environment variables:
| Environment Variable | Description | Default Value |
|---|---|---|
DSH_DEDUPE_WARN_ORPHANS |
When set to true, also warn about undeclared dependencies that are not plugins |
false |
DSH_PROFILE_DIR |
Manually specify the profile root directory | Automatically searches upward |
Usage Scenarios and Notes¶
The suitable scenarios are clear: profiles with many plugins and mixed sources (npm, github, local file, link), or DSH/Agent developers who frequently debug plugins locally and need to switch sources. If you have only one profile and only install plugins from a single source, this plugin’s effect is limited.
A few notes:
- The plugin runs with the permissions of the current dsh process. It is recommended to check the source code and license of third-party plugins before installing them.
- The preinstall hook only works for
pnpm installand needs to be manually configured in the profile’spackage.json. - The boundary between errors (blocking installation) and warnings (only prompting) is shown in the rule table above; adjust the intensity of reminders for undeclared dependencies as needed via
DSH_DEDUPE_WARN_ORPHANS.
Conclusion¶
dsh-plugin-dedupe does something small but very practical: turning “duplicate plugin installation” from post-troubleshooting to pre-installation interception. If you have encountered the problem of same-name plugins with multiple sources coexisting in DSH profile management, it is worth trying.
- Community directory page: https://www.skillhub.cn/plugins/Jiaoyc224/dsh-plugin-dedupe
- GitHub repository: https://github.com/Jiaoyc224/dsh-plugin-dedupe