Plugins that run in the compositor.
Native effect plugins change how LunaDash animates, places and lays out windows. Create one with the generator, build it with the CMake SDK and enable it through the control API.
What a plugin is
A plugin is an effect: a shared library loaded into the compositor. For its target feature LunaDash sends a JSON request with the built-in result, and the plugin answers with a complete replacement (replace) or an adjusted result (augment). Each target accepts one enabled plugin. The shell's look is changed in the shell itself, not through plugins.
Plugins are trusted native code. Metadata and ABI checks are compatibility checks, not signing or a sandbox; a crash or hang takes down the compositor. Plugins stay disabled until you enable them.
Create, build and install
lunadash-create-plugin --list
lunadash-create-plugin --target window-layout --id org.example.layout --output my-layoutIds match ^[A-Za-z0-9][A-Za-z0-9._-]+$; the generator needs a new output directory.
cmake_minimum_required(VERSION 3.21)
project(MyLunaDashPlugin LANGUAGES C CXX)
find_package(LunaDashPlugin 2 CONFIG REQUIRED)
lunadash_add_plugin(my_plugin
METADATA "metadata.json"
SOURCES Effect.cpp
)cmake -S . -B build -G Ninja -DCMAKE_INSTALL_PREFIX="$HOME/.local"
cmake --build build
cmake --install buildmetadata.json
{
"schemaVersion":2,
"sdk":{"name":"LunaDash","apiVersion":2},
"id":"org.example.layout","name":"Example layout","version":"1.0.0",
"author":{"name":"Your name"},
"type":"effect","target":"window-layout","mode":"replace","entry":"libmy_plugin.so",
"enabledByDefault":false,
"settings":{"gap":{"type":"integer","default":12,"control":"slider","minimum":0,"maximum":64}}
}A package can declare up to 16 implementations in targets, sharing one .so. "windowTemplate":"stacking" on a window-layout replacement selects the overlapping, freely movable window policy.
Targets
| Target | Response | Validation |
|---|---|---|
| window-animation | duration, enterOffset, focusOpacity, exitScale, easing | A complete animation profile; turning animations off in Settings still wins. |
| shell-animation | { duration } | One duration from 0 to 600 ms for shell transitions. |
| window-rules | { workspace, maximized } | The rule for a new ordinary window; the workspace must exist. |
| window-layout | { windows:[{id,x,y,width,height},...] } | Every non-minimized id once, positive sizes, inside the work area; overlap only when the template allows it. |
The contract
The SDK generates the exported ludash_plugin_entry_v2; you implement ludash_plugin_process(request, response, capacity) and return the UTF-8 JSON length (without the NUL) or a negative value. Hooks run on the compositor thread: never block, keep host pointers or start work that outlives the call.
{
"target":"window-layout","mode":"replace",
"context":{"workspace":0,"area":{"x":0,"y":40,"width":1920,"height":1040},"newWindows":[23],"windowTemplate":"tiling","allowOverlap":false},
"builtin":{"windows":[...]},"current":{},"settings":{"gap":12}
}builtin is always present; augment also receives the previous valid result in current. Return a complete object. Invalid output keeps the previous valid result and quarantines the plugin.
Plugin settings
Settings use toggle (boolean), select (enum), number and slider (bounded) controls; every field needs a type and a default.
"settings":{
"glow":{"type":"boolean","default":true,"control":"toggle"},
"quality":{"type":"string","default":"medium","control":"select","enum":["low","medium","high"]},
"strength":{"type":"number","default":0.5,"control":"slider","minimum":0,"maximum":1}
}Install and enable
An SDK-built package is found under lunadash/plugins/<id> in the XDG data directories, normally ~/.local/share/lunadash/plugins/<id>; the SDK's .lunadash-sdk.json receipt must match the metadata. Enable it in ~/.config/LuDash/extensions.json through the control API:
lunadashctl extension-save '{"schemaVersion":1,"builtins":{},"plugins":{"org.example.layout":{"enabled":true,"mode":"replace","settings":{"gap":16}}}}'Disable a plugin before replacing its library, install the new build, then enable it again.
Debug checklist
- Check the target with
lunadash-create-plugin --list. - Rebuild with LunaDashPlugin 2 after editing the metadata.
- Read
lunadashctl status→extensions.installedfor the status, error and settings. - After fixing, clear the error with an empty
extension-errorrequest.