🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

Neovim 代理 AlbinZhu/dsh.nvim

DeepSeek Harness
AlbinZhu0 天前有提交已提供中文文档扫描:无法判定

在 Neovim 中使用 DeepSeek Harness 的 AI 编码代理

33/100
综合分
4
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add AlbinZhu/dsh.nvim
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · vision
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 0 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
⚪ 扫描:无法判定尚无人工评估
展开查看扫描说明与证据 ↓

已尝试扫描但取不到可分析的源码:仓库或包不存在、已删除,或为非 JS/TS 实现、未随包发布源码。无法判定,不代表安全。

  • · 包内无可扫 JS
  • · TS 源码(可能为非 JS 实现或未发布源码),无法判定
扫描于 2026/11/3(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 浮窗内AI提问
  • 审查选中代码

README

由 DeepSeek 最新模型翻译生成
dsh.nvim 在 Neovim 中使用 DeepSeek Harness 的 AI 编码代理 English · 简体中文 📸 截图 dsh.nvim 是一个轻量级 Neovim 插件,把 dsh 接入编辑器,支持两种工作方式: - 一次性任务模式(headless profile):在浮窗里提问、审查当前文件、或把选中的代码发给 AI 代理,结果直接显示在浮窗中。 - 交互式终端 TUI:把 dsh-TUI(dsh --profile dsh-tui)跑进 Neovim 内置 :terminal,支持 float / split / vsplit / tab 布局,可随时 toggle。
展开完整文档(README 剩余 1 节)
dsh.nvim

在 Neovim 中使用 DeepSeek Harness 的 AI 编码代理

English · 简体中文

📸 截图

dsh.nvim 是一个轻量级 Neovim 插件,把 dsh 接入编辑器,支持两种工作方式:

- 一次性任务模式(headless profile):在浮窗里提问、审查当前文件、或把选中的代码发给 AI 代理,结果直接显示在浮窗中。
- 交互式终端 TUI:把 dsh-TUI(dsh --profile dsh-tui)跑进 Neovim 内置 :terminal,支持 float / split / vsplit / tab 布局,可随时 toggle。

✨ 特性

- 🪟 浮窗交互 — 提问与结果都在一个浮动窗口里,按 q / <Esc> 关闭
- 💬 三种入口 — 直接提问、审查当前文件、处理选中文本
- 🖥️ 集成 dsh-TUI — 把交互式 TUI 跑进内置 :terminal,四种布局 + toggle
- ⚡ 开箱即用 — 自动探测 dsh 路径(PATH → ~/.npm/_npx 下的最新副本)
- 🧩 完全可定制 — 提示词模板、工作目录、超时、窗口样式、按键映射
- 🔌 Lua API — 可被其它插件或配置脚本调用
- 🔧 兼容 Neovim ≥ 0.10 — 基于 vim.system / vim.fs

📋 要求

- Neovim ≥ 0.10
- DeepSeek Harness 的 dsh CLI(@deepseek-ai/dsh)

请参考 deepseek-harness 安装 dsh;或直接让插件自动探测 ~/.npm/_npx 下的副本。

要使用 TUI,还需把 dsh-TUI 装进 dsh-tui profile(Node ^22.19 || >=24,PATH 上有 pnpm):

npx -y @deepseek-ai/dsh plugin --profile dsh-tui add @deepseek-harness-tui/dsh-tui

也可以在 Neovim 里直接跑 :DshTuiInstall 完成同样的事情。如果你已经按 dsh-TUI 自己的说明 装好了它,就不用再装:dsh-tui 与 dsh --profile dsh-tui 等价。

📦 安装

lazy.nvim

{
"AlbinZhu/dsh.nvim",
lazy = false, -- 插件很小,直接启动加载即可
config = function()
require("dsh").setup()
end,
}

按需懒加载(可选):

{
"AlbinZhu/dsh.nvim",
event = "VeryLazy",
config = function()
require("dsh").setup()
end,
}

packer.nvim

use({
"AlbinZhu/dsh.nvim",
config = function()
require("dsh").setup()
end,
})

vim-plug

Plug 'AlbinZhu/dsh.nvim'
" 然后在你的配置里: " lua require("dsh").setup()

🚀 快速上手

| 命令 | 作用 |
| :Dsh 帮我看看这个项目 | 直接提问 |
| :Dsh | 弹出输入框提问 |
| :DshFile | 审查当前文件 |
| :'<,'>DshSelection | 处理选中的文本 |
| :DshCancel | 取消任务 |

🖥️ dsh-TUI 集成

| 命令 | 作用 |
| :DshTui | 打开/收起 TUI(默认布局) |
| :DshTui [文本] | 打开后把文本输入到 TUI 输入行 |
| :DshTuiFloat / :DshTuiSplit / :DshTuiVSplit / :DshTuiTab | 指定布局打开 TUI |
| :DshTuiFocus | 智能聚焦:光标在 TUI 里则收起,TUI 可见但光标在别处则聚焦,已收起或未启动则打开 |
| :DshTuiResume [id] | 以 --resume [id] 启动 TUI(不给 id 就恢复上一次会话) |
| :DshTuiFile [路径] [起始行] [结束行] | 把文件加进 TUI 输入行(默认 @"路径" 引用);给出行号则只引用这一段;支持 %,不带路径 = 当前文件 |
| :'<,'>DshTuiSelection | 把选中的代码粘贴进 TUI 输入行 |
| :DshTuiTreeAdd | 在文件树里把光标下的文件(或选中的行)加进 TUI 输入行 |
| :DshTuiClose | 关闭/收起 TUI 窗口 |
| :DshTuiInstall | 安装 dsh-TUI 到 dsh-tui profile |

默认按键映射(在 setup() 中注册,可关闭):

| 按键 | 动作 |
| <leader>da | 提问 |
| <leader>df | 审查当前文件 |
| <leader>ds (visual) | 处理选中文本 |
| <leader>tt | 打开/收起 TUI |
| <leader>tf | 把当前文件加进 TUI |
| <leader>ts (visual) | 把选中代码加进 TUI(在文件树里则是选中的文件) |
| <leader>ts(文件树里) | 把光标下的文件加进 TUI |
| <leader>tF | 聚焦 / 收起 TUI(智能切换) |
| <leader>tr | 恢复上一次 TUI 会话 |

打开或聚焦 TUI 后会直接进入终端模式,可以马上输入(设 tui.auto_insert = false 则停在 normal 模式)。TUI 终端内:<C-\><C-n> 进入终端 normal 模式后按 q / <Esc> 收起窗口;TUI 自身快捷键(如 Ctrl+B 侧边栏、Ctrl+R 历史)在终端 job 模式下直接可用。

从 claudecode.nvim 迁移?

TUI 的命令和按键参照 coder/claudecode.nvim 设计,习惯可以直接带过来:

| claudecode.nvim | dsh.nvim |
| :ClaudeCode · <leader>ac | :DshTui · <leader>tt |
| :ClaudeCodeFocus · <leader>af | :DshTuiFocus · <leader>tF |
| :ClaudeCode --resume · <leader>ar(以及 --continue · <leader>aC) | :DshTuiResume · <leader>tr —— 在 dsh-TUI 里 --resume、-c、--continue 都表示“重新打开上一次会话” |
| :ClaudeCodeAdd % · <leader>ab | :DshTuiFile · <leader>tf(也可带行号,如 :DshTuiFile % 10 20) |
| :ClaudeCodeSend · <leader>as(visual) | :DshTuiSelection · <leader>ts(visual) |
| :ClaudeCodeTreeAdd · <leader>as(文件树) | :DshTuiTreeAdd · <leader>ts(文件树) |
| :ClaudeCodeSelectModel · <leader>am | :DshTui /model —— 把 /model 输入到输入行,按回车即可;dsh-TUI 在应用内选模型,没有 --model 启动参数 |
| :ClaudeCodeDiffAccept / DiffDeny · <leader>aa / <leader>ad | —— claudecode.nvim 通过 IDE WebSocket 协议接收 diff;dsh 没有这套协议,所以没有可接受或拒绝的东西 |

⚙️ 配置

require("dsh").setup({
dsh_cmd = nil, -- dsh 可执行文件;nil = 自动探测(PATH → ~/.npm/_npx 最新副本)
profile = "headless", -- dsh profile
launcher_args = {}, -- 额外的启动器参数,例如 { "--patch", "/path/x.yml" }
cwd = "root", -- 运行目录:"root"(git 根) | "buffer" | "cwd" | 绝对路径
timeout_ms = nil, -- 任务超时(毫秒),nil = 不限
include_file_content = true,
max_inline_file_chars = 20000,
close_key = "q",
prompts = {
file = "请查看文件 %s 并给出你的分析与改进建议。",
file_with_content = "以下是文件 %s 的完整内容:\n\n\n%s\n selection = "以下是 %s 中的一段代码:\n\n\n%s\n },
keymaps = {
ask = "<leader>da",
ask_file = "<leader>df",
ask_visual = "<leader>ds",
tui = "<leader>tt",
tui_file = "<leader>tf",
tui_visual = "<leader>ts", -- 选中的代码;在文件树里则是选中的文件
tui_focus = "<leader>tF", -- 智能聚焦 / 收起(:DshTuiFocus)
tui_resume = "<leader>tr", -- 恢复上一次会话(:DshTuiResume)
tui_tree = "<leader>ts", -- 文件树里:添加光标下的文件(normal 模式,仅文件树缓冲区)
},
tui = {
profile = "dsh-tui", -- dsh-TUI 所在的 profile
launcher_args = {}, -- 额外的启动器参数,例如 { "--patch", "/path/x.yml" }
cwd = "root", -- 运行目录:"root" | "buffer" | "cwd" | 绝对路径
layout = "vsplit", -- 默认布局:"float" | "split" | "vsplit" | "tab"
close_key = "q", -- 终端 normal 模式下关闭/收起窗口的按键
file_mode = "mention", -- 添加文件方式:"mention"(引用) | "content"(粘贴全文)
selection_mode = "content", -- 添加选区方式:"content"(粘贴代码) | "mention"(引用 @文件#L起-止)
auto_insert = true, -- TUI 窗口获得焦点后自动进入终端模式(false = 停在 normal 模式)
float = {
relative = "editor",
width = 0.94, -- 小数按编辑器尺寸换算;也支持整数(字符列)
height = 0.9,
row = 0.03,
col = 0.03,
anchor = "NW",
border = "rounded",
title = " dsh-tui ",
title_pos = "center",
style = "minimal",
focusable = true,
},
split = { position = "below", size = 0.4 }, -- position: "below" | "above"
vsplit = { position = "right", size = 0.5 }, -- position: "right" | "left"
},
window = {
relative = "editor",
width = 0.72, -- 小数按编辑器尺寸换算;也支持整数(字符列)
height = 0.5,
row = 0.25, -- (1 - height) / 2,配合 anchor="NW" 居中
col = 0.14, -- (1 - width) / 2
anchor = "NW",
border = "rounded",
title = " dsh ",
title_pos = "center",
style = "minimal",
focusable = true,
},
})

- keymaps 里的某一项设为 nil / false / "" 即禁用该映射。
- 未调用 setup() 时命令仍可用(默认配置),只是不会注册按键映射。

🔌 Lua API

require("dsh").setup(opts) -- 配置 + 注册按键
require("dsh").run(task) -- 运行任务
require("dsh").ask(prompt?) -- 提问(无参数时弹出输入框)
require("dsh").ask_file() -- 审查当前文件
require("dsh").ask_visual() -- 处理视觉选择
require("dsh").cancel() -- 取消任务
require("dsh").open_tui(opts?) -- 打开/聚焦 TUI(opts: { layout, text })
require("dsh").toggle_tui(opts?) -- toggle TUI
require("dsh").close_tui() -- 收起/关闭 TUI 窗口
require("dsh").tui_install() -- 安装 TUI 插件到 tui profile
require("dsh").tui_add_file(path?) -- 把文件加进 TUI(默认 @mention 引用)
require("dsh").tui_add_selection() -- 把视觉选区粘贴进 TUI
require("dsh").tui_paste(text) -- 以 bracketed paste 安全粘贴文本
require("dsh.tui").send(text) -- 向 TUI 输入行发送文本

🧠 工作原理

插件最终执行:

dsh --profile headless -- "<任务文本>"

headless 模式只把最后一条非空回复写到 stdout(成功退出码 0,失败退出码 1),因此浮窗在运行期显示 spinner,结束后一次性展示结果;出错时把 stderr 一并展示。

TUI 集成则执行:

dsh --profile dsh-tui

并把该进程跑进 Neovim 内置 :terminal 缓冲区(dsh-TUI 是全屏交互式终端应用,不能像 headless 那样只收集 stdout)。窗口收起后进程继续在后台运行,再次 toggle 会复用同一个终端。

把代码/文件「加进」TUI 时,走的是终端自身的输入面:

- 选中的代码用 bracketed paste(ESC[200~ … ESC[201~)整段粘贴进输入行,多行代码、转义字符都安全,不会逐行提交;
- 文件默认以 @"路径" @mention 引用,提交时 dsh-TUI 将其展开为附件(文本按大小上限截取,图片作为图片块);tui.file_mode = "content" 则改为粘贴完整内容;
- 行区间用 dsh-TUI 的 #L 后缀::DshTuiFile 路径 12 14 会添加 @"路径"#L12-14。设 tui.selection_mode = "mention" 后,visual 选区也以同样方式引用、不再粘贴代码 —— 更轻量,但 dsh-TUI 是从磁盘读文件,看不到未保存的修改(没有关联文件的缓冲区仍会粘贴代码);
- 在文件树里(nvim-tree、neo-tree、oil.nvim、mini.files、netrw,以及 snacks 的 explorer / picker 列表),<leader>ts 或 :DshTuiTreeAdd 会把光标下的文件或目录以 @"路径" 引用加进去。要一次加多个:在 visual 模式选中多行(neo-tree、oil、mini.files),或先做标记(nvim-tree 书签、netrw 的 mf、snacks 的 <Tab>)。文件树里的添加始终是 @mention,不受 file_mode 影响。

这些都只放进输入行、不自动回车,方便你继续补充说明后再提交。

:DshTuiResume [id] 会以 --resume [id] 启动 TUI。这个参数只在启动新进程时才生效:TUI 已在运行(哪怕窗口收起了)时只会把它显示出来,并提示你在 TUI 里用 /resume。

❓ 常见问题

Q:第一次运行很慢? headless profile 首次使用会自动初始化,第一次运行会多花几秒,属正常现象。

Q:提示找不到 dsh? 插件会按 dsh_cmd → PATH → ~/.npm/_npx/*/node_modules/.bin/dsh 的顺序探测。都不行就显式指定:

require("dsh").setup({ dsh_cmd = "/绝对/路径/dsh" })

Q:结果窗口怎么关闭? 按 q、<Esc> 或 <C-c>。

🗺️ Roadmap

- [x] 交互式终端 TUI 集成(dsh-TUI)
- [ ] 流式输出(配合 dsh 未来支持增量输出)
- [ ] 会话/多轮对话支持(headless 侧;TUI 侧已内置完整会话管理)
- [ ] 把结果写入 split / quickfix

🤝 贡献

欢迎提 issue 和 PR。改动请保持现有代码风格,并确保 require("dsh") 可正常加载。

📄 许可证

MIT © 2026 AlbinZhu

🙏 致谢

感谢 DeepSeek Harness 项目。
预览分享卡片长什么样 ↓AlbinZhu/dsh.nvim
分享 · DeepSeek Harness Hub
AlbinZhu/dsh.nvim

在 Neovim 中使用 DeepSeek Harness 的 AI 编码代理

这是你的仓库?认领条目

回到顶部