* feat(preset): declare Agent compositions in profile YAML * fix(preset): share scope binding cleanup and refresh module graph * fix(preset): use host syntax colors in the YAML editor * fix(preset): write new profile declarations as block YAML * fix(preset): align eager activation with browser and worker surfaces * fix(ui-agent-preset): retain the existing preset card layout * fix(preset): keep rows waiting for a Host service mounted and re-audit after settlement A preset row whose Host provider was still activating at declaration time was reported as waiting for a missing service, and the registry recorded the definition as broken for the rest of the process. Split the mount audit into failed and pending rows: failures and root-realm leaks still reject the mount, while pending rows stay mounted and every read and binding re-audits them after the Host Loader tree settles. Remove the accidental self-dependency of @deepseek-ai/dsh-web-app and its lockfile self-link. Archive the copy-only preset authoring note, which the declarative-preset note fully supersedes, and update the ralph note's restore recipe to the profile-patch mechanism. * chore(lint): re-key and prune the unknown-cast baseline after the master merge * refactor(web-app): ship each Agent preset as its own bundle patch file `dsh.bundle.patch` accepts an ordered file list, so the four shipped preset declarations move out of the 1000-line web patch into `presets/<id>.patch.yml`, one insert per file, applied after the host patch. The host patch keeps the preset registry row. Gates and test scaffolds that read the web layer resolve every patch file through `bundlePatchPaths` instead of one hardcoded path. * refactor(preset): drop the save notice injected into live Agents The notice duplicated the save result the Web editor already shows, and after the producer-owned message sources it would have needed its own persisted source kind. Saving now only persists and reports the activation diagnostic; the persistence catalog is unchanged from master. * docs: regenerate the module graph after dropping the registry's llm dependency * test(ui-agent-preset): cover the guide dialog's keyboard handling on the declarative section * fix(preset): address the remaining review comments Apply the lowercase id rule only when creating a declaration, so presets declared with other ids stay editable. Export `isBuiltInPreset` from the display fold and key the client card groups on it. Remove the dead `error` and `retry` locale keys, the JSDoc orphaned by the `trust` removal, the `trust` fields in the plugin-inventory test fixtures, and the stale `dsh-agent-presets` package name in comments and READMEs. * refactor(preset): make the Web preset page view-and-select only Remove the child-plugin YAML editor, the `agent_preset` tool and the registry's read/save Remote methods. Presets are declared and changed only by bundle patches; the settings page keeps the roster, the new-task default and the mode help, and its question icon explains that and offers to start a Creator-mode task. The `editing-cordis-compositions` skill and the Creator persona describe the bundle-based path, and the authored skill-load Session and Web snapshots are refreshed for it. * docs(skill): make the composition skill self-sufficient for preset authoring State where the shipped declarations live, list every declaration field, inline a complete minimal bundle and an override example, and name the verification calls, so Creator mode no longer reads DSH package sources to infer the format. Refresh the authored skill-load Session for the new text. * test(tools): drop the removed agent_preset tool from the catalog expectation
@deepseek-ai/dsh
English | 中文
The dsh command is the sole supported Node application launcher: profiles are ordered stacks of plugin-bundle patch layers under the user's own overrides. SDK and ACP are profiles, not separate public bins. The Python runtime wheel packages this same command; the SDK defaults to sdk, and the minimal example selects sdk-minimal. src/args.ts owns the command grammar, and src/bin.ts loads only the selected runner. Invalid commands, options from another mode, and fatal configuration or boot failures exit nonzero.
Entry modes
| Command | Purpose |
|---|---|
dsh <name> / dsh --profile <name> |
Boot the named profile under $DSH_HOME/profiles/<name>. |
dsh --profile <name> --from-default-profile <template> |
Create a new custom profile from a shipped template, then boot it. |
dsh --profile acp |
Serve automation clients over ACP stdio until disconnect. |
dsh --profile headless "job" |
Run one fresh persisted session, print the final answer, and exit. |
dsh --profile sdk |
Serve SDK clients over JSON-RPC stdio until shutdown or disconnect. |
dsh --profile sdk-minimal |
Serve SDK clients with the standalone minimal agent tree. |
dsh web |
Boot the Web profile. |
dsh plugin --profile <name> <pnpm args> |
Manage a profile's plugins by forwarding to pnpm in the profile directory. |
The invoking directory is the default workspace root. The web, headless, sdk, sdk-minimal, and acp profiles auto-initialize on first use from shipped templates. Create another profile at an unused, non-shipped name with --from-default-profile, or initialize a base-backed profile through dsh plugin. The desktop name is reserved for the Electron-owned profile, so the CLI rejects boot, config-dump, and plugin-management requests for it.
App arguments
The launcher parses only its own flags and hands everything after them to the booted profile, where any injected app plugin may parse the shared immutable snapshot (dsh-cmdline). The first token the launcher does not recognize starts the app's arguments:
dsh --profile web --port 8080 # --port belongs to the web app
dsh --profile tui --resume <id> # example, assuming the tui profile is installed; --resume belongs to the terminal app
dsh --profile headless "run the tests"
dsh --profile web --help # the web app's flags, not the launcher's
dsh --help # the launcher's own help
Profiles
A profile directory holds a package.json (out-of-tree plugin dependencies plus the profile manifest dsh.profile with its ordered bundles list) and a cordis.patch.yml (the user's own patch layer). dsh-hmr, when enabled in YAML, watches the profile manifest and both profile and home patch files, then recomposes all layers through one serialized reload. Without HMR, changes apply on restart. Edits arriving during watcher registration use the same nonfatal reload reporting as later edits. Plugin Manager shares package operations and the profile write lock with dsh plugin; package updates retain disabled bundle selections. CLI package commands inherit authentication variables and terminal descriptors, including interactive build approval; service calls retain their scrubbed environment and captured diagnostics.
The tree composes over an empty root:
- each bundle's patch in
dsh.profile.bundlesorder - then the profile's
cordis.patch.yml, then the home-level$DSH_HOME/cordis.patch.yml - then
--patchoverlays
Bundles named in dsh.profile.bundles resolve from the dsh installation first (@deepseek-ai/dsh-base, @deepseek-ai/dsh-web-app, @deepseek-ai/dsh-headless, @deepseek-ai/dsh-sdk-app, @deepseek-ai/dsh-sdk-minimal, @deepseek-ai/dsh-acp-app), then from the profile's own node_modules, where pnpm installs out-of-tree plugins.
Use --dump-default-config and --dump-config to inspect the composed tree without booting it.
The CLI behavior reference owns exact layer precedence, flags, shutdown behavior, deployment defaults, and source execution. The startup and reload failure table compares optional and required plugin failures with configuration HMR.
Optional overlays
config/examples/ ships opt-in overlays for GitHub review webhooks, session-local Schedule, memory MCP servers, and runtime Cordis tools. They are never part of a default profile; the user guides and developer practice guides own setup and safety instructions.
Development
Production runs require built package and frontend artifacts. From the repository root, run pnpm run build separately, then use pnpm dsh <args...> to run the TypeScript entry and forward every argument; the source-execution reference owns the module-resolution contract.
The @deepseek-ai/dsh/profile-boot export provides the shared profile lifecycle to the Desktop host. A resolved application profile supplies its own installation anchor for runtime package resolution while retaining the Harness home patch, proxy environment, telemetry switch, patch reload, and bounded shutdown.
The Web failure matrix runs the built CLI through startup failures and native configuration HMR with awaitWriteFinish enabled in test:expected. It verifies authenticated HTTP responses, diagnostics, recovery, process exits, and disposal without model API calls; the startup acceptance also covers the shipped required Web dependencies and port conflicts.