Preface¶
DeepSeek Harness (dsh) splits agent capabilities into plugins: models, tools, conversations, and interfaces can all be replaced or combined. Its official slogan is “Everything is a Plugin”. The fact that a model can write code does not mean it can successfully run a script in a conversation. Very often you need it to execute Python or Node.js locally, retrieve stdout, stderr, and exit code intact, then decide the next step.
The community plugin dsh-plugin-interpreters does exactly this. It exposes two tools to the model: run_python and run_node, which use local interpreters to execute code via stdin. This article is organized after cross-checking the plugin directory page, GitHub repository (including README, package.json, and source code), and npm package: explaining what it is, what it can do after installation, and how to configure interpreter paths.
A preliminary note: the plugin directory mentioned below (deepseek-harness-plugin.com) is a community-curated site, not an official app store for DeepSeek / Fangfu. You should review the source code and license before installing.
What It Is¶
dsh-plugin-interpreters is a conversation and message-type DSH plugin maintained by GitHub user HuanLinOTO. The internal plugin name in the repository is dsh-interpreters, the npm package name is @huanlin/dsh-plugin-interpreters, and the current released version is 0.1.0 (released on 2026-08-13). The repository was created on 2026-08-12, uses master as the default branch, and has the GitHub topic tag dsh-plugin.
It solves a very specific problem: providing two callable tools for the model in the current conversation:
- run_python: Runs code using a configured Python executable
- run_node: Runs code using a configured Node.js executable
Code is written to stdin (equivalent to python - / node -), and execution results are returned in structured fields, including stdout, stderr, exit code, duration, as well as whether it timed out or was cancelled. A new Interpreter Path card will appear in the plugin configuration section of the settings page, used to specify the interpreter location and timeout; the current path will be written in the tool description, so the model can see which executable it will call.
The license is subject to the LICENSE and package.json files in the repository, both are AGPL-3.0 (copyright statement: Copyright (C) 2026 Huanlin). GitHub and the directory page mark the SPDX as NOASSERTION, which is just a recognition result and does not change the AGPL text in the source code. Node.js ≥ 18 is required. The client manifest declares platform as web, and the README also follows the web profile installation method.
As of 2026-08-17, the GitHub API shows 9 stars for this repository; the directory page still shows 6 stars, which is due to indexing cache, please refer to the real-time data of the repository.
Core Features¶
Two Model-Callable Tools¶
The source code in src/tools.ts uses defineTool from @deepseek-ai/dsh-tools to register tools. The two tools have identical parameters:
| Parameter | Required? | Meaning |
|---|---|---|
code |
Yes | Source code to execute |
cwd |
No | Working directory for the child process |
The returned canonical JSON fields are as follows:
| Field | Meaning |
|---|---|
ok |
True when exit code is 0, no timeout, and not cancelled |
exit_code |
Process exit code; -1 if startup failed |
stdout / stderr |
Captured standard output / standard error |
duration_ms |
Wall-clock time elapsed (milliseconds) |
timed_out |
Whether the process was killed due to timeout |
cancelled |
Whether the process was killed due to abort signal |
The text displayed in the conversation is assembled by renderRunCodeOutput, roughly: first a line Exit code: … (…ms), add a note if timed out or cancelled, then list stdout and stderr separately. In repository tests, executing console.log("hello world") for node will return ok: true, exit_code: 0, and stdout as hello world.
Execute via stdin, Do Not Use Command Line Arguments¶
src/runner.ts uses Node.js’s spawn(executable, ['-']), writes code to the child process’s stdin, then closes the write end. The README states that this approach has no command line length limit. The interpreter path can be a name like python or node that exists in the PATH, or an absolute path, such as /usr/bin/python3 used in tests.
There are several edge cases directly readable from the source code during execution:
- Default timeout is 30000 milliseconds, the process is terminated with SIGKILL upon expiration
- The caller can pass an AbortSignal, and the process will also be killed with SIGKILL on abort
- Each of stdout and stderr retains a maximum of 1 MB, and [stdout truncated at 1 MB] or the corresponding stderr prompt will be appended if exceeded
- Situations such as timeout, cancellation, and non-existent interpreter are returned as values (timed_out / cancelled / exit_code: -1) instead of throwing exceptions to the tool layer
This is a local spawn call, not an isolated sandbox. The child process inherits the permissions of the current dsh process, and can access the directory pointed to by cwd and all resources accessible by the interpreter itself.
Interpreter Path is Configurable, Tool Description Updates Automatically¶
The default configuration is written in cordis.patch.yml:
pythonPath: 'python' # Path to Python executable
nodePath: 'node' # Path to Node.js executable
timeoutMs: 30000 # Execution timeout (milliseconds)
An empty string or invalid timeout will fall back to the above default values. Changes made on the plugin configuration page in the settings page during runtime are persisted to the interpreters namespace in $DSH_HOME/settings.yaml. The card copy (Chinese) is:
- Title: Interpreter Path
- Description: Configure the interpreter paths used by the run_python / run_node tools
- Three fields: Python executable path, Node.js executable path, execution timeout (milliseconds)
After modifying the configuration, the host will unregister the old tools and re-register them with the new configuration. The description seen by the model will include the current path, for example, the Python tool will show The Python interpreter is located at: /opt/python3.12. For headless setups without a settings service, it will fall back to the layered configuration in cordis.patch.yml, and the set interface will report that settings are unavailable at this time.
The configuration card uses the plugin’s own mounted HTTP prefix /interpreters/api (POST /interpreters/api/get and POST /interpreters/api/set), because DSH’s default settings RPC whitelist does not include the interpreters namespace. For end users, you only need to save on the settings page, no need to manually adjust this route.
Installation and Activation¶
The installation command given on the community directory page is:
dsh plugin add github:HuanLinOTO/dsh-plugin-interpreters
The repository README recommends installing to the web profile, and also provides the npm package name (consistent with package.json):
dsh plugin --profile web add @huanlin/dsh-plugin-interpreters
The official dsh CLI plugin command format is dsh plugin --profile <profile> add …, which will run pnpm in the corresponding profile directory. The client is declared as web, so it should normally be installed into the web profile. The directory page omits --profile, if the current environment requires explicit specification, add --profile web as per the README.
For reproducible installations, the directory page suggests pinning the commit hash:
dsh plugin add github:HuanLinOTO/dsh-plugin-interpreters#commit
Replace commit with the actual commit SHA from the repository. For local development, you can use link: pointing to the checked-out directory, the README example is:
dsh plugin --profile web add "link:D:/Projects/deepseek-harness/dsh-interpreters"
Modify the path to match your working copy.
Both the directory page and the dsh plugin mechanism remind: Plugins run with the permissions of the current dsh process, and may execute code during installation. When installing from GitHub, pnpm may also require permission to run the prepare build script. Before installing, open the repository to review the LICENSE (AGPL-3.0) and runner.ts, tools.ts under src/.
Typical Usage¶
After installing and starting the web profile, the model in the conversation will see run_python and run_node. The tool description will clearly state the current interpreter path, and that the optional parameter cwd can be used to specify the working directory.
One call corresponds to one spawn operation. Taking the Node code used in the repository unit tests as an example, the parameters can be:
{
"code": "console.log(\"hello world\")"
}
On success, ok will be true, and stdout will be hello world. Syntax errors will result in a non-zero exit_code and stderr; an incorrect interpreter path will result in exit_code -1, with spawn failure information in stderr.
When multiple versions of Python / Node.js coexist, do not rely on the one that happens to be first in the PATH. Write the path as an absolute path on the settings page, for example /usr/bin/python3, and the tool description will update after saving. For longer-running scripts, increase the Execution timeout (milliseconds); the default is 30 seconds, and timed-out processes will be killed with SIGKILL.
If you only modify cordis.patch.yml without using the settings page, the change will take effect as a layered seed configuration; the user layer will still be subject to the interpreters section in $DSH_HOME/settings.yaml. When both exist, the runtime resolution result will be based on the overlayed settings values.
Applicable Scenarios and Notes¶
It is particularly suitable for these use cases:
- Let the model validate a short Python or Node script locally, and continue revising based on real output
- Specify interpreters installed in virtual environments, pyenv, or nvm, instead of the system default python / node
- Need to view stdout, stderr, and exit code separately, instead of just knowing “whether it ran successfully”
Before using, you must accept the following restrictions:
1. Permissions and Security. Both the plugin and the launched interpreters run under the permissions of the current dsh process. code is generated by the model, and cwd can also be passed in by the model. Do not enable these two tools for untrusted tasks in unaudited conversations.
2. Not a Sandbox. The source code has no container, seccomp, or isolated user isolation, only timeout, output truncation, and abort. You should look for other sandbox solutions if isolated execution is required, do not treat this plugin as a security boundary.
3. Platform. package.json marks the client as web; for headless setups without settings support, only the default layered configuration paths can be used, and the settings page card will not work.
4. License. AGPL-3.0 has source code obligations for redistribution and network-provided services, please read the LICENSE before secondary packaging.
5. Output Limit. 1 MB per stream, will be truncated if exceeded. Not suitable for use as a log collector.
6. Early Version. There is only version 0.1.0 on npm so far, the API and configuration channel (the README once mentioned TypertRemote /api, the source code has been changed to self-hosted /interpreters/api) may still change, please refer to the current src/ in the repository.
Summary¶
dsh-plugin-interpreters adds two very lightweight but commonly used capabilities to DeepSeek Harness: local Python and Node.js interpreters, plus a configuration card for modifying paths. It does not wrap complex workflows, the execution model is just spawn + stdin + collecting stdout/stderr/exit code.
Directory page: https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-plugin-interpreters/
GitHub: https://github.com/HuanLinOTO/dsh-plugin-interpreters
npm: https://www.npmjs.com/package/@huanlin/dsh-plugin-interpreters