npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-tweaks-git-bash-terminal-tool

v0.3.3

Published

可将 Windows 环境下的终端工具替换为 Git Bash

Readme

dsh-tweaks-git-bash-terminal-tool

把 DSH 在 Windows 上的默认终端工具从 PowerShell(pwsh) 换成 Git Bash(bash) —— 一个开关,所有 preset(standard / ptc / cordis / minimal)自动跟随,不改 DSH 源码、不改任何 preset 文件 (唯一有代价的是 minimal:它会从「持久 shell」退化成「一次性 shell」,见下文)。

它能做什么

Windows 上的 DSH 默认让模型用一个 PowerShell 工具(工具名 pwsh)执行命令:工具目录、 system prompt、终端卡片里都是 PowerShell 方言。装了这个插件之后,你在 设置 → 通用 → 终端工具 里把终端工具切成 Git Bash:

  • 模型看到的工具叫 bash,描述改成 Git Bash 方言(POSIX 路径、$VAR、不需要 C:\ 转义);
  • pwsh 从模型可见的工具目录里消失(包括 PTC 模式生成的 SDK 签名);
  • system prompt 里那段 PowerShell 提示词被压掉,换成 bash 的那段;
  • 终端卡片、退出码 pill、后台 job_output / job_kill、沙箱拒绝与升级,表现与官方一致。

切换只对新会话生效:运行中的会话保持它启动时的选择(这样工具目录与提示词不会中途变化, KV cache 与历史工具调用都不会错位)。改完开一个新会话即可。

  • 只想用 PowerShell?切回 PowerShell(pwsh) 就行,行为和没装插件一样。
  • 不会碰 DSH 自己的 ctx.shell(host 的 pwsh 执行器原样保留),所以 hooks、内部调用等 用到 ctx.shell 的地方完全不受影响。
  • ⚠️ 官方预设里只有 minimal 用的是「持久 shell」,它会因为本插件退化成「一次性 shell」; standard / ptc / cordis 本来就是一次性的,不受影响。详见下节「极简模式(minimal)的影响」。

怎么用

  1. 打开 设置 → 通用,找到 终端工具 这一行(插件只在 Windows 上挂载,非 Windows 连这一行都不存在)。 默认是 PowerShell(pwsh),而且这里只有两个工具选项 —— 插件不替你选、也不自己切换。
  2. 点 Git Bash(bash):只有这时才出现「Git Bash 路径」与 自动发现 按钮(切回 pwsh 就收起来)。 此时路径若还是空的,新会话仍然跑 pwsh,不会出现半坏状态。
  3. 点 自动发现:扫描 Git for Windows / MSYS2 / Cygwin,把第一个可用的 bash.exe 填进路径栏并持久化;找到多条 git 路径时,路径栏变成下拉列表,重启 DSH 后依然可以选。
  4. 开一个新会话即可生效。

说明:

  • 不会用 WSL 的 bash。C:\Windows\System32\bash.exe 与 ...\WindowsApps\bash.exe 会被 硬排除(where bash 在这些机器上经常先解析到 WSL),发现算法是「先找到 git,再由同一个安装反推 bash」。
  • 路径栏只显示路径本身:候选来源(Git for Windows / MSYS2 / …)与 bash --version 这类扫描细节不再摊在设置页里 —— 多条路径时路径栏就是选择器。
  • 一个候选都没找到时,Git Bash 依然可选(只是还没有路径可用),点「自动发现」会给出一行「没有找到」说明。
  • 路径栏可以手填,但只有真实存在且不是 WSL 的 bash.exe 才会生效:每次新会话替换前校验, 不合法就跳过替换(会话照旧 pwsh)并写一行诊断;路径为空是合法中间态。
  • 运行时如果这台机器/这个 DSH 版本不具备替换所需的扩展点,设置行会显示「当前版本不支持:<原因>」, 会话完全不受影响(插件不抛错、不 veto,只写诊断日志)。

设置 → 通用 → 终端工具:默认只有 PowerShell(pwsh)与 Git Bash(bash)两个选项,切到 Git Bash 后才出现「Git Bash 路径」与「自动发现」

升级到 0.3.3(修复:在 DSH 0.1.6+ 上替换根本没生效)

0.2.0 ~ 0.3.2 的替换逻辑在 DSH 0.1.6 之后是死的(issue #1): 设置照常保存、日志照常写、设置行状态正常,但模型始终只看到 pwsh,bash 从不出现。 两个互相独立的原因,都是本插件当年按 DSH 0.1.5-rc.1 写的契约,而它们在 0.1.6 一起变了:

| 契约 | 0.1.5-rc.1(写码时的部署) | 0.1.6 起(0.1.7 / 0.2.0 都是) | 表现 | |---|---|---|---| | per-agent 初始化事件 | agent/session-start | agent/created | 监听器永不触发:不隐藏 pwsh、不注册 bash、提示词也不替换;日志里连一条 replace: 都没有 | | ctx.sandbox.confine | 同步返回 ConfinedArgv | async,返回 Promise | 受限(read-only / workspace-write)模式下每次 bash 调用都失败:Error: undefined is not iterable |

0.3.3 改的就是这两处(事件名抽成常量 AGENT_INIT_EVENT;confineArgv 改成 async 并在 jobs.start 之前 await),并补了两道防线:

  • scripts/selftest.mjs 现在走公开入口 apply() 断言「订阅的事件名」与「收到事件后的四个动作」, 事件名再写错会立刻红;
  • 新增 scripts/compatcheck.mjs:拿官方产物逐条核对本插件依赖的每个契约, 支持 node scripts/compatcheck.mjs --fetch 0.1.7-rc.2 0.2.0-rc.2。

这两个契约写错的表现都是静默失效(cordis 不会因为事件名不存在而报错;没 await 也只是拿到 一个 Promise),所以别把它们改回去。

已知限制:受限模式下 Git Bash 起不来(与插件无关)

DSH 在 Windows 上用「写受限令牌」实现文件沙箱(dsh-sandbox-windows-acl),而 MSYS2 / Git for Windows 的 bash.exe 启动时必须创建信号管道(\\.\pipe\\)—— 写受限令牌下这一步会被拒:

bash.exe: *** fatal error - couldn't create signal pipe, Win32 error 5

这不是本插件的 bug:在同一个 workspace-write 会话里,用官方 pwsh 工具跑 & "C:\Program Files\Git\bin\bash.exe" -c "echo x" 会得到逐字相同的报错。 实测同一个会话切到 danger-full-access 之后,本插件的 bash 工具正常返回 stdout。

所以要让 Git Bash 真正跑起来,会话沙箱必须是 danger-full-access (启动时 DSH_PERMISSION_MODE=danger-full-access,或在界面上切到完全权限)。 本插件不会绕过 DSH 的沙箱策略。

升级到 0.3.x(安装问题修复)

0.3.0 ~ 0.3.2 没有改运行期行为:host / client 半区的代码与 0.2.1 相同 —— 工具替换、设置面、沙箱升级、 minimal 的取舍都不变。这几版修的是装不上:

  • README 补上「本地 link 留下的 junction 会让后续 npm / 市场安装报 ERR_PNPM_EPERM」的判据与清理步骤 (见「安装 → 装不上?…」),以及开发调试章节里「换回正式版前先清掉 junction」的提醒;
  • 只在文档与版本号上有变化,所以老机器上的持久化设置原样保留 (选择仍存在 profile patch 的 git-bash-terminal-tool 行 config 里)。

| 版本 | 内容 | |---|---| | 0.3.0 | 安装排障文档 + 版本号(首次发布) | | 0.3.1 | 与 0.3.0 内容相同,只把删 junction 的命令从 Remove-Item -Recurse 换成 cmd /c rmdir:旧版 Windows PowerShell(5.1)对 junction 用前者会连链接目标的内容一起删掉 | | 0.3.2 | 与 0.3.1 内容相同,只是改由仓库 CI(npm trusted publishing)发布,带 provenance,并在干净 Ubuntu 上复跑 tsc / build / selftest / clientsmoke |

用部署里的真件复核过 DSH 0.2.0-rc.1 / 0.2.0-rc.2:node scripts/selftest.mjs 与 node scripts/clientsmoke.mjs 全绿(含 @deepseek-ai/dsh-tools 的工具 schema 校验器与 @deepseek-ai/dsh-settings 的 volatileForm)—— tools.restrict / tools.register / systemPrompt.section / entry Config 这几个契约在 0.2.x 上确实没变。

⚠️ 但这几个契约没变不代表插件就是好的:真正变的是 agent/session-start → agent/created 与 confine 的同步 → async(见「升级到 0.3.3」),而它们当年没有被复核到。 现在这类漂移交给 scripts/compatcheck.mjs 逐版本核对。

升级到 0.2.0(DSH 0.1.7)

DSH 0.1.7 换了设置模型(旧 ctx.settings.register 已不存在),本插件 0.2.0 随之上车:

  • 设置从「插件自造的 terminal-tool 命名空间」改成插件 entry 自己的 Config, 表单按 profile entry id git-bash-terminal-tool 定位;
  • 可编辑字段用 schemastery 的 .volatile() 声明,所以插件多了一个运行时依赖 @deepseek-ai/schemastery;
  • 持久化位置从 $DSH_HOME/settings.yaml 变成当前 profile 的 patch (profiles/<profile>/cordis.patch.yml)里本插件那一行的 config。

⚠️ 旧选择不会自动迁移:0.1.7 的旧设置导入按「分区名 = entry id」执行, settings.yaml 里的 terminal-tool: 匹配不到 git-bash-terminal-tool,只会被跳过 (原文件已改名为 settings.yaml.imported)。所以升级后请重新选一次: 设置 → 通用 → 终端工具 → 点 Git Bash → 点 自动发现 → 开一个新会话。

本版按 DSH 0.1.7-rc.2 的设置模型实现:host 侧是 volatile Config;浏览器侧优先用家族兼容层的 webUiSettings,没有它就退回官方原生 configForms.get(entryId)(所以普通 0.1.7 部署也能用)。 更旧的 DSH(0.1.5 那套 ctx.settings.register / settingsScope)请继续用 0.1.0。 0.3.3 起的最低支持版本是 DSH 0.1.7(0.1.5 的 agent/session-start 与同步 confine 都不再兼容, 也不打算兼容)。

极简模式(minimal)的影响

四个官方预设里,只有 minimal 的终端是「持久 shell」:

| 预设(win32 上) | 终端工具 | 调用之间保留状态? | |---|---|---| | standard / ptc / cordis | @deepseek-ai/dsh-tool-pwsh(消费 ctx.shell) | ❌ 一次性:每次调用 spawn 一个新的 pwsh 进程 | | minimal | @deepseek-ai/dsh-tool-pwsh-persistent + @deepseek-ai/dsh-terminal 的 PTY | ✅ 持久:cwd / 环境变量 / 函数 / 交互式程序跨调用保留 |

本插件在 win32 上会隐藏 preset 注册的 pwsh(tools.restrict({ deny: ['pwsh'] }))并注册自己的 Git Bash 工具,于是:

  • 对 standard / ptc / cordis 没有影响:它们本来就是一次性 shell,换成 Git Bash 仍然是一次性,语义一一对应;
  • 对 minimal 有影响:它从「持久 shell」变成「一次性 shell」—— 每次调用都是一个新进程, cd / 环境变量 / 函数 / source 过的脚本不再跨调用保留,也不能再驱动交互式程序(REPL、需要 TTY 的命令)。 机制:minimal 的持久 shell 绑在 preset 自己的 PTY 栈上(isolate: { terminals: true } 的 realm 私有服务), 外部插件没有办法「只换后端、保留工具」—— 隐藏工具就是连持久性一起换掉。

代价的量级:一次性工具每条命令都要启动一个 bash.exe(本机实测含沙箱/杀软约 200–280 ms/次), 而持久 PTY 只在第一条命令付一次启动成本,之后每条是毫秒级。

这不是本插件独有的取舍:你机器上的第三方预设 liangshen 在 win32 上同样把持久 PTY 组 disabled 掉, 改成自己实现的一次性 Git Bash 工具(custom-bash.mjs)—— 原话是「PTY 后端在 linux/darwin 之外没有对应实现, 所以 win32 禁用持久组,走普通的跨平台 subprocess 缝」,两边最后都只剩一个叫 bash 的工具。

如果你一定要「极简模式 + 持久 Git Bash」:本插件做不到(PTY realm 是 preset 私有的)。 唯一的路子是自己复制一份 minimal preset 改造:把 terminal-pwsh / persistent-pwsh 两行换成 @deepseek-ai/dsh-terminal-bash(shellPath 指向 Git Bash)+ @deepseek-ai/dsh-tool-bash-persistent。 后端用的是 node-pty(Windows 上走 ConPTY),理论上可行,但本仓库没有验证过这条路。

安装

# 从 npm(推荐;需要 DSH >= 0.1.7)
npx @deepseek-ai/dsh plugin --profile web add dsh-tweaks-git-bash-terminal-tool

# 或从本仓库源码(开发调试)
npx @deepseek-ai/dsh plugin --profile web add "D:\你的目录\dsh-tweaks\plugins\git-bash-terminal-tool"

然后在 profile 的 package.json 里把 dsh-tweaks-git-bash-terminal-tool 加进 dsh.profile.bundles (本仓库其他插件就是这么挂的;bundle 自带的 cordis.patch.yml 只 insert 自己一行)。

重启一次 DSH,再在浏览器里强制刷新(Ctrl + Shift + R)。

首次挂载必须重启:bundle 自带的 patch 在运行中插入的 row 只进组合树, 宿主半区的 apply 不会被调用(client bundle 会进启动图)。 web 为 DSH 的 profile 名称,可在 C:\Users\你的用户名\.dsh\profiles\ 下确认。

装不上?先看是不是「本地 link 留下的 junction」

如果这台机器之前用本地路径装过本插件(上面那条开发调试命令),profile 的 node_modules 里会留下一个 指向本仓库的 junction:

<profile>\node_modules\dsh-tweaks-git-bash-terminal-tool  ->  D:\...\dsh-tweaks\plugins\git-bash-terminal-tool

之后再用市场 / npm 装正式版时,pnpm add 会把它当成本地包重新导入,并在导入后的目录里重建依赖链接; Windows 上创建真实符号链接需要管理员权限或开发者模式,于是整条命令失败(2026-09 实测:pnpm 11.22 / Node 24 / 非管理员,pnpm 与 dsh 市场都会以同样的形式挂掉):

[ERR_PNPM_EPERM] [importPackage <profile>\node_modules\dsh-tweaks-git-bash-terminal-tool]
EPERM: operation not permitted, symlink 'D:\...\plugins\git-bash-terminal-tool\node_modules\...\@deepseek-ai\schemastery'

先删掉那个 junction,再装正式版。它只是一个指向开发目录的链接,删掉不会动仓库里的任何文件:

$profile = "$env:USERPROFILE\.dsh\profiles\web"   # 换成你自己的 profile 目录
cmd /c rmdir "$profile\node_modules\dsh-tweaks-git-bash-terminal-tool"

用 rmdir(不带 /s)而不是 Remove-Item -Recurse:前者只摘掉链接本身,后者在旧版 Windows PowerShell 上会把链接指向的目录内容一起删掉。

判据:Get-Item "$profile\node_modules\dsh-tweaks-git-bash-terminal-tool" 的 LinkType 显示 Junction / SymbolicLink 就要删;为空(真实目录)说明是正常安装,不要动。

这不是包内容的问题:把同一个包 npm pack 后在干净工程里 pnpm add、或用市场装到没有历史 link 的 profile 里都正常。只有「同一个包里既有本地 link、又要换成 registry 版本」时才会踩到。 想少踩:开发调试改用 tarball(npm pack 后 dsh plugin add .\dsh-tweaks-git-bash-terminal-tool-0.3.0.tgz), 它不会留下 junction。

卸载

从 profile 的 dsh.profile.bundles 里移除、重启 DSH 即恢复原状:

  • DSH 源码 / node_modules:从未写过;
  • preset 文件:从未改过;
  • host 组合:只 insert 了自己一行,移除即消失;
  • 工具目录与提示词:只在 agent 的内存 scope 里注册,随 agent 释放;
  • ctx.shell:从头到尾没接管过。

唯一的持久化状态是当前 profile 的 patch($DSH_HOME/profiles/<profile>/cordis.patch.yml)里 本插件那一行的 config(dialect / bashPath / 上一次自动发现扫到的 bashCandidates)。 dsh plugin remove 没有清理它的钩子,插件也无法区分「重启」与「卸载」(两种情况插件都会被卸载一次, 在 dispose 里删数据会让重启丢掉你要保留的路径),所以那一行是惰性的:卸载后没有任何代码会读它, 手动删掉即可。旧版(0.1.0)写在 $DSH_HOME/settings.yaml 的 terminal-tool: 段不会被 0.1.7 导入 (见「升级到 0.2.0」),它只留在 settings.yaml.imported 里,同样可以手动删。 临时目录下的 dsh-git-bash-terminal-tool.log 同理。

已知限制

| 限制 | 说明 | |---|---| | 只对 Windows 生效 | bundle 自带的 patch 把整行 disabled 在非 win32 上:host 的 apply 不执行、client bundle 也不进启动图 | | 只对新会话生效 | 运行中的会话保持启动时的终端选择(有意为之) | | 极简模式会退化成一次性 shell | minimal 是唯一用持久 PTY 的官方预设;本插件在 win32 上把它的 pwsh 换成一次性 Git Bash(见「极简模式(minimal)的影响」) | | 宿主侧改动要重启 | 与其他 DSH 插件一样:Node ESM 缓存,改宿主代码必须重启 |

排障

宿主半区每次启动、每次替换尝试都会往临时目录写一行日志:

Get-Content "$env:TEMP\dsh-git-bash-terminal-tool.log" -Tail 30

常见几行:

| 日志 | 含义 | |---|---| | apply: platform=win32 pid=… | 宿主半区被加载了 | | settings: dialect=bash bashPath="…" candidates=N(新会话生效) | 从 entry Config 读到的当前设置 | | routes: registered /api/dsh-tweaks-terminal/state | 浏览器取数的路由挂上了 | | replace: applied agent=… bash=… | 某个会话成功换成了 Git Bash | | replace: skipped agent=… reason=… | 跳过的原因(设置是 pwsh / bashPath 为空 / 找不到 pwsh 可限制 …) | | settings: current value is invalid: invalid bashPath: … | 存盘里的 bashPath 不合法(不存在 / 是 WSL)→ 只留痕,不拦启动 | | replace: skipped agent=… reason=invalid bashPath: … | 该会话的替换被跳过(会话照旧 pwsh,绝不注册坏路径的工具) | | replace: failed agent=… unsupported JSON schema: … | 工具 schema 超出当前 DSH 的 JSON Schema 子集 → 只跳过替换并留痕 | | replace: restrict(deny:[pwsh]) refused, skipping | 该 agent 已看不到 pwsh(典型:子代理继承了父层的处理结果)→ 正常跳过 |

安装阶段就失败的(pnpm / 市场报 ERR_PNPM_EPERM ... symlink)与本插件的日志无关: 见「安装 → 装不上?先看是不是「本地 link 留下的 junction」」。

开发者

node build.mjs
node node_modules/typescript/bin/tsc --noEmit
node scripts/selftest.mjs        # 发现算法 / 设置 / 升级契约 / 替换 / 工具契约 + 真机跑 Git Bash
node scripts/clientsmoke.mjs     # client bundle 协议 + apply + 行组件

# 让自测用**部署里的**真件复核:dsh-tools 的工具 schema 校验器 + dsh-settings 的 volatileForm(推荐,CI 里可不设)
DSH_STABLE_HOME="D:/env/node-global/dsh-stable" node scripts/selftest.mjs

拿本地目录调试(dsh plugin add <本目录>)会在 profile 里建一个 junction;换回 npm 正式版之前先把它删掉, 否则 pnpm add 会以 ERR_PNPM_EPERM 失败(原因与判据见「安装 → 装不上?…」)。不想反复删就用 tarball 调试: npm pack → dsh plugin add .\dsh-tweaks-git-bash-terminal-tool-0.3.0.tgz。

设计文档见 docs/plans/git-bash-terminal-tool-design.md(本地文档,不入库), 本仓库的开发约定、DSH 契约与通用坑见 AGENTS.md。

实现要点(细节都在源码注释里):

  • 运行时只依赖 @deepseek-ai/schemastery(entry Config 必须是真 schema,见「升级到 0.2.0」); 其余官方契约全部是 src/host/types.ts 的结构性窄化投影,工具定义与执行器都自带 (因为 win32 上 ctx.shell 就是 pwsh,本插件不接管它)。
  • 替换发生在 per-agent 初始化事件 agent/created(0.1.5-rc.1 的 agent/session-start 自 0.1.6 起已被官方移除, 见「升级到 0.3.3」),动作只有三个:在该 agent 自己的 scope 里 tools.restrict({ deny: ['pwsh'] })、tools.register(<自包含 Git Bash 工具>)、 systemPrompt.section({ name: 'tool:pwsh', order: 1010, text: '' }) 压掉残留提示词。
  • 沙箱升级(sandbox_permissions + 审批)按官方契约逐字复刻(src/host/escalation.ts), 包括错误文案、严格更宽顺序与 fail-closed 语义。
  • 包名/目录已改名为 dsh-tweaks-git-bash-terminal-tool(体现 Git Bash)。设置 namespace 现在是 entry id git-bash-terminal-tool(0.1.7 的设置面按 entry id 定位,见「升级到 0.2.0」); locale 命名空间与设置行 slot id 仍叫 terminal-tool(纯实现标识,不参与设置寻址)。