DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-persona-switch

s

dsh-persona-switch

Manifest valid

Live persona switching for DeepSeek Harness (dsh): switch the system-prompt persona from a running session - TUI, Web UI or headless - no restart. Published on npm as dsh-persona-switch.

hasBundlePatch

dsh-persona-switch

npm github dsh-plugin license MIT verified dsh 0.2.0-rc.2 + 0.2.1-rc.1

Live persona switching for DeepSeek Harness (dsh). Switch the system-prompt persona from inside a running session — TUI, Web UI, or headless — with no restart and no core patch. Ships with the switcher plus the example JB persona (jb); a longer persona variant is deliberately not included and your own personas live in $DSH_HOME/personas/.

/persona              show the active persona + the roster
/persona list         same
/persona jb           switch  (name = personas/<name>.md)
/persona off          stop overriding the system prompt
/persona reload       re-read the persona directory (after editing a file)
/persona complete on|off|auto

Or just ask the agent — persona_switch is registered as a tool:

jbに切り替えて

Proof

Whether a persona actually overrides the prompt is measurable: point the route at a local mock (DEEPSEEK_BASE_URL) and read the request body DSH sends. test/capture-prompt.mjs does exactly that, and the three states differ exactly as the front-matter says:

personacompleteagent-turn system messageharness identity
off—2,823 BPRESENT
jbtrue7,989 B — byte-exact match with personas/jb.mdabsent
jbfalse10,814 B (= 2,823 merged + 7,989 persona)PRESENT

25 tool schemas ride along in every case, thinking stays enabled, and the session-title helper (a separate 363 B request) is untouched.

Why a plugin is needed at all

DSH's own docs are explicit: "Deployment-authored prompt text is config/ composition only … there is no end-user prompt-editing API." The deployment persona lives on the dsh-system-prompt row's config, and dsh-persona only shadows it inside one agent preset. Neither is switchable while a session is up.

This row registers one prompt section whose text is a provider function, evaluated at every assembly:

sp.section({
  name: 'persona-switch:persona',
  order: sp.getSectionOrder('DEPLOYMENT_PERSONA_PREFIX'),
  text: () => activeText(),      // ← read on every turn, not at boot
  interpolate: false,
  complete: activeComplete(),    // persona becomes the whole system prompt
})

Switching disposes and re-registers that section, which emits system-prompt/change; the next turn is assembled against the new persona.

Install

From npm (one line per profile — each dsh profile is a separate install):

dsh plugin --profile web      add dsh-persona-switch
dsh plugin --profile dsh-tui  add dsh-persona-switch
dsh plugin --profile headless add dsh-persona-switch   # for scripting

Restart that profile (or just start it) and /persona is there. Nothing else to configure — the package declares dsh.bundle.patch, so dsh plugin add also appends it to dsh.profile.bundles for you. Pin the version (…add dsh-persona-switch@0.1.2) when a stale pnpm packument could hand you an older release; plain add dsh-persona-switch resolves to latest.

From a checkout (development — a file: dependency is a symlink, so edits take effect on the next dsh start, no reinstall):

dsh plugin --profile web add file:C:/path/to/dsh-persona-switch

Desktop app (Electron). Its desktop profile is reserved: dsh plugin --profile desktop … refuses with profile "desktop" is managed exclusively by the Electron application. Install it by hand (or run scripts/install-desktop.ps1, which does exactly this and verifies the result):

powershell -ExecutionPolicy Bypass -File scripts/install-desktop.ps1

then quit the app completely (tray included) and start it again. The / menu now lists persona; /persona <name> runs host-side (no model turn, no tokens). If an app update rewrites ~/.dsh/profiles/desktop/package.json, re-run the script.

Upgrade / uninstall

dsh plugin --profile web add dsh-persona-switch@0.1.2    # upgrade (pin: pnpm can serve a stale packument)
dsh plugin --profile web remove dsh-persona-switch        # uninstall

