Preface¶
DeepSeek Harness (abbreviated as DSH) is an open-source agent runtime developed by DeepSeek, whose core concept is officially described as Everything is a Plugin. The bash tool is one of its most commonly used capabilities: the model issues a command, the host captures its stdout/stderr, and passes the output to subsequent inference steps.
On Linux or macOS, this workflow mostly works with UTF-8 encoding, so issues are rare. On Windows + WSL combinations, however, the situation is different. DSH runs on the Windows side, and bash is executed via wsl.exe. When WSL is still using NAT networking and HTTP_PROXY/HTTPS_PROXY points to localhost, the launcher will output a UTF-16LE encoded proxy warning to stderr. The core subprocess layer of DSH uses Buffer.toString('utf8') for all output, which discards the original byte data and turns the warning into unrecoverable garbled text. Worse, this warning often appears in the same pipe as the command’s own UTF-8 output, and fixing the encoding for one will corrupt the other.
Community maintainer lhh010 created dsh-bash-encoding, which replaces the ctx.bash executor: it spawns the process itself, collects the raw Buffer, and decodes it only after detection. This plugin is listed in the “Tools and Capabilities” category of the community plugin directory. Note that the directory site (deepseek-harness-plugin.com) is an independent community index and has no official affiliation with DeepSeek / Horizon Robotics. Always verify the repository source code and license before installing.
What It Is¶
dsh-bash-encoding is a host-side DSH plugin with the npm package name @dsh-external/dsh-bash-encoding, current version 0.1.0, licensed under BSD-3-Clause, and primarily written in TypeScript. Its GitHub repository is lhh010/dsh-bash-encoding, which had 7 stars as of 2026-08-18.
It solves a very specific problem: automatically detects UTF-16LE/UTF-8/GBK (as well as GB18030, UTF-16BE, and variants with BOM) in bash output, and restores garbled Chinese text in the web UI, TUI, hooks bridge, and background tasks to readable content. It does not modify DSH’s subprocess core service, but bypasses its lossy decoding layer — any wrapper built on top of ctx.subprocess cannot fix this issue, because it already receives garbled text.
The repository README states compatibility with DSH snapshot0808 (snapshots/20260808T121140Z), snapshot0809 (snapshots/20260809T140917Z), and the npm release @deepseek-ai/dsh@0.0.1-rc.1. Always refer to the repository for the latest version numbers; before switching snapshots, confirm that the DSH bash integration is still named ctx.bash. The official documentation will split this integration into packages like dsh-bash-local and dsh-bash-sandbox, and this plugin replaces the ctx.bash implementation among them.
How Encoding Detection Works¶
The plugin replaces the executor with EncodingBashExecutor: the child process is spawned by the plugin itself, stdout/stderr are collected as raw bytes first, then passed to the streaming segmented decoding logic in src/decode-core.ts. The detection order is clearly documented in the README:
- Pure ASCII fast path: If there are no high bytes, process as UTF-8 to avoid misclassifying strings like
STDERRorwsl:as UTF-16. - BOM detection: Check for UTF-8 (
EF BB BF), UTF-16LE (FF FE), or UTF-16BE (FE FF) byte order marks. - UTF-16 segment detection: Process by chunks. Use NUL parity bits to anchor ASCII subsegments, and CJK high byte prevalence to anchor pure Chinese segments; break the segment when 4 consecutive printable ASCII code units are found (to distinguish
STDERRfrom Chinese characters like “个” or “片”), and hard-break when a UTF-8 three-byte signature is encountered. - If it passes strict UTF-8 decoding (fatal decoder), classify it as UTF-8.
- Try GBK next, then GB18030 (corresponding to Windows Chinese OEM code pages 936 / 54936).
- Fall back to Latin-1 to guarantee successful decoding.
Handling mixed WSL UTF-16LE warnings and command UTF-8 output in the same pipe is the key challenge for this detection chain. The repository provides the following comparison:
Before fix (core exec decodes UTF-16LE as UTF-8):
w s l: �hKm0R localhost �NtM�nFO*g\��P0R WSL0NAT !j_N�v WSL \rN/e c localhost �Nt
After fix:
wsl: 检测到 localhost 代理配置,但未镜像到 WSL。NAT 模式下的 WSL 不支持 localhost 代理。
The README also includes comparison examples for GBK tool output, 8KB+ cross-chunk long UTF-16 streams, and patterns like STDERR: followed by Chinese text. The repository provides 26 test cases covering the decoding kernel, real spawn exit codes, stdin, timeouts, background tasks, and failure paths, which can be run with:
pnpm test
The author’s test results on the npm release baseline show 25/26 passes. The single failure is noted as “environmental noise from the local WSL localhost proxy warning mixed into stderr”, and the decoding behavior itself is still marked as correct.
Installation and Activation¶
The installation command provided on the community directory page is:
dsh plugin add github:lhh010/dsh-bash-encoding
The directory page also reminds users to pin the commit hash for reproducible installations. The current main branch HEAD is 30ecc056cbdade90292ff8ad72a2cd8324fe863f (committed on 2026-08-13), which can be specified as:
dsh plugin add github:lhh010/dsh-bash-encoding#30ecc056cbdade90292ff8ad72a2cd8324fe863f
The plugin runs with the permissions of the current dsh process, and may execute code during installation. Always inspect the source repository and license before installing.
Only one ctx.bash implementation can exist in the same context. After activation, you need to replace the original bash entry in your profile’s cordis.yml (or cordis.patch.yml), replacing either @deepseek-ai/dsh-bash-local or @deepseek-ai/dsh-bash-sandbox with this plugin — they cannot coexist. The repository provides the following configuration:
- id: bash
name: '@dsh-external/dsh-bash-encoding'
config:
cwd: null # Default working directory (defaults to process.cwd())
timeoutMs: 120000 # Default timeout for foreground commands
maxTimeoutMs: 600000 # Maximum single timeout value
maxOutputBytes: 65536 # Per-stream output limit (truncates and marks lossy when exceeded)
graceMs: 3000 # Grace period between SIGTERM and SIGKILL
The meanings of each field are taken directly from the README:
- cwd: Default working directory, defaults to process.cwd() if omitted.
- timeoutMs: Default timeout for foreground commands.
- maxTimeoutMs: Maximum allowed single timeout.
- maxOutputBytes: Per-stream output limit; truncates output and marks it lossy when exceeded.
- graceMs: Time to wait between sending SIGTERM and SIGKILL.
If using cordis.patch.yml, the README specifically notes that the patch’s name field is only for validation and cannot replace the plugin. The correct approach is to first set the original bash entry to disabled: true, then insert this plugin. Restart dsh web for changes to take effect. The output of bash tools, background tasks, and hooks bridges will all go through the encoding detection.
The repository also documents a local linking setup method (DSH requires Node ^22.19 || >=24):
cd /path/to/dsh-bash-encoding && pnpm install && pnpm build
cd "${DSH_HOME:-$HOME/.dsh}/profiles/web"
pnpm add -w link:/path/to/dsh-bash-encoding
There is one versioning pitfall with a plain npm install: the peerDependencies.cordis declaration is set to ^4.0.0-rc.7, while DSH’s npm releases bundle its internal Cordis dependency as pre-releases with version 0.0.1-rc.?, which can trigger an ERESOLVE error. The README recommends adding --legacy-peer-deps as a workaround. Installing via dsh plugin or pnpm will handle this automatically, and runtime behavior is unaffected.
Use Cases and Notes¶
Who this is for: Users running DSH on Windows, using WSL for bash, and frequently seeing garbled Chinese text. The typical triggering conditions require all of the following:
- The operating system is Windows, DSH runs on the Windows side, and bash is executed via WSL.
- WSL is still using NAT networking (%UserProfile%\.wslconfig does not set networkingMode=mirrored).
- The environment variables HTTP_PROXY/HTTPS_PROXY point to localhost.
It also fixes issues with GBK Chinese tools, UTF-16 output, and cases where warnings and command output are mixed in the same pipe.
What this plugin does not cover, or explicitly cannot solve, as stated directly in the README:
1. Disabled by default for Windows native (non-WSL) profiles: The platform layer already registers pwsh-sandbox (SandboxPwshExecutor), which also registers ctx.bash; running both will cause a startup failure (service bash has been registered). This plugin spawns via bash -c and targets POSIX bash stacks, so it is not compatible with pwsh stacks. This is a profile configuration restriction, not a code deprecation.
2. Reading GBK/UTF-16 files with the read utility is not in the current scope, and is marked as a roadmap item for v2.
3. node-pty interactive terminals (tool-pty / dsh-web-terminal) cannot be fixed: node-pty already performs lossy UTF-8 decoding internally, so the plugin cannot access the original bytes.
4. Does not modify the subprocess core layer to avoid replacing foundational services.
5. When output exceeds maxOutputBytes, retains the header and marks it lossy, and does not write spill files.
6. Clears environment variables prefixed with DSH_* or containing KEY/PASSWORD/SECRET/TOKEN in their names. Managed variables are passed explicitly via dshEnv, aligning with the hygiene rules of DSH’s official bash integration.
If you only want to suppress the WSL proxy warning, you can also fix it via environment settings: change networkingMode to mirrored in .wslconfig, or set WSL_UTF8=1. This is a complementary approach rather than a replacement for the plugin.
For sandboxing, the plugin will detect ctx.sandbox/ctx.sandboxPolicy at runtime and use the confine path for non-full-access environments, with sandboxMode read lazily. It has no client bundle and is not affected by the snapshot0809 client plugin mechanism (dshClient declaration / ClientPackageCompositionError).
Summary¶
dsh-bash-encoding does one narrow thing: preserves the raw bytes of bash output, decodes them using encodings like UTF-16LE/UTF-8/GBK, and specifically addresses the “consistent garbled text on every command” issue under Windows + WSL. It is not an official built-in plugin, and its star count is low, but for users stuck on this specific workflow, it is a more direct solution than trying to guess garbled text on the model side. Always inspect the source code and BSD-3-Clause license before installing, and pin the commit hash for reproducible environments.
Community directory page: https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-bash-encoding/
GitHub: https://github.com/lhh010/dsh-bash-encoding