Explicit model routing for Main, Subagents, web_search, and image generation, plus a catalog-driven Composer and Plan Review picker with Model, Effort, Context, Fast, and Thinking variants.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:NOirBRight/dsh-model-switch
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
English | 中文
Choose one explicit route for Main, Subagents, Web Search, image generation, the active conversation, and Plan execution in DeepSeek Harness. Model Switch uses public DSH services and provider-owned adapters; it does not patch DSH Core or manage provider credentials.
The picker retains keyboard focus when changing panes or closing search, without overriding search autofocus. Escape from the summary closes the picker and returns focus to its trigger.
Routes
| Route | Behavior |
|---|---|
| Main model | Default provider, model, and optional effort for newly created sessions. Existing sessions are not migrated. |
| Subagent | Follow the active parent route, or use a fixed provider/model/effort. Workflow overrides remain authoritative. |
| Composer Picker | Changes only the active session and submits the exact catalog model id. Main defaults are preserved. |
| Plan Review | Chooses the execution model before the Plan approval response is sent. |
| Web Search | Keeps official web_search; after deployment opt-in, routes through the selected, dynamically declared provider search adapter. |
| Image generation | Provides one stable generate_image tool routed through a selected Codex or Grok adapter. |
Invalid, unavailable, or unsupported routes fail explicitly. Model Switch never silently falls back to another provider or model. Composer icons identify the execution runtime: DSH-owned LLM routes use the theme-adaptive DSH whale; providers declaring the Agent role use their own mark. Sidebar quota icons remain provider-specific.
Idle blank sessions may pick an External Agent. Submission, pending-first-turn, and running state reserve the selected execution runtime even before a token or native binding exists: native Antigravity keeps its model/effort choices; DSH keeps LLM-provider choices but disables Agent providers. After the first accepted user message, Composer and Plan Review keep Agent-role rows visible but disabled unless the session is already native-bound. After the active session successfully opens a native Antigravity session, the pickers read its plugin-owned binding and disable other providers while keeping available Antigravity model and effort controls. The DSH global picker lock remains authoritative. Binding reads refresh on mount, input-phase, request-activity or catalog changes, and before selection; failed reads show a localized alert and preserve a known native lock. These reads do not start the native runtime or gate conversation history. Antigravity owns the separate execution-time guard; Model Switch does not create custom Core history events.
The existing 3082 lab replay probe is node scripts/check-lab-runtime-lock.mjs [native|runtime-absent|plugin-absent]. It checks the dedicated QA conversation under the already-established condition; it does not disable plugins, select a model, or send a turn. node scripts/check-lab-native-execution.mjs verifies the saved guard rejection, restored native continuation, DeepSeek-parent/Antigravity-child completion, and restoration of temporary subagent preferences through public history streams.
Configure Main and Subagents
Open Settings → Model Switch. Main changes affect new sessions only. Subagents may follow Main or use a fixed provider, model, and effort.
Official DSH 0.1.7-alpha.2 makes ConfigForms memory-only in non-loopback browsers. This page shows an unavailable message there; open Settings on the Host loopback URL instead. The composer picker refuses model changes in that mode because the published session.selectModel also persists the deployment default, which cannot be safely restored without a writable Main ConfigForm. Remote editing and session-only selection require an upstream authenticated ConfigForm seam and a session-only selection API; this plugin does not bypass the official policy.
Changing the Main or fixed Subagent provider/model replaces the previous model's effort with the target model's default. Models without reasoning support receive no effort.

