# DMS Plugin Cheat Sheets These are deliberately condensed surfaces. For full details and current property lists, read the official plugin-development guide for the exact DMS version in use. ## plugin.json — Fields That Actually Matter Required for all: - `id` (camelCase, unique, used for reload and data keys) - `name`, `description`, `version`, `author` - `type`: "widget" | "launcher" | "daemon" | "desktop" - `component`: relative path to the root QML file Strongly recommended: - `icon` (Material icon name shown in the Plugins list) - `permissions`: array — `"settings_write"` is required if you provide a settings component using `PluginSettings` - `capabilities`: helps the UI know where to offer the plugin (e.g. `["dankbar-widget"]`, `["control-center"]`, `["desktop-widget"]`, `["launcher"]`) - `settings`: relative path to the settings QML (only if you want a UI in Settings → Plugins) Launcher-specific: - `trigger`: the prefix string (or `""` for always-visible) - `viewMode`: "list" | "grid" | "tile" - `viewModeEnforced`: boolean Desktop-specific: - `requires_dms`: e.g. `">=1.2.0"` `requires` (array of external tools) is used for documentation and install hints. ## PluginComponent (the base for almost every widget) Auto-injected (never declare these yourself): - `pluginData` — reactive object containing everything saved via the settings system for this plugin - `pluginService` - `pluginId` - `axis`, `section`, `parentScreen`, `widgetThickness`, `barThickness`, `iconSize`, `variants` You define: - `horizontalBarPill: Component { ... }` - `verticalBarPill: Component { ... }` (can be the same or different layout) - `popoutContent: Component { PopoutComponent { ... } }` (optional but very common) - `popoutWidth`, `popoutHeight` - `layerNamespacePlugin: "unique-name"` (strongly recommended for any popout widget) - `pillClickAction` / `pillRightClickAction` (to override the default popout behavior) For Control Center presence, also define: - `ccWidgetIcon`, `ccWidgetPrimaryText`, `ccWidgetSecondaryText`, `ccWidgetIsActive` - `onCcWidgetToggled` - `ccDetailContent` (for the expandable detail panel on CompoundPill) ## PopoutComponent Convenience wrapper that gives you a consistent header + details area + `closePopout()` function. Expose `headerHeight` and `detailsHeight` so your content can compute the remaining space correctly. ## PluginService Data APIs (three different stores) 1. **Settings** (`savePluginData` / `loadPluginData`) - Persisted in the shared `plugin_settings.json` - Shown/edited via the `*Setting` components inside `PluginSettings` - Use for user preferences 2. **State** (`savePluginState` / `loadPluginState`) - Per-plugin `_state.json` file in `~/.local/state/DankMaterialShell/plugins/` - Not shown in settings UI - Good for command history, recent items, runtime caches that should survive reloads 3. **Global Variables** (`getGlobalVar` / `setGlobalVar` + `PluginGlobalVar` helper) - In-memory, reactive across **all instances** of the same plugin - Not persisted - Perfect for "current selection", counters, shared UI state on multi-monitor bars The modern settings UI components (`StringSetting`, `ToggleSetting`, `ColorSetting`, `SliderSetting`, `SelectionSetting`, `ListSettingWithInput`, etc.) live inside a `PluginSettings { pluginId: "..." }` root and handle load/save automatically. ## Launcher Plugin Shape (different from widgets) Root must be a `QtObject { id: root ... }` You must provide (at minimum): - `getItems(query)` → array of item objects - `executeItem(item)` Optional but powerful: - `getContextMenuActions(item)` → array of `{icon, text, action, closeLauncher?}` - `getCategories()` + `setCategory(id)` - `getPasteText(item)` and/or `getPasteArgs(item)` for Shift+Enter paste support Item shape includes `name`, `icon` (or `unicode:...`), `comment`, `action`, `imageUrl`, `animated`, `attribution`, `categories`, `keywords`. Call `pluginService.requestLauncherUpdate(pluginId)` after async data arrives. ## External Commands Prefer `Proc.runCommand(id, argv, (stdout, exitCode) => {...}, debounceMs)` from `qs.Common`. It gives you captured stdout, automatic cleanup, and debouncing by id. Only fall back to a raw `Process` item when you truly need a long-lived or streaming process. ## Desktop Widgets (DesktopPluginComponent) - Set `minWidth` / `minHeight` (and optionally `defaultWidth` / `defaultHeight`, `forceSquare`) - Read `widgetWidth`, `widgetHeight`, `pluginData` - Use the helper methods `getData(key, default)` and `setData(key, value)` if you want the thin wrappers - Position/size is persisted automatically per screen - User interaction: right-click-drag anywhere to move, right-click-drag bottom-right corner to resize ## Permissions (the one that bites agents) If your plugin has a `settings` component that uses `PluginSettings`, you **must** list `"settings_write"` in the `permissions` array. Without it the settings UI will show an error instead of your form. Other permissions (`settings_read`, `process`, `network`) are declared for documentation and future enforcement. ## Layer Namespaces for Popouts On any `PluginComponent` that opens a popout: ```qml layerNamespacePlugin: "my-unique-popout" ``` This gives the popout its own layer namespace under `dms:plugins:...` and avoids focus/z-order fights with other DMS popouts. ## Hot Reload & Debugging - `dms ipc call plugins reload ` - `dms ipc call plugins list` - `dms ipc call plugins status ` - Run the shell from a terminal (`dms run` or equivalent) so you see QML errors and `console.log` ## Theme, Toast, I18n Always go through the singletons: - `Theme.*` for colors, spacing, font sizes, corner radii - `ToastService.showInfo(...)` / `showError(...)` - `I18n.tr("text", "context for translators")` Never hard-code colors or sizes. This is enough to get 80% of plugins correct on the first serious attempt. For the remaining 20%, go to the official development guide for the exact property lists and edge cases.