DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Compose Panel — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
C

dsh-compose-panel

Compose Panel

DeepSeek Harness 插件:在原生右侧边栏中管理 Docker Compose 项目、控制容器并实时查看各服务日志。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:yizhixiaokong/dsh-compose-panel#70cab0dd1b3fa27dfbffe4cfab6ee5932b7d811b
README兼容性版本

兼容性与来源证明

Compose Panel 以 dsh-compose-panel 发布,当前版本为 0.1.1。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/9/15

版本

0.1.1stable
2026/9/15

相关插件

正在加载相关插件…

最新版
0.1.1
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
最近提交
2026/9/16
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 integrations-communication 分类下经过校验的插件。

Acp App@deepseek-ai/dsh-acp-appdsh ACP 配置文件包:基于 dsh-base 的仅限自动化的 JSON-RPC stdio 和进程生命周期管理Remote Web Ui@linxin666/dsh-remote-web-ui通过扫码配对访问 dsh Web GUI,共享一个官方界面:设置按钮旁的二维码可将手机和 PC 配对到同一个 Web GUI(手机采用竖屏触控适配层,PC 使用完整桌面界面),通过一次性令牌和 rPocketdsh-pocket把 DeepSeek Harness 装进你的口袋:一个包、一个设置页,手机扫码即同步访问电脑上的 DSH(局域网 + 公网,实时同屏)。DSCODE@toddzheng024/dscode-bundle完整的 DeepSeek 编码代理,支持持久化 shell、Ultra 协作和自动权限审查。

README

dsh-compose-panel

English | 中文

A DeepSeek Harness plugin that puts your Docker Compose projects in the native right sidebar: one group per project directory, live status per container, start/stop/restart on hover, and a streaming log tab per service.

It is built for the workspace layout that a single-file container viewer gets wrong: one repository whose subdirectories each own a compose.yaml.

工作区 ~/work/shop
├── compose.yaml            → group “shop”           2/2 running
├── services/api/compose.yaml  → group “services/api” 1/3 running
└── tools/mail/compose.yaml    → group “tools/mail”   not started

Features

  • One group per project directory. Projects are keyed by directory, never by the compose project name, so -p, COMPOSE_PROJECT_NAME and .env cannot merge two different stacks into one row.
  • Three discovery sources. Running and stopped containers, projects Docker already knows but that hold no container, and compose files never brought up at all — all three appear, so an untouched compose.yaml still shows as a project that is simply not started.
  • Workspace scoped. Only projects inside a DSH workspace are listed. Containers that belong to a workspace-relative directory are grouped under the longest-matching workspace; everything else is counted, not hidden.
  • Collapsible groups, status on the right, fixed row heights (nothing moves when the pointer crosses a row).
  • Hover actions. Resting on a row swaps its status cell for the actions that apply to it: project-wide up -d / restart / stop, or the same three for one service. Nothing is ever run without a click.
  • Live logs, streamed. Click a service row to open a log tab for that service; click a project header to open one for the whole project. Each target keeps its own tab.
  • Silent refresh. The list re-reads itself every 45s while idle and every 8s while something is still starting, without losing scroll position, open groups or the selection.
  • Product-native styling: it uses the harness' own theme tokens, so it follows light and dark mode and the accent colour without a settings screen.

Requirements

RequirementNotes
DSH with a web profileThe plugin registers a right-sidebar tab type and one HTTP route, both served by webServer.
Docker CLI on PATH for the host processdocker ps and docker compose ls are run as child processes; the compose v2 plugin (docker compose, not docker-compose) is required.
A POSIX hostPaths are handled as POSIX paths; Windows is untested.
A DSH workspaceOnly directories inside a registered workspace are listed.

Install

Straight from GitHub — nothing to clone (pin a tag if you want a fixed release):

dsh plugin --profile web add "github:yizhixiaokong/dsh-compose-panel"
# pinned: dsh plugin --profile web add "github:yizhixiaokong/dsh-compose-panel#v0.1.1"

From a clone, when you want to edit the code:

git clone https://github.com/yizhixiaokong/dsh-compose-panel.git
cd dsh-compose-panel
dsh plugin --profile web add "$PWD"

From npm, once it is published:

dsh plugin --profile web add dsh-compose-panel

