Polishes the draft in the composer into a clearer, better-structured prompt from the ✨ button or Alt+O; streams the result live over SSE with reasoning shown first, and follows the session's default model with zero configuration or any OpenAI-compatible endpoint.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-prompt-optimizer
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:winditer/dsh-prompt-optimizer
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
dsh-prompt-optimizer
English | 中文
One-click prompt polishing for the DSH composer: select nothing, just type a draft and press ✨ (or Alt+O) — the plugin rewrites it into a clearer, better-structured prompt. Zero-config by default: it follows the current session's model through the harness host services, so no API key is needed. A self-configured OpenAI-compatible endpoint is supported as an alternative.
Features
- One-click optimize — a ✨ button on the composer's right;
Alt+Owhile the composer is focused does the same - True streaming preview — real SSE over the harness
webServer: everytext-deltafromllm.streamis pushed immediately and rendered token by token; reasoning is streamed first, so you watch the model think while it works - Zero-config default — reuses the current session/agent default model (host
agentDefaultModel+llmservices), no API key required - Custom endpoint mode — uncheck "follow session model" and plug in any OpenAI-compatible
/chat/completionsendpoint (base URL + key + model) - Action row on completion — replace the draft in place, copy, re-optimize, or dismiss
- Bilingual UI — follows the DSH language (中文 / English) live, no reload
- Self-hosted config — settings persist in
~/.dsh/prompt-optimizer-config.jsonvia a loopback RPC channel, independent of the host settings registry - Dark-mode ready — all colors follow DSH theme variables; fixed brand blue + white text in deep-night mode
- Local-only credentials — the API key (custom mode only) lives in the local config file and goes only to the endpoint you configured
Screenshots
Requirements
- DSH with a
webordesktopprofile - Node.js
^22.19.0or>=24.0.0(only needed to build from source) - pnpm is recommended when installing into a profile
Install
The bundle entry (
id: prompt-optimizer) is self-declared by this package'scordis.patch.yml— no manual patch file is needed.
From GitHub (recommended)
Install by repository identity so the market can match your package to
winditer/dsh-prompt-optimizer unambiguously (several unrelated plugins
share the npm name dsh-prompt-optimizer; a bare npm install hides the
GitHub link and description in dshmarket):
dsh plugin --profile desktop add github:winditer/dsh-prompt-optimizer
For a web profile, use --profile web. Restart DSH (quit fully and reopen), then a ✨ button appears to the right of the composer.
From npm
dsh plugin --profile desktop add dsh-prompt-optimizer
For a web profile, use --profile web. Restart DSH (quit fully and reopen), then a ✨ button appears to the right of the composer.
⚠️ The npm name
dsh-prompt-optimizeris shared by several unrelated plugins. Because the spec carries no repository identity, dshmarket cannot disambiguate it and its Installed tab shows no GitHub link or description. Prefer thegithub:install above.
From source (development)
git clone https://github.com/winditer/dsh-prompt-optimizer.git && cd dsh-prompt-optimizer
npm install
npm run build # produces dist/client.js
dsh plugin --profile desktop add . # links the workspace into the profile by package name
Or install by hand: in the target profile's package.json (e.g. ~/.dsh/profiles/desktop/package.json):
{
"dependencies": {
"dsh-prompt-optimizer": "link:/absolute/path/to/dsh-prompt-optimizer"
// ...
},
"dsh": {
"profile": {
"bundles": [ /* ... */, "dsh-prompt-optimizer" ]
}
}
}
then pnpm install inside the profile directory and restart DSH.
Uninstall
Remove dsh-prompt-optimizer from the profile's dependencies and dsh.profile.bundles, clean up the installed package, and delete the config file ~/.dsh/prompt-optimizer-config.json if you no longer need it.
Usage
- Type a draft in the composer, click ✨ (or
Alt+O) — the preview card appears over the composer - While optimizing: reasoning text scrolls in secondary color first, then the polished prompt streams in token by token
- When done: 替换草稿 writes the result into the composer in place · 复制 copies it · 重新优化 re-runs · 放弃 dismisses
- The preview belongs to the session where you started it: switching sessions hides it, switching back restores it
Configuration
Open 设置 → 通用设置 → Prompt 优化:
| Setting | Default | Meaning |
|---|---|---|
| 使用当前会话模型 | on | Follow the session/agent default model (zero-config). Off: enable the fields below |
| 接口地址 (base URL) | https://api.deepseek.com |
Any OpenAI-compatible /chat/completions endpoint |
| API Key | — | Your key for the custom route (ignored in follow mode) |
| 模型名 | deepseek-v4-flash |
Model name (ignored in follow mode) |
Settings are saved in ~/.dsh/prompt-optimizer-config.json (same directory as other DSH config; removed with the plugin).
Custom endpoints must support CORS and SSE streaming (official DeepSeek, OneAPI-style gateways work).
Architecture
Two halves, one package:
- Host half —
lib/index.js. Persists config over a loopback RPC channel (/dsh-prompt-optimizer,get/set), and registers an HTTP JSON API at/dsh-prompt-optimizer/apithrough the harnesswebServerservice. Runs the session-default optimization viallm.stream; background streams live in an in-memoryMapcleared on unload. - Client half —
src/*.ts, bundled todist/client.js(esbuild, wrapped in__ModuleLoader__.load({ id: "dsh-prompt-optimizer", … }); the id must equal the installed package name). Renders into theconversation.input.rightbutton,conversation.input.overlaypreview card andsettings.general.itemrow; talks to the host withfetchPOSTs.
Host API
All endpoints are POST /dsh-prompt-optimizer/api/<method>; every response is { ok: true, value } or { ok: false, error }.
| Method | Body | Returns |
|---|---|---|
sessionModel |
{} |
{ provider, model, reasoningEffort? } — the session's default model |
optimize.stream |
{ provider, model, text, system?, reasoningEffort? } |
text/event-stream — event: reasoning frames first, then event: delta per token, event: done at the end |
optimize.start |
{ provider, model, text, system?, reasoningEffort? } |
{ taskId } — background accumulation (fallback path) |
optimize.poll |
{ taskId } |
{ done, text, error? } — accumulated text while streaming |
optimize.abort |
{ taskId } |
{ ok } |
Protocol details: only POST is accepted (405 otherwise); the body is JSON with a 1 MB cap; unknown methods return 404.
Security notes
- Default route sends no credentials — it reuses the harness's configured provider.
- The custom-mode API key stays local (
~/.dsh/prompt-optimizer-config.json), and only goes to the endpoint you configured. - Optimizations appear only in the preview card; the polished text reaches a session only if you press 替换草稿.
Development
npm run build # esbuild: src/index.ts → dist/client.js (__ModuleLoader__ bundle)
npm test # node runner over tests/entry.ts (state machines, channels, SSE parser)
Project layout
src/index.ts Client entry — slot wiring, RPC/config glue, host probes
src/OptimizeButton.tsx / PreviewCard.tsx / SettingsRow.tsx
src/optimizer.ts Config defaults, system prompts, OpenAI-compatible fetch/SSE client
src/session-optimizer.ts Host channel: sessionModel + SSE stream + fallback poll
src/preview-state.ts Preview card state machine (pure reducer)
src/preview-bus.ts Module-level event bus shared by button / card / orchestration
lib/index.js Host half — config persistence + HTTP JSON API (makeHandler + createApiRoute)
dist/client.js Built client bundle (__ModuleLoader__ format, load id = dsh-prompt-optimizer)
cordis.patch.yml Bundle entry declaration (insert: { id: prompt-optimizer, name: dsh-prompt-optimizer })
scripts/build.mjs Build script (esbuild + bundle wrapper)
tests/entry.ts Unit + integration tests (61)
assets/ Screenshot
Gotchas (learned the hard way)
Bundle id must equal the package name —
arrive()throwsbundle loaded without registering <id>otherwise.scripts/build.mjshardcodes the correct id.Profile bundles don't get the cordis
timerservice — use plain browsersetInterval/setTimeout(disposed in React effect cleanup), exactly like the siblingdsh-elfbundle.Do not use
session.create/forkfor generation — a background session never executes (the renderer's fabricated ids are silently rejected, forked sub-sessions don't trigger the model), which manifested as "optimizing forever". Drive the model from the host half viallm.streaminstead.Do not run the streaming protocol over
connection.rpc.call— on desktop the renderer's rpc.call hangs on the second call within one flow (verified:sessionModelok, next call never arrives). Host channels go over HTTP (webServer).Prefer
link:overfile:when installing a workspace copy —file:copies files, so edits/rebuilds go stale.Client changes go live on page refresh; host changes require a full DSH restart.
A broken build script silently keeps the old bundle —
npm run buildmust print✓ Built; if it only prints a Node version banner, the script is failing (a past regression left a staledist/client.jsthat looked "current").Fresh publishes can trip the profile's
minimumReleaseAgepolicy — if the profile enforces pnpm's release-age supply-chain check, a version published less than ~24 h ago failsdsh plugin … add <pkg>withERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION. Add the exactname@versiontominimumReleaseAgeExcludein the profile'spnpm-workspace.yaml(and keep the entry current when you release a new version):minimumReleaseAgeExclude: - dsh-prompt-optimizer@2.0.0
License
Links
More in this category
zhu1090093659/dsh-web#packages/dsh-task-board★ 8296
Task board for the dsh web GUI: a sidebar multi-column kanban whose cards run in real DSH agent sessions and can also be scheduled with cron expressions, executed host-side even with the browser closed.
zhu1090093659/dsh-web#packages/dsh-web-all★ 8296
Plugin and skin collection for the DSH Web UI: task board, Git graph, right-side panel, remote mobile UI, pet, live token stats, and a skin center.
omdsh-dev/DSH-better-sidebar★ 3968
Full sidebar workbench with file rendering and editing, terminal, Git, and subagents; third-party plugins can register new tabs.
ccch1mneyyy/dsh-TUI★ 3948
Claude Code-style full-screen terminal UI: pixel-whale header, live status line, and streaming thought expansion.
MeteorNOX/DeepSeek-Balance-Whale-Widget★ 3877
A fixed-corner whale widget for the DSH web GUI — balance, today's usage and per-turn cost with peak/off-peak pricing, editable balance-alert and daily-budget bubbles, a module-based custom bubble queue with A/B weighted choices and random lines or images, 30+ vendor templates (OpenAI, OpenRouter, Kimi, SiliconFlow, Ark, Zhipu, MiniMax and more) with per-model balance and subscription quota, plus task-end sound, imported audio, custom roles and a resource manager. Local-only, no telemetry.
Devin-AXIS/deepseek-design#deepseek-idesign★ 1413
Visual design studio for websites, app prototypes, posters, cards, reports, and magazines, with templates, direct element editing, selection-aware AI draft handoff, and export.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.