.so files. A plugin does not draw pixels. It emits Surface Description nodes through a small C ABI, and the host renders them.
User-facing install, enable toggles, and the example plugins: Plugins. This page is the write-your-own side.
otter-shell already ships otter-shell-plugins (examples) and otter-plugin-factory (opf). You can also install them on their own:
Layout and discovery
Packed plugins look like this:OTTER_PLUGIN_PATH(colon-separated roots)$XDG_DATA_HOME/otter-shell/plugins~/.local/share/otter-shell/plugins/usr/lib/otter-shell/plugins/usr/share/otter-shell/plugins
plugin:<id>. The bare id lives in plugin.conf.
Enable gates live in ~/.config/otter-shell/plugins.conf as <id>_enabled = true|false. Hosts read that file before dlopen. Most plugins treat a missing key as enabled. The packaged snippet-provider is opt-in and defaults to disabled. Per-plugin files under ~/.config/otter-shell/plugins/<id>.conf are reserved for schemas with provides_settings = true. That settings UI is not in yet.
Manifest (plugin.conf)
Factory CLI (opf)
otter-plugin-factory is a separate package from the examples. After install, opf is on PATH. From a checkout, put bin/ on PATH instead.
zig-out/plugins/<id>/ into ~/.local/share/otter-shell/plugins/ or set OTTER_PLUGIN_PATH. Factory docs/publishing.md covers the examples-package layout.
ABI v1
Plugins export C symbols. Zig plugins can@import a mirrored otter_plugin_abi module. ABI major is OTTER_PLUGIN_ABI_VERSION (1).
Required exports:
Bar, when
provides_bar_widget is true:
otter_plugin_bar_attachreturns anOtterPluginBarInstancewith a vtable- Vtable:
preferred_width,contribute,destroy, optionalon_event
otter_plugin_launcher_query/otter_plugin_launcher_activate- Optional
otter_plugin_launcher_contribute_rowfor custom SD rows
sd_rect/sd_label/sd_hit_button- Optional
sd_text_inputfor IME-backed fields. Null-check on older hosts. request_frame,log
BarVTable.on_event can receive click, hover, focus/blur, and text-input (buffer/preedit flags).
Headers and Zig mirrors live in otter-bar, otter-launcher, and otter-shell-plugins (include/otter_plugin_abi.h, abi/abi.zig).
Examples in otter-shell-plugins
hello-label
Smallest SD chip that gets a real click from the host:bar_input_dispatch to the plugin slot to BarVTable.on_event(CLICK).
Left click toggles the label text (Hello / Clicked) and background tint, then calls host.request_frame. No side-channel file.
bar-search
Bar text field using hostsd_text_input with Wayland text-input-v3. Focus the field, type, and confirm IME preedit/commit. Escape blurs. $XDG_RUNTIME_DIR/otter-bar-search is fallback only on old hosts.
Local development
otter-bar’s zig build -Doptimize=ReleaseFast plugin-abi-smoke -- <so>.
Trust
Installed.so plugins are fully trusted and share the host process. Ship examples through otter-shell-plugins, or load plugins you built yourself.
Related repos
- otter-shell-plugins: examples package source
- otter-plugin-factory:
opfCLI and agent skills - otter-zenith: Debian packaging
- otter-bar / otter-launcher: host runtimes

