dsh-custom-mode
A custom agent mode for DeepSeek Harness (dsh): an editable system prompt that takes effect on the next step, per-row plugin switches, and a settings page. 适合需要自由创建、切换和管理自定义智能体模式与提示词的用户。
설치
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:BOWLUNA/dsh-custom-modeUsage
The settings page (Settings → "Custom mode") is an assistant manager: the top of the page lists every custom mode you have — create, switch, delete — and the four blocks below (name, base mode, plugin switches, system prompt) edit whichever one is selected.
- Ordering — "Move up / Move down" writes the order into each assistant's
preset.yml(order, the roster's own sort key), so it survives a restart and the new-session picker follows it. - Import / export a prompt — "Export prompt" saves the current text as a
.md; "Import prompt" reads a file into the editor (nothing is written until you save), so an import goes through the same{{…}}validation as anything typed. - Asking the agent to change its own prompt requires your approval. The in-session
custom_prompttool goes through the platform's approval seam (tools/pre-executereturningask), so the request waits for an explicit「允许一次」and shows what would be written and where. Measured: with theaskapproval policy the panel appears and approving really writes; withnever(full access) nothing prompts and the call is denied. The worst case is therefore "the change does not happen", never "it happened quietly". - 配置了却不生效会被点名 — the page warns when a setting cannot take effect: the「身份(系统提示词)」
row is off while
prompt.mdstill has content (so your prompt is silently ignored), thecustom_prompttool row is off, the assistant has no name or no description (the picker shows the bare id /「暂无描述」). - The agent can change its own prompt, with your approval — the in-session
custom_prompttool reads the prompt, replaces it, or appends to it. Appending matters because it never has to reproduce the whole prompt: an agent that wants to remember one rule cannot lose existing content on the way (measured: it may still read first to see what it is adding to). Both writing actions go through the platform's approval panel first. - Change history — every save, and any change made outside this page (the in-session
custom_prompttool, a hand edit ofprompt.md), leaves a version in the history list under the prompt box, labelled with when and where it came from. Loading one only edits the draft: nothing is written until you save, so browsing old versions cannot destroy the current one. Before this, a prompt changed from inside a session was invisible — the page only ever showed "the current text". - Reset to the factory prompt — one click puts the shipped template (the text a new assistant starts from) back into the editor. It is draft-only like every other edit: nothing is written until you save, and Reload discards it. Before this existed, a prompt you had edited into a corner could only be recovered by deleting the assistant and creating it again.
- New assistant — type a name and click "New assistant". It is seeded from the packaged template: the full Standard row set plus a starter prompt, selectable in a new session as soon as you save it — in an already-open page the picker's list is a load-time snapshot, so refresh (F5) once to see a new assistant there (measured; the roster itself is up to date).
- Duplicate — copies the selected assistant's prompt, base mode and row switches into a new one; the two are independent afterwards.
- Each assistant is independent — its prompt, base mode and row switches are its own; changing one leaves the others alone.
- Base mode is the row set, not the prompt — it decides which rows exist and which tools the mode has;
this plugin always replaces the base's
personarow with its own reader (complete: false), so the base's prompt semantics are not inherited. Minimal is the visible case: you get minimal's tool set, not minimal's prompt. - Switching assistants never discards drafts — each keeps its own unsaved edits, marked "Unsaved" in the list; the only path that throws edits away is the reload button, which renames itself to say so.
- Delete — the shell's own risk-confirmation dialog, which requires ticking an acknowledgement. Deletion only removes the mode directory from disk: sessions already using it keep running (their composition was read when they started), and new sessions no longer offer it.
- Ask the agent — every assistant ships a
custom_prompttool, so a session can read or rewrite its own prompt. - Edit the file —
$DSH_HOME/.agent-presets//prompt.mdis that assistant's single source of truth.
Only {{model}}, {{cwd}} and {{provider}} are interpolated. An unknown {{…}} is rejected when
saved: the renderer throws on it, which would fail every request in that mode.
Every control (buttons, inputs, switches, tags, the confirmation dialog, icons) comes from the
shell's own @deepseek-ai/dsh-client-ui-primitives, so theme, light/dark and future restyling reach
this page automatically; a shell that does not provide those atoms falls back to built-in plain
controls with the same behaviour.
An "assistant" is one directory under the user preset root (default $DSH_HOME/.agent-presets/),
and its directory name is its internal id. The page manages only presets this tool created — the
test is that the directory carries prompt.md and that its composition injects identity through
prompt-reader.mjs. Any other hand-authored preset is neither listed nor touched: the page
regenerates a composition from a base mode, and doing that to a hand-written one would destroy it.
How this differs from the built-in Plugins page
From dsh 0.1.6-alpha.2 the harness ships a Plugins page that can enable and disable plugins live.
It and this mode's per-row switches act at different levels:
| Built-in Plugins page | This mode's per-row switches | |
|---|---|---|
| Scope | The whole profile — what this machine has installed | One agent mode — which rows its composition mounts |
| Typical use | Turn a plugin off globally | Keep Standard fully loaded and trim this mode to what it needs |
They coexist: the harness decides what the machine has, this mode decides which of it the mode uses.
The boundary is drawn by upstream: the Plugins page documents that it manages "the profile's bundles and their uniquely addressable rows", and states plainly that agent-preset rows remain read-only. The preset layer is therefore out of its reach — and that is exactly the layer this mode covers.
A demonstrable example: tool-plugin-manager (the agent-facing install/toggle tool) ships off in
Standard and PTC — only Creator enables it. The official modes give you no way to change that; here
you flip one switch.