# OpenLogi RGB Lighting Control for Keyboards: A Complete Technical Guide

> Master OpenLogi RGB lighting control for Logitech keyboards. This technical guide explains its Rust architecture and HID++ protocol for local-first customization. Get native control today.

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

---

**OpenLogi provides native, local-first RGB lighting control for Logitech keyboards through a layered Rust architecture that translates high-level user settings into device-specific HID++ protocol commands.**

OpenLogi is an open-source replacement for Logitech Options+ that manages keyboard RGB lighting via the HID++ protocol without requiring cloud connectivity or proprietary software. The **OpenLogi RGB lighting control for keyboards** is implemented across six specialized crates that handle everything from protocol abstraction to user-facing CLI commands.

## Architecture Overview

The lighting stack is organized into distinct layers to separate protocol logic from hardware I/O and user interfaces.

### Core Abstraction Layer

The `openlogi-core` crate defines **semantic lighting commands** through the `LightCommand` enum and handles protocol-agnostic logic. Located in [`crates/openlogi-core/src/hid/light.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/hid/light.rs), this layer expands saved TOML settings into the exact set of HID reports that a specific keyboard model supports.

### Device I/O Layer

The `openlogi-device` crate manages HID++ sessions and writes raw reports to hardware. Device-specific encoders—such as those for Litra-compatible lighting—reside in `openlogi-device::write::litra` and translate core commands into byte sequences. This layer ensures that keyboards with different RGB capabilities receive appropriately formatted packets.

### Agent and IPC

The `openlogi-agent` crate runs as a background process that owns HID device handles and performs all I/O operations. It exposes a **tarpc-based IPC surface** defined in [`crates/openlogi-ipc/src/ipc.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ipc/src/ipc.rs), allowing the CLI and desktop UI to communicate with hardware without direct device access.

## How Lighting Control Works Internally

The RGB control flow follows a five-stage pipeline from user configuration to hardware execution.

### Configuration Storage

Users define lighting preferences in `~/.config/openlogi/config.toml`. The `LightSettings` struct in [`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs) stores the power state, normalized brightness percentage (0-100%), and optional color temperature in Kelvin.

### Capability Discovery

When OpenLogi enumerates a keyboard, it queries the device’s HID++ descriptors to populate `LightCapabilities` (defined in [`crates/openlogi-core/src/device/light.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/device/light.rs)). This struct contains boolean flags for power support and optional ranges for brightness and temperature control, ensuring the software only sends commands the hardware can execute.

### Command Expansion

The `commands_for_light_settings` function in [`crates/openlogi-core/src/hid/light.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/hid/light.rs) converts user settings into device-specific `LightCommand` vectors. This expansion filters out unsupported features—a keyboard without temperature control will never receive temperature packets, while a power-only device receives only power commands.

```rust
pub fn commands_for_light_settings(
    settings: LightSettings,
    capabilities: LightCapabilities,
) -> Vec<LightCommand> {
    // Returns only the commands supported by the specific keyboard model
}

```

### Device Write and IPC

The agent’s device layer iterates over the `LightCommand` vector, encoding each entry into HID reports. When using the CLI or UI, clients send `SetLight` requests over tarpc; the agent processes these through the expansion function and writes the final reports, returning the applied state to keep interfaces synchronized.

## Practical Implementation Examples

### Command-Line Interface

For everyday RGB control, use the `openlogi-cli` crate commands:

```bash

# Power on keyboard backlight

openlogi light --device keyboard --power on

# Set brightness to 70%

openlogi light --device keyboard --brightness 70

# Configure color temperature (if supported)

openlogi light --device keyboard --temperature 4500

```

The CLI implementation in [`crates/openlogi-cli/src/cmd/light.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/light.rs) forwards all flags to the `SetLight` IPC request, which triggers the core expansion logic.

### Direct Rust API Integration

Embed OpenLogi’s lighting control in Rust applications using the core library:

