dsh — DeepSeek Harness adapter
Spike of the claude-harness port for DeepSeek Harness (DSH 0.2.1-rc.3).
The Claude Code installation in ~/.claude stays untouched; this directory is a
separate Cordis bundle plus a thin install helper.
What works in the spike:
guard-main/require-plan— the tested bash/Python hooks run throughctx.tools.guard; the agent getsBLOCKEDwith the same messages as in Claude Code;- superpowers bootstrap —
using-superpowersis injected once per session fromagent/pre-stepand re-injected after compaction; - roles — the model loads them with the
roleskill (~/.dsh/roles, then~/.claude/roles, then reporoles/);/role dev|admin|analyst|qaremains the user-facing command and injects the same text, without Claude's auto-memory step; - SDD — the
sddskill executes a plan through asynchronoussubagentdispatches (report files, task review, fix loop, ledger), with controller modes for one plan and for several parallel plans; the optional overlay enables model routes and depth 2. - OpenSpec — воркфлоу идут проектными скиллами
.agents/skills/openspec-*(ставитopenspec init --tools agents); глобальной копии нет, слэш-команд нет. Установка в проект:bash dsh/install.sh --openspec.
Not yet: briefing, harness-check, role-hint, harness-doctor,
auto-memory, caveman. See PORT.md for the design, mapping table, and
risks.
Quick start
# Static check (offline; reports the configured pin and the current source)
bash dsh/install.sh --check
# Superpowers source. The default is a pinned clone: --skills clones or
# updates ~/.dsh/superpowers at $DSH_SUPERPOWERS_REF (default v7.0.1, fetched
# from $DSH_SUPERPOWERS_REPO), then runs sync + verify and copies the adapted
# skills. Offline it reuses the clone only when it is already on the ref.
bash dsh/install.sh --skills
# ...or sync a checkout directly (no network, no pin enforcement):
bash dsh/install.sh --skills --superpowers-from /path/to/superpowers
# ...or export DSH_SUPERPOWERS_SOURCE=/path/to/superpowers
# Global instructions, local role skill, and roles
# (run from a terminal; these write outside the session workspace)
bash dsh/install.sh --global
bash dsh/install.sh --roles
# В корне проекта, где уже есть openspec/: добавить agents-скиллы
bash <harness>/dsh/install.sh --openspec
# Install the bundle in DSH:
# Plugins -> install a bundle from dsh/bundle
# or ask the agent to call plugin_manager install_bundle with that target.
--skills resolves superpowers in this order: --superpowers-from →
$DSH_SUPERPOWERS_SOURCE → the pinned clone ~/.dsh/superpowers at
$DSH_SUPERPOWERS_REF (default v7.0.1, cloned or updated from
$DSH_SUPERPOWERS_REPO; offline it is reused only when already on the ref) →
the Claude Code plugin cache (legacy, warns). Explicit sources are synced in
place with no network; they must be a checkout root or its skills/
directory — a bare skills directory outside that layout is a hard FAIL in
both --skills and --check. Explicit syncs stage into
~/.dsh/.skills.synced, never into ~/.dsh/superpowers (reserved for the
pinned clone). Every sync runs dsh/sync/sync-from-upstream.mjs (DSH
adaptations) and dsh/sync/verify-skills.mjs; a tree that fails verification
or holds zero skills is never installed. Legacy sources are copied raw. A
clean HOME with no source and no clone fails with the clone command instead of
pretending success; the local role and sdd skills are copied either way.
Do not hand-edit $DSH_HOME/profiles/desktop/package.json or
cordis.patch.yml: the Desktop profile is Electron-managed and the plugin
manager owns those writes.
Verify
- In a new session, ask
what skills do you have?— the superpowers catalog should be visible. - In a repository on
main, ask the agent to create a file — expectBLOCKED [guard-main]. - Create a worktree on a feature branch, ask for an edit under
src/— expectBLOCKED [require-plan]until.boundedor a plan for the branch exists. - The model should load a role with
skill({name:"role"});/role devis the user-facing command with the same file. Expect the five-line role summary. - Prompt
Let's make a react todo list—brainstormingmust trigger before any code. - In a project with
.agents/skills, askwhat skills do you have?— the sixopenspec-*skills must be listed.
The injected bootstrap starts with a marker:
<!-- DSH-HARNESS-BOOTSTRAP:<16-hex-hash> -->
After compaction the marker disappears from session.surface.nodes and the next
step injects a fresh copy.
Tests
bash dsh/tests/run.sh
Pure Node; no DSH process is required. The guard tests create a throwaway git
repository and exercise the real hooks/guard-main.sh and
hooks/require-plan.sh through the adapter.
Layout
dsh/
bundle/
package.json DSH bundle manifest (dsh.bundle.patch)
cordis.patch.yml inserts the dsh-harness row
index.js ctx.tools.guard + agent/pre-step + /role
command-role.js /role command glue
lib/guards.js DSH tool call -> claude-harness hook JSON
lib/bootstrap.js superpowers skill resolution, marker, dedupe
lib/role.js role layers and text (pure)
dsh-tools.md superpowers tool mapping
hooks -> ../../hooks local install: tested hooks are reused, not copied
locale/{en,ru}.json
icon.svg
tests/
install.sh
skills/{role,sdd}/SKILL.md model-invocable skills installed into ~/.dsh
subagent-models.yml opt-in overlay: model routes + maxDepth 2
mcp.codegraph.yml optional CodeGraph MCP overlay
PORT.md design, mapping, risks, next phases
В корне проекта (не в dsh/):
.agents/skills/openspec-* скиллы OpenSpec, генерирует CLI
Configuration
The row is configurable from the profile patch; defaults target this repository layout:
- id: dsh-harness
config:
guards: true
bootstrap: true
roleCommand: true
bootstrapSubagents: false
hooksDir: '' # empty -> bundle/hooks -> ../../hooks
rolesDir: '' # empty -> ~/.dsh/roles, legacy ~/.claude/roles, repo roles/
projectRolesDir: '' # empty -> <cwd>/.claude/roles
roleNames: [dev, admin, analyst, qa]
bootstrapSkillPath: '' # empty -> ~/.dsh/skills, then legacy Claude Code paths
toolMappingPath: '' # empty -> bundle/dsh-tools.md
bootstrapMaxBytes: 65536
Known limits
- The guard adapter uses the repository's bash/Python hooks; if
python3is missing, the hooks fail open by design. bundle/hooksis a symlink for local-directory installation. A published bundle needs a real copy ofhooks/(already listed inpackage.jsonfiles).using-superpowersis read from~/.dsh/skillsafter--skills. The install-time source is--superpowers-from,DSH_SUPERPOWERS_SOURCE, or the pinned clone~/.dsh/superpowers(DSH_SUPERPOWERS_REF, defaultv7.0.1); Claude Code locations are a legacy migration fallback and log one warning per process when used, so a partial Claude Code rollback does not break the bootstrap. SetbootstrapSkillPathorDSH_SUPERPOWERS_SKILLfor another layout.- Roles resolve
~/.dsh/rolesfirst;~/.claude/rolesand the repositoryroles/are fallbacks. After--rolesthe runtime never needs~/.claude. - Role loading is model-driven through the
roleskill; there is no automaticagent/pre-stepinjection. If the model skips the skill, use the/rolecommand or ask it to load the role explicitly. - Model names in roles and superpowers (
sonnet,haiku,opus) are not DSH models. Thesddskill uses two live routes from the opt-indsh/subagent-models.ymloverlay; without it every dispatch runs on the session model. - SDD on DSH is asynchronous, not a copy of Claude's
Task. See thesddskill andopenspec/changes/dsh-sdd/. - OpenSpec-скиллы проект получает сам (
openspec init --tools agentsили--openspec); обвязка ставит их только в проект, не в~/.dsh.