dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Give your DeepSeek Harness agent three more pairs of hands. It sends long tasks to Claude Code, Codex and Antigravity using your own subscription logins, keeps one persistent session per lane, and never loses a job. 给 DeepSeek Harness 用的外部 agent 泳道:把长任务派给 Claude Code、Codex、Antigravity 三个 CLI,用你自己已有的订阅登录。每条泳道一个持久会话,作业重启和压缩都不会丢。
Persistent external agent workers for DeepSeek Harness. Delegate long-running tasks to Claude Code, Codex CLI and Antigravity CLI — through their own official CLIs and your existing subscription logins — with jobs that survive a restart or a context compaction.
给 DeepSeek Harness 用的外部 agent 泳道:把长任务派给 Claude Code、Codex、Antigravity 三个 CLI,用你自己已有的订阅登录。每条泳道一个持久会话,作业重启和压缩都不会丢。
English | 中文
Because the economics are lopsided, and because "cheap and general" and "best at this particular job" are two different things.
DeepSeek is cheap enough that talking is the default action: thinking out loud, arguing a design, reading a log, a small edit, a quick check. Routing that to a premium model pays a lot for very little. So the brain stays where it is — DSH holds the conversation, the plan and the context, and it is the thing you actually talk to.
What DSH should not do is everything. Some work is not a question of price but of kind:
So the design is complementary, not competitive: DSH is the orchestrator and the conversational brain; the external workers are specialists you hand one self-contained job at a time. The cheap, fast conversation stays cheap; the expensive model is spent only where it is genuinely better.
Two honest rules of thumb:
And one thing that is not free: workers spend your subscription quota, and a spent Codex allowance falls back to paid credits — which is why this plugin reads the quota before dispatching and asks first (see Quota and credits).
Strip away the features and this plugin does two things. Both exist because a human was doing them badly.
1. Being the wire. Without it, delegating means you do this: copy the failing output, switch to the other app, paste it, explain what you want, wait, copy the answer back, paste it into the project, and keep two windows straight in your head. That is transport work. It costs attention, it breaks focus, and it loses fidelity — what actually crosses over is your paraphrase of the error, not the error. Here the handover is mechanical: the task is written into a packet with the real files, log tails and acceptance criteria inlined, the worker runs in its own session, and the result, the artifacts and any failure come back as a durable record the agent can read. Nobody retypes anything.
2. Being the memory. Nobody remembers everything — and no model does either. Any agent that compacts loses detail eventually, and the loss is silent: if nobody notices in time to put it back, the decision made three hours ago simply is not there any more, and the task quietly goes wrong. Keeping that in a human's head, or in one chat window, means one compaction, one restart or one closed tab can break the work.
So the state of a job never lives inside a conversation. It lives on disk: the job record, the worker's own session id, the packet that was handed over, the artifacts that came back. Compaction and restarts cannot reach it, a different session can still read it, and resuming a job needs nobody to remember what the job was about.
And the loss becomes something a machine can act on, which is the part a human cannot do. You cannot see what a summarizer quietly dropped — what you notice is only that an agent got vaguer. A machine can at least see that a compaction happened, and then go and re-read the state from somewhere durable and re-brief whoever lost it. Compaction stops being an invisible hole and becomes an event with a recovery path.
Two rules keep that honest, because the naive version of the idea does not hold:
The workers are not copies of each other, they are different partitions. A lane working on one part of a project never knew what another lane was doing unless it was told. So recovery does not come from "the other agent still remembers" — it comes from the durable record that every handover writes. Think of the sessions as caches and the disk as the source of truth: compaction is a cache eviction, and recovery is going back to the source.
More workers lowers the chance of an unrecoverable loss, and can raise the chance of two lanes holding two versions of the truth — but that is a property of the arrangement, not of the count. Two things remove the risk entirely, and both are choices you make:
What remains under that arrangement is smaller and worth naming anyway: discipline (a lane that does not write down what it did leaves no trace for the others to recover) and staleness (a shared file can be present but old, so what matters is knowing what is new since you last read). The job ledger helps with both, because it is timestamped and it records what was handed over and what came back — but it starts working only once the writing happens.
What is not automated yet, said plainly: noticing that a worker's own session compacted and re-briefing
it is still a manual step today (resume_external_job, or a fresh packet). The plugin guarantees the
state is recoverable; it does not yet watch for the moment recovery is needed. And the shape of the
recovery is entirely up to how you set the lanes up — the plugin moves the work and keeps the record;
the shared directory that makes one lane's work readable by another is something you point them at.
Give every lane the same project (or the same hand-off directory) as its working context and you get the
arrangement described above: not several agents comparing memories, but several agents reading one
record.
Two things this does not buy, said plainly:
A native DeepSeek Harness (DSH) plugin. It adds six tools to your sessions, plus one
delegate_<product> per custom product you declare:
| Tool | What it does |
|---|---|
delegate_claude | Hand a task to the Claude Code worker |
delegate_gpt | Hand a task to the Codex CLI worker |
delegate_google | Hand a task to the Antigravity CLI (agy) worker |
check_external_job | Read any job — status, result, artifacts, errors — from disk |
resume_external_job | Continue a blocked/failed job in the same worker session |
worker_config | List the real models each product offers, and manage its lanes (role + model + effort + speed) |
Plus a panel in the Web UI: a row above the composer lists every job with its live status, and expands into a drawer with a Lanes tab (one card per lane: role, requested model, the model it last ran on, state, session, directory) and a Jobs tab (per-job detail: task, lane, worker session, artifacts, error, result preview). It renders nothing at all while there are no jobs, so a session that never delegates is untouched.
Each lane is an independent, long-lived session in its own product, in its own working directory
(~/.dsh/workers/<lane id>), with its own tools. One product can run several lanes — that is how gpt
does quick edits on a fast model in one lane while a heavier model grinds through something long in
another. Your DSH agent stays the orchestrator; the lanes do the work.
DSH agent (orchestrator)
│ delegate_gpt(task, lane: "quick", context_files, logs, acceptance, …)
▼
Codex lane `quick` ── runs in ~/.dsh/workers/quick/ ── writes jobs/ext-3/out/*
│ (its own persistent thread)
▼
durable job record (disk) ──► completion notice back into your session
DSH ships a subagent seam, and there are optional product providers
(@deepseek-ai/dsh-subagent-codex, @deepseek-ai/dsh-subagent-claude-code). They are one-shot by
design: a fresh process, a fresh thread, one turn — the upstream provider README states plainly that
there is "no continuation, resume, pooling, progress stream, or product-session persistence."
This plugin is built for the opposite case: the same worker, over and over. Each lane keeps one dedicated session that every later delegation into that lane continues, plus a durable job ledger so nothing is lost when the conversation is compacted or the harness restarts.
Searched the ecosystem (GitHub + the 4,400-entry awesome-dsh-plugin list). The honest summary:
the capability exists elsewhere, but not in this shape.
| Project | What it is | How this differs |
|---|---|---|
| Enderfga/claw-orchestrator ★580+ | A standalone runtime (TypeScript, 78 tools) wrapping Claude Code / Codex / Antigravity / Cursor / OpenCode: persistent sessions, councils, dashboards, MCP server, OpenAI-compatible proxy | Closest in capability, different in architecture: it runs as its own daemon on its own port and you reach it over MCP/HTTP. This plugin is a DSH plugin — one composition row, no extra process, no extra port, tools appear directly in the session. It is also ~80 KB of plain JS instead of a runtime. |
| mjylfz/dsh-subagent-codex | DSH plugin: one subagent_codex tool over the official SubagentProvider seam | Codex only, one-shot (new Codex session every call), subagent-result shaped. This one covers three products and resumes the same session by default. |
@deepseek-ai/dsh-subagent-codex / -claude-code (official, optional) | DSH product providers | Officially one-shot, and the Codex one resolves codex from PATH only. |
| amlyczz/dsh-agy-link, darkings/dsh-agy-provider, DavidRm1911/dsh-llm-subscription | Use these CLIs/subscriptions as model providers in DSH's model picker | Opposite architecture: there, your DSH agent runs on that model. Here, that product's own agent runs the task with its own tools, workspace and session. |
| NOirBRight/dsh-external-agents | DSH plugin: a control plane for the same kind of external coding products (Codex, Claude Code, Cursor Agent, Antigravity) — a Settings section that probes/enables them, tools on the host plane, background jobs in the DSH Job Panel | The closest sibling in intent, and opposite in the one decision that changes daily use: theirs is one-shot by design (their ADR 0003 decides that every delegation pays for a fresh product context, and that you cannot add a line to the same Codex thread), while this plugin keeps a persistent session per lane you continue and can resume. See the direct comparison below. |
| czm15053/dsh-peer-link, kirkchinese/claude2dsh | Peer messaging / session import between DSH and Claude Code | Not delegation: no job, no result contract, no resume-as-a-job. |
What appears to be unique here:
blocked (missing CLI / not logged in), retryable (quota,
timeout, dead process). A worker that dies is never silently lost.config.json (see
Custom products). No fork, no code change, no release.dsh-external-agents, the closest siblingSame problem, same products, and two projects that answer the central question differently. Theirs is documented in an ADR, so this is not a guess about their intent:
dsh-external-agents | this plugin | |
|---|---|---|
| Continuity | one-shot, by design. Every delegation starts a fresh product context; a new process each time | one persistent session per lane, continued by default and resumable after a failure |
| What you can say | "carry out this bounded task" | "continue where you left off, but do X instead" |
| Job records | the harness's own job registry (Job Panel) — in-memory, so a restart loses them | the durable storage domain, readable from any session after a restart or a compaction |
| Sessions per product | one per adapter (one model) | as many lanes as you declare (product + model + role), each with its own directory |
| Adding a product | a fixed set of four shipped adapters; a user-defined argv adapter is an explicit non-goal | any CLI by config recipe — including API-only models with no CLI at all |
| Handover | a bounded task text | a packet on disk (inlined files, logs, images, acceptance criteria) plus collected artifacts |
| Plan quota / credits | not covered | Codex usage is read before dispatch; a spent allowance cannot be spent silently |
| Who sees the tools | host plane — every session in the profile | attached per session; exclusions by preset / workspace / session id |
| What they do better | a real Settings section (probe each product, enable it, pick the default) — this plugin configures through config.json and shows state in the dock panel. And they support Cursor Agent, which this plugin does not. |
If all you want is "enable a worker, fire one task, watch it in the Job Panel", their control plane does that with a nicer settings surface. This plugin exists for the other case: the same worker, used over and over, that has to remember.
dsh-web-app).claude auth login (no API key needed)codex login (ChatGPT subscription)irm https://antigravity.google/cli/install.ps1 | iex, then run agy once
(it usually picks up an existing Antigravity/Google sign-in from the OS keyring)No API keys are created, no browser automation, no cookie reading. A worker that is not installed or
not signed in is simply reported as blocked by check_external_job.
# from a release tarball (the URL never contains a version)
dsh plugin --profile web add --force \
https://github.com/piecuzwhynot/dsh-external-workers/releases/latest/download/dsh-external-workers.tgz
# a fixed version, with a checksum to verify it
dsh plugin --profile web add --force \
https://github.com/piecuzwhynot/dsh-external-workers/releases/download/v0.3.0/dsh-external-workers-0.3.0.tgz
# or from a local checkout / tarball
dsh plugin --profile web add link:C:/path/to/dsh-external-workers
dsh plugin --profile web add file:/path/to/dsh-external-workers-0.3.0.tgz
Then restart the harness (dsh web) — the bundle list is read at boot — and open a session.
Ask it: "list your external worker tools" and you should see all six.
Verify and remove:
dsh plugin --profile web list
dsh plugin --profile web remove dsh-external-workers
The release artifact is built by node scripts/release.mjs, which refuses to pack when the tarball
does not match the working tree byte for byte (that is what catches "packed before rebuilding the
client bundle") and writes SHA256SUMS next to it.
link:installs need a localnode_modules. A linked package resolves its own bare imports from its real path, so it cannot see the profile'snode_modules. Either install from npm/tarball, or drop junctions/symlinks for@deepseek-ai/dsh-tools,@deepseek-ai/dsh-storage-domain,@deepseek-ai/dsh-llmandzodinto the package's ownnode_modules.
Two places, and they edit the same lanes through the same host code, so they can never disagree:
config.json — the declarative version: lanes, products, quota, scope, and per-product
CLI behaviour. Use it to seed a fresh install or to keep the setup in version control.worker_config tool — the same operations, for when you would rather just say it: "give the
quick lane effort high".The drawer's Conversation tab shows the worker's own conversation — not a summary of it: what it was asked, what it said, which tools it called and with what arguments, and what came back. Long tool output and its reasoning fold away; the turn text stays readable.
# 1) see the real model list from each product, then set up the lanes
"Show me the available models for the three external workers."
"Run gpt as two lanes: 'quick' on gpt-6-luna/medium with speed priority, and 'deep' on
gpt-6.1-sol/xhigh with speed priority. Leave claude on opus/high for UI work."
# 2) delegate into a lane
"Delegate to gpt in the 'deep' lane: refactor this module to async, put the result in
its own folder, then read the artifacts and apply them to my project."
# 3) later, from any session
"Check the external jobs."
Details, worked examples and troubleshooting: docs/USAGE.md (中文: docs/USAGE.zh.md).
Everything lives in config.json next to this package; most of it is read on every use, so edits
apply without a restart.
scope)"scope": {
"mode": "per-session",
"excludePresets": ["my-persona-preset"],
"excludeWorkspaces": ["C:\\Users\\me\\companion-workspace"],
"excludeSessionIds": ["session-…"]
}
per-session (default) registers the tools into each chosen agent's own scope. An excluded
session has no registration at all — not a hidden tool, an absent one.off gives them to nobody; global gives them to every session (rarely what you want)."lanes": [ { "id": "main", "worker": "claude", "role": "example lane: planning and code review", "model": "opus", "effort": "high", "speed": null },
{ "id": "quick", "worker": "gpt", "role": "example lane: fast edits and scripted chores", "model": "gpt-6-luna", "effort": "medium", "speed": "priority" },
{ "id": "deep", "worker": "gpt", "role": "example lane: the heavy model work", "model": "gpt-6.1-sol", "effort": "xhigh", "speed": "priority" },
{ "id": "research", "worker": "google", "role": "example lane: research and data gathering", "model": "gemini-3.1-pro-high", "effort": "high", "speed": null }
]
A lane is the unit of work: one product + one model (and effort/speed) + one role, with its own
persistent session and its own working directory ~/.dsh/workers/<lane id> (a lane that inherited a
pre-lanes session keeps that session's original directory instead — see the upgrade note below). The same
product runs several lanes, and that is the point — Codex and Claude each bind a session to one model and
degrade it when that thread is resumed on another, so gpt + gpt-6-luna and gpt + gpt-6.1-sol must
not share a session.
id must match /^[a-z0-9][a-z0-9_-]{0,31}$/, and it names the lane's own workspace
(~/.dsh/workers/<id>) — for a lane that inherited a session, the inherited directory wins.lanes key and the plugin falls back to **one lane