# OpenLogi Rust Workspace Structure: A 23-Crate Agent-Centric Architecture

> Explore the OpenLogi Rust workspace structure. Discover how its 23 crates and agent-centric design streamline hardware I/O, UI, and business logic for efficient development.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: architecture
- Published: 2026-09-10

---

**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`](https://github.com/AprilNEA/OpenLogi/blob/main/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 in [`src/ipc.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/src/ipc.rs) and 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 the `HidBackend` trait 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 the `hidpp` protocol crate exposing the `hidpp` library 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 to [`crates/openlogi-agent/src/main.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/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 in [`crates/openlogi-desktop/src/main.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/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 wraps `openlogi-cli` functionality.
- **`crates/openlogi-cli`**: Dispatches sub-commands, preferring an agent snapshot when available, otherwise falling back to direct hardware operations via `openlogi-device`.
- **`crates/openlogi-fixture`**: Host-free fixture schemas and synthetic identity policies for testing.

### Build and Automation

- **`xtask`**: A build-time helper invoked via `cargo xtask` that handles bundling, packaging, and release manifest generation, defined in [`xtask/src/main.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/xtask/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`](https://github.com/AprilNEA/OpenLogi/blob/main/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`](https://github.com/AprilNEA/OpenLogi/blob/main/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`](https://github.com/AprilNEA/OpenLogi/blob/main/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`](https://github.com/AprilNEA/OpenLogi/blob/main/.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:

1. **Agent Startup**: The `openlogi-agent` binary launches from [`crates/openlogi-agent/src/main.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-agent/src/main.rs), creates a local socket, and initializes the input hook (`openlogi-hook`) and HID transport (`openlogi-hid`).

2. **Device Discovery**: The `openlogi-device` crate enumerates HID++ devices via the transport layer, populating the `openlogi-device-registry` with static metadata.

3. **Configuration Loading**: `openlogi-core` parses the user's TOML configuration (referenced in [`docs/CONFIGURATION.md`](https://github.com/AprilNEA/OpenLogi/blob/main/docs/CONFIGURATION.md)) and builds an in-memory action catalog mapping button presses to system commands.

4. **Client Connection**: The desktop client and overlay connect to the agent's socket, exchanging typed messages defined in the IPC contract.

5. **Input Handling**: Events captured by `openlogi-hook` translate into actions (button remap, DPI changes, SmartShift toggles) and route to the agent, which writes to devices via the HID++ layer in `openlogi-hidpp`.

6. **Rendering**: `openlogi-desktop` renders settings and device status, while `openlogi-overlay` draws the context-sensitive Actions Ring under the cursor.

## Development and Build Tooling

Developers interact with the workspace using standard Cargo commands targeting specific crates:

```bash

# 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:

```bash

# 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`:

```toml
[button_remap."Button 4"]
short_press = "LaunchApp { command = \"firefox\" }"

```

The `xtask` crate automates release workflows:

```bash

# Execute build automation

cargo xtask bundle-release

```

## Summary

- The OpenLogi workspace comprises **23 member crates** with a unified version `0.8.3` and Rust edition `2024`.
- **Agent-centric architecture** isolates all hardware I/O within the `openlogi-agent` crate, while GUI and overlay clients communicate exclusively via IPC.
- **Tarpc-based IPC** in [`crates/openlogi-ipc/src/ipc.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ipc/src/ipc.rs) provides type-safe communication over local sockets with versioned wire formats.
- **Platform abstraction** occurs through trait-based backends (`HidBackend`) and conditional compilation, keeping `openlogi-core` free 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`](https://github.com/AprilNEA/OpenLogi/blob/main/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`](https://github.com/AprilNEA/OpenLogi/blob/main/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`](https://github.com/AprilNEA/OpenLogi/blob/main/.claude/rules/objc-ffi.md).