All three end the same way, and none of them needs a manual registration step: dsh plugin runs pnpm, then reads each installed dependency's package.json; a package that declares dsh.bundle has its name appended to dsh.profile.bundles, which is what mounts the cordis.patch.yml beside it. (A dependency without that declaration is installed as a plain library and warns instead.) There is no build step either — the client half is a hand-written bundle that ships in lib/.

Then restart the harness so the client bundle is picked up:

dsh web

To remove it:

dsh plugin --profile web remove dsh-compose-panel

The client half is baselined when the host boots. Editing lib/client.js in a running harness changes nothing until dsh web restarts — a browser refresh is not enough.

Usage

  1. Open the right sidebar and pick the 🐳 容器 capsule from the guide page.
  2. Each workspace is a section; each project directory is a collapsible group headed by its path, with the aggregate container state on the right.
  3. Hover a project header to act on the whole project; hover a container row to act on that one service. The action buttons replace the status cell while the pointer is on the row, and the result is reported in a short banner.
  4. Click a container row (not a button) to open logs for that service in a new tab. Click the group header to open logs for the whole project.

Log tabs have their own controls: replay size (tail), whether to re-open the stream, timestamps on/off, line wrapping, and — for a whole-project tab — the service-name column.

How projects are discovered

One list call runs three commands and joins their results by directory:

SourceCommandContributes
Containersdocker ps -a --format '{{json .}}'Every container, grouped by the com.docker.compose.project.working_dir label.
Known projectsdocker compose ls --all --format jsonProjects that exist but currently have no container (its ConfigFiles are absolute).
Untouched filesone bounded find per workspaceCompose files that were never brought up: depth 4, with node_modules, .git, vendor, dist, build, target, .venv, venv, __pycache__, .next, .cache and .tox pruned.

A project's directory is the join key. Compose file names recognised by the scan are compose.yml, compose.yaml, docker-compose.yml, docker-compose.yaml and the compose.<name>.y*ml / docker-compose.<name>.y*ml variants.

HTTP API

The host half registers one prefix route, /compose/api. Every response uses the same envelope: {"ok":true,"value":…} on success, {"ok":false,"error":{"code","message"}} on failure.

Every call is fenced before any command runs. For the two POST methods the Host header must name a loopback authority (localhost, 127.0.0.1, ::1, *.localhost, with or without a port) or an authority in the web runtime's trusted list; a request the browser marks Sec-Fetch-Site: cross-site is refused; and if an Origin is present its host must equal Host. The log stream uses the read-side variant: the socket peer must be loopback (or the Host trusted), no forwarding header (forwarded, x-forwarded-for, x-real-ip) may be present, and a missing Origin is accepted — browsers send none on a same-origin EventSource.

POST /compose/api/list

// request — root is optional; without it every workspace is listed
{ "root": "/home/me/work/shop" }
// response value
{
  "workspaces": [{ "path": "/home/me/work/shop", "title": "shop" }],
  "groups": [{
    "root": "/home/me/work/shop",
    "title": "shop",
    "scanError": "",
    "projects": [/* … */]
  }],
  "total": 7,       // containers inside the selected workspaces
  "outside": 2,     // containers found but outside every workspace
  "standalone": 1,  // containers with no compose project label
  "notices": []
}

POST /compose/api/action

{
  "action": "restart",          // "up" | "stop" | "restart" — a closed set
  "dir": "/home/me/work/shop",  // the project directory, must be in a workspace
  "service": "api",             // optional; omitted = the whole project
  "files": ["/home/me/work/shop/compose.yaml"]  // optional compose files (-f)
}
// response value; `code` is docker's exit code, `output` its combined output
{ "action": "restart", "dir": "…", "service": "api", "code": 0, "output": "" }

There is deliberately no down: removing containers and volumes is not a sidebar-click operation. service is matched against ^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$, and every -f path must lie inside dir. argv is passed to spawn directly and never goes through a shell.

GET /compose/api/logs (Server-Sent Events)

QueryMeaning
dirProject directory (required, must be in a workspace).
serviceOne service; omitted streams the whole project.
tailLines replayed first: default 200, clamped to 1…5000.
timestamps1 adds --timestamps; off by default.
fileCompose file (-f), repeatable. Without it the host derives the files from docker compose ls and, failing that, a shallow find.