Uninstalling leaves $DSH_HOME/personas/*.md alone (your files, not the package's).

Personas

$DSH_HOME/personas/*.md — seeded from personas/ on first run, then yours to edit. The file stem is the persona name. Optional front-matter:

---
title: JB core (persona slim2 / 8KB)   # shown by /persona list
complete: true                          # true = this becomes the ENTIRE system prompt
suffix: ""                              # optional text after first-party guidance
---

<persona prose>
fielddefaultmeaning
titlefile stemlabel in the roster
completefalsetrue replaces the whole system prompt (harness identity, guidance, everything). false puts the text at the persona-prefix slot and keeps first-party guidance.
suffix—appended at the persona-suffix slot instead of the prefix

Shipped seeds:

personasizecompletewhat it is
jb~8 KByesthe example JB persona
terse0.5 KBnoexample of a non-complete persona
_selftest0.3 KByesanswers only BANANA — proves the wiring

jb_full (an 84 KB variant) is not in this repo and not in its history — it was removed on 2026-10-12 and .gitignore / .git/info/exclude keep it out.

complete: true makes a persona the entire system prompt (see Proof); false keeps first-party guidance and puts the persona at the deployment-persona slot. Optional suffix: lands after first-party guidance. Your own personas live in $DSH_HOME/personas/ — drop a .md there and run /persona reload.

Adding your own

Drop a .md file in $DSH_HOME/personas/, then /persona reload. No restart.

Files

$DSH_HOME/personas/              your personas (seeded once)
$DSH_HOME/persona-switch.json    { "active": "...", "complete": true|null }
$DSH_HOME/persona-switch.log     what registered, when, and why anything failed

State is deployment-wide (one $DSH_HOME), so a switch made in the TUI is the persona the next headless run uses too. That is what makes scripted use easy:

'{ "active": "jb" }' | Set-Content "$env:USERPROFILE\.dsh\persona-switch.json"
dsh headless "..."        # runs under jb

Config

cordis.patch.yml:

- id: persona-switch
  name: dsh-persona-switch
  config:
    maxPersonaBytes: 400000   # truncate a longer persona (0 = no cap)
    tool: true                # register the model-facing persona_switch tool

Test

npm test                                  # node test/unit.mjs — 30 assertions, no network
node test/capture-prompt.mjs --persona _selftest    # proves the system message
node test/capture-prompt.mjs --persona off          # and the stock prompt, for contrast

test/unit.mjs drives the real apply() against a fake Cordis context: seeding, roster, switching, complete toggling, state persistence, the tool path, unknown names, teardown.

test/capture-prompt.mjs starts a local mock that speaks Anthropic Messages and OpenAI chat-completions, points DEEPSEEK_BASE_URL at it, runs dsh headless and reports the system message it received. Nothing reaches a real provider, so it costs nothing to run. Set DSH_CAPTURE_DIR=<dir> to dump full request bodies.

The live path was verified the same way:

$ node test/capture-prompt.mjs --persona _selftest "What is 1+1?"
#   system bytes     : 256
#   harness identity : absent
#   persona "_selftest" : system message IS the persona (exact match)

Notes / limits

  • complete: true is heavy. The persona is the entire system prompt every turn; an 84 KB persona costs those tokens on every request and can change prefix-cache behaviour. Watch it with dsh-whale-widget / dsh-context.
  • Two complete sections would fail assembly — this row is the only one it registers, so keep other persona plugins out or switch them off.
  • No client bundle: the switcher is a slash command + tool, not a Web settings panel. In the Web UI the command works from the composer.
  • Nothing here is JB-specific — it is a persona switcher. The JB presets are just the seeds that were asked for.
  • The DeepSeek route speaks Anthropic Messages (POST /v1/messages) with thinking enabled and output_config.effort set per model route; the plugin does not touch either.
  • Released: the repo is public and the package is on npm (npm view dsh-persona-switch version for the current one). For the next release see PUBLISHING.md — §0 is the current state and §3 records the JB-seed call (made 2026-10-12, jb.md ships / jb_full.md never).

Comments

Loading…

Similar plugins

dsh-agent-persona

by Awoodwhale

Workspace personas for DeepSeek Harness (DSH): many system-prompt personas, each scoped by workspace path or session id, managed from the Web settings page (Apache-2.0)

Tools & CapabilitiesManifest valid

★ 4

Apache-2.0

TypeScript

Oct 8, 2026

dsh plugin --profile web add dsh-agent-persona

by huaizhuanghub

Persona library plugin for DeepSeek Harness: built-in personas, import your own, switch without restart.

Tools & CapabilitiesTerminal & ClientsSessions & MessagesManifest valid

★ 39

↓ 1.2k/wk

MIT

JavaScript

Oct 12, 2026

dsh plugin --profile web add dsh-persona-dafeiyu

by 0gl20shk0sbt36

DSH deadman switch: run a command unless a living agent keeps holding it off. Arms a watchdog that asks the owning session on every firing, skips when somebody holds, and acts when nobody answers.

Tools & CapabilitiesManifest valid

★ 0

MIT

JavaScript

Sep 30, 2026

dsh plugin --profile web add dsh-deadman

by penglai-doll

SOUL.md-backed living persona for DeepSeek Harness: injects a trusted SOUL.md as a system-prompt section refreshed at every session start, registers soul_view / soul_remember / soul_edit / soul_rewrit

Manifest valid

★ 0

↓ 154/wk

MIT

JavaScript

Aug 17, 2026

dsh plugin --profile web add dsh-soul

Persona wardrobe for DeepSeek Harness: save multiple personas, apply them globally or per workspace, with a master switch, an adjustable API balance guard, and a lazy token-loving tired mode that spea

UI & ExperienceModels & ProvidersManifest valid

★ 0

dsh plugin --profile web add dsh-guise

by lsz-asd

Delete DeepSeek Harness sessions from the UI: header danger button + sidebar session-row menu item (no conversation jump), risk-consent dialog with session name/id, stops running agents first, in-plac

Sessions & MessagesManifest valid

★ 40

JavaScript

Aug 14, 2026

dsh plugin --profile web add @huanlin/dsh-plugin-session-delete