dsh-claude-live
Run Claude Code as a subagent inside DeepSeek Harness with its steps streaming live into the session UI. Works on the released harness.
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 25, 2026
- Updated
- Aug 27, 2026
Introduction
dsh-claude-live
Run Claude Code headless as a subagent from the DeepSeek Harness, with its steps streaming into the session view while it works.
One tool. One child process. No registry, no role library, no continuable sessions.
Why this exists
Two things that don't work today:
- Polling is a lie.
subagent_progressonly reports what the child has already flushed; between polls you see nothing, and the model burns turns asking. Progress has to be pushed, not sampled. - Custom events break the viewer.
dsh-background-agentswrites its ownbackground-agents/factevent type. The rc.2 persistence read path refuses to interpret any event outsideKNOWN_SESSION_EVENT_TYPES, so the web UI cannot replay those sessions at all.
This plugin pushes progress through an event pair the installed harness
already understands: tool/code-dispatch-start / tool/code-dispatch — the
same pair the core's own Code Mode bridge uses to log nested sub-calls. Both
are documented as log-only: deriveMessages() ignores them, so the digest
lines never re-enter model context, but UIs use them for live per-sub-call
state. The digest therefore renders as sub-rows under the still-running
claude_live call, exactly like nested tool calls under run_code.
Requirements
- DeepSeek Harness
0.1.1-rc.2or later. claudeonPATH(or~/.local/bin,~/.claude/local,/usr/local/bin,/opt/homebrew/bin), authenticated.- Node ≥ 18.
Install
dsh plugin --profile web add dsh-claude-live
dsh plugin --profile headless add dsh-claude-live # optional
For a local checkout, install the directory into the profile with pnpm and add the layer yourself:
cd ~/.dsh/profiles/web
pnpm add file:/path/to/dsh-claude-live
# ~/.dsh/profiles/web/cordis.patch.yml
- insert:
- id: claude-live
name: 'dsh-claude-live'
config:
timeoutMs: 1800000
Restart the harness afterwards. See TESTPLAN.md for the full install +
smoke-test sequence.
Usage
claude_live task="Refactor src/calc.js and run its tests" permissionMode="full" cwd="/srv/project"
| Argument | Required | Meaning |
|---|---|---|
task | yes | Complete, self-contained prompt. The child does not see this conversation. |
cwd | no | Working directory. Defaults to the harness process directory. |
permissionMode | no | readonly → --permission-mode plan; full → --dangerously-skip-permissions; default (the default) → Claude's own configuration. |
model | no | --model override. Omit for Claude's default. |
Returns { ok, result, stats: { events, toolCalls, durationMs } }, or
{ ok: false, error } when the CLI could not start, timed out, was cancelled,
or exited without a result event. Every return value is sanitized to strict
lossless JSON (no undefined, no NaN/Infinity/-0, no class instances,
no cycles) — the harness rejects anything else.
While the run is in flight you see ONE self-updating row under the
claude_live call (throttled ≤1/s) — the header tracks the current step,
the body is a rolling window of recent digest lines plus a live counter:
claude:Bash · npm test ← header = current step
▸ claude full: Refactor src/calc.js and run its tests
✱ Reading the module to see what the tests cover
▸ Read: /srv/project/src/calc.js
▸ Bash: npm test
◦ 4 steps · 0:12 ← rolling counter
The row settles to claude:done when Claude finishes. No row-per-step
stacking — the transcript stays flat, like the Claude Code CLI.
Config
| Key | Default | Meaning |
|---|---|---|
timeoutMs | 1800000 (30 min) | Hard cap per run. On expiry the child's whole process group gets SIGTERM, then SIGKILL after 5s. |
command | auto-detected | Explicit path to the claude binary. Used strictly — a bad value fails loudly rather than falling back. |
Cancelling the tool call (exec.signal) kills the child the same way.
Coexistence
Distinct plugin id (claude-live) and tool name (claude_live), so it runs
alongside dsh-plugin-product-subagents without collision.
License
MIT
Prior art
- relay-dsh-plugin-claude also streams Claude Code activity into the DSH conversation — as a session backend: you pick "Claude Code" as the session mode and DSH's own agent loop steps aside. dsh-claude-live is the subagent shape: DSH stays the driving agent and delegates, so DeepSeek plans/orchestrates and Claude executes chunks, with both visible in one session.
- dsh-plugin-product-subagents runs Claude as a subagent (richer lifecycle: roles, continuable children) but its trace tool currently fails with "value is not lossless JSON" (issue #4), so no live steps.
- dsh-background-agents streams via custom event types the released harness can't replay (needs unreleased core).
Contributing
Small by design, and there's plenty to do: streaming for codex and ACP CLIs as the child, cancellation from the UI, richer digests (diffs, token counts), tests against future dsh releases. Issues and PRs welcome.