dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Plugin environment backup and migration for DeepSeek Harness
English | 中文
Backup and migrate your DeepSeek Harness plugin environment via a git repository on GitHub — VSCode settings-sync style.
~/.dsh/dsh-*.json configs, locally-developed plugins packed into tarballs); ②assets outside the plugin system (helper scripts under ~/.dsh/scripts + com.dsh.*.plist launchd timers); ③the user-content layer — ~/.agents/skills, ~/.dsh/.agent-presets, ~/.dsh/adapters, ~/.dsh/AGENTS.md, ~/.dsh/settings.yaml, ~/.mnemon/runtime (memory) and ~/.mnemon/documents (distilled notes) — then git commit + git push. Missing entries are skipped, so it works on anyone's machine.dsh.profile.bundles, the user patch layer cordis.patch.yml and the config files, then drop the scripts/plists back in place (source-machine home paths and the node interpreter are rewritten, and plists are launchctl loaded automatically).autoBackup and backups run on an interval (daily by default) — no manual button and no external launchd job; windows missed while the machine slept are caught up on the next start.DSH plugins come from four sources: npm registry, github:user/repo#commit, link:<local path> and file:<tgz>. On a new machine the link:/file: local paths do not exist — without packing them, those plugins would be lost. This plugin detects them and npm packs each into the backup repo.
Some DSH side-services deliberately live outside the plugin system — TickTick deferred sync is the canonical example: its launchd timer must keep flushing the staged queue into TickTick while the DSH GUI is closed, so it cannot be a plugin bundle. Those files are scattered:
~/.dsh/scripts/ticktick-pending.mjs (script — invisible to the plugin manifest)~/Library/LaunchAgents/com.dsh.ticktick-deferred-sync.plist (timer — under the home dir)~/.dsh/dsh-ticktick-pending.json (queue + threshold config — already captured as a dsh-*.json config)A plugin-environment-only backup silently dropped the script and the timer on migration. They now travel in the repo's aux/ directory: on restore the recorded source home is rewritten to the target home (/Users/alice → /Users/bob), the node interpreter falls back to this machine's node when the recorded one is absent, files land at their original locations, and plists are launchctl load -wed.
The same registry also carries blog sync (created 2026-09-19, after a task-board cron silently skipped for days):
~/Library/LaunchAgents/com.dsh.blog-sync.plist (21:00 main + 09:00 fallback + RunAtLoad)~/dsh-blog-sync/after-blog-sync.sh (the real entry point: article sync with retry → card refresh)~/dsh-blog-sync/sync_blog_notion.mjs (current Node fetch sync), sync_blog_notion.py (legacy, kept for rollback)~/dsh-blog-sync/sync_now.mjs + now.config.json (refresh the "what I'm doing" card)Timer and scripts must be backed up together: a plist without its scripts fires on schedule but fails every run — a different flavour of silent failure.
Requires DeepSeek Harness ≥ 0.1.5-rc.1 (declared as dsh.engines.dsh in the package manifest, so the DSH plugin marketplace can report it) and is verified against 0.1.5-rc.1. Since 0.4.4 the peerDependencies range explicitly declares compatibility with DSH 0.2.0-rc.2 (^0.2.0-rc.2 is now included), so no compatibility warning appears on 0.2.0-rc.2. This build carries the DSH 0.1.5 adaptations: the strict tool-result contract (lossless-JSON snapshot, additionalProperties: false schema validation, and output.render returning ContentBlock[]) plus executable resolution that survives a launchd-started host whose PATH is only /usr/bin:/bin.
dsh plugin --profile web add github:zhengjy01/dsh-backup-migrator
# or local dev:
# from npm (published package)
dsh plugin --profile web add dsh-backup-migrator
# or local development
dsh plugin --profile web add link:/path/to/dsh-backup-migrator
Restart the GUI (dsh web) to load the plugin.
dshbackup_config:dshbackup_config backupDir: ~/Documents/DSH-Backup # local git repo dir (clone it on new machines)
dshbackup_config repoUrl: git@github.com:user/dsh-backup.git
| Tool | Purpose |
|---|---|
dshbackup_backup | scan profiles → build manifest + configs + packed local plugins + aux (scripts/timers) → commit → push |
dshbackup_restore | pull/clone the backup repo → reinstall all plugins → restore configs + scripts/timers |
dshbackup_verify | preflight before backup or restore (source reachability, git remote, secrets, aux presence) |
dshbackup_list | backup history (git log) + latest manifest summary |
dshbackup_config | view/change backupDir, repoUrl, includeSecrets, includeAux, autoBackup, backupIntervalMinutes, backupRetryMinutes, autoBackupPush; also reports scheduler state when called without arguments |
Config is stored at ~/.dsh/dsh-backup-migrator.json (mode 0600).
No button to remember and no external launchd job needed: turn the switch on and the plugin runs a backup identical to the manual one (same code path) from inside the host process, on an interval.
dshbackup_config autoBackup: true # master switch (off by default)
dshbackup_config backupIntervalMinutes: 1440 # minutes, minimum 15, default 1440 (daily)
dshbackup_config backupRetryMinutes: 30 # retry gap after a failure, minimum 5, default 30
dshbackup_config autoBackupPush: false # optional: local commits only, never push
backupRetryMinutes (default 30) instead of waiting a whole interval, so a network blip does not push your backup to tomorrow; 3 consecutive failures are called out in the log. (The first release counted a failed push as ok: true and reset the failure counter — i.e. silently losing backups; fixed.)dshbackup_config (no args) and GET /status both report last attempt / last success / consecutive failures / next expected run. State lives in ~/.dsh/dsh-backup-migrator-state.json (machine-local runtime state, never backed up).A scheduled run pushes the credentials it finds in your configs (when
includeSecrets: true). Make sure the backup repo is private; if unsure, setautoBackupPush: falsefirst so runs only commit locally.
GET /api/dsh-backup-migrator/probe — liveness probe returning { ok, plugin, version }GET /api/dsh-backup-migrator/status — read-only: current config + latest backup summary (incl. the aux list) + scheduler state<backupDir>/
├── manifest.json # machine + profile + plugin + config + aux index
├── README.md # human-readable summary (auto-generated)
├── profiles/<name>/cordis.patch.yml # user patch layer (if any)
├── profiles/<name>/packages/*.tgz # locally-sourced plugins (npm pack)
├── configs/... # ~/.dsh/dsh-*.json + dsh-* dirs (0600)
└── aux/ # assets outside the plugin system, by kind:
├── scripts/ # helper scripts (0755)
├── launchagents/ # com.dsh.*.plist timers (macOS)
├── files/ # single-file user content (AGENTS.md, settings.yaml)
└── dirs/<id>/ # directory trees (skills, agent-presets, adapters, memory, notes)
1. install DSH, launch once (web/headless profiles are auto-created)
2. install this plugin, then:
dshbackup_config backupDir: <same local dir>
dshbackup_config repoUrl: <same repo url>
dshbackup_restore # clone + reinstall + configs + scripts/timers
3. restart the GUI (launchd timers need no restart — restore already loaded them)
Prerequisite: the backup repo already has an aux/ section (one new-version dshbackup_backup run on the old machine).
# 1) on the new machine, install DSH + this plugin, then one command
dshbackup_config backupDir: ~/dsh-backup
dshbackup_config repoUrl: https://github.com/<you>/dsh-backup.git
dshbackup_restore # clone → reinstall plugins → configs → scripts/plist → launchctl load
# 2) verify (10 seconds)
node ~/.dsh/scripts/ticktick-pending.mjs status # prints queue/threshold/idle = script OK
launchctl list | grep com.dsh.ticktick-deferred-sync # any output = timer loaded
# 3) stage once for real
node ~/.dsh/scripts/ticktick-pending.mjs stage --by "migration-check" \
--json '[{"title":"migration check","content":"source: migration; why: verify deferred sync; done: visible in status"}]'
node ~/.dsh/scripts/ticktick-pending.mjs status
If step 1 reports a launchctl load failure (e.g. blocked by a sandbox), add it manually:
launchctl load -w ~/Library/LaunchAgents/com.dsh.ticktick-deferred-sync.plist
The queue/threshold config
~/.dsh/dsh-ticktick-pending.jsonand credentials~/.dsh/dsh-ticktick.jsonare restored as configs (needsincludeSecrets: true+ a private repo). Without credentials the timer still runs but skips writing to TickTick.
includeSecrets defaults to true — use a private backup repo, or set includeSecrets: false to exclude secret-flagged files. dshbackup_verify lists which files are secret-flagged.A backup carries configuration, not runtime data — otherwise every round copies hundreds of MB inside the host process and freezes the UI.
~/.dsh/dsh-runtimes (plugin runtime: Python+Node+pnpm, ~360 MB), dsh-pocket, dsh-provider-usage, dsh-usage-hud, dsh-config-manager, dsh-restart, dsh-updater, dsh-skill-recommender, plus any other dsh-* directory above 4 MB (so a newly installed plugin cannot blow the backup up again).*.json files of at most 64 KB each (e.g. dsh-updater/config.json — update channel; dsh-skill-recommender/config.json — match index/weights). token/credentials-like files never enter a backup; status.json/history.json/logs//reports//trend/ are state and are left behind.warnings and in manifest.configs (with runtime + kept fields), and surfaced by dshbackup_verify — never silent.Measured on this machine:
configs/dropped from ~400 MB to ~1.3 MB with no loss of user-tunable settings (update channel, match index, restart options, usage adapters).
MIT