dsh-loopx-plugin
loopx-project/loopxLoopX——面向长周期 Agent 的提供商中立、本地优先状态内核与控制平面:在 DeepSeek Harness 执行层之上持久化 Goal、Todo、门禁、证据、配额、恢复与交接状态;插件负责引导安装 CLI 与技能、准入有界的同会话续跑,并为精确绑定的工作循环提供本地 GoalBar。
安装 Orchestrator 智能体预设:规划任务并分派给指定模型的专家子代理(explorer、oracle、librarian、designer、fixer、council),支持命名模型配置(用 omoslim CLI 切换)与 Web 端查看当前子代理模型的按钮。
DeepSeek Harness (dsh) bundle that installs an Orchestrator agent preset
in the style of oh-my-opencode-slim:
the main agent plans and dispatches, and model-pinned specialist subagents do
the work.
One agent preset, orchestrator:
models.d/ (provider defaults to null, i.e.
inherit the main agent's provider):| Tool | Role | Model |
|---|---|---|
subagent | generic worker (background, continuable) | inherit |
subagent_fork | forks parent context | inherit |
subagent_explorer | fast codebase navigation (read-only) | deepseek-v4-flash |
subagent_oracle | architecture / review advisor (read-only) | glm-5.2 |
subagent_librarian | docs / external research | minimax-m2.7 |
subagent_designer | frontend UI/UX | kimi-k2.6 |
subagent_fixer | bounded implementation | deepseek-v4-flash |
subagent_councillor_alpha/beta/gamma | independent multi-model reviews | glm-5.2 / kimi-k2.7-code / qwen3.7-max |
subagent_council | multi-model consensus synthesis | kimi-k3 |
The models above mirror the OMO
opencodepreset found in~/.config/opencode/oh-my-opencode-slim.json. The OMO council modelgpt-5.6-lunais not in the opencode-go catalog, sokimi-k3is used.All model and provider names are examples from the OMO author's environment. The factory profiles seed
provider: null(the subagent inherits the main agent's provider); setproviderinmodels.d/<name>.jsonto pin one (e.g."opencode-go"), and make sure each model name exists in that provider's catalog.
A dsh bundle is an npm package declaring
"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }. This bundle's patch
layer inserts one row: the preset-installer plugin. On boot the plugin
installs/updates config/presets/* in the harness-home user preset root
(~/.dsh/.agent-presets), which the agent-presets roster always scans.
Why install into the user root instead of registering a new root? The dsh
launcher's composeProfile forcibly overwrites agent-presets.config.roots
with the shipped root, so a bundle cannot contribute its own root. The user
root is the supported extension path.
Each subagent's model and persona live in different files on purpose — you are far more likely to tweak a model than a persona, and plugin updates should not clobber your model choices. On top of that, you can keep many named model profiles and switch the active one at any time:
| File (in the bundle) | File (in ~/.dsh/.agent-presets/orchestrator/) | What you edit |
|---|---|---|
config/models.d/*.json | models.d/*.json | factory profiles (seeded on install; user-editable afterwards) |
| — | models.d/default.json | the default profile (user-owned) |
config/presets/orchestrator/agent.cordis.yml.tmpl | agent.cordis.yml (rendered) | personas / tool wiring (generated from template) |
| — | .generated | render stamp { active, sourceHash, renderedHash } (managed) |
The active profile is stored in ~/.dsh/settings.yaml under
omoslim.active (defaults to default). Every boot the plugin re-renders
agent.cordis.yml from the current template + the active profile. Rules:
omoslim switch <name> re-renders
agent.cordis.yml in place. dsh mounts each preset's composition once per
process, so restart dsh (or the dsh-web service) for the new models
to load, then create a new session.models.d/<name>.json
(provider: null = inherit the main agent's provider), then switch to it.models.d/*.json profiles are never overwritten.agent.cordis.yml directly,
the plugin detects it (hash differs from the stamp) and leaves your file
alone. You own it then; delete the preset directory to take plugin updates.A profile must name every slot the template references (explorer, oracle, librarian, designer, fixer, councillor_alpha, councillor_beta, councillor_gamma, council). A missing slot fails closed rather than rendering a half-populated composition.
# from the profile directory (web is the default profile)
dsh plugin --profile web add dsh-plugin-omoslim
dsh plugin forwards to pnpm and reconciles dsh.profile.bundles, so the
package is both installed and activated as a bundle layer. Then restart the
web app:
systemctl --user restart dsh-web
# or: restart your `dsh web` process
For local development instead of a published package:
# in ~/.dsh/profiles/web/
pnpm add file:/home/<you>/Coding/dsh-plugin-omoslim
# then add the package name to the "dsh.profile.bundles" array in package.json
Open the web UI, start a new session and pick the orchestrator preset in
Settings → General (it becomes the default only if you set it, or if
~/.dsh/settings.yaml has agent-presets.default: orchestrator). The main
agent will plan and dispatch; the subagent tools appear in its tool catalog.
In the web UI, click the plugin's button to the left of the model selector (a stack/panel icon). It opens a panel showing the active profile's per-subagent provider/model at a glance:
provider: null (shown as "inherits main agent") means that subagent uses
the main agent's provider.The button is shown only while the current session runs the orchestrator
preset — under dsh's own presets or third-party presets these subagent slots
don't exist, so the inspector hides instead of showing misleading data. It is
also hidden on the blank new-session screen (a preset pick there is only
staged, not applied, so the button appears once the orchestrator session
actually starts running).
The data is served read-only by
GET /dsh-plugin-omoslim/subagent-models (JSON), so the panel reflects what
the orchestrator preset is literally composed with. Switching the active
profile (omoslim switch <name>) and opening the panel again shows the new
mapping.
After updating the plugin, restart the web app so the new route and button are picked up —
systemctl --user restart dsh-web, or restart yourdsh webprocess — then refresh the page.
dsh plugin --profile web remove dsh-plugin-omoslim
(or drop the dependency + dsh.profile.bundles entry manually), restart.~/.dsh/.agent-presets/orchestrator/ — delete
that directory to remove them, or keep it to keep using the preset without
the plugin.Each profile is one JSON file under
~/.dsh/.agent-presets/orchestrator/models.d/, holding a slot → mapping table:
{
"oracle": { "provider": null, "model": "glm-5.2" },
"explorer": { "provider": "opencode-go", "model": "deepseek-v4-flash" }
}
provider: null (or omitted) = inherit the main agent's provider."oracle": "glm-5.2" still works.cp models.d/default.json models.d/economy.json, then edit it.Manage profiles with the CLI:
omoslim list # list profiles; the active one is marked *
omoslim current # print the active profile name
omoslim switch economy # switch + re-render now
omoslim ships as an npm bin (declared in package.json). Installing the
plugin also links it into the profile's node_modules/.bin/, but that
directory is not added to your shell $PATH automatically — npm/pnpm bins
never modify your shell config. Make omoslim callable from anywhere with one
of these:
Option A — add the profile's bin dir to your PATH (one line, persistent):
# zsh (default on macOS):
echo 'export PATH="$HOME/.dsh/profiles/web/node_modules/.bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
# bash:
# echo 'export PATH="$HOME/.dsh/profiles/web/node_modules/.bin:$PATH"' >> ~/.bashrc
# source ~/.bashrc
Option B — install the package globally (bin lands on your global PATH):
npm install -g dsh-plugin-omoslim
# then `omoslim` works everywhere; note the global copy is separate from the
# profile's copy, so re-run this after upgrading the plugin.
Option C — one-off, no PATH changes:
~/.dsh/profiles/web/node_modules/.bin/omoslim list # full path
# or, from inside the profile directory:
# npx --no-install omoslim switch economy
omoslim switch <name> writes omoslim.active to ~/.dsh/settings.yaml and
re-renders agent.cordis.yml in place. Because dsh mounts a preset's
composition once per process, the running process keeps the models it was
composed with — restart dsh (or the dsh-web service), then create a
new session to use the new models.
Change a subagent's model / provider → edit
~/.dsh/.agent-presets/orchestrator/models.d/<name>.json, then
omoslim switch <name> (or let the next boot re-render it). Your profiles
are never overwritten by plugin updates.
{
"oracle": { "provider": null, "model": "glm-5.2" },
"explorer": { "provider": "opencode-go", "model": "deepseek-v4-flash" }
}
provider: null (or omitted) = the subagent inherits the main agent's
provider. The legacy flat format "oracle": "glm-5.2" still works
(provider is treated as inherited). Model names must exist in the chosen
provider's catalog.
Change personas / tool wiring → edit the template in the bundle
(config/presets/orchestrator/agent.cordis.yml.tmpl) and bump the plugin,
or hand-edit the rendered ~/.dsh/.agent-presets/orchestrator/agent.cordis.yml
— hand edits are detected (stamp mismatch) and left alone. To take plugin
updates again, delete the preset directory first.
Reinstall the pristine preset → rm -rf ~/.dsh/.agent-presets/orchestrator
and restart dsh.
dsh-plugin-omoslim/
├── package.json # dsh.bundle.patch declaration + "omoslim" bin
├── cordis.patch.yml # bundle patch layer (inserts the installer row)
├── config/
│ ├── models.d/ # factory model profiles (default.json, cheap.json, …)
│ └── presets/orchestrator/
│ ├── preset.yml
│ └── agent.cordis.yml.tmpl # composition template (@@models.<key>@@ slots)
└── lib/
├── index.js # Cordis plugin: installer + template renderer + profile helpers
└── cli.js # omoslim CLI: list / switch / current