dsh-plugin-gitbash

August 23, 2026 · View on GitHub

CI

DeepSeek Harness(DSH)中运行 Windows 主机侧 Git for Windows Bash 命令的 Cordis 插件。

一个零运行时依赖的自包含插件,向模型注册一个工具:gitbash。典型场景:

  • 操作 Windows 原生仓库的 git(git-bash 里的 git,而不是 WSL 里的)。
  • 在 WSL 里跑着 harness,却需要执行 Windows 可执行文件、原生 Windows 路径(D:\...C:\...)、或者不带 cmd/PowerShell 的 Windows 脚本。
  • 任何必须触达 Windows 侧的操作,不必离开 agent 会话。

English

工作原理

每次调用都会启动一个全新的 Git Bash 进程:

<bash.exe> -c '<command>'

stdin 置为 ignore(fd 0 接到 /dev/null),因此 shell 必然以非交互方式运行并在执行结束后退出,不会卡在交互提示符上。每次调用都是全新进程:cwd、环境变量、shell 函数等状态不会在调用之间保留。

command 内部的路径语义:被启动的是 Windows 的 Git Bash,所以里面要写 git-bash / Windows 路径(/d/toolsD:/toolsC:\...)。WSL 的 /mnt/... 路径在 command 内部无效

workdir 语义workdir 参数(缺省为会话工作目录)会被归一化——/mnt/X/.../X/...X:\... 三种写法都会映射为 /mnt/X/...,再由 WSL interop 转成原生 Windows 目录。无法映射的 WSL 独有路径(如 /home/...)不会让调用失败,而是在会话工作目录中启动(WSL interop 下表现为 //wsl.localhost/...)。

环境要求

  • DSH profile 运行在:
    • WSL / Linux:Windows 驱动器已挂载,且装有 Git for Windows;或
    • 原生 Windows:装有 Git for Windows。
  • harness 主机能访问 bash.exe(见下方路径解析)。

安装

从 npm(发布后)

dsh plugin --profile <name> add dsh-plugin-gitbash

dsh plugin 会把包装进 profile;因为包声明了 dsh.bundle,它会自动追加到 profile 的 bundle 栈(dsh.profile.bundles)。重启 profile(dsh web / dsh --profile <name>)即挂载 gitbash 工具。

直接从 GitHub 安装(npm 发布前)

dsh plugin --profile <name> add https://github.com/<owner>/dsh-plugin-gitbash

生产环境建议锁定不可变 commit(社区审核惯例):

dsh plugin --profile <name> add https://github.com/<owner>/dsh-plugin-gitbash#<commit-sha>

手动改 profile 清单

在 profile 的 package.json dependencies 里加依赖,并把 dsh-plugin-gitbash 追加到 dsh.profile.bundles,然后执行 dsh plugin --profile <name> install

Agent preset 行(免安装、直接放文件)

插件刻意只依赖 Node 内建模块 node:fs,所以也可以作为 preset 组合里的相对路径行直接使用,无需安装任何包。把 lib/index.js(或改名 gitbash.mjs)拷进你的 preset 目录,然后加一行:

# agent.cordis.yml
- id: tool-gitbash
  name: ./index.js   # 或你拷贝后的文件名

验证

node test/smoke.mjs

用本机真实的 Git Bash 跑真实插件,输出 SMOKE: ALL PASS;主机上没有 git-bash 时优雅跳过(exit 0)。

配置

bundle 行(或 preset 行)的 config 字段:

类型默认含义
gitBashPathstringbash.exe 的显式路径。直接信任,不再探测。
autoDetectbooleantrue未显式配置时,搜索常见安装位置。
timeoutMsnumber120000每次调用的默认超时;单次调用可用 timeoutMs 参数覆盖。
maxOutputCharsnumber65536stdout/stderr 每条流尾部截断到该字符数(完整捕获仍在收集器/spill 中)。

解析优先级:config.gitBashPath → 环境变量 DSH_GITBASH_PATH → 自动探测(除非 autoDetect: false)。自愈:挂载时没解析到路径也没关系,每次调用都会重新解析——之后装了 Git for Windows 或挂了新盘,无需重启 DSH 即可生效。

自动探测的候选位置:

  • Windows 主机%ProgramFiles%\Git\bin\bash.exe%ProgramFiles(x86)%\Git\bin\bash.exe,最后退化为 PATH 里的 bash
  • WSL / POSIX/mnt/<c..z>/Program Files/Git/bin/bash.exe(x86) 变体(逐个盘符检查)。

显式路径示例(行配置):

- id: tool-gitbash
  name: 'dsh-plugin-gitbash'
  config:
    gitBashPath: '/mnt/e/Program Files/Git/bin/bash.exe'

不想改配置?直接用环境变量:

export DSH_GITBASH_PATH='/mnt/e/Program Files/Git/bin/bash.exe'

排障

  • No Git for Windows bash.exe found / Git Bash not found at ... —— 安装 Git for Windows,确认驱动器已挂载,然后设置 gitBashPathDSH_GITBASH_PATH
  • 命令卡住不返回 —— git-bash 的 stdin 来自 /dev/null,交互式提示符按设计无法阻塞它;真正耗时的命令调大 timeoutMs 即可,进程始终可被终止。
  • workdir 没生效 —— WSL 独有路径(如 /home/...)无法作为 Windows 进程的工作目录,调用会在会话工作目录启动,提示信息会说明原因。要用 /mnt/X/.../X/...X:\... 写法控制。
  • command 内部报 WSL 路径错误 —— 在 command 里你处于 Windows git-bash:写 /d/...D:/...,绝不要写 /mnt/d/...
  • 状态在调用间丢失 —— 这是设计使然:每次都是新进程;需要状态时把命令串在一条里(cd /d/tools && git status)。

目录结构

lib/index.js        Cordis 插件本体(零运行时依赖)
cordis.patch.yml    dsh.bundle patch —— 插入工具行
dsh.plugin.json     DSH 插件清单(工具发现元数据)
test/smoke.mjs      独立 smoke 测试(Linux + Windows CI 双跑)
.github/workflows   CI:Linux 语法/分支测试 + Windows 真实 git-bash 测试

许可

MIT —— 见 LICENSE