Preface

When developing agents with DeepSeek Harness (DSH), most of the time is spent in the web GUI. However, once you need to execute shell commands—starting services, viewing logs, temporarily entering vim to modify configurations—you have to switch to a separate terminal window and manually verify the directory and session state upon returning.

dsh-web-terminal solves this problem: it adds a Terminal entry point to the web GUI sidebar, opening a multi-tab terminal panel where each tab is a real PTY shell on the host process. DSH’s philosophy is “everything is a plugin,” and this plugin does not modify the dsh source code; it just needs to be mounted into the web profile. Below, we introduce it in the order of functionality, installation, configuration, and verification.

What is this

dsh-web-terminal is a local terminal plugin for the DeepSeek Harness web GUI maintained by iamsee123, currently version 0.1.1, under the MIT license (both the License section in the README and package.json indicate this). One-sentence positioning: a sidebar multi-tab xterm.js panel, where each tab runs a real PTY shell on the host process via node-pty and streams via WebSocket.

The dependency stack is straightforward: node-pty ^1.1.0 is responsible for the PTY, @xterm/xterm ^6.0.0 is responsible for frontend rendering, @xterm/addon-fit ^0.11.0 is responsible for size adaptation, ws ^8.18.0 is responsible for transmission, and react ^18.2.0 serves as a peer dependency.

Core Features

According to the README, the capabilities are focused on six points:

  1. Real pseudo-terminal shell: Interactive programs (vim, top, htop), Ctrl-C, and resize are all available;
  2. Multi-tab terminal panel, providing controls for New / Close / Disconnect / Reconnect / Clear;
  3. Auto-fit (automatic adaptation) when the panel opens, window resizes, or the container changes;
  4. Configurable shell and working directory (via settings panel or patch yaml);
  5. All routes are protected by a loopback-only trust fence (same-origin + 127.0.0.1/localhost verification);
  6. Hot-pluggable: No modification to dsh source code, mounted via the web profile bundle list, using the same dual-face plugin mode as dsh-ssh.

Dual-half Architecture

The plugin is split into two halves: host and client:

Half Entry Responsibilities
host (node) lib/index.js (source code src/index.ts) node-pty shell session, /api/dsh-terminal/info route, /api/dsh-terminal/terminal WebSocket upgrade, system-prompt announcements, settings namespace (shell/cwd)
client (browser) lib/client.js (source code src/client/index.ts) Sidebar Terminal entry point (DOM injection, self-healing), multi-tab terminal panel (React + xterm.js)

Wire Protocol

Communication between the two ends follows the wire protocol defined in src/protocol.ts:

client → host: {type:"input",data}、{type:"resize",cols,rows}
host → client: {type:"ready",shell}、{type:"output",data}、{type:"exit",code,error?}

The client sends keyboard input and size changes, while the host returns ready, terminal output, and exit events.

Installation and Enablement

First, confirm the Node version: the engines requirement in package.json is ^22.19.0 || >=24.0.0. The official distribution provides two installation methods.

First, allow the build scripts, then add dependencies and mount them to the bundle list. Operate under ~/.dsh/profiles/web:

# 1) One-time: allow build scripts in ~/.dsh/profiles/web/pnpm-workspace.yaml
#    allowBuilds:
#      esbuild: true
#      node-pty: true

# 2) Add dependency (replace the path with your checkout location)
cd ~/.dsh/profiles/web
pnpm add dsh-web-terminal@link:/path/to/dsh-web-terminal

# 3) Append "dsh-web-terminal" to dsh.profile.bundles in package.json
#    (The bundle's built-in cordis.patch.yml will insert a plugin row with id=terminal)

# 4) Restart dsh web

The first step cannot be skipped: the build scripts for node-pty and esbuild need to be allowed in pnpm-workspace.yaml first, otherwise they cannot be installed.

Option B: Manual patch line

If the package is already installed to the profile, you can also manually add a patch line in ~/.dsh/profiles/web/cordis.patch.yml:

- insert:
    - id: terminal
      name: 'dsh-web-terminal'

Configuration

Both shell and working directory can be configured in the settings panel or patch yaml:

- id: terminal
  config:
    enabled: true
    announceToAgent: true
    shell: /bin/zsh      # Defaults to $SHELL
    cwd: /path/to/work   # Defaults to host process cwd (i.e., workspace root)

The four items control the switch, whether to announce to system-prompt, the shell to start, and the working directory. When not configured, the shell takes $SHELL and the working directory falls back to the host process cwd (workspace root).

Verification

After restarting dsh web, first confirm that the host route is in place using curl:

curl http://127.0.0.1:3080/api/dsh-terminal/info
# {"shell":"/bin/zsh","platform":"darwin",...}

If it returns shell and platform information, it indicates that the host half has been mounted successfully. Then refresh the browser GUI: the Terminal entry appears in the sidebar, create a new tab, and you can input commands.

Development and Known Issues

To build from source or participate in development, the official commands are as follows:

pnpm install                   # pnpm-workspace.yaml must allow esbuild / node-pty build scripts
pnpm run typecheck             # tsc --noEmit
pnpm run build                 # esbuild generates lib/index.js (host) + lib/client.js (ModuleLoader wrapper)
pnpm test                      # client bundle syntax + jsdom ModuleLoader simulation
node scripts/smoke.mjs         # host WebSocket connection smoke test
node scripts/browser-diag.mjs  # Playwright: open real GUI, click Terminal, type a command

The build script will embed node_modules/@xterm/xterm/css/xterm.css into src/client/xterm-css.ts (generated file) because the ModuleLoader environment does not have a CSS loader.

The README lists three known pitfalls:

  1. @xterm/* must be bundled into the bundle. Only platform seed modules (the entire react family) and shell built-in modules (@deepseek-ai/*) can remain external. If xterm remains external, it will report require("@xterm/xterm") missed the module table.

  2. Panel height chain. [data-dsh-terminal-view] is an absolute positioned container, and its direct child .dshTermView must be set to height: 100%; otherwise, the inner .dshTermPanel { height: 100% } will resolve to auto height for the parent, causing the entire flex chain to collapse, and the terminal will be crushed into a 2px line.

  3. Spawn-helper executable bits. The precompiled prebuilds/<platform>/spawn-helper may lose executable bits, reporting posix_spawnp failed; run pnpm run fix:spawn-helper to fix this (postinstall will automatically run during pnpm install). Also note: node-pty’s spawn will be blocked inside the dsh file sandbox, so the smoke test needs to run against a real dsh process.

Use Cases and Notes

Suitable scenarios: You are already using the DSH web GUI and want to execute commands within the same interface—viewing logs, running scripts, or temporarily entering vim or top while debugging agents, without having to switch windows back and forth.

Regarding permissions, it is essential to be clear: this terminal executes commands with the permissions of the current dsh process (i.e., the host user), which is equivalent to direct shell access. Although all routes have a loopback-only trust fence (same-origin + 127.0.0.1/localhost verification), they should only be used in a local environment. Before installing any third-party plugins, it is recommended to check the source code and license; this plugin is under the MIT license.

Conclusion

To recap: dsh-web-terminal puts a real PTY shell into the DSH web GUI, is hot-pluggable without modifying source code, and supports interactive programs, Ctrl-C, and resize. If you spend your daily time in the dsh web GUI, you can install a copy and give it a try.

  • Directory Page: https://www.skillhub.cn/plugins/iamsee123/dsh-web-terminal (Community-maintained directory site, no official affiliation with DeepSeek / 幻方)
  • GitHub: https://github.com/iamsee123/dsh-web-terminal