The `cordis` preset's `editing-cordis-compositions` skill is the only guidance an agent has when it authors a preset, and four of its statements were false. `tool-bash` was named as the worked example of a row that hides a service; it provides nothing and injects `bashEnv` from the host's own `bash-env` row, so following that advice strands the row behind its realm and the preset fails to mount. The `isolate` example composed `tasks-local` with `tool-tasks`, which the shipped compositions' own comments say breaks `run_in_background`. A string realm label was described as pooling one instance; labels join realms and `provide()` still throws on the second registration. Rows were to be checked against a package README, which no harness package publishes. Verification is now the agent's own: `standingKeyFor(id)` runs the same mount a session start performs and rejects an unresolvable package, an invalid config, a service in the root realm, and a row that never activated. The skill states that `list()`'s `broken` field is a shape check that every one of those passes, ships the `cordis_mount` plugin that reaches the roster service, and names `copy()` as the authoring write. The prohibition on touching the shipped install is promoted to its own section and extended to the host composition. Fixes #2266
@deepseek-ai/dsh
English | 中文
The dsh command is the product launcher for profiles: ordered stacks of plugin-bundle patch layers under the user's own overrides. src/args.ts owns the command grammar, and src/bin.ts loads only the selected runner. Invalid commands, options from another mode, configuration errors, and boot failures exit nonzero.
Entry modes
| Command | Purpose |
|---|---|
dsh --profile <name> |
Boot the named profile under $DSH_HOME/profiles/<name>. |
dsh --profile headless "task" |
Run one fresh persisted session, print the final answer, and exit. |
dsh web |
Alias of --profile web. |
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 and headless profiles auto-initialize on first use from shipped templates; any other profile must be created through dsh plugin.
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). Launcher flags therefore come first, and 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> # --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, hot-reloaded on long-lived surfaces). The tree composes over an empty root: each bundle's patch in dsh.profile.bundles order, then the profile's cordis.patch.yml, then the home-level $DSH_HOME/cordis.patch.yml, then --patch overlays. 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), 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.
Development
Production runs require built package and frontend artifacts. From the repository root, pnpm dsh <args...> builds those artifacts, runs the TypeScript entry, and forwards every argument; the source-execution reference owns the module-resolution contract.