Frames are data: JSON objects:

{ "open": true, "command": "docker compose -f … logs -f --tail 200 api" }
{ "out": "api-1  | listening on :3000\n" }   // stdout chunk, already UTF-8 safe
{ "err": "…" }                               // stderr chunk, same shape
{ "eof": true, "code": 0 }                   // docker exited
{ "error": "spawn failed: …" }

The stream carries NO_COLOR=1, sends a comment ping every 15s so a dead peer is noticed, stops after 4 MB, and terminates the docker process as soon as the tab closes, reloads or navigates away — logs -f never ends on its own.

Limits and known behaviour

  • Read-only elsewhere. Only up -d, stop and restart are reachable; nothing else in the sidebar mutates state.
  • Label parsing. docker ps returns the compose project labels as a comma-separated string; compose labels never contain a comma, so splitting on , is safe here.
  • Log prefix. Docker's own <service> | prefix stays in a project-wide log tab and is hidden by default in a single-service tab, where it only repeats the tab title.
  • First paint. The very first list shells out to find once per workspace; on a very large tree the panel can take a moment to fill in. Later refreshes reuse the last result.
  • No shell plugin. Container state comes from the Docker CLI, so a stopped Docker daemon shows up as an error notice rather than an empty panel.

Development

lib/index.js        host half — routes, discovery, docker invocations
lib/client.js       client bundle — sidebar tab, list, log viewer
cordis.patch.yml    the single host row this package contributes
scripts/smoke.mjs   offline checks (no Docker, no harness, no network)
npm test          # node scripts/smoke.mjs

The smoke test materializes the client bundle against stub globals and applies the host half to a stub context. It pins the two failures that are expensive to reach live: a factory binding read before its declaration (which throws during profile boot and unloads every later plugin row) and a changed set of sidebar seats or routes.

After changing lib/client.js or lib/index.js, restart dsh web — the client bundle is baselined at boot.

Repository notes

Versions are tagged to match package.json — this tree is v0.1.1.

The yizhixiaokong placeholder in package.json, CHANGELOG.md, the badges and the install commands above stands for the GitHub account this repository is pushed to; replace it before publishing. The commits here were authored under a neutral dsh-plugins <noreply@example.com> identity so that no personal address ends up in the published history; if you want your own name on them, set git config user.name / user.email and run git commit --amend --reset-author before pushing.

Getting listed in the marketplace

The plugin list at awesome-dsh-plugin is generated from one YAML file per plugin, and its CI checks a submission's shape against this repository. The mechanical part is already satisfied here: dsh.bundle is declared in package.json beside cordis.patch.yml, the official @deepseek-ai/* packages are declared as peerDependencies (this package imports none of them, but it is a Cordis plugin), there are no dependencies to install and no build step. What is left belongs to the repository owner:

  1. add the dsh-plugin topic — gh repo edit yizhixiaokong/dsh-compose-panel --add-topic dsh-plugin;

  2. let the repository age past 1 day (the list's CI rejects younger ones);

  3. open one PR adding data/plugins/yizhixiaokong__dsh-compose-panel.yml:

    url: https://github.com/yizhixiaokong/dsh-compose-panel
    name: yizhixiaokong/dsh-compose-panel
    category: dev
    description:
      en: 'Lists the Docker Compose projects of your DSH workspaces in the right sidebar, one group per project directory, with container status, project- and service-level up/stop/restart, and streamed per-service logs.'
      zh: '在右侧栏列出各 DSH 工作区中的 Docker Compose 项目,按项目目录分组,显示容器状态,支持项目级与服务级 up/stop/restart 以及单服务日志流。'
    

The storefront reads a screenshots.json next to package.json (1–8 images) for its screenshot strip; this repository declares assets/01-projects.png, assets/02-actions.png and assets/03-logs.png, in that order.

Publishing to npm

npm login --registry=https://registry.npmjs.org   # a mirror accepts neither a login nor a publish
npm publish --registry=https://registry.npmjs.org

npm publish --dry-run prints the tarball contents without uploading anything, and prepublishOnly runs npm test before either. The published package's repository field points back here; that is what lets the plugin list link the two and then offer the registry install form instead of the GitHub one.

License

MIT