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

网页版部署容器 Tom6814/dsh-web

DeepSeek Harnessv1.3.0
Tom681478 天前有提交已提供中文文档扫描:含敏感能力

用 Docker 一键部署,浏览器打开即用完整界面

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

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

自动兼容检查有告警:npm 同名包「dsh-plugin-market」归属 veloce-ailab/dsh-plugin-market,装到的可能不是本插件;安装清单取自 plugin-market/package.json。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Tom6814/dsh-web
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · ui
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 78 天前
档位由哪些信号合成

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

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/10/27) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

npm 同名包「dsh-plugin-market」归属 veloce-ailab/dsh-plugin-market,装到的可能不是本插件;安装清单取自 plugin-market/package.json

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-plugin-market @ 1.3.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/20 14:13:05

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 120 处,展示前 94 条)
  • 发起网络请求
    plugin-market/lib/client.js:155
    fetch('/api/plugin-market/search?q=' + encodeURIComponent(kw))
  • 发起网络请求
    plugin-market/lib/client.js:172
    fetch('/api/plugin-market/install', {
  • 发起网络请求
    plugin-market/lib/client.js:188
    fetch('/api/plugin-market/restart', { method: 'POST' })
  • 发起网络请求
    plugin-market/lib/client.js:195
    fetch('/api/plugin-market/list', { method: 'GET' })
  • 发起网络请求
    plugin-market/lib/client.js:212
    fetch('/api/plugin-market/uninstall', {
  • 发起网络请求
    plugin-market/lib/client.js:712
    fetch('/api/plugin-market/export')
  • 请求外部主机registry.npmjs.org
    plugin-market/lib/index.js:62
    const r = await fetch(`https://registry.npmjs.org/${encodeURIComponent(name).replace(/%2F/g, '/')}/latest`, {
  • 发起网络请求
    plugin-market/lib/index.js:62
    const r = await fetch(`https://registry.npmjs.org/${encodeURIComponent(name).replace(/%2F/g, '/')}/latest`, {
  • 请求外部主机raw.githubusercontent.com
    plugin-market/lib/index.js:77
    const r = await fetch(`https://raw.githubusercontent.com/${fullName}/HEAD/${filePath}`, {
  • 发起网络请求
    plugin-market/lib/index.js:77
    const r = await fetch(`https://raw.githubusercontent.com/${fullName}/HEAD/${filePath}`, {
  • 请求外部主机github.com
    plugin-market/lib/index.js:94
    const r = await fetch(`https://github.com/${fullName}/tree/HEAD/${dir}`, {
  • 发起网络请求
    plugin-market/lib/index.js:94
    const r = await fetch(`https://github.com/${fullName}/tree/HEAD/${dir}`, {
  • 请求外部主机registry.npmjs.org
    plugin-market/lib/index.js:171
    const r = await fetch(`https://registry.npmjs.org/${encodeURIComponent(name).replace(/%2F/g, '/')}/latest`, {
  • 发起网络请求
    plugin-market/lib/index.js:171
    const r = await fetch(`https://registry.npmjs.org/${encodeURIComponent(name).replace(/%2F/g, '/')}/latest`, {
  • 读取本地文件
    plugin-market/lib/index.js:265
    text = readFileSync(wsPath, 'utf8');
  • 写入本地文件
    plugin-market/lib/index.js:283
    writeFileSync(tmp, text, 'utf8');
  • 写入本地文件
    plugin-market/lib/index.js:284
    renameSync(tmp, wsPath);
  • 读取本地文件
    plugin-market/lib/index.js:297
    const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
  • 读取本地文件
    plugin-market/lib/index.js:304
    if (!existsSync(pkgPath)) continue;
  • 读取本地文件
    plugin-market/lib/index.js:306
    const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
  • 写入本地文件
    plugin-market/lib/index.js:319
    writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
  • 读取本地文件
    plugin-market/lib/index.js:334
    const manifest = JSON.parse(readFileSync(join(profileDir, 'package.json'), 'utf8'));
  • 读取本地文件
    plugin-market/lib/index.js:344
    return JSON.parse(readFileSync(join(profileDir, 'package.json'), 'utf8'));
  • 写入本地文件
    plugin-market/lib/index.js:452
    mkdirSync(dirname(HOME_PATCH), { recursive: true });
  • 写入本地文件
    plugin-market/lib/index.js:454
    writeFileSync(tmp, lines.join('\n') + '\n', 'utf8');
  • 写入本地文件
    plugin-market/lib/index.js:455
    renameSync(tmp, HOME_PATCH);
  • 发起网络请求
    plugin-market/lib/index.js:485
    const gh = await fetch(
  • 执行外部命令固定命令
    plugin-market/lib/index.js:555
    const child = execFile(
  • 执行外部命令固定命令
    plugin-market/lib/index.js:703
    const child = execFile(
  • 发起网络请求
    plugin-market/lib/index.js:1188
    const proxy = http.request({
  • 读取本地文件
    plugins/automation/lib/index.js:35
    return JSON.parse(readFileSync(storePath(), 'utf8'));
  • 写入本地文件
    plugins/automation/lib/index.js:41
    mkdirSync(dirname(storePath()), { recursive: true });
  • 写入本地文件
    plugins/automation/lib/index.js:43
    writeFileSync(tmp, JSON.stringify(store, null, 2), 'utf8');
  • 写入本地文件
    plugins/automation/lib/index.js:44
    renameSync(tmp, storePath());
  • 写入本地文件
    plugins/automation/lib/index.js:86
    try { mkdirSync(task.cwd.trim(), { recursive: true }); } catch { }
  • 读取本地文件
    plugins/automation/lib/index.js:87
    if (existsSync(task.cwd.trim())) return task.cwd.trim();
  • 写入本地文件
    plugins/automation/lib/index.js:90
    try { mkdirSync(dir, { recursive: true }); } catch { }
  • 读取本地文件
    plugins/automation/lib/index.js:97
    if (existsSync(headlessPatchPath())) args.push('--patch', headlessPatchPath());
  • 执行外部命令固定命令
    plugins/automation/lib/index.js:103
    const child = execFile(
  • 读取本地文件
    plugins/automation/lib/index.js:188
    if (existsSync(mePath)) {
  • 读取本地文件
    plugins/automation/lib/index.js:190
    try { cfg = JSON.parse(readFileSync(mePath, 'utf8')); } catch { }
  • 发起网络请求
    plugins/automation/lib/index.js:194
    const r = await fetch(cfg.baseURL.replace(/ +$/, '') + '/models', { headers: { Authorization: 'Bearer ' + cfg.apiKey } });
  • 发起网络请求
    plugins/github-sync/lib/client.js:141
    const r = await fetch(url, body ? { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) } : undefined);
  • 读取本地文件
    plugins/github-sync/lib/index.js:30
    try { file = JSON.parse(readFileSync(cfgPath(), 'utf8')); } catch { }
  • 读取密钥环境变量
    plugins/github-sync/lib/index.js:38
    clientSecret: process.env.GITHUB_CLIENT_SECRET || file.clientSecret || '',
  • 写入本地文件
    plugins/github-sync/lib/index.js:42
    writeFileSync(cfgPath(), JSON.stringify({
  • 读取本地文件
    plugins/github-sync/lib/index.js:71
    if (!existsSync(root)) throw new Error('没有会话目录');
  • 读取本地文件
    plugins/github-sync/lib/index.js:72
    for (const dir of readdirSync(root)) {
  • 读取本地文件
    plugins/github-sync/lib/index.js:74
    if (existsSync(p)) return { dir, p };
  • 读取本地文件
    plugins/github-sync/lib/index.js:80
    const raw = zstdDecompressSync(readFileSync(p));
  • 请求外部主机api.github.com
    plugins/github-sync/lib/index.js:99
    return fetch('https://api.github.com' + url, {
  • 发起网络请求
    plugins/github-sync/lib/index.js:99
    return fetch('https://api.github.com' + url, {
  • 读取本地文件
    plugins/github-sync/lib/index.js:129
    const raw = zstdDecompressSync(readFileSync(p));
  • 请求外部主机github.com
    plugins/github-sync/lib/index.js:233
    const tr = await fetch('https://github.com/login/oauth/access_token', {
  • 发起网络请求
    plugins/github-sync/lib/index.js:233
    const tr = await fetch('https://github.com/login/oauth/access_token', {
  • 发起网络请求
    plugins/image-gen/lib/client.js:72
    fetch('/api/image-gen/config').then((r) => r.json()).then((d) => { if (d.ok) setCfg((c) => ({ ...c, ...d.config })); });
  • 发起网络请求
    plugins/image-gen/lib/client.js:76
    const api = (url, body) => fetch(url, { method: body ? 'POST' : 'GET', headers: body ? { 'Content-Type': 'application/json' } : {}, body: body ? JSON.
  • 读取本地文件
    plugins/image-gen/lib/index.js:30
    const j = JSON.parse(readFileSync(configPath(), 'utf8'));
  • 写入本地文件
    plugins/image-gen/lib/index.js:37
    mkdirSync(dshHome(), { recursive: true });
  • 写入本地文件
    plugins/image-gen/lib/index.js:39
    writeFileSync(tmp, JSON.stringify(cfg, null, 2), 'utf8');
  • 写入本地文件
    plugins/image-gen/lib/index.js:40
    renameSync(tmp, configPath());
  • 发起网络请求
    plugins/image-gen/lib/index.js:64
    const r = await fetch(`${base}/images/generations`, {
  • 发起网络请求
    plugins/image-gen/lib/index.js:82
    else if (url) buf = Buffer.from(await (await fetch(url, { signal: AbortSignal.timeout(120_000) })).arrayBuffer());
  • 写入本地文件
    plugins/image-gen/lib/index.js:91
    mkdirSync(dirname0(abs), { recursive: true });
  • 写入本地文件
    plugins/image-gen/lib/index.js:92
    writeFileSync(abs, buf);
  • 发起网络请求
    plugins/image-gen/lib/index.js:182
    const r = await fetch(`${base}/models`, {
  • 读取本地文件
    plugins/mcp-skill/lib/index.js:33
    const j = JSON.parse(readFileSync(configPath(), 'utf8'));
  • 写入本地文件
    plugins/mcp-skill/lib/index.js:40
    mkdirSync(dshHome(), { recursive: true });
  • 写入本地文件
    plugins/mcp-skill/lib/index.js:42
    writeFileSync(tmp, JSON.stringify(store, null, 2), 'utf8');
  • 写入本地文件
    plugins/mcp-skill/lib/index.js:43
    renameSync(tmp, configPath());
  • 读取本地文件
    plugins/mcp-skill/lib/index.js:63
    if (!existsSync(root)) return [];
  • 读取本地文件
    plugins/mcp-skill/lib/index.js:65
    for (const dir of readdirSync(root)) {
  • 读取本地文件
    plugins/mcp-skill/lib/index.js:68
    if (!statSync(dirPath).isDirectory()) continue;
  • 读取本地文件
    plugins/mcp-skill/lib/index.js:71
    if (!existsSync(mdPath)) continue;
  • 读取本地文件
    plugins/mcp-skill/lib/index.js:72
    const raw = readFileSync(mdPath, 'utf8');
  • 写入本地文件
    plugins/mcp-skill/lib/index.js:302
    mkdirSync(dir, { recursive: true });
  • 写入本地文件
    plugins/mcp-skill/lib/index.js:303
    writeFileSync(join(dir, 'SKILL.md'), content, 'utf8');
  • 写入本地文件
    plugins/mcp-skill/lib/index.js:475
    mkdirSync(dir, { recursive: true });
  • 删除本地文件递归
    plugins/mcp-skill/lib/index.js:500
    if (existsSync(p) && p.startsWith(skillsRoot() + '/')) { rmSync(p, { recursive: true, force: true }); removed = true; }
  • 发起网络请求
    plugins/model-extras/lib/client.js:153
    fetch('/api/model-extras/deepseek-key').then((r) => r.json()).then((d) => { if (d.ok) { setDsConfigured(!!d.configured); setDsKey(d.apiKey || ''); } }
  • 发起网络请求
    plugins/model-extras/lib/client.js:154
    fetch('/api/model-extras/config').then((r) => r.json()).then((d) => { if (d.ok) setCfg((c) => ({ ...c, ...d.config })); });
  • 发起网络请求
    plugins/model-extras/lib/client.js:155
    fetch('/api/image-gen/config').then((r) => r.json()).then((d) => { if (d.ok) setImg((c) => ({ ...c, ...d.config })); });
  • 发起网络请求
    plugins/model-extras/lib/client.js:159
    const api = (url, body) => fetch(url, { method: body ? 'POST' : 'GET', headers: body ? { 'Content-Type': 'application/json' } : {}, body: body ? JSON.
  • 读取本地文件
    plugins/model-extras/lib/index.js:27
    return JSON.parse(readFileSync(configPath(), 'utf8'));
  • 写入本地文件
    plugins/model-extras/lib/index.js:33
    mkdirSync(dshHome(), { recursive: true });
  • 写入本地文件
    plugins/model-extras/lib/index.js:35
    writeFileSync(tmp, JSON.stringify(cfg, null, 2), 'utf8');
  • 写入本地文件
    plugins/model-extras/lib/index.js:36
    renameSync(tmp, configPath());
  • 发起网络请求
    plugins/model-extras/lib/index.js:139
    response = await fetch(`${connection.baseURL}/responses`, {
  • 发起网络请求
    plugins/model-extras/lib/index.js:262
    const r = await fetch(`${base}/models`, {
  • 读取本地文件
    plugins/model-extras/lib/index.js:302
    const raw = readFileSync(credentialsPath(), 'utf8');
  • 写入本地文件
    plugins/model-extras/lib/index.js:312
    mkdirSync(dshHome(), { recursive: true });
  • 写入本地文件
    plugins/model-extras/lib/index.js:315
    writeFileSync(tmp, lines.join('\n') + '\n', 'utf8');
  • 写入本地文件
    plugins/model-extras/lib/index.js:316
    renameSync(tmp, credentialsPath());
  • 发起网络请求
    plugins/model-extras/lib/index.js:352
    const r = await fetch(`${base}/models`, {
扫描于 2026/11/3(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库
涉及外部主机:registry.npmjs.org、raw.githubusercontent.com、github.com、api.github.com

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

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

功能亮点

  • Docker一键部署
  • 浏览器打开即用

README

由 DeepSeek 最新模型翻译生成
DeepSeek Harness Web 部署版 DeepSeek Harness(@deepseek-ai/dsh)的 Web 网页部署版,基于 Docker 一键部署。部署后通过浏览器访问完整的 Harness Web 界面:对话、工作区(网页内目录浏览 + 新建文件夹)、插件市场(搜索 GitHub dsh-plugin 插件并安装)等。 目前项目正在高速开发中,很快将增加更多功能 Docker 部署 构建镜像 docker build -t dsh-web . 运行 docker run -d --name dsh \ -p 8080:8080 \ -e PORT=8080 \ -v dsh-data:/data \ dsh-web 浏览器打开 http://localhost:8080 💡 DeepSeek API Key 在网页里配置:首次打开后进入「设置 → 模型」填入 DEEPSEEK_API_KEY(dsh 把密钥保存在配置文件中,不通过环境变量注入)。 ⚠️ 务必挂载持久化目录:-v dsh-data:/data 将数据卷挂载到容器 /data,用于保存 dsh 的配置、工作区、会话记录和安装的插件。不挂载的话,容器重建后这些数据会全部丢失。
展开完整文档(README 剩余 1 节)
DeepSeek Harness Web 部署版

DeepSeek Harness(@deepseek-ai/dsh)的 Web 网页部署版,基于 Docker 一键部署。部署后通过浏览器访问完整的 Harness Web 界面:对话、工作区(网页内目录浏览 + 新建文件夹)、插件市场(搜索 GitHub dsh-plugin 插件并安装)等。

目前项目正在高速开发中,很快将增加更多功能

Docker 部署

构建镜像
docker build -t dsh-web .

运行
docker run -d --name dsh \
-p 8080:8080 \
-e PORT=8080 \
-v dsh-data:/data \
dsh-web

浏览器打开 http://localhost:8080

💡 DeepSeek API Key 在网页里配置:首次打开后进入「设置 → 模型」填入 DEEPSEEK_API_KEY(dsh 把密钥保存在配置文件中,不通过环境变量注入)。

⚠️ 务必挂载持久化目录:-v dsh-data:/data 将数据卷挂载到容器 /data,用于保存 dsh 的配置、工作区、会话记录和安装的插件。不挂载的话,容器重建后这些数据会全部丢失。

其他常用参数:

绑定其他端口(如 9000) -p 9000:8080 -e PORT=8080

国内网络构建较慢时,可换 npm 镜像源加速
docker build --build-arg NPM_REGISTRY=https://registry.npmmirror.com -t dsh-web .

环境变量

| 变量 | 默认值 | 说明 |
| DEEPSEEK_API_KEY | — | 在网页「设置 → 模型」中配置,不通过环境变量注入 |
| PORT | 8080 | 对外端口 |
| DSH_HOME | /data/dsh | dsh 数据目录(即持久化卷挂载点 /data) |
| DSH_TRUSTED_HOSTS | — | 额外信任的主机(逗号分隔),通过域名访问时使用 |
| PREVIEW_ALLOW_PORTS | 3000-9999 | 预览面板可反代的容器内端口白名单(如 5173,8000-9000),防止任意端口探测 |
| PREVIEW_EXTRA_ROOTS | — | 预览可读的额外根目录(逗号分隔),默认含 /tmp |

项目结构

├── Dockerfile # 镜像构建(Node LTS + nginx 反代 + dsh + Patchright 浏览器) ├── start.sh # 启动脚本 ├── patches/ # 部署适配配置(网页目录浏览 + 插件市场 + 浏览器 MCP + 自动化) │ ├── web.cordis.patch.yml # web profile:browse 交互 / 插件市场 / MCP 浏览器 / 自动化 │ └── headless.cordis.patch.yml # headless profile:仅浏览器 MCP(自动化任务执行时使用) ├── plugin-market/ # 插件市场插件(搜索安装 / 预览面板 / 导出项目) ├── plugins/floatboat-style/ # Floatboat 风格提示词注入插件(prompt sections) ├── plugins/automation/ # 自动化插件(定时触发 AI 执行任务) ├── plugins/image-gen/ # 图片生成插件(对话内生成图片,gpt-image-1/2 等) ├── plugins/model-extras/ # 模型增强插件(OpenAI Responses API / 自定义模型) ├── plugins/mcp-skill/ # 技能与 MCP 管理(侧栏入口 + Cursor mcp.json 导入) ├── presets/floatboat/ # 「Floatboat 风格」agent preset(部署到用户预设目录) └── vendor/dsh-routing-suite/ # 第三方:dsh-super-injector(运行时注入器)+ router-standard 路由预设

说明

- 模型配置走官方原生:「设置 → 模型」配置 DeepSeek API Key 或添加任意 OpenAI 兼容自定义提供方(官方支持)。额外提供 OpenAI Responses API 适配器(Codex / gpt-5 的 /v1/responses 协议,原生仅支持 chat/completions):在官方 Models 页选择 openai-responses 提供方后,把端点配置写入 $DSH_HOME/model-extras.json(baseURL / apiKey / models), /models 自动获取模型列表。
- 对话内生成图片(GPT Image 1/2 等):「设置 → 插件 → 图片生成」配置图片端点(OpenAI 兼容 /images/generations)与 Key,自动获取图片模型(gpt-image-1、gpt-image-2、dall-e-3…)。
之后直接让 Agent 生成图片——工具 generate_image 会把图片保存到工作区 images/ 并可预览。
- 自动化(主页侧栏):左侧栏底部「⏰ 自动化」入口(类 TRAE 任务栏),点击打开抽屉面板,可创建定时任务——间隔分钟、每天几点、每周周几几点,到点由 dsh 自带 headless 运行器执行任务(复用同一模型配置);支持「✨ AI 优化」把一句话需求扩展为结构化任务指令、立即运行、运行历史查看。
- 技能与 MCP(侧栏):左侧栏「技能与 MCP」入口(自动化下方)打开管理面板——
- MCP 服务器:新增/编辑/删除/启停(stdio 命令或 streamable-http URL);热插拔:保存/启停后立即连接或断开并注册/注销工具(mcp____),无需重启;面板显示「已热连接 N 工具」状态;重启后自动恢复连接;
- OAuth 浏览器授权:需要浏览器验证的远程 MCP(如 Supabase 等 streamable-http + OAuth 服务器)自动进入「需浏览器授权」状态,点击「打开授权」在浏览器完成登录/授权(授权码流:回调 → token 交换 → 自动连接注册工具),授权持久化,无需重启;
- Cursor 格式:导入区直接粘贴 JSON 文本(.cursor/mcp.json 的 mcpServers 内容, command/args/env 与 url/headers 均支持)即批量导入并热生效;「以 Cursor 格式显示」一键把当前服务器以 Cursor mcpServers 结构展示/导出;
- Skills:管理 $DSH_HOME/skills//SKILL.md(Claude 风格技能根)——上传 SKILL.md 文件或 zip 压缩包(自动解压定位 SKILL.md 并保留附属文件)、手动新建/删除/ 启停;「AI 帮我创建」(一句话描述 → LLM 生成标准 SKILL.md 并安装)、「AI 帮我安装」(粘贴任意教程/规则文本 → AI 整理成标准技能安装);保存即出现在输入框「/」技能菜单(dsh 技能文件监听,实时生效)。
- GitHub 同步(会话底部):每个会话底部一行「GitHub 同步」——可选,同一工作区下所有会话复用同一仓库+分支。绑定方式二选一:
- OAuth App(推荐):配置 GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET (GitHub Settings → Developer settings → OAuth Apps 创建)。回调地址必须填你实际访问的域名:https:///api/github-sync/oauth/callback (多个访问域名需逐个添加回调;也可用 PUBLIC_URL 显式固定对外地址)。
回调地址由服务端按当前请求域名动态生成,与注册一致才能授权成功。
会话底部点「用 GitHub 登录」→ 浏览器授权 → 自动获取账号与邮箱 → 在账号下选择任意仓库(所有仓库)+ 分支 → 点「同步」把会话导出为 Markdown 提交到该仓库(dsh-sessions/.md,重复同步覆盖更新)。OAuth token 持久化,可「解绑」。
- 手动令牌:环境变量 GHP / GH_USER / GH_EMAIL,或在行内折叠的高级项填 GHP。
- 侧栏折叠:「自动化」「技能与 MCP」按钮随侧栏收窄自动隐藏文字、图标居中放大。
- 浏览器自动化(MCP):镜像内置 Patchright(playwright 的 stealth 分支,驱动级反检测,能过基础机器人验证)的 MCP server。Agent 工具集中出现 mcp__browser__browse / interact / extract / close,可查看、填写、点击网页。web 与 headless(自动化任务)profile 都可用。
- dsh-routing-suite(vendored,MIT):
- dsh-super-injector v0.3.3:运行时注入器,dev_ 工具全家桶——注入/卸载/热重载/ 侧挂转正/脚手架/构建发布/插件自检(dev_inject_plugin、dev_uninject_plugin、 dev_reload_package、dev_plugin_status、dev_scaffold_plugin 等 14 个), junction 链接 + loader.create 免重启装配;设置页「插件」区提供插件管理 UI (列表/卸载/拖入内化);清单持久化重启自动恢复。
- router-standard 预设 v0.1.1:任务感知思维模式路由(spec/react/weak 三模式 + 近距离引导 + 单任务三锚)。新建会话选择 Router Standard (experimental) 预设,生成类任务自动 react、维护类任务自动 spec;AI 自优化工具 dev_router_status / dev_router_mode / dev_mode_subagent。
- 构建方式见 vendor/dsh-routing-suite/README.md。
- 导出:右上角「导出」按钮二级菜单——导出项目(工作区打包 zip 直接下载,不落盘,自动排除 node_modules/.git/dist 等)、导出会话日志(复用官方 Session log)。
- 预览面板:对话中的 localhost 链接与文件在右侧分栏预览(可拖宽、缩放、移动端全屏);地址栏显示 127.0.0.1:端口 / file:// 格式;除二进制外任意文件可预览(文本直接显示,二进制给出下载页)。

- 镜像基于 Node 22 LTS,内置 nginx 反向代理(dsh 出于安全设计不支持 0.0.0.0 直绑)。
- 首次使用:添加工作区 → 网页内目录树选目录 → 开始对话;模型配置在 设置 → 模型。
外部 http(s) 链接保持默认新标签页打开。PREVIEW_ROOT 可覆盖文件预览根(默认 /workspace), PREVIEW_EXTRA_ROOTS 追加额外可读根(逗号分隔;未设置时默认含容器临时目录)。
- 插件启停:设置 → 插件 → 「插件列表」展开任意插件卡片,详情里带「启用 / 停用」按钮,通过写入 $DSH_HOME/cordis.patch.yml 用户补丁层即时生效(dsh 热更新),重启后保持。
- Floatboat 风格预设:新建会话时在预设选择器中选「Floatboat 风格」——将 Floatboat (AOE Tech Labs)提示词工程的精华迁移到 dsh:交付完整度优先的工作哲学、工具使用纪律(文件最小变更/来源可信度/浏览器与检索选择/凭据处理)、交付真实性契约(不虚构产物)、安全边界(防套取/防泄露)与委派记忆纪律。基于官方 standard preset,工具能力完全一致;提示段落由 plugins/floatboat-style 插件以 systemPrompt.section() 注入(对应 Floatboat 的 prompt-segment 机制),每段可独立关闭。⚠️ 该 preset 依赖 dsh-floatboat-style 插件(镜像已内置),单独复制 preset 到未装插件的环境会挂载失败。
- 插件安装:搜索 GitHub topic:dsh-plugin 仓库后,自动检测每个仓库对应的
npm 包(读根 package.json;monorepo 探测 packages/ 子包,免 GitHub API 限流):
卡片标注 ✓ npm: 表示该仓库有已发布的 npm 插件包,点击「安装」直接安装
npm 包*(而非 GitHub 根包,避免 monorepo 根包无 dsh.bundle 装完不生效的坑)。
安装时自动处理 pnpm 构建授权(allowBuilds 占位自动批准 + 重试)与兜底 reconcile;安装后做插入条目冲突检测(聚合包与单包同时装会致重启崩溃,装时即警告并可一键卸载 /api/plugin-market/uninstall)。
- 重启服务:安装成功后点「重启服务」→ 进程以非零码退出(exit(1),平台判定崩溃必重启;优雅退出 exit 0 可能被平台视为正常关闭而不重启)→ 容器平台自动拉起新实例 → 插件进入 loader 组合与 Web UI。前端在服务恢复后自动提示并引导刷新页面(index.html 已禁缓存,保证新插件入口图 __DSH_BOOT__ 重新拉取)。请确保已为 /data 挂载持久化卷,否则重启会丢失新装的插件与会话数据。
- 排查日志:插件市场所有操作(install/uninstall/toggle/restart)都以 [plugin-market] 前缀输出详细日志(spec、profile 路径、pnpm 输出、allowBuilds 处理、bundles 现状、冲突检测结果),在 Zeabur 日志面板可直接 grep 定位问题。
预览分享卡片长什么样 ↓Tom6814/dsh-web
分享 · DeepSeek Harness Hub
Tom6814/dsh-web

用 Docker 一键部署,浏览器打开即用完整界面

这是你的仓库?认领条目

回到顶部