royenheart
dsh-plugin-opencode-omo
deepseek harness opencode + omo (oh-my-openagent) preset
- Stars
- 0
- Language
- Python
- Created
- Aug 16, 2026
- Updated
- Aug 16, 2026
Introduction
@royenheart/dsh-plugin-opencode-omo
A DeepSeek Harness plugin that adds an opencode-omo agent preset (mode) to the web profile. The mode replicates the behavior of opencode + the omo plugin (oh-my-openagent), scoped to this mode only — other presets (standard/…) keep the default dsh loop, sandboxed fs, and no omo hooks.
What the mode provides
- opencode + omo system prompt — the real opencode
default.txtpersona (tone, style, proactiveness, conventions, code style, task guidance) + omo's Sisyphus orchestrator identity, declared as the complete system prompt: the dsh harness identity and runtime-context snapshot are suppressed for this mode. The loop shim additionally prepends opencode's live environment block (exact model id, working dir, workspace root, git, platform, date, recomputed every step). - omo role picker in the composer — in dsh's existing
conversation.input.lefttool-row slot (after the access/plan chips):sisyphus,hephaestus(Deep Agent),prometheus(Plan Builder),atlas(Plan Executor),sisyphus-junior,athena/athena-junior/council-member,metis,momus,oracle,librarian,explore,multimodal-looker. Selecting a role swaps the session's complete system prompt and applies that role's configured model. - Global "Role Settings" in the dsh settings panel (
settings.section): per-role primary model dropdown (follow current / fixed) under a centered "Primary model" label; a dsh-style circle "+" button opens a fallback model list below the role box (repeatable additions, cancel/close adds nothing), persisted inopencode-omo-rolessettings. On request failure the loop shim advances through the role's fallback chain before the harness retry policy runs. - opencode toolchain (complete) — persistent
bash,read/write/edit/read_image,apply_patch,glob/grep,todo_write,skill,web_fetch/web_search,lsp,exit_plan_mode(plan),ask_user_question.tool-surface.mjsoverwrites the model-visible descriptions/parameters with opencode'stool/*.txttext and shimsread/edit/writeto opencode's parameter names. - omo
task()surface —task-shim.mjsregisters the omo-styletask(category/subagent_type/load_skills/run_in_background/task_id)invocation, mapping it onto dsh named subagents + generic delegation. - omo multi-role subagents —
oracle(read-only advisor),librarian(external docs/code search),explore(codebase grep),metis(pre-planning),momus(plan reviewer),multimodal-looker(media), plus genericsubagent/subagent_fork+workflow/ralph. - omo context injection — AGENTS.md/CLAUDE.md walk-up +
skills/+ omo'srules-injector(.omo/rules,.cursor/rules,.github/instructions,copilot-instructions.md). - omo hooks —
comment-checker(rejects AI-slop comments on write/edit),hashline(read taggingN#HH|content+hashline_editstale-ref guard). - per-mode execution backend — local filesystem (
dsh-fs-local) + persistent PTY shell, isolated from other modes' sandboxed fs/shell. - native-seam loop shim — no dsh-side driver seam.
driver.mjsis an ordinary preset plugin using the shipped seams: a dynamicctx.systemPrompt.section({ complete: true })recomputes opencode's env block and the selected omo role prompt per assembly;system-prompt/assembleapplies opencode's model tool gating;agent/inbox/claimed,agent/pre-step,agent/request, andagent/request-errorprovide ultrawork detection, maxSteps, role model routing, and fallback retry. Other presets are untouched by construction.
Layout
cordis.patch.yml # bundle patch: self host row
install.py # idempotent install/uninstall (incl. user preset root)
src/ # host + client plugin halves (role registry, settings, picker UI)
lib/ # built host/client bundles (npm run build)
scripts/build.sh # typecheck + tsdown build
presets/opencode-omo/
agent.cordis.yml # the composition (tools, roles, hooks, LSP)
preset.yml # display metadata
persona.md # opencode default.txt + omo Sisyphus persona
roles/*.md # subagent personas (also main-role prompts)
roles/prompts/*.md # primary-role complete prompts (hephaestus/prometheus/atlas/…)
skills/ # omo shared skills
driver.mjs # native-seam loop shim (prompt/route/fallback/maxSteps/ultrawork)
rules.mjs # rules-injector
comment-checker.mjs # comment-checker hook
apply-patch.mjs # apply_patch tool
hashline.mjs # omo hashline read-tagging + hashline_edit
Install
Build the package first (host + client bundles):
npm run build
install.py then automates install/uninstall idempotently — it symlinks the package into ~/.dsh/profiles/<profile>/node_modules/, edits the profile's package.json (adds/removes the dependency + bundle entry), and publishes the preset through dsh's native user preset root as a real directory under $DSH_HOME/.agent-presets/opencode-omo (entries symlinked into the package, so updates stay live):
python3 install.py --profile web # install (idempotent)
python3 install.py --profile web --uninstall # remove
Manual alternative — the package is a dsh bundle: it declares dsh.bundle.patch and ships the preset. Load it into a profile:
dsh plugin --profile web add link:/path/to/dsh-plugin-opencode-omo
then add it to the profile's bundle list in $DSH_HOME/profiles/web/package.json and create the user-root preset directory yourself:
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@royenheart/dsh-plugin-opencode-omo"] } }
mkdir -p "$DSH_HOME/.agent-presets/opencode-omo"
for f in /path/to/dsh-plugin-opencode-omo/presets/opencode-omo/*; do
ln -s "$f" "$DSH_HOME/.agent-presets/opencode-omo/"
done
Restart dsh and select opencode-omo from the mode picker.
Required dsh-side changes
This release depends on one dsh-side patch. Apply it to deepseek-harness for full maxSteps fidelity; the patches are under patches/, split by feature:
patches/0001-agent-pre-step-assistant-prefill.patch— adds optionalassistantPrefilltoPreStepDecision, letting the loop record an assistant-role prefill before the model request. The plugin uses it to restore opencode'sMAX_STEPS_PROMPTassistant-role semantics. Runtime compatibility: the host plugin scans the installed@deepseek-ai/dsh-agent-loopbundle for the compiledassistantPrefillmarker. When the patch is absent, maxSteps automatically degrades to an equivalent synthetic user message (nothing is silently dropped) and the/rolesresponse carries the warning to the browser; the web client shows it once per page load via the native@deepseek-ai/dsh-client-ui-primitivesToast(4 seconds, non-blocking).
cd /path/to/deepseek-harness
git apply /path/to/dsh-plugin-opencode-omo/patches/0001-agent-pre-step-assistant-prefill.patch
npm run build:lib:host
npx vitest run packages/core/agent-loop/tests/interception.spec.ts
- Provider-visible
format/toolChoiceis still a proposal (seeDSH_CHANGE_PROPOSALS.md); omo's regular path does not use it and the standalone structured-output plugin covers the common route.
Everything else runs on unmodified dsh seams: the preset is published through $DSH_HOME/.agent-presets and the composer picker occupies the existing conversation.input.left slot (the client registers through ctx.slots.inject(), so it waits for the declaring parent regardless of out-of-tree bundle apply order).
Bench experiments (equivalence validation)
Runners and reproduction notes live in tests/benches/; reports are written to docs/exps/. The scientific methodology (paired design, McNemar/bootstrap/TOST, A/A noise floor, trace alignment, cache and latency protocols) is documented in docs/exps/2026-08-16-scientific-bench-methodology.md. Design highlights:
- Run an isolated-port dsh (
opencode-omomode, isolated$DSH_HOME) and the machine's installed opencode + oh-my-openagent (isolatedXDG_CONFIG_HOME). - Both use
deepseek-official/deepseek-v4-pro(dpsk v4 pro); the API key comes from theDEEPSEEK_API_KEYenvironment variable. Scripts hardcode no machine paths or secrets. - Tiered benches: L1 HumanEval, L2 MBPP, L3 SWE-bench-verified-mini (sampled), comparing pass@1, CoT/reasoning exposure, tool-call chains (read/edit/write/bash/test/subagents), and final patches/answers.
- Performance:
bench_metrics.mjsnormalizes token usage (includingcacheRead) and tool timestamps on both sides;eval_perf.mjs/eval_swe_perf.mjsproduce cache hit rate, TTFT, step duration, and per-tool timing offline (see report §5). - MBPP fix: MBPP rows have no
entry_point; the scripts infer the function name from the firstassert fn(...)or the referencedef fn. The old implementation hardcodedFunction name: undefined, which was the root cause of MBPP behavioral divergence (see report §0 and §6.4). - Raw bench data is downloaded to
tests/benches/.data/and is not versioned;fetch-benches.shreproduces the downloads andsetup-homes.shreproduces both isolated homes.
Latest results (dpsk v4 pro; L1 30×3, corrected L2 5×2, legacy L3 sample)
| level | dsh pass@1 | opencode+omo pass@1 | per-item agreement |
|---|---|---|---|
| HumanEval (30 tasks × 3 repeats) | 1.00 | 1.00 | 1.00 |
| MBPP (corrected entry_point, 5 tasks × 2 repeats) | 1.00 | 1.00 | 1.00 |
SWE-bench-verified-mini sample (sphinx-doc__sphinx-10323) | same patch | same patch | byte-identical git diff |
Full report: docs/exps/2026-08-15-opencode-omo-equivalence-bench.md; raw transcripts are under tests/benches/.runs/.
Alignment status (audited against reference/opencode + reference/oh-my-openagent)
- Aligned: opencode default persona (complete system prompt + live env block whose provider/model now follow the same per-step route as the actual request — session live model selection or the role primary/fallback — so prompt and request cannot split; workspace root now derived as the git root); opencode tool families + gpt apply_patch/edit-write tool gating enforced on BOTH the model-visible schema and execution (
tools/pre-executedeny mirror); opencode maxSteps + verbatim MAX_STEPS_PROMPT; verbatim opencode plan.txt / plan-mode.txt with dynamic${planInfo}and the plan→build BUILD_SWITCH reminder; omo role catalog/display names; sisyphus/hephaestus/atlas/sisyphus-junior + specialist subagents; comment-checker/hashline/rules-injector hooks; generated Sisyphus routing sections; extracted omo Sisyphus model-family templates (GPT-5.5/GPT-5.4/claude-opus-4-7/claude-opus-4-8/claude-fable-5/gemini/kimi-k3/kimi-k2-7/kimi-k2-6/glm-5-2, with the dynamic Sisyphus fallback for unknown families) plus hephaestus GPT variants, all 8 atlas variants, and specialist model variants (oracle/metis/momus); omo-default per-role PRIMARY model resolution (provider-scope ordered) and fallback chains that start AFTER the primary; omo role sampling defaults (sisyphus/hephaestus GPT effort medium, atlas temperature 0.1); omo-style retryable-error gating before fallback advance; reasoning-effort selectors in role settings; ultrawork keyword override;/start-work,/remove-ai-slops,/refactor,/stop-continuation,/handoff,/hyperplan,/team-modecommands; composer role picker + global per-role model/fallback settings; omo skills published asuser-dshso the third-party skills-manager can manage them. The omo rules-injector text is now folded into the complete system prompt (driver.mjs+rules.mjs) instead of being dropped bysuppressRuntimeContext(); approved plans are persisted at.opencode/plans/<created>-<session>.md; specialist subagent personas now load the extracted reference prompt files (oracle/librarian/explore/metis/momus/multimodal-looker). - MCP: separate plugin
dsh-plugin-mcp-supportmounts native@deepseek-ai/dsh-mcp-clientservers from composition config or the persistedmcp-supporsettings namespace. (The directory was renamed fromdsh-plugin-mcp-suppor; the npm id and settings namespace inside that repository still use the old spelling until that repository is updated.) - Structured output: separate plugin
dsh-plugin-structured-outputprovides opencode-style/json-schema+StructuredOutputvalidation on native seams (no dsh-side format field). - Partial: extracted family templates keep dynamic sections filled by dsh-native data rather than omo's builder output; structured output is tool-enforced rather than
tool_choice: required; hooks are regex/simplified ports; AGENTS.md injection is dsh-native; child subagents inherit the session model because dsh child headers/descriptors do not carry the subagent role id (primary-role sampling defaults ARE applied). - Requires one dsh-side patch (see
patches/, audited 2026-08-15):PreStepDecision.assistantPrefillfor opencode's MAX_STEPS_PROMPT. Provider-visibleformat/toolChoiceremains a proposal; omo's regular path does not use it and the standalone structured-output plugin covers the common route.
Remaining gaps
- dsh-side (patch provided):
PreStepDecision.assistantPrefill. Without thepatches/patch the maxSteps prompt is degraded to a synthetic user message; after applying the patch this gap is closed. - dsh-side (proposal, medium):
GenerateOptions.format/toolChoice. omo's regular path does not use them; the standalone structured-output plugin covers the common route. - Child subagent per-role sampling cannot reliably resolve the role id (dsh child headers/descriptors do not carry it); primary-role sampling defaults ARE applied and children inherit the session model.
- Plan files: dsh itself does not persist them; the plugin writes
.opencode/plans/*afterexit_plan_modeapproval. A first-class plan-file seam remains an optional improvement. - team-mode TUI, comment-checker CLI, and hashline diff enhancer remain non-LLM/editing experience differences.