DSH 服务农场:注册、启动、停止、重启长驻项目服务,提供 agent 工具(farm_status/start/stop/restart/logs/register)与 farm.yaml 声明式服务,总览抽屉支持按工作区分组、实时日志 follow、搜索与导出。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:MarchLiu/dsh-farm
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
该插件的 README 只有英文版本。
DSH service farm plugin: register, start, stop, restart and watch long-running project services — the agent can do it through tools, you can do it through the web UI.
Install
dsh plugin --profile <name> add /path/to/dsh-farm
Restart the DSH web surface afterwards.
What you get
UI: a 🚜 button at the sidebar foot with a running-services badge; clicking it opens the overview drawer — services grouped by workspace with status dots, start/stop/restart buttons, and a log view with live follow (SSE), substring search and download/export. With DSH-better-sidebar installed the same panel becomes a Farm tab in that sidebar instead — see Where the UI lives.
Delete: 🗑 on a row removes that one service.
☑ selectswitches the drawer into multi-select — tick rows (or select all), then delete (n) opens a confirmation dialog listing the targets; nothing is deleted until you confirm it.farm.yamlservices are greyed out in both paths: the file owns them, so you remove them by editing it.Agent tools:
farm_status/farm_start/farm_stop/farm_restart/farm_logs(service, tail, search)/farm_register(name, workspace, command, ...)/farm_unregister(service | services). Say "帮我把 dev server 注册到 farm 并启动" in a session and the agent does the rest.farm.yaml (optional, per workspace, commit-friendly):
services: dev-server: command: pnpm dev # cwd: sub/dir # optional, resolved against the workspace autoRestart: true env: PORT: 5173Declared services appear in the UI and
farm_statusautomatically (source: yaml); the file is always the source of truth.
Where the UI lives
dsh-farm renders its panel in whichever home is available, decided at runtime:
| DSH-better-sidebar | Where the panel appears |
|---|---|
| installed | a 🚜 Farm tab in better-sidebar (single-instance, with a running-count badge); dsh-farm's own footer button and drawer stand down |
| not installed | dsh-farm's own 🚜 footer button + right-hand drawer |
Nothing to configure, and better-sidebar is not a dependency — dsh-farm looks the service up by name at runtime and keeps working when it is absent. It also follows better-sidebar being enabled or disabled while DSH is running, in both directions.
Implementation note for anyone extending this:
betterSidebaris deliberately not in the client half'sinject. In DSH's cordis a declared-but-missing service parks the whole plugin, which would take the fallback UI down with it — the plugin would vanish entirely rather than fall back. The runtime's optional-lookup hook isctx.get('betterSidebar')(undefined when absent), andctx.on('internal/service', …)catches better-sidebar arriving or leaving later. That event can fire more than once for the same arrival, so registration is idempotent.
Behavior notes
- Services are spawned as children of the DSH process (
/bin/sh -c), so they are reclaimed when DSH exits. Dynamic registrations persist across restarts in$DSH_HOME/storages/dsh-farm/services.json(state does not). - Stop = SIGTERM, then SIGKILL after a 3s grace.
autoRestartretries an abnormal exit up to 5 times with exponential backoff (1s → 16s).- Logs: 5000-line in-memory ring per service plus an append-only file under
$DSH_HOME/storages/dsh-farm/logs/<id>.log. - Deleting a service stops it first, then drops its registry row, its live log
stream and its log file. Ids are derived from
workspace + name, so this keeps a later re-registration of the same name from inheriting stale logs. Project files are never touched.
HTTP API (localhost only, prefix /farm)
| Route | Meaning |
|---|---|
GET /farm/services?workspace= |
list (farm.yaml entries merged in) |
POST /farm/services |
register/update a dynamic service |
GET /farm/services/:id |
one service |
DELETE /farm/services/:id |
unregister one (stops it first; 400 for farm.yaml services) |
POST /farm/services/batch-delete |
unregister many — { ids: [] } → { ok, deleted, failed } |
POST /farm/services/:id/start|stop|restart |
lifecycle |
GET /farm/services/:id/logs?tail=&search=&export=1 |
logs, export=1 downloads |
GET /farm/services/:id/logs/stream |
SSE live follow |
Config (override in the profile patch)
- id: farm
config:
dataDir: /abs/path # default $DSH_HOME/storages/dsh-farm
ringLines: 5000
stopGraceMs: 3000
链接
同类插件
yjh051108/dsh-routing-suite★ 6997
一个仓库三件套:DSH 插件包的运行时注入器(注入、热重载、卸载、开发侧挂区一键转正、路由自愈,外带设置页插件管理:列出、卸载、拖入文件夹内化)、任务感知的思维模式路由 agent 预设(router-standard / router-spec / router-react)、以及分级两级任务协议(commit_star / lock_stage / revise_do / edit_plan / mark_task / redteam_verdict 六个工具,任务状态落盘)。注入器实现直接在库内,安装的是它自己的行为而不是一份依赖清单。
strukto-ai/mirage#dsh★ 3696
把文件系统与 bash 提供者换成 mirage 虚拟工作区:文件工具与 shell 命令作用于挂载的资源(RAM、S3、Redis、Slack、Gmail、Notion、Postgres)而非宿主磁盘,支持按挂载点设置读/写/执行模式、按命令选择沙箱(进程内 monty、pyodide、quickjs;远程 docker、e2b、daytona),并可在虚拟终端中安装 CLI(git、gh、slack、linear、ntn、gws,或自行注册的程序树)作为命令头词。
first-fluke/oh-my-agent#dsh★ 1344
在工具执行前后以及尝试结束当前轮次时运行项目 OMA 检查。随插件安装 OMA CLI 依赖,并在首次使用时初始化未配置的项目。需要 Node.js 22+;首次初始化需要网络连接和项目目录写入权限。
hust-open-atom-club/oh-dsh★ 322
社区发行版:TUI、桌面端与 Web UI 统一体验,分层安装、一步到位。
weijiafu14/pi2dsh★ 217
Pi Host ABI 兼容引擎:装一次之后,npm 上的 Pi 扩展原包经 `dsh plugin add <pi-package>` 直接作为 DSH 原生插件挂载。已在官方 DSH 上端到端验证 pi-mcp-adapter(完整 MCP 管理面:OAuth、resources、prompts、MCP Apps、elicitation、sampling)、@tintinweb/pi-subagents、pi-code、pi-hermes-memory、pi-background-tasks;`pi2dsh inspect` 在安装前报告一个包的兼容情况。
Fishquito7/dsh-skill-mcp-panel★ 207
在 DSH Web 设置中管理技能与 MCP 服务器:技能卡片热启停、工作区作用域、分组、批量迁移与拖拽导入,以及 stdio/HTTP MCP 增删改查、连接测试、密钥脱敏,并附带统一 dsh-panel 命令行。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。