Third-party Plugins
Install and use third-party dsh-plugin packages inside a profile
Third-party plugins ship as npm packages installed into a profile with dsh plugin. Once installed, the cordis.patch.yml the package declares becomes a layer in that profile's composition.
Install and remove
dsh plugin --profile <name> <args...> initializes the profile when missing, then forwards <args...> to pnpm with the profile directory as the working directory — so add, remove, update, why, and every other pnpm verb work unchanged; pnpm must be on PATH.
dsh plugin --profile tui add github:deepseek-harness/turtle-ui
dsh plugin --profile tui remove turtle-ui
dsh --profile tuiRelative paths anchor to the invoking directory
Relative path specs (., ../plugin, and their file: / link: forms) are anchored to the invoking directory first, so add . from a plugin checkout installs that checkout, not the profile.
What makes a package a plugin bundle
A package joins the layer stack when its manifest declares a bundle relationship:
{
"name": "turtle-ui",
"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }
}After every successful run, dsh.profile.bundles is reconciled against the installed state:
- a dependency that declares
dsh.bundle.patchjoins the layer stack (so anupdatethat gains the declaration activates it); - a bundle-less dependency stays plain with a one-time warning;
- a removed dependency leaves the stack.
The installed package owns its dependencies and contributes its declared cordis.patch.yml layer.
Git-hosted plugins and builds
Git-hosted plugins that ship sources and build in their prepare script are blocked by pnpm ≥10 until you allow it: the first add fails with pnpm's allowBuilds hint (plus a pointer at the profile's pnpm-workspace.yaml); copy the printed key there and re-run. Installing a built tarball or a local checkout needs no allowance.
Discovery and trust
- Add the
dsh-plugintopic to your plugin repository for discoverability; - like in-box bundles, a plugin bundle's patch layer stacks in
dsh.profile.bundlesorder, followed by the profile and homecordis.patch.ymloverlays (see CLI & Profiles); - any package a plugin's
cordis.patch.ymlreferences through!!jsmust be declared in its resolver manifest's dependencies.
Arbitrary code execution
Installing a third-party plugin runs its declared patch and plugin code inside your profile composition. Only install packages from sources you trust.
Next steps
- Composition syntax and patch semantics live in the developer guide's Cordis primer.
- To build a plugin package yourself, see dynamic plugins.