6.7 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Overview
Official native plugins for the Owlry application launcher. Each plugin is compiled as a shared library (.so) and loaded by the owlry-core daemon at runtime via the ABI-stable plugin interface.
Build & Development Commands
just build # Debug build (all plugins)
just release # Release build (all plugins, LTO + stripped)
just plugin <name> # Build specific plugin release (e.g., just plugin calculator)
just plugins # Alias for release build of all plugins
just check # cargo check + clippy
just test # Run tests
just fmt # Format code
just show-versions # List all plugin crate versions
just install-local # Build release + install all .so to /usr/lib/owlry/plugins/
# Build a specific plugin manually
cargo build -p owlry-plugin-calculator --release
# Output: target/release/libowlry_plugin_calculator.so
# Bump versions
just bump-crate owlry-plugin-weather 0.5.0 # Bump specific plugin
just bump-all 0.5.0 # Bump all plugins
# Tagging convention: every changed crate gets its own tag
# Format: {crate-name}-v{version}
# Examples:
# owlry-plugin-bookmarks-v1.0.1
# owlry-plugin-calculator-v1.0.1
#
# IMPORTANT: After bumping, tag EVERY changed plugin crate individually.
# Unchanged plugins don't need new tags.
#
# Plugin API dependency uses a git tag from the core repo:
# owlry-plugin-api = { git = "...", tag = "plugin-api-v1.0.1" }
# Update this tag reference when the core repo bumps plugin-api.
Workspace Structure
owlry-plugins/
├── Cargo.toml # Workspace root
├── crates/
│ ├── owlry-plugin-bookmarks/ # Firefox/Chrome bookmarks
│ ├── owlry-plugin-calculator/ # Math expression evaluation
│ ├── owlry-plugin-clipboard/ # Clipboard history (cliphist)
│ ├── owlry-plugin-emoji/ # Emoji picker
│ ├── owlry-plugin-filesearch/ # File search (fd/mlocate)
│ ├── owlry-plugin-media/ # Media player controls (widget)
│ ├── owlry-plugin-pomodoro/ # Pomodoro timer (widget)
│ ├── owlry-plugin-scripts/ # User script runner
│ ├── owlry-plugin-ssh/ # SSH host picker
│ ├── owlry-plugin-system/ # System actions (shutdown, reboot, etc.)
│ ├── owlry-plugin-systemd/ # systemd user unit control
│ ├── owlry-plugin-weather/ # Weather display (widget)
│ └── owlry-plugin-websearch/ # Web search providers
├── aur/ # AUR PKGBUILDs for all plugins + meta-packages
└── docs/ # Plugin development documentation
Plugin API Dependency
All plugins depend on owlry-plugin-api from the core repo. Currently referenced as a local path (for development), will be a git dependency for releases:
# In each plugin's Cargo.toml
[dependencies]
owlry-plugin-api = { path = "/path/to/owlry/crates/owlry-plugin-api" }
Each plugin crate is compiled as cdylib:
[lib]
crate-type = ["cdylib"]
Plugin Architecture
Every plugin exports a single C-ABI function:
#[no_mangle]
pub extern "C" fn owlry_plugin_vtable() -> &'static PluginVTable
The PluginVTable provides function pointers for:
info()- Plugin metadata (name, version, description)providers()- List of providers the plugin offers (id, name, prefix, icon, position, priority)provider_init(id)- Initialize a provider instanceprovider_refresh(handle)- Populate/reload items (static providers)provider_query(handle, query)- Search items (dynamic providers)provider_drop(handle)- Clean up provider instance
All types cross the ABI boundary using abi_stable crate types (RVec, RStr, RString, etc.).
Provider Categories
| Category | Plugins | Behavior |
|---|---|---|
| Static | bookmarks, clipboard, emoji, scripts, ssh, system, systemd | refresh() populates items at startup; query() filters them |
| Dynamic | calculator, websearch, filesearch | query() generates results per keystroke |
| Widget | weather, media, pomodoro | Displayed at top of results via position: Widget |
Submenu System
Plugins can return items with SUBMENU:plugin_id:data as the command. When the user selects such an item, the daemon calls provider_query(handle, "?SUBMENU:data") to get contextual action items (e.g., systemd service start/stop/restart).
Adding a New Plugin
- Create crate:
cargo init --lib crates/owlry-plugin-myplugin - Set
crate-type = ["cdylib"]in Cargo.toml - Add
owlry-plugin-apiandabi_stabledependencies - Implement
owlry_plugin_vtable()returning a staticPluginVTable - Add the crate to workspace members in root
Cargo.toml - Register the provider ID prefix in the core repo's
ProviderFilterif desired
See docs/PLUGIN_DEVELOPMENT.md for detailed guidance.
AUR Packaging
The aur/ directory contains PKGBUILDs for:
| Category | Packages |
|---|---|
| Plugins (13) | owlry-plugin-{bookmarks,calculator,clipboard,emoji,filesearch,media,pomodoro,scripts,ssh,system,systemd,weather,websearch} |
| Meta-bundles | owlry-meta-essentials, owlry-meta-widgets, owlry-meta-tools, owlry-meta-full |
Plugin .so files are installed to /usr/lib/owlry/plugins/ with consistent naming: libowlry_plugin_*.so.
All plugin PKGBUILDs include .install files that clean up old plugin files on upgrade.
Testing
# Run all plugin tests
just test
# Test a specific plugin
cargo test -p owlry-plugin-calculator
Most plugins are tested via their query() and refresh() implementations. The owlry-plugin-api crate provides the types needed for test assertions.
External Dependencies
Some plugins require external tools at runtime:
| Plugin | Dependencies |
|---|---|
| clipboard | cliphist, wl-clipboard |
| filesearch | fd or mlocate |
| emoji | wl-clipboard, noto-fonts-emoji |
| systemd | systemd (user services) |
| bookmarks | None (bundled SQLite via rusqlite) |
| media | D-Bus (MPRIS) |
| websearch | xdg-open or configured browser |
Key Patterns
- All plugins are
cdylibcrates producing.sofiles - ABI stability via
abi_stablecrate - never break the vtable contract - Plugin API v3:
ProviderInfoincludesposition(Normal/Widget) andpriorityfields - Plugins have independent versions from the core (currently 0.4.x)
- No direct dependency on GTK or UI code - plugins are pure data providers