Follow Main resolves the active parent request first, then the configured Main default. A fixed route is injected before the official Subagent descriptor is created. DSH 0.1.2-alpha.4 carries provider, model, and fixed reasoning effort in that descriptor.
How custom models appear in the Picker
Model Switch does not turn an arbitrary string in its own settings into a model. A provider plugin must publish the model to the official DSH model catalog first:
Provider configuration
→ provider publishes model rows to the DSH catalog
→ the active session Model Directory exposes provider/model metadata
→ Model Switch groups those catalog rows
→ the Picker submits the original provider id and model id
The catalog supplies the provider name, model id/name, reasoning efforts, and default effort. A saved route that is no longer present remains visible as unavailable in Settings; the Picker does not pretend it is routable.
Variant id grammar
Model Switch groups catalog rows by provider and by the model id after peeling these suffixes:
| Catalog model id | Picker variant |
|---|---|
acme-v1 |
Standard row |
acme-v1-fast |
Fast |
acme-v1-128k |
Context 128K |
acme-v1-1m |
Context 1M |
acme-v1-1m-fast |
Context 1M + Fast |
Rules:
-fastcreates the Fast axis.-<n>kand-<n>mcreate Context tiers; suffixes may be combined with-fastin either order.reasoning.effortscreates the Effort choices;reasoning.defaultEffortselects the initial value.- Switching Fast, Context, or Thinking variants keeps the current effort only when the target catalog row supports it; otherwise the target row's default effort (or no effort) is used.
- Reasoning metadata marks a catalog row as Thinking-capable.
- Unrecognized ids remain independent model families; Model Switch never drops them.
To support a combined selection, the provider must publish the combined row. Publishing only acme-v1-fast and acme-v1-1m cannot represent Fast + 1M; publish acme-v1-1m-fast as well. The Picker never synthesizes a model id that the provider did not publish.
Plan Review
Plan Review owns an execution-model draft separate from Main. Confirm first commits that model to the active session, then answers the pending Plan review. A failed model commit leaves the review pending and retryable. Reject and Discuss in chat do not execute the Plan.

