--- name: dms-plugin-dev description: Guidance, decision trees, cheat sheets, ecosystem map, and generic vertical-slice starter templates for building plugins for Dank Material Shell (DMS / DankMaterialShell) using Quickshell QML. Use when the user asks to create, extend, debug, review, or publish a DMS plugin, or mentions plugin.json, PluginComponent, DankBar widgets, launcher plugins, desktop widgets, or the DMS plugin registry. license: MIT compatibility: opencode --- # DMS Plugin Development ## Mental Model (Read This First) Dank Material Shell plugins are **small, self-contained directories** dropped into `~/.config/DankMaterialShell/plugins//`. Each plugin declares what it is in `plugin.json` (type, capabilities, entry component, permissions, dependencies). The shell discovers them, loads the QML components into its running context, and injects services (`PluginService`, `Theme`, `ToastService`, etc.). Plugins do **not** run in isolation like a normal QML app. They participate in the larger DMS object tree. There are four primary plugin types (see `docs/plugin-types.md` for the decision tree): - **widget** — Appears in the DankBar or Control Center (most common). - **launcher** — Extends the Spotlight-style launcher with searchable items (root is a `QtObject`, not an `Item`). - **daemon** — Background logic, no UI (react to events, run automation). - **desktop** — Free-floating, user-positionable and resizable widgets on the desktop layer (uses `DesktopPluginComponent`). ## Development Loop (Fastest Feedback) 1. Create your plugin directory anywhere (e.g. `~/src/my-dms-plugin`). 2. Symlink it: `ln -s ~/src/my-dms-plugin ~/.config/DankMaterialShell/plugins/MyPlugin`. 3. Work in the source tree. 4. After changes: `dms ipc call plugins reload myPlugin` (uses the `id` from plugin.json). 5. For popout widgets, set `layerNamespacePlugin: "something-unique"` in your `PluginComponent`. 6. Set up qmlls for autocomplete (see official docs; create `.qmlls.ini` in a DMS checkout). 7. Use the `Proc` singleton (from `qs.Common`) for any external command whose output you need to capture. It handles debouncing and auto-cleanup. Never restart the whole shell while iterating on a plugin unless absolutely necessary. ## Must-Read Official Sources This skill is deliberately a **thin orientation + index + templates layer**. The canonical, detailed, and up-to-date reference is the official documentation: - Plugin Overview: https://danklinux.com/docs/dankmaterialshell/plugins-overview - Plugin Development (the big one): https://danklinux.com/docs/dankmaterialshell/plugin-development - Plugin schema (validation): Look for `plugin-schema.json` in the DMS repo or registry. **Always** check the version notes at the top of those pages and match them to the DMS version the user is running. ## High-Signal Cheat Sheets in This Skill - `docs/plugin-types.md` — Decision tree for choosing the right plugin shape. - `docs/cheatsheets.md` — Condensed surfaces for `plugin.json`, `PluginComponent`, `PluginService`, settings components, popouts, and permissions. - `docs/ecosystem.md` — Where to find real examples (first-party plugins, monorepo PLUGINS/, registry, community). ## Generic Vertical-Slice Templates Located in the `templates/` directory of this skill. Each is a minimal, correct, modern starter for one plugin type. **How to use them**: 1. Copy the entire template folder to `~/.config/DankMaterialShell/plugins/YourPluginName/`. 2. Rename files and update `plugin.json` (especially `id`, `name`, `author`, paths). 3. Run `dms ipc call plugins reload ` (or restart). 4. Enable in DMS Settings → Plugins. Current templates: - `widget-bar/` — Simple DankBar widget with settings. - `widget-popout/` — Bar widget that opens a nice popout (uses `PopoutComponent` + layer namespace). - `launcher/` — Basic launcher extension (QtObject root + `getItems`/`executeItem`). - `desktop/` — Minimal desktop layer widget (uses `DesktopPluginComponent`). These templates follow current best practice (PluginSettings + `*Setting` components, proper permissions, `Proc` where relevant, etc.). They are intentionally small. ## Common Agent Failure Modes Specific to DMS Plugins - Assuming the plugin is a standalone QML application (it lives inside DMS's context and singleton graph). - Writing settings UI without declaring `"permissions": ["settings_write"]` (the settings simply won't appear). - Using raw `Process` items for one-shot commands that need stdout (use the `Proc` singleton instead). - Forgetting that `pluginData` comes from the settings store and is not a general reactive property bag. - Neglecting `layerNamespacePlugin` on popout widgets (z-order and focus problems). - Treating launcher plugins like normal QML Items (they must be `QtObject` and export specific functions). - Over-caching or pre-computing things at load time that the shell can provide on demand. - Not testing the hot-reload path early. ## Publishing & Distribution - Add good screenshots, a README, and a license. - Validate your `plugin.json` against the schema. - Submit via PR to https://github.com/AvengeMedia/dms-plugin-registry (follow their CONTRIBUTING.md). - The site at https://plugins.danklinux.com/ rebuilds automatically. ## How to Explore When Stuck 1. Re-read the two official development pages for the exact DMS version in use. 2. Look at the small example plugins inside the main DMS repo (`quickshell/PLUGINS/`). 3. Study first-party plugins in https://github.com/AvengeMedia/dms-plugins (they are maintained to current standards). 4. Browse the registry for real-world usage of the feature you need. 5. Use `dms ipc call plugins list` and the logs from `dms run` for runtime diagnostics. --- This skill exists to reduce uncertainty and variability when an agent is asked to work on a DMS plugin. It is intentionally lightweight and points at the official sources for depth. Written by AI agent working for @jtmorris. Model: grok-build-0.1.