Preface¶
The standard settings mechanism of DSH manages configuration through ctx.settings. Customizing these settings for a specific profile (such as web) usually requires manually managing complex override logic in the global settings.yaml. The xmoon/dsh-profile-settings plugin adds a transparent profile overlay on top of the official user settings mechanism, allowing each profile to have its own override file (settings.patch.yml) without breaking existing settings behavior.
Introduction¶
This is a DSH profile plugin maintained by XMoon. It adds profile-specific settings overrides, separating the global settings.yaml from profiles/<name>/settings.patch.yml, and allowing each profile to inherit global settings while overriding specific namespaces.
Core Features¶
- Adds profile-specific settings overrides under
ctx.settings. - Transparent layering: global
settings.yaml+profiles/<name>/settings.patch.yml. - Recursive object merging, with arrays and scalars replaced as a whole.
- Supports the YAML
!unsetdirective to explicitly hide inherited values. - Provides a Web UI that displays a source marker for each field (Default / Composition / Global / Profile / Masked) and action buttons.
- Supports hot reloading, with write locks and transactions to guarantee file integrity.
Installation and Enablement¶
This plugin requires the profile bundle to include @deepseek-ai/dsh-base (all built-in web / headless templates meet this requirement). The installation command is as follows:
dsh plugin --profile web add @xmoon76/dsh-profile-settings
The installation process automatically adds the package to dsh.profile.bundles. After restarting the Harness, the plugin performs the following actions:
1. Disables the base settings line (@deepseek-ai/dsh-settings-file).
2. Inserts a new line that owns ctx.settings.
Note: A composition can have only one ctx.settings owner. If the base line is still active and not fully disabled, bootstrapping fails with a Cordis duplicate service error.
Configuration¶
The inserted line is configured by default as follows (usually no modification is required):
| Key | Default | Meaning |
|---|---|---|
profile |
auto-detected | Explicitly specified active profile name |
globalPath |
$DSH_HOME/settings.yaml |
Path to the global settings document |
profileFile |
settings.patch.yml |
Override file name inside the profile directory |
dshHome |
$DSH_HOME or ~/.dsh |
Harness home directory |
watch |
true |
Hot-reload both documents |
debounceMs |
100 |
Stabilization window for listener writes |
writable |
true |
Allow in-process writes to the override file |
The resolution order for the active profile is: explicit profile configuration -> installation location (profiles/<name>/node_modules/…) -> launcher argument --profile <name> -> DSH_PROFILE environment variable. If it cannot be determined, bootstrapping fails.
Overlay File Example¶
The overlay file is located at $DSH_HOME/profiles/<name>/settings.patch.yml. The file can be edited manually or modified through the settings command. In-process writes go to this file, rather than to settings.yaml.
# $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 used for overrides; !unset hides values from lower layers (inherited values are removed unless the overlay provides a new value). These masks do not enter the final resolved JSON document, and the UI does not display them as values.
Settings Commands¶
After the plugin is mounted, the ctx.profileSettings and settings command families are available:
settings layers [ns [path]] 查看每个叶子节点的来源证明
settings get <ns.path> 获取有效值
settings set <ns.path> <value> 写入配置文件覆盖
settings unset <ns.path> 删除覆盖值(重新继承)
settings mask <ns.path> 写入 !unset
settings unmask <ns.path> 移除掩码
settings reset <ns> 对覆盖层执行 replace({})
settings promote <ns.path> 将值上移至全局文档
settings demote <ns.path> 将值下移至配置文件覆盖
settings migrate <ns.path> [--copy] 移动全局值到覆盖层(带 .bak 时间戳备份,--copy 保留原值)
settings diff [ns] 叶子级全局与覆盖的差异
settings ui [ns] 机器可读的层快照(Web UI)
settings profile 查看活动配置文件和文档路径
Web UI¶
The plugin includes a browser-side component (dsh.client). The Web settings panel adds a “Profile Settings” section, showing the source marker, effective value, and actions (set/unset/mask/promote/reset, etc.) for each field. All host interactions are performed through the host-registered /profile-settings loopback RPC channel and do not involve session context or command logs.
Concurrency Model and Limitations¶
- In-process operations: Ordinary
update/replace/mutatecalls follow the official settings semantics (namespace serialization queue,expectedRevisionconflict detection). - Cross-process file integrity: Guaranteed using a write lock + atomic rename.
- Cross-process custom layer operations (
promote/demote/migrate/mask/unmask): Uses fixed-order locks and fences to ensure transactional consistency; each textual change advances the layer revision.
Limitations and failure modes:
* Requires Node >= 22.6.
* Bootstrapping fails if the profile cannot be resolved, the overlay root is not a map, a namespace is not an object, !unset appears inside an array, an unsupported YAML tag is used, the overlay path escapes the profile directory, the global and overlay files point to the same file, or a duplicate ctx.settings owner exists.
* Temporarily invalid YAML during hot reloading triggers a warning, but the last valid version is retained.
Summary¶
This plugin provides a standardized settings management solution for DSH profiles, enabling isolation across multiple profiles without modifying the underlying settings logic. For more details, refer to the directory page or the GitHub repository.