Skip to main content

dms-plugin-dev

Develop plugins for DankMaterialShell (DMS), a QML-based Linux desktop shell built on Quickshell. Supports widget (bar, dock + Control Center), daemon (background service), launcher (search + actions), desktop (draggable desktop widgets), dash (dash tab), dashCard (dash overview card), and composite (multi-surface) plugins. Covers manifest creation, QML component development, startup checks, settings UI, data persistence, theme integration, PopoutService usage, IPC runtime discovery, and external command execution. Use when the user wants to create, modify, or debug a DMS plugin, or asks about the DMS plugin API.

Quellinformationen

Repository
AvengeMedia/DankMaterialShell
Letzte Quellaktivität
17. September 2026 um 20:51
Erkannte Sprache von SKILL.md
Englisch
Sterne
8.450
Forks
552

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
29 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
dms-plugin-dev
description
Develop plugins for DankMaterialShell (DMS), a QML-based Linux desktop shell built on Quickshell. Supports widget (bar, dock + Control Center), daemon (background service), launcher (search + actions), desktop (draggable desktop widgets), dash (dash tab), dashCard (dash overview card), and composite (multi-surface) plugins. Covers manifest creation, QML component development, startup checks, settings UI, data persistence, theme integration, PopoutService usage, IPC runtime discovery, and external command execution. Use when the user wants to create, modify, or debug a DMS plugin, or asks about the DMS plugin API.
compatibility
Designed for Claude Code (or similar products)
metadata
{"author":"DankMaterialShell","version":"1.2","domain":"qml-desktop-development","framework":"DankMaterialShell","languages":"qml, javascript"}
allowed-tools
Bash Read Write Edit
# DankMaterialShell Plugin Development ## Overview DMS plugins extend the desktop shell with bar and dock widgets, background services, launcher integrations, desktop widgets, and dash tabs and cards. Plugins are QML components discovered from `~/.config/DankMaterialShell/plugins/`. **Minimum plugin structure:** ``` ~/.config/DankMaterialShell/plugins/YourPlugin/ plugin.json # Required: manifest with metadata YourComponent.qml # Required: main QML component YourSettings.qml # Optional: settings UI *.js # Optional: JavaScript utilities ``` **Plugin registry:** Community plugins are available at https://plugins.danklinux.com/ **Plugin types:** | Type | Purpose | Base Component | Bar/dock pills | CC integration | |-------------|--------------------------------|----------------------------|----------------|----------------| | `widget` | Bar or dock widget + popout | `PluginComponent` | Yes | Yes | | `daemon` | Background service | `PluginComponent` (no UI) | No | Optional | | `launcher` | Searchable items in launcher | `Item` | No | No | | `desktop` | Draggable desktop widget | `DesktopPluginComponent` | No | No | | `dash` | Tab in the dash popout | `DashTabComponent` | No | No | | `dashCard` | Card in the dash overview grid | `DashCardComponent` | No | No | | `composite` | Multi-surface plugin | One component per surface | Optional | Optional | ## Step 1: Determine Plugin Type Choose the type based on what the plugin does: - **Shows in the bar or a dock?** - Use `widget`. Displays a pill in DankBar or a dock (same component), optionally opens a popout or an attached dock panel, optionally integrates with Control Center. - **Runs in background only?** - Use `daemon`. No visible UI, reacts to events (wallpaper changes, notifications, battery level, etc.). - **Provides searchable/actionable items?** - Use `launcher`. Items appear in the DMS launcher with trigger-based filtering (e.g., type `=` for calculator, `:` for emoji). - **Shows on the desktop background?** - Use `desktop`. Draggable, resizable widget on the desktop layer. - **Full page in the dash?** - Use `dash`. A tab in the dash popout, id `plugin_<pluginId>`. - **Small tile on the dash overview?** - Use `dashCard`. A resizable card in the overview grid. - **Needs multiple surfaces?** - Use `composite`. A single plugin that registers any combination of the above (e.g., a daemon + bar widget + desktop widget). Each surface gets its own QML component file. ## Step 2: Create the Manifest Create `plugin.json` in your plugin directory. See [plugin-manifest-reference.md](references/plugin-manifest-reference.md) for the full schema. **Minimal manifest:** ```json { "id": "yourPlugin", "name": "Your Plugin Name", "description": "Brief description of what your plugin does", "version": "1.0.0", "author": "Your Name", "type": "widget", "capabilities": ["your-capability"], "component": "./YourWidget.qml" } ``` **With settings, startup check, and permissions:** ```json { "id": "yourPlugin", "name": "Your Plugin Name", "description": "Brief description", "version": "1.0.0", "author": "Your Name", "type": "widget", "capabilities": ["your-capability"], "component": "./YourWidget.qml", "icon": "extension", "settings": "./Settings.qml", "startupCheck": "./StartupCheck.qml", "requires_dms": ">=0.1.0", "dependencies": ["mytool"], "permissions": ["settings_read", "settings_write"] } ``` **Composite plugin (multi-surface):** ```json { "id": "myComposite", "name": "My Composite Plugin", "description": "Daemon + widget + desktop from one plugin", "version": "1.0.0", "author": "Your Name", "type": "composite", "capabilities": ["daemon", "dankbar-widget", "desktop-widget"], "icon": "extension", "components": { "daemon": "./MyDaemon.qml", "widget": "./MyBarWidget.qml", "desktop": "./MyDesktopWidget.qml" }, "settings": "./Settings.qml", "permissions": ["settings_read", "settings_write"] } ``` **Standalone dash tab or card:** same single file form, `"type": "dash"` or `"type": "dashCard"` plus `"component"`. A tab and a card together (or with a bar widget) use `components` with the keys `dash` and `dashCard`. Both accept an optional `dash` block for labels, card size and options. See [dash-plugin-guide.md](references/dash-plugin-guide.md). **Key rules:** - `id` must be camelCase, matching pattern `^[a-zA-Z][a-zA-Z0-9]*$` - `version` must be semver (e.g., `1.0.0`) - Provide either `component` (single-surface) or `components` (multi-surface), not both - `component` / component paths must start with `./` and end with `.qml` - `type: "launcher"` (or a `components` object with a `launcher` key) requires a `trigger` field - `settings_write` permission is **required** if the plugin has a settings component - `dependencies` replaces the deprecated `requires` field ## Step 3: Create the Main Component ### Widget ```qml import QtQuick import qs.Common import qs.Widgets import qs.Modules.Plugins PluginComponent { property var popoutService: null horizontalBarPill: Component { StyledRect { width: label.implicitWidth + Theme.spacingM * 2 height: parent.widgetThickness radius: Theme.cornerRadius color: Theme.surfaceContainerHigh StyledText { id: label anchors.centerIn: parent text: "Hello" color: Theme.surfaceText font.pixelSize: Theme.fontSizeMedium } } } verticalBarPill: Component { StyledRect { width: parent.widgetThickness height: label.implicitHeight + Theme.spacingM * 2 radius: Theme.cornerRadius color: Theme.surfaceContainerHigh StyledText { id: label anchors.centerIn: parent text: "Hi" color: Theme.surfaceText font.pixelSize: Theme.fontSizeSmall rotation: 90 } } } } ``` See [widget-plugin-guide.md](references/widget-plugin-guide.md) for popouts, CC integration, and advanced features. ### Launcher ```qml import QtQuick import qs.Services Item { id: root property var pluginService: null property string trigger: "#" signal itemsChanged() function getItems(query) { const items = [ { name: "Item One", icon: "material:star", comment: "Description", action: "toast:Hello!", categories: ["MyPlugin"] } ] if (!query) return items const q = query.toLowerCase() return items.filter(i => i.name.toLowerCase().includes(q)) } function executeItem(item) { const [type, ...rest] = item.action.split(":") const data = rest.join(":") if (type === "toast") ToastService?.showInfo(data) else if (type === "copy") Quickshell.execDetached(["dms", "cl", "copy", data]) } } ``` See [launcher-plugin-guide.md](references/launcher-plugin-guide.md) for triggers, icon types, context menus, and image tiles. ### Desktop ```qml import QtQuick import qs.Common Item { id: root property var pluginService: null property string pluginId: "" property bool editMode: false property real widgetWidth: 200 property real widgetHeight: 200 property real minWidth: 150 property real minHeight: 150 Rectangle { anchors.fill: parent radius: Theme.cornerRadius color: Theme.surfaceContainer opacity: 0.85 border.color: root.editMode ? Theme.primary : "transparent" border.width: root.editMode ? 2 : 0 Text { anchors.centerIn: parent text: "Desktop Widget" color: Theme.surfaceText } } } ``` See [desktop-plugin-guide.md](references/desktop-plugin-guide.md) for sizing, persistence, and edit mode. ### Daemon ```qml import QtQuick import qs.Common import qs.Services import qs.Modules.Plugins PluginComponent { property var popoutService: null Connections { target: SessionData function onSomeSignal() { console.log("Event received") } } } ``` See [daemon-plugin-guide.md](references/daemon-plugin-guide.md) for event-driven patterns and process execution. ### Dash Tab ```qml import QtQuick import qs.Common import qs.Widgets import qs.Modules.Plugins import qs.Modules.DankDash DashTabComponent { id: root property date now: new Date() implicitHeight: DashMetrics.tabMinHeight Timer { interval: 1000 repeat: true running: root.live onTriggered: root.now = new Date() } StyledText { anchors.centerIn: parent text: root.now.toLocaleTimeString(I18n.locale()) color: Theme.surfaceText } } ``` ### Dash Card ```qml import QtQuick import qs.Common import qs.Widgets import qs.Modules.Plugins DashCardComponent { id: root tone: options.tone ?? "" StyledText { anchors.centerIn: parent text: I18n.trFor("myPlugin", "Hello") color: root.contentColor } } ``` Gate timers and animations on `live`; the dash content stays alive after the popout closes. Cards must lay out for every size in their manifest range. Use the card colors (`accentColor`, `contentColor`, `mutedColor`) so tones work. See [dash-plugin-guide.md](references/dash-plugin-guide.md). ### Composite For composite plugins, create a separate QML file per surface. Each surface uses the same base component as the corresponding single-surface type (PluginComponent for widget/daemon, Item for launcher, etc.). All surfaces share the same `pluginId` and `pluginService`. ``` MyCompositePlugin/ plugin.json MyBarWidget.qml # PluginComponent (widget surface) MyDaemon.qml # PluginComponent (daemon surface) MyDesktopWidget.qml # Item with desktop widget properties Settings.qml # Shared settings for all surfaces ``` `pluginService.availablePlugins[pluginId].surfaces` lists the surfaces a plugin registered. ## Step 4: Add Startup Check (Optional) Gate plugin activation on dependency checks by providing a `startupCheck` component. This runs before the plugin loads and blocks activation if a required tool or condition is missing. Create a `StartupCheck.qml` (non-visual QtObject): ```qml import QtQuick import qs.Common QtObject { function check(done) { Proc.runCommand("myPlugin.depCheck", ["sh", "-c", "command -v mytool"], (stdout, exitCode) => { if (exitCode === 0) { done(null); return; } done({ "title": I18n.tr("mytool is required"), "details": I18n.tr("Install 'mytool' and re-enable this plugin.") }); }); } } ``` The `done` callback accepts: - `null` - allow activation - A string - block with a short error message - `{ title, details }` - block with a title and expandable details body A synchronous variant (no `done` parameter, return the result directly) is also supported. Failed checks show a toast error and store the error in `pluginService.pluginLoadErrors`. Add to your manifest: ```json { "startupCheck": "./StartupCheck.qml", "dependencies": ["mytool"] } ``` ## Step 5: Add Settings (Optional) Wrap settings in `PluginSettings` with your `pluginId`. All settings auto-save and auto-load. ```qml import QtQuick import qs.Common import qs.Widgets import qs.Modules.Plugins PluginSettings { pluginId: "yourPlugin" StringSetting { settingKey: "apiKey" label: "API Key" description: "Your API key" placeholder: "sk-..." } ToggleSetting { settingKey: "enabled" label: "Enable Feature" defaultValue: true } SelectionSetting { settingKey: "interval" label: "Refresh Interval" options: [ { label: "1 min", value: "60" },
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen