dsh-agent-picker

toolstested: passnpmMIT

Agent mode picker for DSH: pick an external Agent CLI (Claude Code, Codex, Qwen Code, Gemini CLI, Aider, Goose, Hermes…) as the session's default executor from a control next to the input box, instead of editing configuration files. The agent roster is data-driven, and installed CLIs are discovered

下载量 / Downloads
2,548
依赖体积 / node_modules
0.23 MB
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

Install

dsh plugin --profile web add dsh-agent-picker

Sandbox test results

StageResult
1 install✓
2 list✓
3 mount✓
4 boot—

Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).

README

dsh-agent-picker

Agent 模式选择器 —— 在 DSH(DeepSeek Harness)Web 界面的输入框右侧加一个控件,

像选推理档位那样选定一个外部 Agent CLI作为当前会话的默认执行体。

它把"有哪些外部 Agent、各自怎么启动"做成数据(agents.json),

所以加一个新 Agent 只需加一条数据,不必改代码。

从旧版本升上来? 先看 [CHANGELOG](./CHANGELOG.md) —— 0.5.0 的行为和 0.4.1
有明显区别(列表变成"你这台机器上装了什么")。

它解决什么问题

DSH 本身能调用外部 CLI,但"调哪一个"通常要写死在配置里。这个插件把选择权交回给你:

输入框右边一个下拉,选谁,这一轮就交给谁。名册驱动的设计意味着

同一个插件能挂任意多个 Agent,包括你自己写的。

安装

dsh plugin add dsh-agent-picker

装完重启 DSH。插件第一次启动会把自带的 agents.json 复制一份到

$DSH_HOME/agent-picker.agents.json(默认 ~/.dsh/),之后你改的是这一份,

插件升级不会覆盖它。

名册:怎么加一个新 Agent

编辑 $DSH_HOME/agent-picker.agents.json,往 agents 数组里加一条:

字段 · 说明

id · 唯一标识

name · 显示名

tool · DSH 里对应的工具名

bin · 包装器文件名(用于"是否已安装"的探测)

available · 初始可用性建议;真实可用性由插件探测包装器是否存在

kind · task=任务型(结果可概括)/chat=对话型(原样转述)

expertise · 菜单里显示的「擅长」一行

note · 健康状态/接线说明

desc · 展开后的详细能力介绍

launch · 可选。自带执行配方:bin / argv / env / keepEnv / timeoutMs / graceMs / maxBytes。写了它,本插件就自己注册 cli_<id>_direct 工具

launch.keepEnv · 可选。要从父进程继承的环境变量名白名单(名字里带 KEY/TOKEN/SECRET/PASSWORD 的变量默认会被剥离,靠环境变量授权的 CLI 必须写在这里)

keep · 可选。写 true 表示永不自动清理(见下面"旧版残留会自动清理")

改完重启 DSH 生效。

旧版残留会自动清理(0.6.0 起)

插件只在你没有名册文件时才生成一份,存在就永不覆盖。但旧版本留下的名册里

常有一批指向别的机器路径的条目(比如 *-dsh.ps1)——它们在新机器上永远跑不起来,

却一直占着列表。所以每次启动会做一件事:

  • 把名册里能证明跑不起来的条目删掉(判据:配方 argv 引用的脚本在本机不存在)
  • 删之前完整备份到 <名册>.legacy-<时间戳>.bak,想找回就改回文件名
  • 没有 launch 的"借用型"条目绝不碰(工具可能由别的插件提供)
  • 一条都不用删时,文件一个字节都不动
  • 想保护某一条?在它里面加 "keep": true

launch.argv 的路径规则(重要)

名册是跨机器的,所以不要写死绝对路径。argv 里写裸文件名即可,

插件会在运行时按下面顺序解析:

codex-dsh.ps1            ->  <cliBinDir>/codex-dsh.ps1
{cliDir}/codex-dsh.ps1   ->  <cliBinDir>/codex-dsh.ps1
C:\some\where\x.ps1      ->  原样保留(你想钉死绝对路径时用)

cliBinDir 的取值:环境变量 DSH_AGENT_PICKER_CLI_DIR 优先,

否则默认 ~/dsh-clis/bin(与 dsh-sub-cli 的约定一致)。

占位符

argv 里可用的占位符:{task}(任务正文)、{permflags}、{permission}、{model}、{image}。

{permflags} 是特殊的:它会展开成多个参数,取值来自名册里的

permFlags[<权限档>];没指定权限档时取 defaultPermFlags。

所以一条模板就能携带"权限档 → 这个 CLI 自己的 flag"的映射,调用方不必知道每个 CLI 的语法。

{image} 只对命令行真的支持图片参数的 CLI 有意义(例如 Codex 的 -i/--image)。

其余 CLI 就算它自己有读图能力,也不是靠这个占位符——那种情况请把图片路径写进任务正文,

让那个 Agent 用自己的读文件工具去读。

你需要自备什么

这个插件只负责调度,不附带任何 Agent。装好一个 CLI,它就会被自动发现并列出来。

探测来源(按顺序):PATH → 托管目录(~/dsh-clis/bin,可用 DSH_AGENT_PICKER_CLI_DIR 覆盖)

→ ~/.local/bin。

出厂名册是空的,这是有意的 —— 列表里的成员全部来自"本机实际探测"。

所以别人机器上看到的列表,取决于他装了哪些 CLI。

各 Agent 的兼容性(实测声明)

内置识别 31 个 Agent 名字。分两类:

  • 11 个带启动配方 → 探测到即可直接调用
  • 20 个只识别 → 探测到会出现在列表里(带名字和介绍),但需要你补一条启动配方才能真正调用
为什么不全给配方:启动参数写错比不写更糟 —— 那会变成"列表里能点,一点就报错"。
所以只有参数经过验证的才给配方,其余诚实标成"需配置"。

✅ 有启动配方(探测到即可调用)

Agent · 启动参数 · 权限映射 · 参数验证

Aider · --message {task} · --dry-run / --yes-always · --help 复核 ✓

Qwen Code · -p {task} · --approval-mode plan / yolo · --help 复核 ✓

Gemini CLI · -p {task} · --approval-mode plan / yolo · --help 复核 ✓

Goose · run -t {task} · — · --help 复核 ✓

Hermes · -z {task} · — · --help 复核 ✓

Codex · exec --skip-git-repo-check {task} · -s read-only / workspace-write / danger-full-access · 取自已跑通的包装脚本

Claude Code · -p {task} · --permission-mode plan / acceptEdits / bypassPermissions · 取自官方参数(未本机复核)

Ollama · run qwen3:4b {task} · — · 见下方条件

opencode · run {task} · — · 官方文档给出 run 子命令;未实机跑过

Cursor CLI · -p --trust {task} · --mode plan / --force · 官方 --help 实测记录 ✓

Kimi · -p {task} · 非交互模式自带 auto 权限 · 官方文档 ✓

🔍 只识别、不给配方(会显示"需配置启动方式")

GitHub Copilot CLI · Trae · Amp · Droid · Augment Code ·

OpenHands · Cline · Windsurf · Qoder · CodeBuddy · Grok CLI ·

CodeGeeX · Plandex · CodeBuff · gptme · Open Interpreter ·

(OpenClaw · Kilo Code · Crush · WorkBuddy)

这些出现在列表里时是这样的:

○ GitHub Copilot CLI     已检测到,需配置启动方式
  自动发现(…\copilot.CMD);识别到 CLI,但还没有启动配方
  ─────────────────────────────────────────────
  GitHub 官方的命令行 Copilot,和 GitHub 生态贴得最近。
  —— 用约定目录或名册补一条 launch 就能调用

怎么补一条配方(插件里有现成引导)

不用翻这份文档 —— 在列表里点那一行的 「怎么补?▼」,会就地展开三步:

1. 查出它的参数 —— 命令里已经填好这个 CLI 的真实路径,一键复制:

"C:\...\copilot.CMD" --help

2. 找“一次性执行”的标志 —— --prompt / -p / exec / run 这类

3. 存成约定目录里的文件 —— 路径和模板都由插件给出,id / 名字 / bin 已填好,

你只改 argv 这一行,模板可一键复制:

{
  "id": "copilot",
  "name": "GitHub Copilot CLI",
  "tool": "cli_copilot_direct",
  "kind": "task",
  "launch": { "bin": "C:\\你的路径\\copilot.CMD", "argv": ["-p", "{task}"] }
}

存好后重启 DSH,它就会从「可安装」升到主列表。

引导是纯提示,不写盘、不拦截 —— 现在不想配也完全可以,那一行就安静待着。

关于探测名的取舍

探测名越短越容易误报(机器上有个同名的无关程序,就会被当成某个 agent)。

所以本项目有一条硬规则:只接受 4 个字符以上的探测名 —— amp 是唯一例外,

因为它是 Sourcegraph 官方 CLI 名。Pi、Roo Code 这类既有条目因此被移除,

而不是靠猜名字去凑数量。

另外 Crush 目前只识别、不给配方:Charm 的仓库里有一个未关闭的 issue 在请求

“非交互批处理模式”(charmbracelet/crush#1030),说明 crush run <任务> 这条路

当时并不存在。猜一个不存在的子命令 = 用户点了必报错,所以宁可不给。

查过、但没收进目录的(都有原因)

工具 · 为什么没加

iFlow CLI · 官方文档写明 2026-04-17 已停止服务,并要求迁移到 Qoder

通义灵码(Lingma) · 已并入 Qoder,所以只留 qoder 一条,不重复

文心快码 / Zulu-CLI · 只查到产品名,没查到确切命令名;写错等于死条目

ZCode · 旧版本里有这一条,但探测名始终无法核实 —— 0.5.1 已移除

原则:名字可以少,但不能猜。少一个的代价是"没被发现",写错一个的代价是

"列表里出现一条永远点不动的东西"。

⚠️ 需要额外条件

Agent · 条件

Ollama · 本机要有 ollama 服务在跑;配方里模型名写死为 qwen3:4b,装的是别的模型请改名册或约定目录

Gemini CLI · 还要一个协议翻译层(如 LiteLLM)把你的端点转成 Gemini 协议

Qwen Code · 需要 DEEPSEEK_API_KEY(它自己读 ~/.qwen/.env)

Goose · 需要 GOOSE_PROVIDER / GOOSE_MODEL / OPENAI_API_KEY / OPENAI_HOST

⚠️ 上表里名字带 KEY 的变量,默认不会被传给子进程(见下面"安全边界"一节)。
如果你就是靠环境变量给它授权,请在名册该条目里显式白名单:
```json
"launch": {
"bin": "goose",
"argv": ["run", "-t", "{task}"],
"keepEnv": ["OPENAI_API_KEY", "OPENAI_HOST", "GOOSE_

…(truncated)

Rendered from the README published on npm. Formatted only, not edited.

Versions

Published on npm::11,最后更新 2026-11-01

Links

GitHub · Homepage · npm

Same category