dsh-profile-settings
Manifest validPer-profile settings overlay for DeepSeek Harness: global settings.yaml stays the baseline while each profile overrides any namespace through its own profiles/<name>/settings.patch.yml — object sectio
@xmoon76/dsh-profile-settings
English | 中文
A DSH profile bundle that adds a per-profile settings overlay on top of the
official user-settings seam. $DSH_HOME/settings.yaml stays the global
baseline; every profile can override any settings namespace through its own
$DSH_HOME/profiles/<name>/settings.patch.yml — object sections merge
recursively, arrays and scalars replace wholesale, and !unset explicitly
deletes an inherited value.
Schema Defaults
↓
Composition Base
↓
~/.dsh/settings.yaml (global user layer)
↓
~/.dsh/profiles/<name>/settings.patch.yml (profile user layer)
↓
Effective Settings
Existing plugins keep using ctx.settings exactly as before — the overlay is
transparent. Writes (update / replace / mutate) land in the profile
overlay only; replace({}) re-inherits the global layer, never the
composition default. The official schema validation, revision semantics,
expectedRevision conflict detection, watchers, and events are untouched.
Installation
Requires a profile whose bundles include @deepseek-ai/dsh-base (every
shipped web / headless template does). Install into each profile that
should get its own overlay:
dsh plugin --profile web add @xmoon76/dsh-profile-settings
dsh plugin --profile pi-tui add @xmoon76/dsh-profile-settings
dsh plugin --profile <name> add installs the package and reconciles it into
the profile's dsh.profile.bundles automatically (the manifest declares
dsh.bundle). On the next boot the bundle patch (cordis.patch.yml)
- disables the base
settingsrow (@deepseek-ai/dsh-settings-file), and - inserts the
profile-settingsrow owningctx.settings.
One composition may only hold one ctx.settings owner: if the base row is
still active beside this one, boot fails loud (Cordis duplicate-service
error) — never a silent override.
Configuration
The inserted row needs no config (defaults below); a profile's own
cordis.patch.yml may override the row's config:
| key | default | meaning |
| ------------ | ---------------------------------------------------- | -------------------------------------- |
| profile | auto-detected | explicit active profile name |
| globalPath | $DSH_HOME/settings.yaml | global settings document |
| profileFile| settings.patch.yml | overlay filename inside the profile dir |
| dshHome | $DSH_HOME or ~/.dsh | harness home |
| watch | true | hot-reload both documents |
| debounceMs | 100 | watcher write-settle window |
| writable | true | allow in-process writes into the overlay |
The active profile is resolved in this order (never from cwd): explicit
profile config → install location
(profiles/<name>/node_modules/…, the dsh plugin layout) → launcher
--profile <name> / --profile=<name> → DSH_PROFILE environment variable.
If none can be determined, boot fails loud.
The overlay file
# $DSH_HOME/profiles/web/settings.patch.yml
agent-default-model:
provider: pi-ai
model: gpt-5.6
permission:
mode: danger-full-access
some-plugin:
endpoint: !unset
Plain YAML values are overrides; !unset masks the lower layers (the
inherited value is deleted and the schema default applies unless the overlay
supplies its own value). Masks never enter the resolved JSON document — the
UI never sees them as values. The file is edited by hand or through the
settings command; in-process writes land here, never in settings.yaml.
The settings command
When a command runtime is mounted, ctx.profileSettings and the settings
command family are available:
settings layers [ns [path]] per-leaf source provenance
settings get <ns.path> effective value
settings set <ns.path> <value> write the profile overlay
settings unset <ns.path> delete an overlay value (re-inherit)
settings mask <ns.path> write !unset
settings unmask <ns.path> remove the mask
settings reset <ns> replace({}) on the overlay
settings promote <ns.path> move a value up to the global document
settings demote <ns.path> move a value down to the profile overlay
settings migrate <ns.path> [--copy] move a global value into the overlay with
.bak.<timestamp> backups (--copy keeps it)
settings diff [ns] leaf-level global vs overlay diff
settings ui [ns] machine-readable layer snapshot (Web UI)
settings profile active profile and document paths
Web UI (Profile Settings page)
The bundle ships a browser half (dsh.client): the web Settings panel gains
a Profile Settings section with per-field source badges (Default /
Composition / Global / Profile / Masked), the effective value, and
set / unset / mask / unmask / promote / reset actions. All host interaction
flows through the /profile-settings loopback RPC channel registered by the
host half — no session context, no command logs.
Configuration chain and design notes
The provider keeps the official base-class document as the profile raw
section, so update/replace/mutate/revision/expectedRevision/
describe keep their exact semantics; the global layer is folded into each
registration's composed base (applyMasks(merge(composition, global), masks)).
Only a narrow typed facade over the base class's TS-private members is
touched — no Settings machinery is forked. See docs/research.md for the
full M0 findings.
Fail-loud (boot): unresolvable profile, overlay root not a map, non-object
namespace section, !unset inside an array, unsupported YAML tags
(!!js/*, !!python/*, custom tags), overlay path escaping the profile
directory, global and overlay pointing at the same file, duplicate
ctx.settings owner.
Warn + keep last good (hot reload): temporarily invalid YAML in either document, unregistered namespaces (they are preserved for later-loading plugins).
Concurrency model and limitations
| Scope | Guarantee |
| --- | --- |
| In-process ordinary update/replace/mutate | official Settings semantics (per-namespace serialized write queue, expectedRevision conflict detection) |
| Cross-process file integrity (read-modify-write) | writer locks on both documents + atomic rename |
| Cross-process custom layer operations (promote/demote/migrate/mask/unmask) | true transactions: both locks in a fixed order, fences checked inside the locks, layer revisions advance on every text change |
| Cross-process ordinary update/mutate on the SAME profile + namespace | inherits the official seam limitation: the official revision is process-local to its write queue, so cross-process CAS on one namespace is best-effort (the last writer wins under the file lock) |
Development
npm run typecheck # tsc over src + tests
npm test # vitest
npm run build # tsc build + copy-lib (lib/)
npm pack # prepack build + postpack tarball smoke (leak checks)
Requires Node ≥ 22.6 (type stripping) and a DSH harness (0.1.1-rc.2 family) for the peer dependencies, which resolve from the running installation — the package never bundles its own harness copy, so no module twin.
License
MIT
Compatibility
Versions
| Latest version | Published | Size |
|---|---|---|
| 0.1.0 | — | — |
Similar plugins
Per-model system prompt injector for DeepSeek Harness: append custom prompt text to the END of the system prompt for locally configured models, matched by exact provider/model route or a provider-wide
★ 0
↓ 25/wk
dsh plugin --profile web add @duke-dsh-plugins/dsh-model-prompt-injectorby bowenliang123
The best DeepSeek Harness plugin for context insight and management, with context dashboard / browser / sidebar and context command, for context statistics, composition, breakdown, evolution details,
★ 1.4k
↓ 25.3k/wk
Apache-2.0
TypeScript
Sep 15, 2026
dsh plugin --profile web add dsh-contextAll-in-one UI enhancement layer for DeepSeek Harness web: prompt library with quick-insert and management, two-step AI polish, predicted-reply dock with click-to-send, MCP tool management, scheduled a
★ 0
dsh plugin --profile web add dsh-enhance-toolby WYH66666666
是一层高自由度的玻璃质感主题,套在 DeepSeek Harness 网页端。顶栏、侧边栏、输入框、统计行、轨迹视图都成了磨砂玻璃片。玻璃模糊度、磨砂度、背景(流体或自定义壁纸,壁纸还能单独调模糊和磨砂)全都能在设置卡片里自由调节。关掉开关就回到原生界面,不改 DSH 任何一行源码。
★ 405
AGPL-3.0
JavaScript
Aug 22, 2026
dsh plugin --profile web add @deepseek-ai/dsh-client-ui-aquaby JoukoPuro
一个 DeepSeek Harness(DSH)插件: 在 Web 输入框的工具行中添加一个 ✨ 图标按钮。点击后选择打磨风格,已接入的大模型 会把你草稿中的提示词改写得更专业、更易被 AI 理解 。A DeepSeek Harness plugin: icon-only composer button that rewrites your prompt via the connected LLM
★ 4
↓ 87/wk
MIT
JavaScript
Aug 14, 2026
dsh plugin --profile web add dsh-prompt-polishby sgzxs
A global task library plugin for DeepSeek Harness featuring cross-session persistence, a real-time generative-UI browser panel, and subagent job synchronization.DeepSeek Harness 全局任务插件:提供跨会话持久化任务库、生成式
★ 3
↓ 203/wk
MIT
TypeScript
Sep 11, 2026
dsh plugin --profile web add dsh-global-task-list