research phase 8 t1 deepseek harness - sinrimin/harness-nexus GitHub Wiki
Status: studied (2026-09). Ground truth: the
deepseek-ai/deepseek-harnessrepo at tagdsh-v0.1.2-rc.1(commita66e470, sparse checkout ofdocs/,apps/cli/,packages/), cross-checked against the local ACP reference demo (~/acp-ref/— a working DSH plugin, studied for C5 inphase-8-c5-acp-web-demo.md). dsh is a developer preview ("THERE WILL BE COMPATIBILITY-BREAKING CHANGES"), MIT, 214k+ stars. Re-verify the concrete paths below when bumping past 0.1.x. Parent design:design-phase-8-t1-deepseek.md.
DeepSeek Harness (dsh) — released 2026-08-13 as an open-source rival to
Claude Code's agent infrastructure. Not a single coding CLI but a
composable harness: an npm-distributed runtime
(npx @deepseek-ai/dsh web) whose every capability (skills, tools, LLM
providers, subagents, MCP, the web UI itself) is a Cordis plugin stacked
into profiles. A profile is a boot preset (web, headless, sdk,
sdk-minimal, acp ship as templates; custom ones are user-created).
The relevance to Harness Nexus: it is exactly the kind of agent home we manage, with a file surface we can write declaratively.
-
Home:
$DSH_HOMEenv override, default~/.dsh(packages/util/home-paths/src/index.ts:DSH_HOME_DIR_NAME = '.dsh'). -
Profiles live at
$DSH_HOME/profiles/<name>/— each has apackage.jsoncarrying thedsh.profilemanifest (orderedbundleslist,patchReload: live|startup) plus its owncordis.patch.ymland pnpm-managednode_modules(managed viadsh plugin --profile <name> <pnpm args>, pnpm must be on PATH). -
Composition order (
apps/cli/reference/README.md): bundle patches (fromdsh.profile.bundles) → profilecordis.patch.yml→ home-level$DSH_HOME/cordis.patch.yml→--patchCLI overlays. Later layers win per row; a row patch replaces the wholeconfig(no deep merge); new rows arrive viainsertdirectives. -
Hot reload: with
patchReload: live(the default for custom profiles), ordinary edits to the profile or homecordis.patch.ymltake effect without a restart; only bundle membership changes need a restart. → writing the home-level patch is our integration seam: it applies to every profile on the machine and reloads live.
A YAML list; each element is either a row override (matched by id) or an
insert directive adding rows (from the shipped docs + the demo's
overlay.yml):
# override an existing row by id (replace-or-disable)
- id: headless-startup
name: '@deepseek-ai/dsh-headless/startup'
disabled: true
# config-only override
- id: system-prompt
config:
persona: >-
...
# add new rows — this is how third-party + MCP entries land
- insert:
- id: mcp-github
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: github
transport: stdio
command: npx
args: ['-y', '@modelcontextprotocol/server-github']
env:
GITHUB_TOKEN: !!js process.env.GITHUB_TOKENname resolves as a package name through the profile's node parent walk to a
maintained installation fallback — in-box packages like
@deepseek-ai/dsh-mcp-client need no pnpm step to be referenceable from a
patch row. (Out-of-tree plugins DO need dsh plugin add — that distribution
path, an npm package with "dsh": { "bundle": { "patch": "./cordis.patch.yml" } },
is what the acp-ref demo uses; it is NOT our path — we are local-write only.)
dsh natively speaks the Agent Skills format:
- Discovery roots (rank order):
<projectRoot>/.dsh/skills(100) →<projectRoot>/.agents/skills(200) →Config.customSkillDirs(300) →<dshHome>/skills(400) →<agentsHome>/skills(500) → bundled (600). - Formats: directory bundles
<name>/SKILL.md(+ sibling bundle files) or flat<name>.md. No recursive nested discovery. Chokidar-watched — new bundles appear live. -
Frontmatter is mandatory: YAML frontmatter with
name+descriptionrequired (skill-filesystem/src/index.tsrejects files without it — "ignored: missing YAML frontmatter" / "frontmatter requires name and description");whenToUseoptional;disable-model-invocation/disable-user-invocationbooleans. - Names must be kebab-case
^[a-z0-9]+(?:-[a-z0-9]+)*$. - Skills are dual-invocable: the model sees a
skillloader tool + catalog; users invoke directly as/name— i.e. dsh's slash-command surface IS the skill surface (there is no separate prompts directory).
One patch row per server (dsh-mcp-client is the bridge; tools surface as
mcp__<serverName>__<tool>):
-
transport: stdio→command/args/env/cwd -
transport: streamable-http→url/headers -
serverNameconstraint:[A-Za-z0-9_-]{1,32}, unique per scope. - Reconnect/backoff defaults; startup failure is non-fatal by default
(
failOnStartupError: false) — a broken server never blocks boot. -
stdio is our shape: the
hnx mcp serve --profile <id> --server <base>shim entry slots in exactly like the Codex TOML row.
-
Hooks: dsh itself has no declarative hook format — but it ships
bridge plugins (
@deepseek-ai/dsh-hooks-claude-code,dsh-hooks-codex) that run an existing Claude-Code/Codexhooks.jsonduring agent runs ("mount the matching bridge, point it at your existing hooks.json"). They are optional packages requiring per-profile opt-in (pnpm-managed) — NOT something a local-write install can wire reliably in v1.HOOK_SUPPORT['deepseek'] = null(same treatment as Hermes/Codex), with the bridge noted for a future phase. -
Subagents: a provider registry (
ctx.subagents) with in-process / ACP / real-Codex / real-Claude-Code children — programmatic composition, no declarative file format.sub_agentresources: skipped, like Codex. -
Rules: no user-scope always-on rules file exists; the persona is a
config row (
system-promptpersona / per-agent persona). Overwriting a user's persona from an install would be destructive —ruleresources: skipped with a warning, like Codex.
-
dsh --profile acpstarts a ready-to-use ACP v1 server over stdio (no options; stdout is pure protocol traffic;authenticatesucceeds immediately). - Surface: ACP v1 +
session/list/session/resume/ Streamable-HTTP MCP mounts;session/newvalidates the absolute cwd; one prompt in flight per session;session/request_permissionwith one-shot allow/reject options (optionIdsemantics standard);session/cancel/$/cancel_request; semanticsession/updatestream (messages, thoughts, generic tool lifecycle, usage). Unsupported:session/load, fork, delete, replay, elicitation, modes/commands/plans/terminals. - This maps 1:1 onto our C5 daemon's ACP client contract — the adapter row is
just a command line:
dsh --profile acp(requiresdshon PATH and a configured provider route — same class of prerequisite ascodexneeding the Codex CLI or Hermes needing theacp_adapterextra). Env override hook:HN_ACP_COMMAND_DEEPSEEK. - Sessions persist across process restarts (list/resume) — richer than our v1 "no resume" daemon model, but compatible: we simply never call resume.
-
Wire dialect differs from the Zed adapters (verified 2026-09-10 against
the real
dsh-acp0.1.2-rc.1 on the rig — the cause of a full day of "empty turns"): message/thought chunks carry the block ascontent({type:'text', text}), NOTcontentBlock; tool calls spread the fields FLAT on the update object (toolCallId/title/kind/status/rawInput— notoolCallUpdatewrapper),kindis alwaysotherwith the tool name intitle;usage_updatereports context occupancy (usedofsize), not per-turn token counts. The C5 daemon'smapAcpUpdatenow speaks BOTH dialects (Zed shape first, dsh shape fallback; usage mapsused/size→contextUsed/contextSize).
Research + implementation target dsh-v0.1.2-rc.1 (2026-09). The format
surface we depend on (~/.dsh home, home-level cordis.patch.yml,
skills/<name>/SKILL.md, dsh-mcp-client rows, --profile acp) is stable
across the 0.1.x line per the reference docs, but the project's own preview
warning stands — the adapter should fail loud (not corrupt) on unexpected
patch content, and the managed-block marker approach below keeps our writes
surgically reversible.
| Surface | dsh ground truth | Our emission |
|---|---|---|
| skills |
~/.dsh/skills/<name>/SKILL.md (+files), mandatory frontmatter |
write bundle; synthesize name(slug)+description frontmatter when missing |
| commands | skills are the /name surface |
flat ~/.dsh/skills/<name>.md with frontmatter |
| mcp | home cordis.patch.yml insert row, stdio supported |
managed - insert: block: dsh-mcp-client + the hnx mcp serve shim |
| hooks | bridges exist, opt-in packages | skip (warning); HOOK_SUPPORT: null
|
| sub_agents | programmatic providers | skip (warning) |
| rules | persona config only | skip (warning) |
| chat (C5) | dsh --profile acp |
ACP adapter table row |
| inventory (C3) | the three file surfaces above | scanner: skills dir + home patch MCP rows |