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.pysyncs them all: upstream tracking, building, registering, planning, and rollback.
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-editingpackage.json/cordis.patch.ymlmanaged 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:
--plandry-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,
--fastincremental mode (skips unchanged assets by upstream commit), version/commit tracking inversions.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 uppackage.json/cordis.patch.yml/pnpm-lock.yamlto.backups/<timestamp>/first;--rollback <TAG>restores and reinstalls.--planshows the diff before you commit to anything.
Asset sources
| source | meaning | sync action |
|---|---|---|
npm | registry package (monorepo subpackage / native build) | installed via pnpm during assembly |
github | single-repo plugin; clone, optionally build | clone → build → copy to plugins/<dir>, file: dep + bundle |
release | GitHub Release tarball, prebuilt (projects whose source build needs special env) | download → extract → copy to plugins/<dir> |
skill | skill collection repo (SKILL.md set) | clone → extract skills → generate "entry + references router" plugin |
preset | agent preset (agent.cordis.yml / preset.yml) | clone → copy to ~/.dsh/.agent-presets/<id> (not a dependency) |
local | self-built plugin | registered 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
- Edit
manifest.yml: add the repo torepos(if new), add a row toassets, add MCP servers tomcp. uv run python provision.py --sync --asset <id>(single) or--sync(full).- A full
--syncrewrites profile dependencies, runspnpm install, and regenerates the patch managed section.
Self-built (local) plugins are edited directly in plugins/<dir> — sync never overwrites them.
Notes
manifest.ymlis the single source of truth; managed sections ofpackage.jsonandcordis.patch.ymlare generated and will be overwritten.- After assembly, restart
dsh web(skills/presets need a new session) for changes to take effect. - Full
--syncre-runspnpm install(file: deps are copies and must be reinstalled; provision handles purging automatically). versions.ymlrecords the upstream commit per sync for rollback reference.