Back to home@beihzb

dsh-envsel

Per-session environment selector for DeepSeek Harness: Python / R / CLI slots from conda, standalone R, WSL, or custom paths, via /env, session_env, DSH_ENV_* facts, and a header dropdown.

Stars
3
Language
TypeScript
Created
Aug 17, 2026
Updated
Aug 21, 2026

Introduction

dsh-envsel

npm version npm downloads license GitHub stars

English | 中文

Session environment selector for DeepSeek Harness (DSH). Per-language slots — Python, R, CLI tools — each hold one first-priority environment drawn from conda, standalone R installs, WSL distributions, or user-pinned custom paths. Selections are per-session, persisted across restarts, and take effect for the model from the very next turn.

This is a standalone, npm-installable DSH plugin. It installs with dsh plugin add — no source patching, no monorepo checkout.

Features

  • /env command — read, assign, clear, and list environments from the chat.
  • session_env model tool — the agent can list, select, pin, and unpin environments on its own.
  • DSH_ENV_* shell facts — every shell call sees DSH_ENV_PYTHON, DSH_ENV_RSCRIPT, DSH_ENV_CLI_PREFIX for the session's selection.
  • Header dropdown — a per-language selector in the conversation header (Python / R / CLI tools), with an "Add path" form to pin any interpreter or install directory.
  • Cross-platform discovery — conda environments, standalone R (Windows Program Files, macOS framework + Homebrew, Linux /opt/R), WSL distributions on Windows, and manually pinned paths. WSL scanning is skipped automatically on non-Windows hosts.
  • Bilingual UI — product copy (the /env command, the header dropdown, and discovery warnings) follows the DSH interface language: English by default, Chinese when the DSH language preference is set to 中文.

Requirements

  • DeepSeek Harness 0.1.0-rc.7 or a compatible 0.1.0-rc.x (the web profile). The plugin's peers are the official @deepseek-ai/dsh-*@0.1.0-rc.7 packages that ship with that release.
  • pnpm on PATH (used by dsh plugin).

Installation

dsh plugin --profile web add @beihaizb/dsh-envsel

Restart dsh web, open an existing session, and the Env dropdown appears in the conversation header; /env and session_env work immediately.

Installing from a local checkout instead:

dsh plugin --profile web add "file:/absolute/path/to/this/repo"

Usage

/env command

/env                        show the current selection
/env python=mycondaenv    set the Python slot (conda name / R name / wsl:distro:name / custom:name)
/env r=R-latest            set the R slot
/env cli=base               set the CLI slot (PATH prefix)
/env python=                clear one slot
/env list [filter]          list all discoverable environments
/env add <path>             remember an interpreter or install directory on this machine
/env unpin custom:<name>    forget a pinned path
/env clear                  clear every slot
/env wsl                    rescan WSL distributions (Windows only)

session_env tool

The model can manage selections itself with action=list|get|set|pin|unpin.

Header dropdown

The Env button in the conversation header opens per-language dropdowns. The catalog is scanned lazily on first open (probing conda and WSL takes a few seconds). "Add path" pins any absolute interpreter or install path into the machine-local cache.

Configuration

The plugin works with no configuration. Optional config on the envsel row in your profile's cordis.patch.yml:

KeyDefaultMeaning
listTtlMs300000Catalog cache TTL in milliseconds.
condaCommandcondaConda executable name or absolute path.
standaloneRRoots[]Extra standalone-R roots scanned after the platform defaults.
wslEnabledtrueWhether WSL discovery is enabled (Windows only).
registerTooltrueWhether the session_env model tool is registered.
probeTimeoutMs20000Per-probe watchdog timeout in milliseconds.

Example:

# in your profile's cordis.patch.yml, after the bundle layer
- id: envsel
  name: 'dsh-envsel'
  config:
    wslEnabled: false
    registerTool: true

How it stores selections

Selections persist in a machine-local JSON store ($DSH_HOME/envsel-state.json, keyed by session id) — not in the session event log. The harness's session-persistence reader refuses a log containing an event type it does not know unless the event is marked ignorable, and Session.append provides no way for a downstream plugin to set that marker. Writing selection changes into the log would make the owning session unreadable after a restart, so this plugin owns its own durable state instead.

Development

pnpm install
pnpm run build    # tsc (types) + tsdown (lib/index.js host + lib/client.js browser bundle)
pnpm run test     # node:test unit tests

The build produces two artifacts: lib/index.js (the host plugin, loaded from the package root) and lib/client.js (the browser bundle, served by the client-modules scanner from the package's dsh.client declaration). A single package can be both a host row and a client row.

Known limitations

  • No per-session runtime-context text. The official AssembleContext has no agent binding, so the selection is not rendered into the model's system prompt. The model still sees the selection through DSH_ENV_* on every shell call and can query it with /env / session_env.
  • Peer-bound to 0.1.0-rc.x. The plugin declares @deepseek-ai/dsh-*@^0.1.0-rc.7 peers. A future DSH major/minor that changes these APIs needs a plugin update.
  • Selections are not part of the session log. They survive restarts in envsel-state.json but are not replayed from (or carried by) session logs.

License

MIT