OpenLogi RGB Lighting Control for Keyboards: A Complete Technical Guide

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, 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, 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 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). 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 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.

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:


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

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:


# ~/.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:

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

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 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.
  • 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). 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. 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.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →