OpenLogi Rust Workspace Structure: A 23-Crate Agent-Centric Architecture
OpenLogi organizes its codebase as a multi-crate Rust workspace containing 23 member crates that separate hardware I/O, UI rendering, and business logic, with all peripheral communication centralized in a background agent process.
OpenLogi is an open-source alternative to Logitech Options+ implemented in Rust. The AprilNEA/OpenLogi repository uses a meticulously structured workspace defined in the root Cargo.toml to enable cross-platform device management while enforcing strict architectural boundaries between input hooks, HID++ protocols, and interface layers.
Workspace Composition and Crate Responsibilities
The workspace resolver declares 23 member crates sharing a unified version (0.8.3), Rust edition (2024), and MSRV (1.98). This ensures consistent dependency resolution across all components.
Core Infrastructure Crates
crates/openlogi-core: Houses the pure data layer, including TOML configuration parsing, device models, action catalogs, and locale handling. This crate performs no I/O operations.crates/openlogi-ipc: Defines the tarpc IPC contract insrc/ipc.rsand implements local-socket transport using an append-only, versioned wire format.crates/openlogi-permissions: Provides read-only privacy-permission status and system-settings deep links for macOS TCC and Linux device probes.
Hardware Abstraction Layer
crates/openlogi-device: Implements HID++ device abstraction, including enumeration, probing, writes, and sessions. It relies on theHidBackendtrait to remain platform-agnostic.crates/openlogi-hid: Contains host-specific HID++ transport logic using async-hid, macOS Input Monitoring permissions, and probe caching.crates/openlogi-hidpp: A fork of thehidppprotocol crate exposing thehidpplibrary name.crates/openlogi-hidpp-derive: A private procedural macro crate that generates HID++-specific boilerplate.crates/openlogi-device-registry: Maintains a static database of device identities, receiver protocols, and driver metadata.
Input Capture and Injection
crates/openlogi-hook: Handles OS input capture using macOS CGEventTap, Linux evdev with uinput, and Windows WH_MOUSE_LL.crates/openlogi-inject: Manages OS input synthesis via macOS CGEvent, Linux uinput with MPRIS, and Windows SendInput.
Agent and Orchestration
crates/openlogi-agent: The long-running background binary that owns all HID and input I/O. According tocrates/openlogi-agent/src/main.rs, this process initializes the input hook and HID transport, creating a single source of truth for device state.crates/openlogi-agent-core: Shared orchestration logic for the hook runtime, HID++ writes, DPI cycles, and Actions-Ring state management.
User Interface and Client Crates
crates/openlogi-desktop: The GPUI-based desktop client that polls the agent and renders the main settings window. As implemented incrates/openlogi-desktop/src/main.rs, this binary never touches hardware directly.crates/openlogi-overlay: A minimal IPC client that draws the cursor-centered Actions Ring overlay. It functions as a pure IPC client communicating with the agent.crates/openlogi-ui: Shared UI components, ring geometry, icons, and GPUI asset sources used by both the desktop app and overlay.crates/openlogi-assets: Device-render registry and cached asset fetcher for hardware-specific images and icons.crates/openlogi-camera: Cross-platform Logitech UVC camera enumeration, capture, and control APIs.
CLI and Entry Points
crates/openlogi: The thin CLI entry point that wrapsopenlogi-clifunctionality.crates/openlogi-cli: Dispatches sub-commands, preferring an agent snapshot when available, otherwise falling back to direct hardware operations viaopenlogi-device.crates/openlogi-fixture: Host-free fixture schemas and synthetic identity policies for testing.
Build and Automation
xtask: A build-time helper invoked viacargo xtaskthat handles bundling, packaging, and release manifest generation, defined inxtask/src/main.rs.
Agent-Centric Architecture Design
The OpenLogi Rust workspace structure enforces a strict agent-centric pattern where only the openlogi-agent binary accesses hardware directly. The architectural documents in AGENTS.md specify that GUI applications (openlogi-desktop) and overlay components (openlogi-overlay) function as pure IPC clients.
This design centralizes device state management and input hook ownership within a single persistent process, preventing resource contention and permission conflicts. The agent exposes a typed interface through the tarpc protocol defined in crates/openlogi-ipc/src/ipc.rs, allowing client crates to request operations without linking against platform-specific HID libraries.
Inter-Process Communication Design
All inter-process communication uses the tarpc protocol transported over local sockets via the interprocess crate. The IPC contract lives in crates/openlogi-ipc/src/ipc.rs and features a versioned, append-only wire format that maintains backward compatibility.
Platform-specific code remains gated behind #[cfg(target_os = …)] attributes within each crate, keeping core logic OS-agnostic. The FFI contracts for macOS specifically reside in .claude/rules/objc-ffi.md, while runtime adaptations handle Linux and Windows specifics within their respective transport layers.
Runtime Execution Flow
Understanding the OpenLogi workspace requires following the data flow across crate boundaries at runtime:
-
Agent Startup: The
openlogi-agentbinary launches fromcrates/openlogi-agent/src/main.rs, creates a local socket, and initializes the input hook (openlogi-hook) and HID transport (openlogi-hid). -
Device Discovery: The
openlogi-devicecrate enumerates HID++ devices via the transport layer, populating theopenlogi-device-registrywith static metadata. -
Configuration Loading:
openlogi-coreparses the user's TOML configuration (referenced indocs/CONFIGURATION.md) and builds an in-memory action catalog mapping button presses to system commands. -
Client Connection: The desktop client and overlay connect to the agent's socket, exchanging typed messages defined in the IPC contract.
-
Input Handling: Events captured by
openlogi-hooktranslate into actions (button remap, DPI changes, SmartShift toggles) and route to the agent, which writes to devices via the HID++ layer inopenlogi-hidpp. -
Rendering:
openlogi-desktoprenders settings and device status, whileopenlogi-overlaydraws the context-sensitive Actions Ring under the cursor.
Development and Build Tooling
Developers interact with the workspace using standard Cargo commands targeting specific crates:
# Launch the desktop GUI (automatically spawns agent if needed)
cargo run -p openlogi-desktop
The CLI provides direct hardware access when the agent is unavailable:
# List connected devices via CLI
openlogi list
# Set DPI through the agent IPC channel
openlogi dpi set 1600
Configuration changes require editing the TOML schema processed by openlogi-core:
[button_remap."Button 4"]
short_press = "LaunchApp { command = \"firefox\" }"
The xtask crate automates release workflows:
# Execute build automation
cargo xtask bundle-release
Summary
- The OpenLogi workspace comprises 23 member crates with a unified version
0.8.3and Rust edition2024. - Agent-centric architecture isolates all hardware I/O within the
openlogi-agentcrate, while GUI and overlay clients communicate exclusively via IPC. - Tarpc-based IPC in
crates/openlogi-ipc/src/ipc.rsprovides type-safe communication over local sockets with versioned wire formats. - Platform abstraction occurs through trait-based backends (
HidBackend) and conditional compilation, keepingopenlogi-corefree of I/O code. - Clear separation exists between input capture (
openlogi-hook), input synthesis (openlogi-inject), device protocols (openlogi-hidpp), and user interfaces (openlogi-desktop/openlogi-overlay).
Frequently Asked Questions
What is the role of the openlogi-agent crate?
The openlogi-agent crate contains the long-running background process that owns all hardware interactions, including input hooks and HID++ communication. As defined in crates/openlogi-agent/src/main.rs, it initializes the transport layers and exposes device state to GUI clients through the IPC interface, ensuring only one process requires elevated permissions for input monitoring.
How do the GUI and overlay communicate with Logitech devices?
Neither openlogi-desktop nor openlogi-overlay communicate directly with hardware. Instead, they function as pure IPC clients that send requests over a local socket to the agent process using the tarpc protocol defined in crates/openlogi-ipc/src/ipc.rs. The agent handles all HID++ writes and input injection, then returns status updates to the UI components.
Why is the workspace split into so many separate crates?
The 23-crate structure enforces strict dependency boundaries and enables selective compilation. For example, openlogi-core contains only pure data structures and parses TOML configs without async runtimes, while openlogi-hid contains platform-specific async transport code. This separation allows the CLI to function without linking GPUI dependencies and ensures the agent can run headless without UI assets.
Where is platform-specific code handled in the OpenLogi workspace?
Platform-specific implementations use #[cfg(target_os = …)] gates within their respective crates rather than separate directories. The openlogi-hid crate handles macOS Input Monitoring permissions and probe caching, openlogi-hook implements CGEventTap for macOS, evdev for Linux, and WH_MOUSE_LL for Windows, and macOS FFI contracts specifically reside in .claude/rules/objc-ffi.md.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →