Documentation, example config, and one validator-test fix. Version bump and AUR push intentionally deferred. data/owlry.example.lua (new): - Annotated reference config exercising every surface (set / providers / tabs / theme / profiles / provider / util). Active section is minimal and validates clean. aur/owlry/PKGBUILD: - Ships data/owlry.example.lua to /usr/share/doc/owlry/owlry.example.lua. pkgver kept at 2.0.1. README.md: - Config table puts owlry.lua first (preferred from 2.1), config.toml marked legacy/fallback with precedence note linking lua-api.md §2. - New "Quick Start (Lua config)" section with migrate-config blurb. - migrate-config row: [--force], deterministic. config validate row: exit 1 errors / exit 2 warnings. - Roadmap section flips Lua config from "lands in 2.1/3.0" to "shipped in 2.1"; lists 2.2 follow-ups (dynamic providers, owlry.bind, util.http_get). CLAUDE.md: - Project shape tree expands lua/ module with per-file descriptions. - Build section documents the `lua` cargo feature. - CLI shape line for migrate-config: [--force]. config validate: exit codes 1/2 mentioned. - New "Lua config layer (2.1+)" section covers precedence, the notify-based watcher, desktop-notification errors, and the Arc<Lua> / LoadedConfig invariants. data/owlry.1: - --profile mentions both owlry.profiles (lua) and [profiles.<NAME>] (toml). - config validate paragraph describes the categorised report and lists 0/1/2 exit codes. - migrate-config description no longer says "stub" — covers determinism, --force/-f, pre-v2 alias normalisation, links §9. - FILES adds ~/.config/owlry/owlry.lua and the example .lua; config.toml labelled legacy. ROADMAP.md: - "Lua-driven configuration" reworded as shipped in 2.1; example uses owlry.lua and the v2 API; 2.2 follow-ups listed. cli.rs help: migrate-config stub-era text → "TOML → owlry.lua (--force to overwrite)". lua/validate.rs: loosen pre_v2_aliases_are_known to assert only that aliases aren't flagged as unknown ids. is_clean() failed under --no-default-features --features lua because uuctl correctly triggered the compiled-out warning (uuctl → systemd, systemd feature off → silently dropped at runtime). Test matrix (all green): - --features full 352 lib tests - --no-default-features 182 lib tests - --no-default-features --features lua 305 lib tests Clippy silent in all three configurations. Smoke (release build, isolated XDG): 1. config validate on the shipped owlry.example.lua → OK exit 0 2. migrate-config: TOML → owlry.lua with the precedence notice 3. Daemon loads, watcher armed; appending owlry.provider triggers hot-reload within the debounce window 4. :phase310 prefix routes the empty query to the new provider 5. config validate against the live file still OK
5.8 KiB
Owlry Roadmap
Feature ideas and future development plans. For the v2 rewrite story (where 14 packages and the dynamic plugin system went), see docs/RESTRUCTURE-V2.md.
Locked-in for an upcoming 2.x release
Lua-driven configuration — shipped in 2.1
~/.config/owlry/owlry.lua is the canonical config from 2.1 onwards (TOML stays supported as a back-compat fallback until 3.0). Real Lua 5.4 via vendored mlua. The full surface is documented in docs/lua-api.md:
owlry.set/owlry.providers/owlry.tabs/owlry.theme/owlry.profilesfor declarative configowlry.provider {}for user-defined providers (Hyprland-style configs-as-code)owlry.util.{shell, shell_lines, read_file, glob, env, hostname}host helpers inside provider callbacks- Hot reload on save via the
notifycrate — broken edits surface as desktop notifications and keep the previous state live owlry migrate-config [--force]— deterministic TOML → Lua migrationowlry config validate— categorised report (errors exit 1, warnings exit 2)
owlry.set { theme = "owl", width = 850 }
owlry.providers { "app", "cmd", "power", "systemd" }
owlry.tabs { "app", "cmd", "uuctl" }
owlry.provider {
id = "hs", prefix = ":hs", tab_label = "Shutdown",
items = function() return { { name = "Lock", command = "hyprlock" } } end,
}
2.2 follow-ups: dynamic (per-keystroke) Lua providers via dynamic = true; owlry.bind for runtime keybindings; owlry.util.http_get.
Widget providers return
Weather, MPRIS media controls, and pomodoro timer were deferred from 2.0 while the widget-row UI is redesigned. They'll come back as a feature group once the placement model is settled. (D20 in the v2 plan.)
Bookmarks return
Firefox + Chromium bookmarks were deferred from 2.0 — the rusqlite dep used to read Firefox's places.sqlite made the AUR chroot build brittle (libsqlite3-sys's bundled feature kept slipping out of the resolved feature graph). Returns when we wire up a pure-Rust path: Chromium's bookmarks file is already JSON, and Firefox exposes JSON backups under ~/.mozilla/firefox/<profile>/bookmarkbackups/. No SQLite required.
High Value, Low Effort
Frecency pruning
Add max_entries and max_age_days config options. Prune old entries on startup to prevent frecency.json from growing unbounded.
:recent prefix
Show last N launched items. Data already exists in frecency.json — just needs a provider to surface it.
Clipboard images
cliphist supports images. Extend the clipboard provider to show image thumbnails in results.
Dynamic providers in owlry doctor
Today doctor lists static providers only. Surface the dynamic ones (calc, conv, websearch, filesearch) too.
Medium Effort, High Value
Actions on any result
Generalize the submenu system beyond systemd. Every result type gets contextual actions:
| Provider | Actions |
|---|---|
| Applications | Open, Open in terminal, Show .desktop location |
| Files | Open, Open folder, Copy path, Delete |
| SSH | Connect, Copy hostname, Edit config |
| Bookmarks | Open, Copy URL, Open incognito |
| Clipboard | Paste, Delete from history |
This is the difference between a launcher and a command palette. The Provider::submenu_actions() trait method (added in 2.0 for the systemd provider) is the foundation.
Result action capture
Calculator shows = 5+3 → 8. Allow pressing Tab or Ctrl+C to copy the result to clipboard instead of launching. Useful for calculator output, file paths, URLs.
Split the 1000+ LOC files
providers/mod.rs, ui/main_window.rs, providers/converter/units.rs are all over a thousand lines each. Carve them into focused modules to make code review and onboarding less painful. (Phase 5 hygiene in the v2 plan.)
Bigger Bets
Window switcher with live thumbnails
A windows provider using Wayland screencopy to show live thumbnails of open windows. Hyprland and Sway expose window lists via IPC. Could replace Alt+Tab.
Cross-device bookmark sync
Firefox and Chrome sync bookmarks across devices. Parse sync metadata to show "recently added on other devices".
Natural language commands
Parse simple natural language into system commands:
"shutdown in 30 minutes" → systemd-run --user --on-active=30m systemctl poweroff
"remind me in 1 hour" → notify-send scheduled via at/systemd timer
"volume 50%" → wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.5
Local pattern matching, no cloud required.
Drop the daemon
After Lua config lands and we profile startup honestly: if the daemon's keep-providers-warm justification doesn't hold up against an mmap'd cache, collapse to a single-process model. Eliminates the socket protocol, IPC types, and most of client.rs + server.rs. (D17 deferred this decision past 2.0.)
Technical Debt
expr-solver-lib evaluation
The calculator's expr-solver-lib dep is small and old. If it stagnates further or becomes unsupported, switch to evalexpr v13+ which is actively maintained.
Submenu protocol redesign
The SUBMENU:<plugin_id>:<data> string-encoded command is a workable hack. A typed IPC variant would be cleaner — keep the surface in Request::Submenu but stop overloading the command field. (Phase 5 hygiene.)
Double-daemon spawn
Pre-2.0, the systemd unit and a Hyprland exec-once = owlryd could both spawn a daemon. The 2.0 socket-activation path (owlry.socket) eliminates the need for an explicit autostart — verify nothing else still launches the daemon directly. (Phase 5 hygiene.)
Priority
If we had to pick one for the next release: Actions on any result. It transforms every provider from "search and launch" to "search and do anything". The ROI is massive and the trait foundation is already in 2.0.