Bundle
dsh-science
Claude Science-style research workbench for DeepSeek Harness: ReAct research-loop engine (research_* tools), versioned artifacts with provenance (artifact_* tools), SSH remote-compute engine for long bioinformatics jobs on workstations/HPC (remote_* tools), and 11 science skills for genomics / pathogens / bioinformatics. Ships the tiered cross-provider model router via the companion dsh-model-tier bundle.
- Source
- biociao
- stars
- 27 stars
- License
- MIT
- Updated
- Updated 16 days ago
Readme
# dsh-science
[](https://www.npmjs.com/package/dsh-science)
[](LICENSE)
[](package.json)
[](https://github.com/topics/dsh-plugin)
---
<img width="865" height="795" alt="Screenshot 2026-08-14 at 19 49 06" src="https://github.com/user-attachments/assets/b6ef210f-6081-42b7-91fd-484f554c955e" />
**A Claude Science–style research workbench for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — for genomics / pathogens / human health / bioinformatics projects.**
> One-liner: **dsh-science** — Claude Science-style research workbench for DSH: ReAct research-loop engine (research_* tools), versioned artifacts with provenance (artifact_* tools), an SSH remote-compute engine (remote_* tools, mirroring Claude Science's Computer / Remote compute clusters), and 11 science skills for genomics / pathogens / bioinformatics.
- **ReAct research loop engine** — `research_init` / `research_state` / `research_hypothesis` / `research_experiment` / `research_findings` / `research_phase` / `research_review` / `research_report`, persisted in a `research-manifest.json` state machine (Question → Hypothesis → Experiment → Observe → Analyze → Conclude → Next Question).
- **Versioned artifacts with provenance** — `artifact_save` / `artifact_list` / `artifact_show` / `artifact_diff` / `artifact_verify` / `artifact_deprecate` / `artifact_reproduce`: every result saved as `artifacts/<name>/v<N>/` with per-file SHA-256, `artifact.json` provenance (command / inputs / environment / envFile) and an append-only `provenance.md`.
- **Remote compute engine (SSH / HPC clusters)** — 16 tools: `remote_host_add` / `remote_host_probe` / `remote_host_notes` / `remote_run` / `remote_status` / `remote_logs` / `remote_pull` / `remote_cancel` / `remote_exec` etc. Connect lab workstations or HPC clusters via `~/.ssh/config` aliases (nothing installed on the host, zero third-party deps). Long bioinformatics jobs run as detached processes on workstations or via `sbatch` on SLURM — they survive connection loss; submission asks for approval by default; `remote_status` batch-monitors and auto-transitions state (running → succeeded/failed/killed); `remote_pull` fetches outputs back (files over the size threshold stay on the host with their paths recorded).
- **Remote Hosts config UI (bundle/profile-level)** — a Settings > 远程主机 page (the analog of Claude Science's Settings > Compute > SSH hosts): list/add/probe/edit/remove hosts, plus each project's access allowlist and job summary. Host-side REST API (`webServer` route `/dsh-science/remote-hosts/*`, `engines/remote-hosts-ui.mjs`) + client bundle (`client/remote-hosts-ui/`, built by `scripts/build-client-bundle.mjs`) sharing the same data files as the remote engine. Requires a web-process restart to activate (see [docs/remote-hosts-ui.md](docs/remote-hosts-ui.md)).
- **Model Tier router (tiered, cross-provider)** — via the companion bundle [`dsh-model-tier`](packages/dsh-model-tier/): within one session, automatically routes auxiliary requests (session titles, compaction summaries) and subagent/background tasks to a **light tier**, keeps the main conversation on the **default tier**, and escalates complex work (deep subagent chains, very long inputs) to a **strong tier** — each tier may point at a **different provider** (e.g. strong GLM-5.3 / default deepseek-v4-flash / light minimax-M3), mirroring Claude Code's Opus/Sonnet/Haiku strategy. Built on DSH's native `agent/request` + `llm/stream` waterfall extension points; a no-op when the tier's provider is unregistered. Installed automatically with dsh-science, but also standalone-installable into any profile (`dsh plugin add dsh-model-tier`).
- **11 science skills** — research-loop, science-project-setup, artifact-provenance, scientific-reviewer, literature-connector, parallel-delegation, manuscript-writing, bioinformatics-toolkit, conda-environments, data-inventory, remote-compute.
All in-repo engine plugins are **zero-dependency** (Node built-ins + the system OpenSSH binaries, sharing `engines/core.mjs`) and register plain cordis tools; the companion `dsh-model-tier` router is likewise zero-dependency. Installable either as a profile bundle (`dsh plugin add`) or as an agent preset (`科学模式`).
### v0.2.0: Model Tier router (new, companion bundle)
Mirrors Claude Code's Opus/Sonnet/Haiku tiering: within one session, auxiliary requests (`purpose ∈ {session-title, compaction}`) and subagents (`session.meta.origin === 'subagent'`) are routed to the **light tier**; the main conversation keeps its own per-session model selection (never overridden); deep subagent chains (`delegationDepth ≥ subagentDepthStrong`) and very long inputs (`escalateOnChars`, opt-in) escalate to the **strong tier**. An optional LLM pre-classifier (`routing.classify`) grades each user prompt / subtask dispatch by complexity (light / default / strong) before routing. Each tier is `{provider, model, reasoningEffort?}` and may span providers.
Ships as the standalone bundle **[`dsh-model-tier`](packages/dsh-model-tier/)** — dsh-science depends on it and mounts it in its `cordis.patch.yml`, but it can equally be installed on its own into any profile (`dsh plugin add dsh-model-tier`):
```yaml
- id: model-tier
name: dsh-model-tier
config:
tiers:
strong: { provider: zai-coding-cn, model: glm-5.3 }
default: { provider: deepseek-official, model: deepseek-v4-flash }
light: { provider: opencode-go, model: minimax-m2.7 }
routing:
auxiliary: [session-title, compaction]
subagents: light
subagentDepthStrong: 3
```
- **Host plane** — mounted in the profile bundle (`cordis.patch.yml`), not the agent preset, so it applies to every session and subagent on the profile.
- **Safety rails** — no `tiers` configured → inert no-op; target provider unregistered → no routing; a failing light-tier call automatically falls back to the original route (auxiliary features never break).
- **Verified** — `node packages/dsh-model-tier/test/model-tier.test.mjs` (zero-dependency unit matrix) + `bash packages/dsh-model-tier/scripts/test-model-tier.sh` (E2E: light tier pointed at a local mock LLM; asserts the title request is actually routed).
### v0.2.0: Remote compute (new)
Mirrors Claude Science's **Remote compute clusters / Computer** capability, following its documented mechanism:
- **Host registration + read-only probe** — `remote_host_add` takes a `~/.ssh/config` alias (or `user@host`; ProxyJump etc. handled by OpenSSH), with optional port/identityFile overrides; probing records CPUs, memory, GPUs, CUDA driver, conda/module/Apptainer presence, scratch dirs, `sbatch` and SLURM partitions (`remote_host_probe` re-runs it). Host registry: `$DSH_HOME/remotes/hosts.json`.
- **Job submission** — `remote_run` copies script + inputs into `<scratch>/<jobId>/` (default `~/dsh-scratch`); workstations run it as a detached `nohup+setsid` process (connection-loss safe), SLURM clusters get `sbatch` (with `--time`); default job timeout 30 min; submission asks for approval by default (the analog of Claude Science's "Run this job on <host>?" card).
- **Monitoring & reaction** — `remote_status` batch-probes (ps / squeue+sacct / done+exitcode markers) and auto-transitions state; `remote_logs` tails logs; `remote_pull` fetches outputs and writes `pulled-manifest.json` (files > 100 MB stay on the host with recorded paths); `remote_cancel` kills (process group / scancel). Job registry: `<project>/.dsh/remotes/jobs.json`, persists across sessions.
- **Host Details document** — `remote_host_notes` maintains per-host notes (environment activation, partitions/account, conventions) that the model reads before submitting jobs.
- **Per-project access allowlist (allowed servers, isolated per project)** — every host-connecting action (add/probe, `remote_host_probe`, `remote_exec`, `remote_run`) requires the host to be in the project's allowlist (`.dsh/remotes/allowlist.json`) by default; **first use pops an approval dialog** and, on approval, persists the grant at project scope (the analog of Claude Science's "This project" approval scope). The project root resolves by priority: `research-manifest.json` (research project) → `.dsh` (workspace) → `.git` → session cwd — **multiple research projects in one workspace keep separate allowlists**; grants never leak across projects (authorization paths fail closed when no session cwd is available). Review with `remote_host_allowlist`, revoke with `remote_host_revoke`, pre-grant with `remote_host_allow` (approval-gated); disable with `requireHostAccess: false` for unattended runs.
### v0.1.1 hardening (robustness update)
- **Concurrency-safe state**: all manifest/artifact writes go through a lightweight file lock (O_EXCL + stale reclaim) and atomic tmp+rename — parallel subagents can no longer corrupt or lose updates on `research-manifest.json` / `artifacts.json`.
- **Structured error codes** (`ERR_NOT_INIT` / `ERR_NOT_FOUND` / `ERR_VALIDATION` / `ERR_PATH` / `ERR_QUOTA` / `ERR_LOCK_TIMEOUT` / `ERR_IO`) instead of opaque strings.
- **Hypothesis state machine** (proposed → testing → supported/refuted/inconclusive) and **forward-only phase transitions** (rewind requires config).
- **manifest ↔ artifacts linked**: `research_state` merges the artifact index; `artifact_save` writes back to the manifest.
- **Manifest schema v1→v2 migration** on load, persisted on next write.
- **Artifact upgrades**: streaming SHA-256 (big files), identical-content dedup via hardlink, `artifact_diff` / `artifact_verify` / `artifact_deprecate`, envFile + input hashes in provenance.
- **Structured JSON outputs** (`research_report`, `artifact_diff`, `artifact_verify`) and an audit log at `<root>/.science.log`.
## Install
### Option A — profile bundle (community standard)
```bash
dsh plugin --profile web add dsh-science # after npm publish
# or straight from GitHub:
dsh plugin --profile web add "github:biociao/dsh-science"
```
Restart the profile (or refresh the Web GUI). The bundle inserts the three engines
into the profile layer stack; the `research_*` / `artifact_*` / `remote_*` tools
become available to every agent on that profile.
### Option B — agent preset (full 科学模式 experience, per-agent)
```bash
git clone https://github.com/biociao/dsh-science ~/.dsh/.agent-presets/science
# or from a local checkout:
bash scripts/install.sh # copy (or: bash scripts/install.sh link)
```
Then create a session in the DSH Web GUI and pick the **科学模式** preset — the
preset carries the research persona + engines with per-agent scoping.
### Skills
The 11 skills are discovered automatically from a project's `.dsh/skills/`
(drop this repo's `skills/` into your project), or install them machine-wide:
```bash
bash scripts/install-skills.sh # -> ~/.dsh/skills (respects $DSH_HOME)
```
## Quick start (first session)
1. `research_init` — create `research-manifest.json` + the project skeleton
(`experiments/ literature/ artifacts/ analyses/ figures/ manuscript/ reviews/ data/ envs/`).
2. Read `research_state` at the start of every session; the loop state persists
across sessions.
3. Run the loop: `research_hypothesis` (H1/H2/…) → `research_experiment` (E01/…,
creates `experiments/<id>/{design.md,log.md,code/,results/}`) → run code →
`research_findings` (appends to log.md, updates hypothesis status, advances
the loop) → `artifact_save` for anything worth citing or reproducing.
4. When GPU/cluster/specialized environments are needed: `remote_host_add` the host
→ `remote_run` a background job (approval required) → poll `remote_status` /
`remote_logs` → `remote_pull` outputs when done → `artifact_save` to archive.
See [docs/remote-compute.md](docs/remote-compute.md) and the `remote-compute` skill.
5. For key claims: extract the claim, have a review subagent check it against the
execution records (see the `scientific-reviewer` skill), archive with
`research_review` (writes `reviews/R0n/report.md`).
## Repository layout
```
dsh-science/
├── package.json # dsh.bundle.patch -> ./cordis.patch.yml (+ dsh.client + exports)
├── cordis.patch.yml # bundle patch: inserts the engines by subpath export + mounts dsh-model-tier
├── packages/
│ └── dsh-model-tier/ # 配套独立 bundle:模型分档路由(可单独 dsh plugin add)
├── engines/ # canonical engine sources (bundle form)
│ ├── core.mjs # shared core: locks, atomic writes, error codes, streaming sha256, structured tools, audit
│ ├── research-loop.mjs
│ ├── artifact-registry.mjs
│ ├── remote-compute.mjs# SSH/local transports, host registry + probe, job submit/monitor/pull/cancel
│ └── remote-hosts-ui.mjs# Remote Hosts 设置页的宿主 REST API(webServer 路由)
├── client/ # client 插件(设置页 UI,bundle/profile 级)
│ └── remote-hosts-ui/ # src/index.js 源码 · lib/client.js 打包产物(build-client-bundle.mjs)
├── preset/ # agent-preset form (mirrors engines/ via sync-engines.sh)
│ ├── agent.cordis.yml # references ./engines/*.mjs (relative, preset mount)
│ ├── preset.yml
│ └── engines/ # mirror — keep in sync: bash scripts/sync-engines.sh
├── skills/ # 11 SKILL.md skills
├── scripts/
│ ├── install.sh # install preset -> ~/.dsh/.agent-presets/science
│ ├── install-skills.sh # install skills -> ~/.dsh/skills
│ ├── sync-engines.sh # mirror engines/ -> preset/engines/
│ ├── init-project.sh # project skeleton without a science session
│ ├── build-client-bundle.mjs # wrap client src -> __ModuleLoader__ bundle (lib/client.js)
│ ├── smoke-test.mjs # 125 checks against a temp workspace (node >= 18)
│ └── stability-test.mjs# 25 concurrency/atomicity/stress checks (locks, lost-update, soak, migration)
└── test/verify-bundle.sh # isolated end-to-end bundle install + boot + client scan check
```
## Verification
```bash
node scripts/smoke-test.mjs # engine logic + end-to-end loop + error codes + migration
node scripts/stability-test.mjs # concurrency / atomicity / lock / stress stability checks
bash test/verify-bundle.sh # pnpm pack -> isolated profile -> install -> boot check
```
All are part of the release checklist and are safe to run in CI (both test scripts
write only to a temp workspace; the bundle test uses an isolated `$DSH_HOME`).
## FAQ
**Why subpath exports and not relative paths in the bundle?**
`dsh plugin add` installs the package into the profile and its `cordis.patch.yml`
rows join the profile composition. The profile loader resolves a row `name`
relative to the **profile directory** (not the package), so `./engines/x.mjs`
fails with `ERR_MODULE_NOT_FOUND`. Referencing `dsh-science/engines/x.mjs`
(subpath export, `exports` in `package.json`) resolves from the profile's
`node_modules` and works — verified experimentally on dsh `0.1.0-rc.6`.
The agent-preset mount, by contrast, resolves relative names from the preset
directory, which is why `preset/agent.cordis.yml` can use `./engines/*.mjs`.
**Bundle or preset — which should I use?**
- Bundle: tools available to every agent on the profile; one command to install.
- Preset: the full 科学模式 experience (research persona, per-agent scoping).
The persona row in `cordis.patch.yml` is commented out because a profile-wide
persona would apply to all agents — uncomment it before publishing if that is
what you want.
**Where do the skills come from?**
A project's `.dsh/skills/` is auto-discovered; `scripts/install-skills.sh` puts
them machine-wide in `~/.dsh/skills` (respecting `$DSH_HOME`).
## Development
Branching model & release workflow (main = release, dev = integration, `feat/*` = features,
tag-triggered npm publish + GitHub Release via Actions): see
[docs/branching.md](docs/branching.md).
```bash
bash scripts/sync-engines.sh # after editing engines/*.mjs — keeps preset/engines in sync
node scripts/smoke-test.mjs # logic + static package checks
node scripts/stability-test.mjs # concurrency / atomicity / lock stability checks
bash test/verify-bundle.sh # end-to-end bundle install + boot
```
**Workspace-isolation patch** — DSH's New Session used to fall back to the most
recently used Workspace, letting automation spawn sessions into unrelated
projects. `scripts/patch-session-isolation.mjs` applies the one-line guard
(idempotent, backs up first; re-apply after every `dsh` upgrade). See
[docs/workspace-isolation.md](docs/workspace-isolation.md).
```bash
node scripts/patch-session-isolation.mjs apply # idempotent, backs up first
node scripts/patch-session-isolation.mjs status # check current state
node scripts/patch-session-isolation.mjs revert # restore pristine file
```
## Community
- Topic: [github.com/topics/dsh-plugin](https://github.com/topics/dsh-plugin)
- Curated lists: [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin) · [awesome-deepseek-harness](https://github.com/0xsline/awesome-deepseek-harness)
## License
MIT — see [LICENSE](LICENSE).
Install
dsh plugin --profile web add github:biociao/dsh-science#23767ab2f8d7bcf84a0820daa4c6ae79549da000
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-science from the hub