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

6.9 KiB
Raw Permalink Blame History

CLAUDE.md

Guidance for Claude Code (claude.ai/code) when working in this repository.

The v2 rewrite is the load-bearing context here. Read docs/RESTRUCTURE-V2.md first if you're picking the project back up — it captures every design decision (D1D21), the phased plan, and the per-task commit log.

Project shape

Owlry is a single-binary Wayland launcher. Workspace has exactly one member:

crates/owlry/                  -- everything
├── Cargo.toml                 -- one binary + one library, features per provider
├── src/
│   ├── main.rs                -- subcommand router
│   ├── cli.rs                 -- clap definitions
│   ├── lib.rs                 -- module re-exports for integration tests
│   ├── server.rs              -- IPC daemon (bind + accept loop)
│   ├── client.rs              -- IPC client (UI mode)
│   ├── backend.rs             -- SearchBackend abstraction
│   ├── app.rs                 -- GTK4 setup
│   ├── ui/                    -- GTK widgets
│   ├── config/                -- TOML config loader
│   ├── data/                  -- FrecencyStore
│   ├── filter.rs              -- ProviderFilter + prefix parser
│   ├── ipc.rs                 -- Request/Response types
│   ├── paths.rs               -- XDG paths (honours $OWLRY_SOCKET)
│   ├── commands.rs            -- subcommand dispatchers (doctor / providers / config / …)
│   └── providers/             -- ALL providers
│       ├── mod.rs             -- Provider/DynamicProvider traits, ProviderManager
│       ├── application.rs     (feature: app)
│       ├── command.rs         (feature: cmd)
│       ├── calculator.rs      (feature: calc)
│       ├── converter/         (feature: conv)
│       ├── power.rs           (feature: power — pre-v2 name: sys/system)
│       ├── dmenu.rs           (feature: dmenu)
│       ├── clipboard.rs       (feature: clipboard)
│       ├── emoji.rs           (feature: emoji)
│       ├── ssh.rs             (feature: ssh)
│       ├── systemd.rs         (feature: systemd — type_id "uuctl")
│       ├── websearch.rs       (feature: websearch)
│       └── filesearch.rs      (feature: filesearch)

There is no crates/owlry-core, owlry-plugin-api, owlry-lua, or owlry-rune. They were deleted in the v2 demolition. There is no ~/.config/owlry/plugins/ discovery directory and no /usr/lib/owlry/plugins/*.so loading — every "plugin" is a feature-gated module compiled into owlry.

Build & development

# Default features (minimal — app, cmd, calc, conv, power, dmenu)
cargo build

# Full features (matches AUR build)
cargo build --release --features full

# Tests
cargo test --workspace --features full     # 252+ tests
cargo test --workspace --no-default-features

# Verbose dev logging
cargo run -- --features dev-logging -- -d

# Format + lint
cargo fmt --all
cargo clippy --workspace --features full

# Install locally (sudo)
just install-local

The daemon binary is owlry. There is no separate owlryd binary anywhere — the daemon is owlry -d (or owlry daemon). The systemd user unit is owlry.service (pre-2.0 name: owlryd.service).

Running locally without disturbing prod

For side-by-side testing against a production daemon, set $OWLRY_SOCKET:

OWLRY_SOCKET=/tmp/owlry-dev.sock target/release/owlry -d &
OWLRY_SOCKET=/tmp/owlry-dev.sock target/release/owlry -m uuctl
pkill -f 'target/release/owlry -d'

$OWLRY_SOCKET overrides $XDG_RUNTIME_DIR/owlry/owlry.sock for both the daemon (bind path) and the UI client (connect path).

CLI shape

owlry                          UI, auto mode (default)
owlry -m <mode>                UI, single-provider mode
owlry --profile <name>         UI, named profile from config
owlry -p <prompt>              custom prompt text

owlry daemon                   run the daemon (alias: -d)
owlry dmenu [-p <prompt>]      dmenu mode (reads stdin, prints selection)
owlry doctor                   config + socket + providers status
owlry providers [<id>]         list providers (or show one)
owlry config validate          parse config, report errors
owlry config show              print resolved effective config
owlry migrate-config           TOML → init.lua (stub; lands with Lua config)

The owlry plugin ... subcommand tree from 1.x is gone in 2.0. Nothing to install, manage, or run via the CLI.

Provider model

Two traits in src/providers/mod.rs:

  • Provider — static providers (apps, commands, power, bookmarks, clipboard, emoji, ssh, systemd). Populate self.items in refresh(), return &self.items from items(). Optional: prefix(), icon(), tab_label(), search_noun(), position(), priority(), submenu_actions(data), execute_action(command).
  • DynamicProvider — per-keystroke providers (calculator, converter, filesearch, websearch). Generate items in query(text). No refresh/items cache.

ProviderManager::new_with_config is the canonical registration site. Each provider is gated by both a cargo feature (compile-time) and a config flag in [providers] (runtime).

Submenu protocol

A provider returns items whose command field looks like SUBMENU:<type_id>:<data>. When the user selects one, the UI parses out (plugin_id, data), sends a Request::Submenu { plugin_id, data }, and the daemon routes that to Provider::submenu_actions(data) on the matching provider. The systemd provider uses this for service start/stop/restart/enable/disable/status/journal actions.

For now the protocol is string-encoded; a typed redesign is on the roadmap.

v2 naming rules

Old (pre-v2) New (2.0+) Notes
owlryd binary owlry -d Single binary
owlryd.service / owlryd.socket owlry.service / owlry.socket .install hook handles upgrade
:sys / :system / "System" provider :power / "Power" provider :sys and :system kept as aliases
providers.system = true (config) providers.power = true Old key still accepted via serde alias
badge_sys (theme color) badge_power Old key aliased; CSS var --owlry-badge-sys still emitted for transition
Plugin("sys") type_id Plugin("power") type_id CLI mode parsing maps all three to power

Frecency

~/.local/share/owlry/frecency.json. Auto-saved every 5 min by the daemon; flushed on SIGTERM/SIGINT/SIGHUP. Boost weight via providers.frecency_weight (0.0 disabled, 1.0 strong).

When you need to verify behavior live

  1. cargo build --release --features full
  2. OWLRY_SOCKET=/tmp/owlry-dev.sock target/release/owlry -d &
  3. Run smoke queries via socket OR the UI with OWLRY_SOCKET set
  4. pkill -f 'target/release/owlry -d'

Don't fight the prod daemon for the default socket path during testing. The env var exists for exactly this.