Profile management card for the DSH Web GUI: view, create (base / web / headless templates), copy, rename and delete DSH profiles under ~/.dsh/profiles, with per-profile port configuration and a copyable launch command.
Install
# from npm (prebuilt)
dsh plugin --profile web add @hyzyn/dsh-profile
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:hyzyn/dsh-plugin-kit#path:/packages/profile
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
中文 | English
The “Profile Management” card in DSH Settings → Plugins: view, create, copy, rename, and delete DSH profiles without memorizing commands.
Features
- Template-based creation, no hand-copied manifests: create one from three templates in one click (
@deepseek-ai/dsh-basecore only, or adddsh-web-app/dsh-headless); copying skipsnode_modulesand lockfiles and runspnpm installautomatically. - The port is stored with the profile: a startup port is recorded for each profile and copied startup commands carry
--port, so multiple web profiles no longer collide on ports. - Rename moves the directory and the manifest together: one operation performs both the directory move and the
package.jsonrename; deletion asks for a second confirmation inside the panel (irreversible). - Status and structure read straight from disk: initialization badge, bundle layer, dependency count and directory path; a missing
cordis.patch.ymlis flagged.
What is a profile
Each profile is a standalone directory under $DSH_HOME/profiles (default ~/.dsh/profiles, overridable with the DSH_HOME environment variable), with its own bundle layer and patch file:
~/.dsh/profiles/<name>/
├── package.json # dsh.profile.bundles: the bundle layers for this profile
├── cordis.patch.yml # Patch layer: loader patches applied after the bundle layers
├── pnpm-workspace.yaml # Profile workspace (nodeLinker: hoisted)
└── profile.runtime.json # (Optional) runtime configuration for this plugin, e.g. the startup port
Structure
| File | Description |
|---|---|
src/index.ts |
Host half: profile directory read/write, validation, create / copy / rename / delete, /api/dsh-profile/* routes (loopback-only fence) |
client.js |
Browser half: registers the settings.plugin.item card (React shell + plain-DOM management panel, window.__ModuleLoader__.load format) |
cordis.patch.yml |
Bundle patch: inserts the plugin line into the profile roster |
Routes (loopback + same-origin only):
GET /api/dsh-profile/list— list all profiles and their statusPOST /api/dsh-profile/create— create (name+ optionaltemplate/port)POST /api/dsh-profile/duplicate— copy (name+from)POST /api/dsh-profile/rename— rename (name+newName)POST /api/dsh-profile/port— set the port (name+port; leaveportempty to clear)POST /api/dsh-profile/delete— delete (name)
Installation
pnpm --filter @hyzyn/dsh-profile build
dsh plugin --profile web add link:$(pwd)/packages/profile
The plugin's own line is mounted by insert: { id: profile-manager, name: '@hyzyn/dsh-profile' } in cordis.patch.yml; dsh plugin add also installs this package into the profile dependencies and adds it to the dsh.profile.bundles patch layer, so this mount step is only needed once — it takes effect after restarting dsh web.
Configuration
interface Config {
/** Disable the whole plugin. Defaults to false. */
enabled?: boolean
/** Whether to inject the plugin capability announcement to the agent. Defaults to true. */
announceToAgent?: boolean
}
UI preview
Settings → Plugins → the “Profile Management” card (configuration UI):
Where the settings surface lives depends on the DSH version, but it is always the same form: from
0.2.0-rc.1 it is registered as plugins.bundle.config — inline on the plugin detail page, directly
below the description, with no extra ">" step; older hosts (the 0.1.6 line) fall back to the row's ">"
sub-page under the Plugins sidebar, and ≤0.1.5 uses the settings-page card.
After creating a profile from the headless template, you can start a headless session with that profile directly from the command line (answer one task, print the result, then exit):
# Start with the headless profile: answer one task, print the result, then exit
dsh --profile headless "run the tests"
# dsh web is an alias for --profile web
Notes
- Creation logic matches
initProfileindsh-app-boot: it generatespackage.json(dsh.profile.bundles), an empty patch filecordis.patch.yml([]), andpnpm-workspace.yaml - Names must match
[A-Za-z0-9][A-Za-z0-9._-]*and cannot benode_modules/./.. - Copying skips
node_modulesandpnpm-lock.yamlautomatically and does not carry over installed artifacts, but runspnpm installto rebuild dependencies;profile.runtime.jsonis copied along with the directory - Port configuration is stored in
profile.runtime.jsonand only affects the startup commands this plugin generates; it is never written to DSH's officialpackage.json/cordis.patch.yml - Deletion is recursive and irreversible, with a second confirmation inside the panel; the built-in
webdefault profile cannot be deleted, whileheadlesscan be deleted - A new profile needs its dependencies installed on demand before first use:
dsh plugin --profile <name> add <package>(runs pnpm inside the profile directory) - The browser half depends on the core
slotsservice; only the official settings panel ofdsh-web-appprovides that slot
Links
More in this category
yjh051108/dsh-routing-suite★ 7026
One repository, three parts: a runtime injector for DSH plugin packages (inject, hot-reload, unload, promote a dev staging tool to the front, route self-heal, plus a settings-page plugin manager that lists, unloads and drags folders in to internalize), a task-aware reasoning-mode router agent preset (router-standard / router-spec / router-react), and a graded two-level task protocol whose six tools (commit_star, lock_stage, revise_do, edit_plan, mark_task, redteam_verdict) pin task state to disk. The injector implementation ships in-tree, so the install carries its own behaviour rather than a dependency list.
strukto-ai/mirage#dsh★ 3686
Swaps the filesystem and bash providers for a mirage virtual workspace: file tools and shell commands run over mounted resources (RAM, S3, Redis, Slack, Gmail, Notion, Postgres) instead of the host disk, with per-mount read/write/exec modes, per-command sandbox routing (monty, pyodide, quickjs in process; docker, e2b, daytona remote), and installed CLIs (git, gh, slack, linear, ntn, gws, or one you register) as head words in the virtual terminal.
hust-open-atom-club/oh-dsh★ 322
Community distribution: TUI, desktop, and Web UI as one bundle with layered installation.
weijiafu14/pi2dsh★ 213
Pi Host ABI compatibility engine: after one install, unmodified Pi extensions from npm mount as native DSH plugins with `dsh plugin add <pi-package>`. Verified end to end on stock DSH with pi-mcp-adapter (full MCP manager: OAuth, resources, prompts, MCP Apps, elicitation, sampling), @tintinweb/pi-subagents, pi-code, pi-hermes-memory and pi-background-tasks; `pi2dsh inspect` reports a package's compatibility before installing.
Fishquito7/dsh-skill-mcp-panel★ 197
Manages DSH skills and MCP servers from the web settings: skill cards with hot enable/disable, workspace scopes, groups, batch migration and drag-and-drop import, plus stdio/HTTP MCP CRUD with connection tests, secret redaction and the unified dsh-panel CLI.
lire1131/dsh-undo-savepoint★ 181
Undo/redo & rollback system for DSH: every config change is auto-snapshotted; undo/redo/restore to any version from the WebUI or the offline CLI/GUI tools (works even when DSH fails to boot).
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.