Files
vikingowl a7af0e5d46 feat(v2): defer bookmarks provider (D22) — drop rusqlite dep
The bookmarks provider opened Firefox's places.sqlite directly via
rusqlite, which pulled libsqlite3-sys with its bundled feature to
compile sqlite3.c statically. In clean Arch chroots the bundled feature
kept slipping out of the resolved feature graph and the chroot build
failed at link time with every sqlite3_* symbol undefined. Inline
features = ["bundled"] on the optional dep didn't help; neither did
the explicit "rusqlite/bundled" feature wiring (commit 7569b2d).

Rather than fight Cargo's resolver further, defer the bookmarks
provider alongside the widgets per the same pattern (D20 -> D22).
Returns in a later 2.x release with a pure-Rust reader:
- Chromium's Bookmarks file is already JSON.
- Firefox exposes JSON backups under ~/.mozilla/firefox/<profile>/
  bookmarkbackups/<dated>.jsonlz4 — needs lz4 + JSON parse, no SQLite.

Removed:
- crates/owlry/src/providers/bookmarks.rs
- bookmarks module + registration in providers/mod.rs
- bookmarks feature + rusqlite dep in Cargo.toml
- ProvidersConfig.bookmarks field (existing user configs that still
  have 'bookmarks = true' silently ignore it — serde default behavior)
- :bm prefix from README's search-prefix table
- bookmarks acknowledgement in README + ROADMAP roadmap section

Cargo.lock loses rusqlite, libsqlite3-sys, fallible-iterator,
fallible-streaming-iterator, foldhash, hashlink, rsqlite-vfs,
sqlite-wasm-rs (-80 lines).

PKGBUILD: owlry-plugin-bookmarks stays in replaces= (any user who has
it installed still needs a clean upgrade), but moved from the 'folded'
comment block to the 'deferred (D20+)' block.

Docs:
- README: bookmarks removed from optional-providers list, feature
  table, search-prefix table, config example. Added to upcoming
  roadmap section alongside widgets.
- ROADMAP: 'Bookmarks return' subsection added next to 'Widget
  providers return'.
- CLAUDE.md: provider tree updated.
- docs/RESTRUCTURE-V2.md: new decision D22 with chroot-build
  rationale; task #6 plugin count 8 -> 7 -> 6.

245 tests pass with --features full (was 252; the 7 bookmarks unit
tests went with the module). Build verified locally; chroot build
should now succeed since libsqlite3-sys is no longer in the graph
at all.
2026-05-13 03:13:16 +02:00

5.2 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 (Phase 3)

Replace config.toml with ~/.config/owlry/init.lua. The config is real Lua, evaluated at startup via embedded mlua (Lua 5.4). User-defined providers, keybindings, and theme overrides all live in the same file — Hyprland-style configs-as-code. Ships with owlry migrate-config (TOML → init.lua) and hot-reload on save.

local owlry = require("owlry")

owlry.set { theme = "owl", width = 850, tabs = { "app", "cmd", "uuctl" } }
owlry.providers { "app", "cmd", "power", "bookmarks", "systemd" }

owlry.provider {
  id = "hs", prefix = ":hs", tab_label = "Shutdown",
  items = function() return { { name = "Lock", command = "hyprlock" } } end,
}

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.