Send-time context protection
When a sent message will use a different model or context-tier id than the last request, Model Switch checks the full pending request against the target window before that request is sent. Choosing a model in the picker does not compact. If the target is over budget, history is compacted once with the previous model through a private compaction engine; DSH's own automatic compaction settings are not changed. Progress appears as plugin notices in the transcript. The budget includes the completion notice and pending model-change notice; an oversized summary blocks the request. Failure keeps the user message in the session and does not send the target request or emit a switch-success notice. Turn the behavior off with Settings → Model Switch → Check and compact context on send (on by default). Native External Agent runtimes are not treated as DSH-compactable history.
What Model Switch does not change
web_fetchand its configured provider- Vision routing,
read_image, and ordinary chat attachments - Provider login, credentials, or provider settings cards
- Official Agent Presets
- Existing provider-specific image tools
- Existing sessions when the Main default changes
- Global compaction policy, titles, or DSH Core
Installation
Install Model Switch and only the provider adapters you use. This release was checked against official DeepSeek Harness 0.1.7-rc.2:
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-llm-providers-ui/releases/latest/download/dsh-llm-providers-ui-0.2.14.tgz
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-llm-codex/releases/latest/download/dsh-llm-codex-0.3.23.tgz
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-llm-grok/releases/latest/download/dsh-llm-grok-0.3.19.tgz
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-model-switch/releases/latest/download/dsh-model-switch-0.4.16.tgz
Search routing (0.4.7)
Providers declare independent search adapters and model metadata on the existing Host ModelSwitchAdapterRegistry. The browser receives only id/name/model metadata over authenticated Connection RPC, not adapters or credentials. Registration/unload updates subscribers; in-place catalog changes are picked up by the bounded 20-second heartbeat. ProviderDirectory remains the client role/usage owner, not a second Host execution registry. Published 0.2.8 sortCatalogGroups only ranks hardcoded LLM routes; Model Switch ranks live catalogRoutes itself so Agent catalog ids follow saved card order when the Owner publishes them. Native catalogId / unknown account styling still need a newer Owner than published 0.2.8.
DeepSeek uses the official public DeepSeekSearchProvider, the existing web-search-deepseek settings and credential service. Codex uses its existing ChatGPT credentials; Grok uses its existing subscription token and provider-owned Responses search. Native conversational networking alone does not create a search option. Missing credentials, invalid settings, unsupported models and unavailable adapters fail explicitly, without fallback.
Registering an adapter does not select the global Web route. Installation leaves the deployment's existing Web configuration untouched. To opt in, set the existing Web entry's searchProvider to model-switch while retaining every other existing config field, especially fetchProvider. DSH id-targeted patches replace the entire config rather than deep-merging it: copy the complete effective config from dsh --profile web --dump-config, then change only searchProvider in the deployment/user patch. Do not copy an assumed fetchProvider: http over a custom pin.
After opting in, configure the requested search provider/model in Model Switch Settings. No complete supported route means WEB_PROVIDER_CONFIGURED_UNAVAILABLE through the official selector; there is no automatic DeepSeek fallback. Without the global pin, the dropdown does not control web_search. An unpinned Web service can become ambiguous when multiple search providers are usable. Before uninstalling Model Switch, restore the deployment's prior search pin; otherwise the official selector correctly reports a missing configured provider. The official web_search and web_fetch tools are never replaced.
Release-aligned search regression: DSH_RELEASE_ANCHOR=/path/to/official/install/package.json pnpm exec vitest run --config tests/vitest.release.config.ts. See search audit and acceptance for exact baselines, dependencies and live status.
If dsh-composer-picker is installed, remove it from the profile before enabling Model Switch. Model Switch already owns the Composer Picker and Plan Review seat; two owners produce duplicate or competing UI.
Production profiles must use released GitHub tags rather than workspace-local dependencies. Restart the selected DSH profile after installation or route changes.
Compatibility
DSH Host peers and development dependencies accept >=0.1.7-alpha.2, including rc.1 and later releases. The development lockfile resolves to rc.2. Cordis accepts >=4.0.4 <5.0.0.
The verified releases in package.json#dsh.compatibility.dshReleases are evidence, not an allowlist. Review public API changes and test new Host releases before adding a verification claim.
Development
Requires Node 22.19+ and pnpm.
pnpm install
pnpm run check
check builds Host and Client artifacts, runs unit and Cordis/Settings composition tests, validates the extracted package, and verifies reproducible bundles. Product scope is defined in PRODUCT.md; implementation constraints live in IMPLEMENTATION_PLAN.md.
Release installation (Latest)
Explicit model routing for Main, Subagent, Composer, Plan Review, and capability tools, checked on official DeepSeek Harness 0.1.7-rc.2. The release artifact contains built Host/Client files, not sibling source or local paths.
Latest installation (the asset filename must match the current latest release):
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-llm-providers-ui/releases/latest/download/dsh-llm-providers-ui-0.2.14.tgz
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-model-switch/releases/latest/download/dsh-model-switch-0.4.16.tgz
Fixed-version installation:
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-llm-providers-ui/releases/download/v0.2.14/dsh-llm-providers-ui-0.2.14.tgz
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-model-switch/releases/download/v0.4.16/dsh-model-switch-0.4.16.tgz
Update, uninstall, and verify:
# Update to the latest Release
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-llm-providers-ui/releases/latest/download/dsh-llm-providers-ui-0.2.14.tgz
dsh plugin --profile web add --force \
https://github.com/NOirBRight/dsh-model-switch/releases/latest/download/dsh-model-switch-0.4.16.tgz
# Verify the loaded version
dsh plugin --profile web list
# Uninstall only this plugin
dsh plugin --profile web remove dsh-model-switch
Configuration: use the plugin section in Settings for Web UI plugins, or the profile dsh.profile.bundles entry for Host-only plugins. Start with this README's minimal YAML/JSON example and provide credentials/backend addresses explicitly.
Rollback: reinstall the immutable v0.4.15 archive and restore the recorded profile; no Host downgrade is required. Inspect journalctl --user -u dsh-web.service; never link a checkout into production.
Links
More in this category
corrinehu/dsh-workbuddy-connect★ 589
Brings the models in the WorkBuddy desktop app straight into DeepSeek Harness — zero configuration in the DSH chat.
V1ki/dsh-plugin-subscriptions★ 448
Use ChatGPT (Codex), Claude, and Grok subscriptions as DeepSeek Harness LLM providers, with Settings login, model catalogs, usage, plus image_generate, video_generate, and x_search tools.
Mars-Sea/dsh-commandcode-provider★ 384
Unofficial Command Code LLM provider: registers a `commandcode` route with a live model catalog and reasoning-effort support.
cv-superding/dsh-deepseek-web-login★ 261
Adds a deepseek-web provider that uses chat.deepseek.com web models in DSH, with browser login capture, PoW request signing, SSE streaming, and prompting-based tool calls.
FishBottle7/opencode2dsh★ 179
Exposes OpenCode Zen free models to DeepSeek Harness, with no API key.
WSL043/dsh-codex-subscription★ 168
ChatGPT OAuth provider for Codex models with subscription web search, quota and safe reset, image tools, Fast mode, and model-aware context; no API key or Codex CLI.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.