Back to home

MoYuSOwO

dsh-provision

Manifest-driven multi-source asset manager for DeepSeek Harness profiles (npm/github/release/skill/preset/local) — sync, plan, conflict detection, transactional rollback.

Stars
2
Language
Python
Created
Aug 15, 2026
Updated
Aug 15, 2026

Introduction

dsh-provision

Manifest-driven provisioning for DeepSeek Harness profiles. One manifest declares every asset — plugins, skills, agent presets, MCP servers — and provision.py syncs them all: upstream tracking, building, registering, planning, and rollback.

中文说明 · MIT

What it does

DSH profile assets come from many places (npm packages, GitHub repos, skill collections, agent presets, self-built plugins). dsh-provision is the single source of truth for all of them:

  • One manifest (manifest.yml) records each asset's source, version, build method, and registration — no more hand-editing package.json / cordis.patch.yml managed sections.
  • Six asset sources: npm (registry packages), github (clone → build → install), release (GitHub Release tarballs, no build needed), skill (SKILL.md collections → auto-generate entry+router plugin), preset (agent presets → ~/.dsh/.agent-presets/), local (self-built, registered only).
  • Skill extraction: skill repos are cloned, sub-skills extracted, and an "entry skill + references routing" plugin is generated automatically — the entry skill shows in the catalog, sub-skills load on demand via read.
  • MCP registration: MCP servers declared in the manifest are written into the profile patch managed section by --patch.
  • Safety: --plan dry-run diff before touching anything, conflict detection (duplicate entry ids, unresolvable bundles, duplicate MCP names), and automatic transactional backups with --rollback.
  • Fast: sparse checkout for huge repos, --fast incremental mode (skips unchanged assets by upstream commit), version/commit tracking in versions.yml.

Quick start

cd ~/.dsh/provision
uv sync                                  # first run: install deps (pyyaml)
cp manifest.example.yml manifest.yml     # first run: build your asset manifest from the template
uv run python provision.py --check       # read-only status check (includes conflict warnings)
uv run python provision.py --sync --fast # incremental sync (seconds when nothing changed)

manifest.yml / ASSETS.md / versions.yml / .cache/ / .backups/ are gitignored — your personal configuration never gets published. The repo ships manifest.example.yml as the template.

Usage

uv run python provision.py --check            # status of all assets (read-only, includes conflict warnings)
uv run python provision.py --plan             # dry-run: show the diff that assembly would produce (no execution)
uv run python provision.py --sync             # full sync (clone/build/extract/install/generate patch, auto-backup)
uv run python provision.py --sync --fast      # incremental: skip unchanged upstreams; skip assembly when nothing changed
uv run python provision.py --sync --asset latex    # sync a single asset (multiple ids allowed)
uv run python provision.py --install          # rewrite dependencies + pnpm install only
uv run python provision.py --patch            # regenerate the profile patch managed section (MCP)
uv run python provision.py --backups          # list transactional backup points
uv run python provision.py --rollback <TAG>   # restore package.json/patch from .backups/<TAG> and reinstall

Transactions: every assembly (--sync / --install / --patch) backs up package.json / cordis.patch.yml / pnpm-lock.yaml to .backups/<timestamp>/ first; --rollback <TAG> restores and reinstalls. --plan shows the diff before you commit to anything.

Asset sources

sourcemeaningsync action
npmregistry package (monorepo subpackage / native build)installed via pnpm during assembly
githubsingle-repo plugin; clone, optionally buildclone → build → copy to plugins/<dir>, file: dep + bundle
releaseGitHub Release tarball, prebuilt (projects whose source build needs special env)download → extract → copy to plugins/<dir>
skillskill collection repo (SKILL.md set)clone → extract skills → generate "entry + references router" plugin
presetagent preset (agent.cordis.yml / preset.yml)clone → copy to ~/.dsh/.agent-presets/<id> (not a dependency)
localself-built pluginregistered only, never touched

How skill assets are generated

Each skill asset produces a plugin package plugins/dsh-<id>/:

dsh-<id>/
├── package.json          # name/dsh.bundle.patch → cordis.patch.yml
├── index.js              # skills provider: registers the entry skill
├── cordis.patch.yml      # insert row (the plugin assembles via bundles)
└── skills/
    ├── <entry>/SKILL.md  # entry skill (visible in catalog), guides reads of references
    └── references/<name>/  # sub-skill originals (with their own resources)

The entry SKILL.md carries a "dsh adaptation" note: $name / namespace:name references resolve to skills/references/<name>/SKILL.md — read the file and follow its instructions when needed.

Adding / modifying assets

  1. Edit manifest.yml: add the repo to repos (if new), add a row to assets, add MCP servers to mcp.
  2. uv run python provision.py --sync --asset <id> (single) or --sync (full).
  3. A full --sync rewrites profile dependencies, runs pnpm install, and regenerates the patch managed section.

Self-built (local) plugins are edited directly in plugins/<dir> — sync never overwrites them.

Notes

  • manifest.yml is the single source of truth; managed sections of package.json and cordis.patch.yml are generated and will be overwritten.
  • After assembly, restart dsh web (skills/presets need a new session) for changes to take effect.
  • Full --sync re-runs pnpm install (file: deps are copies and must be reinstalled; provision handles purging automatically).
  • versions.yml records the upstream commit per sync for rollback reference.