In DeepSeek Harness (DSH), plugin configurations often differ across profiles (for example, the web profile web and the desktop profile desktop). Manually copying files is error-prone: you may omit allowBuilds, causing native builds to fail silently, or trigger port conflicts. dsh-profile-sync is a plugin migration tool that, by default, safely pulls the web profile’s plugin set into the desktop profile.
It does not install anything directly itself; it performs only four things: computing differences, running preflight checks, writing a “script to run after exit”, and verifying after the next startup that the changes actually landed. The actual installation is delegated to official channels (the desktop profile uses the in-app manager; other profiles use dsh plugin).
Core Features¶
- Compute differences: compares the source and target plugin lists to identify newly added plugins, changed plugins, differences only in pinning, etc.
- Preflight checks: before installation, checks potential blockers, including entry-id collisions, loadable entry points, declaration completeness, engine scope, git source conditions, etc.
- Script generation and verification: generates a script to be executed after exit, and verifies actual changes after restart.
- Panel interaction: adds a “Plugin Migration” panel in the left sidebar, allowing users to select plugins to migrate, generate an execution script, or apply immediately.
- Agent tool: provides the
profile_synctool for agents, supporting operations such asplan/write/status.
Installation and Enablement¶
Installation does not rely on Node.js to run the plugin itself; instead, install.cmd registers the plugin into DSH.
- Open DeepSeek Harness (it should already be running).
- Double-click
install.cmd. - Refresh the page — the “Plugin Migration” panel appears in the left sidebar.
install.cmd first runs a self-check (manifest invariants + real loading) and confirms the official /api/plugin-manager endpoint is available before installing the plugin into the profile. The desktop app must remain running because it needs to invoke the official in-app manager.
Usage¶
Double-click Operations¶
install.cmd: Runs pre-install self-check + installs this plugin into the profile.sync-plan.cmd: Computes differences and generates a plan + generatesapply.cmd.
Command Line¶
Node.js 20+ must be available on PATH.
# 算差异并落成产物(plans/<时间>/plan.json + plan.txt + apply.cmd)
node bin/plan-cli.mjs plan --source web --target desktop --write
# 只看报告
node bin/plan-cli.mjs plan
# 核对上一次迁移是否真的落地
node bin/plan-cli.mjs status
# 应用计划(会先查目标端是否还在运行)
node bin/apply.mjs --plan "<plans/.../plan.json>"
# 只算不写,看看会改什么
node bin/apply.mjs --plan "<...>" --dry-run
# 退回最近一次快照
node bin/apply.mjs --rollback
# 装前自检(清单不变式 + 真加载)
node bin/check.mjs
Panel Operations¶
In the “Plugin Migration” panel on the left sidebar:
1. Select source/target.
2. Compute differences and select the plugins to migrate.
3. Click “Generate Execution Script” or “Apply”.
4. Verify the result of the last migration.
Preflight Mechanism¶
Before installation, six items are checked. The official dsh plugin add does not check items 2 and 3, so this plugin must block them:
- Local-path specs: whether the path referenced by
link:/file:exists. - cordis entry ID collisions: when two bundles insert the same loader entry ID, cordis rejects launching the entire tree. Only IDs inside
insert:blocks are counted. - Packages without loadable entry points: packages without
lib/in a source checkout that are promoted into the bundle layer can cause startup failure. - Did you declare
dsh.bundle.patch?: a package included in thebundleslist but not declared will only be installed as a regular dependency by the official tool and will not become a profile-layer plugin. - Engine scope: handles prerelease versions correctly (for example,
0.2.0-rc.2). - git source conditions: only a warning, not blocking. A successful
git ls-remotedoes not guarantee thatpnpmcan connect; the mechanisms differ. Provides a tarball alternative syntax.
Notes¶
- Desktop profile must not be modified via CLI: This is hard-blocked; there is a guard in
@deepseek-ai/dsh/lib/bin.jsthat blocks all CLI invocations by name. This plugin only calls the official manager on desktop. - cordis.patch.yml is not synchronized: It contains instance configuration (ports, coordinates, Tailscale addresses); it is not synchronized to avoid port conflicts.
- Different pinning styles ≠ version changes: Some profiles pin exact versions, while others use version ranges. This plugin classifies these separately as
repin, reporting them only and leaving them unchanged by default. - Version downgrades are only warned: if
version-downgradewarnings appear in the plan, the official manager will reject and roll them back. The plugin states this in advance to avoid ineffective operations. - Preserve allowBuilds semantics: An explicit
falseintentionally disables build scripts. During synchronization, the source-side value is retained, rather than uniformly writingtrueor flippingfalsetotrue. - You can preview effects without installing the plugin:
bin/plan-cli.mjsis completely standalone and does not depend on DSH being running.
Summary¶
dsh-profile-sync reduces the error-prone nature of plugin migration between DSH profiles through difference calculation, strict preflight checks, and script generation. It delegates installation to official channels and ensures instance configurations such as cordis.patch.yml are not mistakenly synchronized. It is suitable for developers who need to synchronize plugin sets between web and desktop profiles.