```rust
use openlogi_core::config::LightSettings;
use openlogi_core::device::{LightCapabilities, LightValueRange, LightValueUnit};
use openlogi_core::hid::light::{commands_for_light_settings, LightCommand};

fn main() {
    // Define capabilities discovered from the keyboard
    let brightness_range = LightValueRange::new(
        0, 100, 1, LightValueUnit::Percent
    ).unwrap();
    
    let caps = LightCapabilities {
        power: true,
        brightness: Some(brightness_range),
        temperature: None,
    };

    // Create settings (normally loaded from TOML)
    let settings = LightSettings::new(true, 75, None);

    // Generate device-specific commands
    let cmds: Vec<LightCommand> = commands_for_light_settings(settings, caps);
    
    // cmds is ready for transmission to the agent
}

```

This example demonstrates the core expansion pipeline without requiring the background agent for command generation logic.

### TOML Configuration Management

Batch configure keyboard lighting via the configuration file:

```toml

# ~/.config/openlogi/config.toml

[light_settings.keyboard]
enabled = true
brightness_percent = 60

# temperature_kelvin = 4600  # Optional

```

After editing, apply settings immediately with `openlogi light --apply` or restart the agent to load changes from disk.

### Desktop UI Color Management

The `openlogi-ui` crate provides color utilities for the GPUI-based interface:

```rust
use openlogi_ui::color::Rgb;
let rgb = Rgb::from_hsv(120.0, 0.8, 0.6);

```

The UI module in [`crates/openlogi-ui/src/color.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ui/src/color.rs) handles color space conversions and synchronizes the on-screen preview with the actual hardware state returned by `SetLight` IPC calls.

## Advanced Use Cases

### Camera-Based Automation

OpenLogi supports automatic RGB control based on camera activity, particularly for Litra-style lights. The agent listens to camera capture events through `crates/openlogi-camera` and triggers power commands when the webcam activates:

```rust
if camera.is_active() && light_capabilities.power {
    send_light_command(LightCommand::Power(true));
}

```

This automation logic resides in `crates/openlogi-agent/src/watchers` and enables hands-free lighting control during video calls.

## Summary

- **OpenLogi RGB lighting control for keyboards** operates through a layered architecture separating core logic, device I/O, and user interfaces.
- The `commands_for_light_settings` function in [`crates/openlogi-core/src/hid/light.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/hid/light.rs) ensures only supported commands reach specific hardware models.
- Configuration persists in `~/.config/openlogi/config.toml` via the `LightSettings` struct, parsed by [`crates/openlogi-core/src/config.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config.rs).
- The tarpc-based IPC layer allows CLI, UI, and automated systems to control hardware through the single agent process.
- Device capabilities are discovered dynamically through HID++ protocol queries stored in `LightCapabilities`.

## Frequently Asked Questions

### What protocols does OpenLogi use for keyboard RGB control?

OpenLogi uses the **HID++ protocol** for all keyboard lighting communication, implemented in the `openlogi-device` crate. This proprietary Logitech protocol allows direct control over brightness, power states, and color temperature without requiring Logitech Options+ software or internet connectivity.

### How does OpenLogi handle keyboards with different RGB capabilities?

The system queries each device during enumeration to populate `LightCapabilities` (defined in [`crates/openlogi-core/src/device/light.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/device/light.rs)). The `commands_for_light_settings` function then filters commands based on these capabilities—a keyboard supporting only brightness will never receive temperature packets, preventing protocol errors and ensuring compatibility across the Logitech hardware lineup.

### Can I control RGB lighting without the background agent running?

No. The `openlogi-agent` process owns exclusive HID device handles and is the only component with direct hardware access. All clients—including the CLI and desktop UI—communicate via tarpc IPC defined in [`crates/openlogi-ipc/src/ipc.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ipc/src/ipc.rs). This design prevents conflicts when multiple applications attempt simultaneous device access.

### Where does OpenLogi store keyboard lighting settings?

Settings persist in `~/.config/openlogi/config.toml` as TOML-serialized `LightSettings` structs. The configuration stores power state, brightness percentage, and optional temperature values. Changes can be applied immediately via CLI commands or automatically loaded when the agent restarts.