The core design philosophy of DeepSeek Harness (DSH) is “everything is a plugin.” When developing agents on the Web, if you need the model to execute Shell commands directly and maintain session state, traditional approaches often require switching to a local terminal. The dsh-interactive-terminal plugin solves this fragmentation by embedding a persistent PTY terminal in the browser, enabling interaction between the model and the user within the same interface.
Plugin Positioning¶
This is a client-side plugin developed by the maintainer mingzhicode. It uses xterm.js to render a terminal in the DeepSeek Harness Web interface, allowing an Agent to run programs through tool calls (shared_terminal_send) and also supporting human users to take over control and continue interacting. The core goal of the plugin is to provide a single-Agent terminal control mechanism, ensuring that only one view can write to the terminal at a time, while other views remain read-only.
Core Features¶
- Persistent Bash session: Runs a persistent Bash terminal in DSH Web. Collapsing the panel or reconnecting after a disconnection does not terminate the Shell.
- Shared by model and user: The model can run programs through tool calls, and human users can take over and continue interacting.
- Based on xterm.js: Uses a standard Web terminal UI for rendering.
- Single-controller mechanism: Only one browser view can control the Agent’s terminal; other views are read-only.
- State recovery: Supports PTY screen snapshot recovery and reconnection after disconnection.
Installation and Enablement¶
Installation and startup must use the same DSH_HOME (defaults to ~/.dsh).
Prerequisites:
* Operating system: macOS or Linux
* Shell: Bash
* Tooling: Node.js (^22.19 || >=24), pnpm (must be available in PATH, version 10.18.3)
* DSH version: 0.1.0-rc.8
Installation steps:
- Run the following command in the terminal to install the plugin package into the Web profile configuration:
dsh plugin --profile web add dsh-interactive-terminal@0.1.0
- Start DeepSeek Harness Web:
dsh --profile web
-
Open the printed URL in your browser. After configuring the model and session, click Open terminal.
-
At an idle prompt, type
echo helloto verify browser input.
Interaction Flow¶
After the plugin takes over the terminal, there is an explicit control-handoff logic:
- Open the terminal: Click Open terminal. The Shell is created lazily on first expansion or when the Agent invokes the tool.
- Confirm controller: Confirm that the status is shown as Controller. If you type directly at an idle prompt, the first key press requests human input ownership, and subsequent key presses wait for authorization.
- Model execution: The model invokes
shared_terminal_sendto run a program. At this point, the model owns the operation queue, and normal keyboard input is ignored. - Take over input: When the program requests input, click Take over input and wait for authorization before typing. This takeover preserves the process, does not send a signal, and removes the model’s operation timeout.
- Continue interacting: Continue typing text, newlines, or UTF-8 characters in the same PTY. A newline submits input but does not release ownership until the Shell prompt is confirmed or the process exits.
- Interrupt: Use Interrupt input to send
SIGINT. This interrupts the program and retains ownership until the prompt returns.
Configuration¶
The plugin supports overriding default behavior through a configuration file. The configuration file path is ~/.dsh/profiles/web/cordis.patch.yml (or a custom $DSH_HOME/profiles/web/cordis.patch.yml).
Configuration example:
- id: dsh-interactive-terminal
config:
shellPath: /bin/bash
shellArgs: [--noprofile, --norc, -i]
rows: 40
cols: 160
After applying the configuration, DSH must be restarted. The following table lists the configurable fields, their default values, and effects:
| Field | Default | Effect |
|---|---|---|
shellPath |
/bin/bash |
Bash executable. Only Bash is supported; other Shells are rejected. |
shellArgs |
--noprofile --norc -i |
Interactive Shell arguments. Empty arguments are rejected. |
rows |
40 |
Fixed number of rows generated for each PTY. |
cols |
160 |
Fixed number of columns for each PTY. |
scrollbackLines |
10000 |
Number of history lines retained outside the viewport. |
scrollbackMaxBytes |
4194304 |
Byte limit for serialized ANSI history. |
maxToolOutputBytes |
262144 |
Complete limit for tool result JSON. |
maxInputBytes |
65536 |
Byte limit for each human input lease sent or accepted by the model. |
maxQueuedOperations |
128 |
Number of changes allowed per Agent, including the current operation. |
maxSessions |
32 |
Maximum number of active Agent terminals. |
pollIntervalMs |
50 |
Polling interval for foreground process checks. |
operationTimeoutMs |
30000 |
Timeout for model changes. |
interruptTimeoutMs |
5000 |
Controlled prompt recovery timeout after SIGINT. |
disconnectGraceMs |
15000 |
Grace period before restoring the connection. |
disposeGraceMs |
3000 |
Process tree termination grace period during reset or cleanup. |
Notes¶
- Environment consistency: Installation and startup must use the same
DSH_HOME; otherwise, the plugin may fail to load. - Dependency check: If pnpm reports that no version is available, check whether the public registry is being used (for example,
registry.npmjs.org). - View limit: Only one browser view can control the Agent’s terminal at a time; other views and mobile views are read-only. To take over, you must close the current controlling view and reconnect after
disconnectGraceMs. - Updates: After changing the configuration file, restart DSH for the changes to take effect.
Summary¶
dsh-interactive-terminal provides a standardized terminal interaction solution for the DSH ecosystem. Through a shared PTY and fine-grained input control logic, it brings the model’s automated operations in the Web interface closer to a real terminal experience, while also giving developers flexible configuration options.
- Plugin directory: dsh-interactive-terminal
- Source code: mingzhicode/dsh-interactive-terminal