简体中文 | English
让 DeepSeek Harness (dsh) 在 Windows 上全部使用 Git Bash 的官方风格插件 —— 以 Git for Windows 的
bash.exe替换 PowerShell 执行器,并为所有模式 注册对应的 Git Bash 版 agent preset。
官方 Windows 组合默认把 dsh-pwsh-sandbox 作为 ctx.shell(PowerShell 执行器),
且各 preset 的 tool-bash 行在 win32 上被禁用——因为在 Windows 上裸 bash
会解析到 C:\Windows\System32\bash.exe(WSL 占位),本插件直接指定
C:/Program Files/Git/bin/bash.exe。沙箱语义在 POSIX 宿主上完整保留;
Windows 宿主上受限模式有一处重要例外——见下方
「安全语义:Windows 上的受限模式」。
安装本插件后:
| 模式 | preset id | 说明 |
|---|---|---|
| 标准模式 · Git Bash | standard-gitbash |
完整编码 Agent,shell 为 Git Bash |
| 极简模式 · Git Bash | minimal-gitbash |
持久 Git Bash 终端 + str_replace_editor |
| PTC 模式 · Git Bash | code-gitbash |
PTC(Code Mode SDK)+ Git Bash |
| 创造模式 · Git Bash | cordis-gitbash |
自引用 Cordis 工具集 + Git Bash |
原有的 标准模式/极简模式/PTC 模式/创造模式(shipped,不可修改)在
Git Bash host 下会拿到"暗示 PowerShell 语法的工具",请改用上面的变体;
已装 dsh-ptc-cordis-preset 的话,PTC 创造模式 用户 preset 不受影响。
自 v0.32.0 起宿主下限为 dsh >= 0.1.7-rc(经 peer @deepseek-ai/dsh 声明,
prerelease 含入求值;旧宿主不再支持)。四个变体的行集是 src/compositions.js
里已提交的 JS 数据,镜像官方 0.1.7 的 standard/minimal/ptc/cordis 行切分并叠加
Git Bash 增量;跟随 dsh 升级的对齐由冒烟测试
compositions: full variants mirror the official row split 锁住。
preset id 保持 code-gitbash 不变——会话钉在 id 上,dsh 0.1.2 把内置 code
改名 ptc 时本插件的变体 id 就没有跟随(改名会让已固定的会话报 preset not found)。
npm: dsh-gitbash-shell, 源码与 Release: github.com/KannaKuron/dsh-gitbash-shell
# web 图形界面
dsh plugin --profile web add dsh-gitbash-shelldsh plugin add 会自动:① pnpm 安装 npm 包 dsh-gitbash-shell;
② 检测到包声明的 dsh.bundle 后把它追加进该 profile 的
dsh.profile.bundles。重启该 profile 的 host 后生效。
bundle patch(cordis.patch.yml)应用三个改动:
pwsh-sandbox行disabled: true—— 每进程只允许一个ctx.shell;- 插入
gitbash-executor(dsh-gitbash-shell/shell):继承官方@deepseek-ai/dsh-bash-sandbox,仅把内层 argv 换成<git-bash.exe> -c <command>。沙箱策略/拒绝分类/后台任务/超时/设置节 沿用官方实现;full-access 分支单独接 Git Bash(父类那里硬编码裸bash); Windows 上受限分支有一处例外,见下一节; - 插入
gitbash-shell(dsh-gitbash-shell):以声明式注册 (ctx.agentPresets.register,v0.32.0 起)提供上表 4 个 preset 变体—— 行集是仓库里已提交、可 diff 的 JS 数据(src/compositions.js),不再物化 任何目录;旧版本遗留在磁盘上的物化树,启动时仅当 marker 判定为 「未被用户改过」才单向清理,用户改过的绝不碰。
环境变量:bash.exe 是 host 进程的直接子进程(不经 git-bash 登录壳),完整继承
系统环境变量与 DSH_* 快照,和原来 pwsh 拿到的完全一致。
POSIX 宿主:官方沙箱语义完整保留——受限令牌、工作区围栏、拒绝分类,
与 @deepseek-ai/dsh-bash-sandbox 完全一致。本节只讲 Windows。
Windows 宿主上的事实:read-only / workspace-write 权限预设下的 shell 命令,
实际以不受限(unconfined)方式执行:
- 为什么:MSYS2 运行时无法在 restricted-token 沙箱下启动——
msys-2.0.dll初始化时创建的 cygheap 映射与信号管道,DACL 只含用户 SID;而 WRITE_RESTRICTED 令牌的二次写检查要求 restricting-SID ACE → 初始化即死于 Win32 error 5 / 0xC0000142,任何版本、任何参数都无解(cmd/pwsh 走匿名管道不受影响)。 这是 OS 层冲突,插件内没有真正的修法,只有两个选择:如实标注的绕过(本插件, v0.13.0 起)或直接拒绝执行。选了前者,是因为装这个插件的目的就是用 Git Bash—— 静默换 pwsh 顶上、或让每条命令都失败,都不如把真相摆在结果里。 - 如何标注(绝不静默):每条此类结果的元数据携带
sandbox: { mode: "<请求的模式>", denied: false, enforcement: "unconfined" }, 并在每个进程首次受限调用时打印一行说明日志(File sandbox enforcement is partial on this host.)。 - 文件工具不受影响:read / write / edit / glob / grep 的沙箱是另一层
(fs-tool policy),照常拦截工作区外访问——也就是说
workspace-write下 shell 能写出工作区、文件工具不能,两者的边界并不一致。 - 可观察的对照(相对 pwsh-sandbox 时代):会话进程的完整性级别不再被压低
(Low → Medium);
$env:TEMP不再被重定向到 per-session 隔离目录。
如果你需要 shell 也被硬性拦住(例如不希望模型经 shell 写工作区外的任何路径),
这个插件在 Windows 上不适合你——卸载即回到 pwsh-sandbox 的受限语义,没有中间态。
danger-full-access 预设本来就不受限,装不装本插件行为一致。
这一取舍的完整分析(含 0.6.0~0.13.1 的故障史与社区两派对比)见 CHANGELOG v0.13.2 与
src/shell.js头注释。
gitbash-shell 行(行 id 自 v0.24.0 起与设置命名空间同串;≤ v0.23.0 为 gitbash-presets)
支持 presets 数组,只注册你常用的模式(未列出的变体不再进入名录;改动经
volatile-update 触发重注册):
- id: gitbash-shell
config:
presets: [standard-gitbash, minimal-gitbash] # 默认注册全部 4 个
suppressPeerCordis: false # 与 dsh-ptc-cordis-preset 去重,默认关去重开关 suppressPeerCordis(布尔,默认 false)只在两个事实同时成立时才把
创造模式 · Git Bash(cordis-gitbash)从名录里摘掉:开关为 true 且
dsh-ptc-cordis-preset 报告它的 PTC 创造模式 已经是 Git Bash 版。默认关 ⇒ 名录与
0.24.x 的四个变体逐字不变;判定细节、生效时机与两侧同步方式见下方
「与 dsh-ptc-cordis-preset 联动」。
- id: gitbash-shell
config:
subagentDialect: true # 默认;false = 方言只对主代理生效默认开启时,子代理、团队队员(含嵌套子代理)与主代理走同一条方言链路:提示词里的路径同样是 /c/... 形式、
路径参数同样被翻译、结果与报错同样回显为 MSYS 形式、run_code 程序里的路径字面量同样被翻译,DSH_PATH_DIALECT 环境事实也照常下发。
关闭后这些只对主代理生效:委托出去的请求保持官方 shell 语义(提示词不改写、路径参数原样传递),适合"子代理要跑原生 Windows 工具链"的场景。
能力边界(如实说明):dsh 每个进程只有一个 shell 执行器(
ctx.shell是单例服务),所以 Git Bash 二进制本身仍是全局的, 这个开关管的是方言/翻译层,不是"换一个 shell"。关闭后委托代理见到与写出的是 Windows 形式路径(C:/...),Git Bash 同样接受,行为自洽。 委托身份的判据用会话头的origin === 'subagent'/delegationDepth > 0(与 dsh 自身一致),判定不出来时按主代理处理(保留方言)。
配合 agent-presets 的 default,新会话直接落在 Git Bash 模式,免去每次在
模式选择器里翻找(原版 shipped 模式无法替换或隐藏——部署级、只读):
- id: agent-presets
config:
default: ptc-cordis # 或 standard-gitbash / minimal-gitbashbashPath 默认留空 = 自动探测;解析顺序就是契约:
- 设置里填的(显式值优先,失败也不会被别的路径顶替):
gitbash-executor行 config 的bashPath>gitbash-shell行 / 设置卡的「Git Bash 路径」; - 默认安装位置:
C:/Program Files/Git/bin/bash.exe、%ProgramFiles(x86)%\Git、%ProgramW6432%\Git、%LOCALAPPDATA%\Programs\Git\bin\bash.exe; - PATH(用户 PATH + 系统 PATH,进程内已合并)逐目录找
bash.exe; - PATH 上的
git.exe反推<gitdir>/../bin/bash.exe; git --exec-path反推 + GitForWindows 注册表(v0.33.0):对 PATH 上的git.exe(Scoop / choco 的 shim 也照常启动真身)跑--exec-path,从输出向上找 Git 根 —— 兼容mingw64/ucrt64两种运行时 布局,补上「Scoop 安装、PATH 上只有 shims、没有bash.exe」的盲区;随后兜底读注册表HKLM\SOFTWARE\GitForWindows的InstallPath;- 注册表
Path(HKCU\Environment、HKLM\...\Session Manager\Environment)——覆盖"GUI 启动时 PATH 快照过期"; - 全落空 ⇒ 报错 + 引导(启动日志一份完整报告,客户端弹一次引导框)。
解析结果是活的,不是启动时判一次(v0.33.0,issue #13):启动那一刻插件行可能还没全部挂载,显式配置 会被短暂读成空 —— 现在启动日志、状态接口、弹窗与侧栏终端接管都在使用时实时重读,执行器能用, 它们就不会再说「解析失败」;启动日志也会在行挂载稳定后补一份最终结论。
只认 Git for Windows 的 bash。 WSL(
C:\Windows\System32\bash.exe,永远在 PATH 且排序靠前)、 WindowsApps 别名、MSYS2、Cygwin 的 bash 一律拒绝;候选还要通过 Git 布局(usr/bin+cmd\git.exe+mingw64)、git --version的.windows.指纹,以及实跑bash -c "uname -s"必须是MINGW*_NT-*。本插件不会回退到 PowerShell / cmd / 任何其它 shell。 找不到 Git Bash 就是找不到:设计如此 —— 装了本插件就是要用 Git Bash,偷偷换一个能跑的顶上是错的。失败时弹窗给两件事:在弹窗里直接填 bashPath (写入设置卡同一字段)或去下载 Git for Windows;同一 boot 只弹一次,可关闭。
DSH 自己的「新建终端」不经过本插件的执行器:它由官方的 terminal-controller 决定 shell,未配置时用
「执行环境的默认 shell」——而在 PATH 里 bash 指向 C:\Windows\System32\bash.EXE(WSL 启动器)的机器上,
新终端跑起来就是 Ubuntu。本插件现在会自动把它切过来:
- 仅 Windows、且已解析出通过验证的 Git Bash 时;设置开关 「自动接管侧栏终端」默认开启(
autoTerminalShell)。 - 只在官方那一行没有自己的 shell 时写入
{ path: <Git Bash>, name: 'Git Bash', args: ['-i'] }(-i就是官方对 bash 的默认参数;显示名固定为Git Bash,这样菜单里不会与那条解析到 WSL 的候选bash混淆)。 已经由 v0.29.0 写入过、名字还是bash的历史配置会在启动时只改名字(path/args 原样保留,幂等); 只迁移我们自己写的那个旧默认名bash—— 你自己起的名字(例如My Bash)一律不动(它本来也不会与 WSL 候选混淆)。 你已经手动指定过别的 shell(例如某个 WSL 配置)⇒ 绝不覆盖,只在宿主日志里提示,并告诉你如何交还给 Git Bash(清空该字段)。 - 写入走官方配置编辑器(设置 UI 用的同一个 API),落到 profile 的 patch 层;新终端立即生效,已打开的终端保持原样。
- 不需要重启,也不会写坏「新建终端」:只写我们验证过存在的 Git Bash(官方对无法解析的路径没有回退,会直接启动失败)。
- 失败时 fail-loud:日志写清原因,并通过读回校验确认值真的落进去了(不出现"假成功")。
⚠️ 如实说明:我们没有改shellCandidates,所以「新建终端」的 shell 选择菜单里仍可能列出一条解析到 WSL 的 候选bash—— 被改掉的是默认项/首项(它现在是我们写入的 Git Bash),不是整条菜单。想彻底不让 WSL 出现在菜单里, 需要另外调整terminal-controller行的shellCandidates(本插件本轮不做,以免覆盖别人的部署配置)。
三步复验(Windows):
- 装好 Git for Windows,重启 DSH,打开本插件设置卡:开关「自动接管侧栏终端」为开;宿主日志出现
official sidebar terminal switched to Git Bash: …。 - 新建终端,在终端里确认它确实是 Git Bash(两条判据任选,
uname -s最硬):uname -s⇒MINGW64_NT-10.0-<build>(Git Bash 的 system name;WSL 这里是Linux);echo $MSYSTEM⇒MINGW64(最简)。⚠️ 不要用uname -r判定:Git Bash / MSYS2 下它是 MSYS 运行时版本(形如3.6.9-b4195d69.x86_64, 真实用户实测就是这个值),而 WSL 的uname -r才是6.x.y.z-microsoft-standard-WSL2—— 两者都不能单独用来判定。
- 回退:
⚠️ 关掉设置卡里的开关只阻止以后的自动写入,不会删除已经写进配置的字段。要彻底恢复原样, 请把 profile 的 patch 里terminal-controller行的shell字段删掉,再重启 DSH(终端随即回到原来的 shell); 只想让它别再自动改、但不介意保留现状的话,关开关即可。
gitbash-executor 行支持:
config:
bashPath: "D:/Tools/Git/bin/bash.exe" # 默认 C:/Program Files/Git/bin/bash.exe
timeoutMs: 60000 # 默认 60s,可继续用 shell 设置节调整npm test重启 host 后新会话:
- 工具列表里出现
bash(不再有pwsh),描述为 Git Bash; echo \$BASH_VERSION有输出、command -v bash指向 Git 安装目录。
dsh plugin --profile web remove dsh-gitbash-shell或删除 profilepackage.json 中依赖 + dsh.profile.bundles 中的条目后
dsh plugin --profile web install。卸载并重启后,未改过的 * -gitbash
preset 会被插件自动清理;宿主 shell 回退为 PowerShell。
本插件在 host 上发布 gitBash 能力服务({ active, bashPath },仅 Windows 为 active)。
dsh-ptc-cordis-preset v0.5.0+ 在注册
PTC 创造模式 时会检测该信号:两个插件都安装时,PTC 创造模式自动注册为 Git Bash 版
(tool-bash 启用、tool-pwsh 禁用),无需新增模式、无需手工修改 preset;
只装本插件时 PTC 创造模式保持原样(由它自己的插件管理)。
联动生效后,创造模式 · Git Bash(本插件的 cordis-gitbash)与对方已经 Git Bash 化的
PTC 创造模式 面向的是同一件事,而两插件同装时它们默认并列出现。把本插件行 Config 上的
suppressPeerCordis 打开,本插件才会把自己的那个变体摘掉(需求与取舍见
issue #7)。
判定 = 两个事实同时成立,缺一不可:
- 开关为
true; - 且对方通过 host 能力服务
ptcCordisPreset报告gitBashActive: true(即它的PTC 创造模式确实按 Git Bash 版生效)。
对方没装 / 尚未挂载 / 没生效 / 版本低于 0.14.0 ⇒ 一律不摘:宁可名录里多一个条目, 也绝不因为"探测不到对方"就少给用户一个模式。默认关,所以不主动打开就没有任何行为变化。
生效时机:
- 开关是实时的:走行 Config 的 volatile 通道,对方的能力则经
ctx.inject(['ptcCordisPreset'])观察(与插件行激活顺序无关),两边任一变化都当场 reconcile——摘掉打日志preset 'cordis-gitbash' retired (dsh-ptc-cordis-preset covers Creation mode on Git Bash),恢复打preset 'cordis-gitbash' registered declaratively。已经挂载的会话 钉在自己的组合快照上,不受影响;名录变化从新会话开始可见。
两侧设置卡上是同一份状态:权威值只有本插件这一行 Config 一份;对方的设置卡通过
ctx.configForms.get('gitbash-shell') 绑定同一行、写同一个字段(DSH 官方支持编辑另一个
插件所拥有的命名空间),所以任一侧改动另一侧立即同步——不存在两份拷贝,也没有同步逻辑。
旧宿主上 configForms 不存在、镜像卡片不出现,开关只在本插件自己的设置面(gitbash-shell
命名空间)可改。
依赖版本:去重开关本体在本插件 ≥ 0.25.0;对方的协作能力在 dsh-ptc-cordis-preset ≥ 0.14.0。
dsh 有一个实验性 CPython 后端用于 PTC 的 run_code
(@deepseek-ai/dsh-experimental-ptc-runtime-python)。它换掉的是 profile 级的
ptc-runtime 行(不是 preset 里的行),所以权威开关属于 dsh-ptc-cordis-preset:它那一行
Config 的布尔字段 pythonRuntime(默认 false),由它在 profile 组合期决定挂哪个后端。
本插件做的是第二张设置卡——同装 dsh-ptc-cordis-preset 时,本插件的设置页也会出现这一行,
通过 ctx.configForms.get('ptc-cordis') 读写同一个字段,任一侧改动两侧立即同步
(与 suppressPeerCordis 同构,方向相反)。对方没装、或版本低于 0.15.0(没有该字段)时,
这一行不显示。
- 开关关闭(默认):
run_code用官方 Node/TypeScript 后端,组合与官方逐字节一致。 - 开关开启:
run_code的语言、生成的 SDK 提示词与工具呈现整体切到 Python(由后端实例的language/executionInstructions决定,组合文本不变)。 - 生效时机:重启 dsh 之后生效(后端行的替换在 profile 组合期求值);设置卡上的状态 两侧即时同步,只有后端切换需要重启。若开启后没有生效,原因见 dsh 启动日志。
- "想开"与"真的开了"是两件事:后端不可用(包被移除 / 解释器低于 3.10 / Windows)时,开关的
意图仍可为"开",但组合照旧跑 Node —— 此时 workflow 侧不再被连带禁用(v0.26.1:互斥只看
实际生效的后端;v0.26.0 只看意图,会让用户白丢 workflow 能力),原因见 dsh 启动日志。
关于卡片上的"后端不可用,当前仍为 Node"这行提示:本插件已实现该降级文案(21 语言),但它要等 对方把生效态投影进行 Config 快照后才会亮起 —— 浏览器只读得到那份快照,而生效态目前只在 宿主侧的能力服务里(见 AGENTS.md §4f)。在此之前:对方卡片显示"已开启 + 原因",本插件卡片 显示"已开启"(hint 指向宿主日志)。
- 平台:该后端仅支持 POSIX——它在 Windows 上构造即抛错,所以 Windows 上开关显示为 禁用并注明原因,宿主侧也会拒绝写入。
- 与 workflow 互斥:
workflow-ptc硬要求 TypeScript 后端(ctx.ptcRuntime.language === 'typescript'),官方 Python 组合同样把workflow-ptc/tool-workflow一起禁用。因此开启 期间本插件四个变体的这两行一律禁用(用户自己的 workflow 设置值保留,关掉后端后下次启动 恢复)——不这样做,选标准/创造模式会因一行构造失败而拒绝整棵 preset 挂载。 - 依赖:python 运行时包由 dsh-ptc-cordis-preset 声明(
optionalDependencies,0.1.7-rc.2);本插件不声明该依赖、也不 insert 任何运行行(两个插件各插一行会造成ptcRuntime二次注册)。
Windows 上本插件把宿主 shell 换成 Git Bash 的同时,让模型看到的路径统一成 MSYS 盘根
POSIX 形式(/c/Users/...、/c/Program Files/...)。开关是 settings 命名空间
gitbash-shell 的布尔字段 posixPaths,默认开启(v0.10.0 起),可在 设置 → 插件
里本插件的「Git Bash 路径方言」卡片上随时切换;不修改任何 preset / 组合文件,标准/极简/
PTC/创造及用户自建模式一律覆盖。
开启时(仅 Win32),posixPaths 门控以下全部行为:
- 提示词源头替换:组装期(
system-prompt/assemble)把官方提示词 sections / contexts / variables 里的 Windows 绝对路径原位改写成/c/...——不增删任何内容、不动工具 schema; - 一句话指示:经
systemPrompt.context(order 126)注入全局指示——shell 是 Git for Windows bash,路径用 MSYS 盘根,所有工具都直接接受这种写法——含~、/tmp、/dev/null、/usr等 bash 原生习惯(v0.17.0 起与 Git Bash 挂载表一致地解析); - 参数翻译:
tools/execute上把工具的路径参数(file_path/path/workdir,含 present 的嵌套files[].path)由/c/...翻回C:/...交给 Node 文件工具;bash 的command字段 不动——那是 Git Bash 母语;bash 虚拟路径按 Git Bash 挂载表解析(v0.17.0):/tmp→ 用户 TEMP、/dev/null→ Windows NUL 空设备、~→ 家目录、/usr/bin/etc等 → Git 安装根, 与 bash 写入/读取同一物理位置;glob 的绝对 pattern(/c/.../*.md)自动拆成path+ 相对pattern(原先静默匹配空);/c/...翻回C:/...交给 Node 文件工具;bash 的command字段不动——那是 Git Bash 母语; - 结果回流:成功结果里的路径元数据(
read/read_image/write/edit的path、glob的paths[]、grep的matches[].path、present的files[].path)改写回 MSYS 形式,其中落在 用户 TEMP 下的路径回显为/tmp/...(与 bash 的$TMP一致);文件内容与错误结果不动;grep的matches[].path)改写回 MSYS 形式;文件内容与错误结果不动; - 运行时事实:向官方
dsh-shell-env注册表贡献DSH_PATH_DIALECT=msys,模型可在执行时 核验(随开关实时生效); - 右侧栏文件链接(v0.31.0):对话里的文件链接带着
/c/...拼写进入 dsh 原生右侧栏 (ui-sidebar-documentpreview),而宿主文件系统只认 Windows 盘符/UNC 拼写 ——/c/...会被 解析成<当前盘符>:\c\...,于是显示「文件不存在,可能已被移动或删除」。插件在右侧栏的唯一 入口(ctx.sidebarRight.openResource)上把地址还原成宿主拼写,~//tmp//dev/null//usr等挂载点按与工具参数翻译同一张表处理;宿主事实经只读路由GET /dsh-gitbash-shell/api/pathmap提供,只有宿主自报win32时才改写 (macOS/Linux 宿主永不翻译,事实未到时也不翻译)。没有改动任何 dsh 源码,包装随插件卸载还原。
关闭后回到 dsh 原生行为:指示文本为空(组装期直接丢弃,零提示噪声),路径参数与结果元数据 都不再改写,文件工具收 Windows 路径。bash 始终是 Git Bash,不受此开关影响——它只决定 跨工具的路径方言。
装了 dsh-better-sidebar(v0.15.2+) 时,Windows 上本插件会通过它的官方设置补丁口(运行时 terminalShell 设置,对方文档明示"settings-page overrides win for terminals opened afterwards")把它打开的终端 shell 指向 Git Bash——UI 终端标签与模型侧 terminal_* 工具统一生效,不改对方一行代码、新开的终端即生效。此外,本插件的 bundle patch 还会给对方的行补上 config.shell(启动期解析,连 tab 标题也会显示 bash;对方未安装时该行无害跳过)。规则:
- 插件全权接管:Windows 上每次启动都无条件把它的
terminalShell设为 Git Bash——即使你在设置页/别处改过,下次插件启动也会改回来; - 卸载本插件 → 自动还原为你改之前的原值(回到它的默认解析:pwsh / powershell);
- 想关掉本联动 → 本插件 row 配置加
betterSidebarShell: false。
MIT © KannaKuron。参考与致敬:dsh-ptc-cordis-preset。