# How to Customize Lighting for Devices in OpenLogi: A Complete Guide

> Customize device lighting in OpenLogi using declarative TOML configuration. Control power, brightness, and color temperature across all hardware. Learn more in this complete guide.

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

---

**TLDR;** OpenLogi uses a declarative TOML configuration that automatically translates semantic lighting preferences into device-specific HID commands, supporting power, brightness, and color temperature across all connected hardware.

OpenLogi provides a unified, capability-aware system for customizing lighting on supported devices. Whether you're adjusting a Logitech Litra light or keyboard backlighting, the configuration remains portable while the core handles device-specific translation. This article explains how to customize lighting for devices in OpenLogi using configuration files, CLI commands, and programmatic APIs.

---

## Understanding the Lighting Configuration Model

OpenLogi stores lighting preferences in a semantic format decoupled from hardware protocols. The `[light]` table in [`OpenLogi.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/OpenLogi.toml) contains three fields that describe the desired state:

- **`enabled`** — Boolean toggle for power state
- **`brightness_percent`** — Normalized 0-100% brightness level
- **`temperature_kelvin`** — Optional color temperature (e.g., 4600K for neutral white)

```toml
[light]
enabled = true
brightness_percent = 37
temperature_kelvin = 4600

```

This configuration lives in the **config module** within [`crates/openlogi-core/src/config/settings.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/settings.rs), which defines the `LightSettings` struct that holds these values at runtime.

---

## How OpenLogi Translates Configuration to Device Commands

### Semantic to Physical Command Translation

The key transformation happens in [`crates/openlogi-core/src/hid/light.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/hid/light.rs). The **`commands_for_light_settings`** function takes your `LightSettings` and the device's reported `LightCapabilities`, then produces a filtered `Vec<LightCommand>` containing only operations the hardware supports.

```rust
let cmds = commands_for_light_settings(settings, capabilities);
// Result: [LightCommand::Power(true), LightCommand::BrightnessPercent(37), ...]

```

This capability-aware filtering prevents invalid commands. If a device lacks temperature control, that `LightCommand` variant is simply omitted from the output vector.

### Device Capability Detection

Each connected device reports its capabilities through `LightCapabilities`, defined in [`crates/openlogi-core/src/device/light.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/device/light.rs):

- `power` — Can toggle on/off
- `brightness` — Supports percentage-based dimming
- `temperature` — Supports Kelvin-based color temperature

The core queries these capabilities before generating commands, ensuring compatibility without manual device-specific configuration.

---

## Methods to Customize Lighting in OpenLogi

### Method 1: Edit Configuration File Directly

Modify `~/.config/OpenLogi/OpenLogi.toml` with your preferred values:

```toml

# $HOME/.config/OpenLogi/OpenLogi.toml

[light]
enabled = true
brightness_percent = 45
temperature_kelvin = 5500

```

Apply changes by restarting the agent or using the CLI command below.

### Method 2: Apply Settings via CLI

The `openlogi-cli` frontend provides direct control. Located in [`crates/openlogi-cli/src/cmd/light.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-cli/src/cmd/light.rs), it parses TOML, builds command lists, and forwards them through IPC.

Apply your saved configuration:

```bash
openlogi light apply

```

Set individual attributes without editing the file:

```bash
openlogi light set --brightness 75

```

This preserves other existing settings while updating only the specified parameter.

### Method 3: Programmatic Control via Rust API

For integration into custom tools, use the core library directly:

```rust
use openlogi_core::config::LightSettings;
use openlogi_core::device::LightCapabilities;
use openlogi_core::hid::light::commands_for_light_settings;

// Construct settings programmatically
let settings = LightSettings::new(true, 60, Some(5000));

// Query actual device capabilities from the agent
let caps = LightCapabilities {
    power: true,
    brightness: Some(0..=100),
    temperature: Some(2700..=6500),
    ..Default::default()
};

// Generate capability-filtered commands
let commands = commands_for_light_settings(settings, caps);

```

---

## IPC Communication Architecture

The **IPC contract** in [`crates/openlogi-ipc/src/ipc.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ipc/src/ipc.rs) defines two critical methods:

- **`set_lighting`** — Batch update multiple lighting parameters
- **`set_light`** — Targeted single-parameter changes

These RPC methods allow the CLI to communicate with the background agent, which maintains device connections and handles HID report generation. The separation between frontend and agent enables persistent lighting state across CLI invocations.

---

## Hardware-Specific Implementation

Each device driver implements the final encoding step. For example, Litra lights use `openlogi_hid::write::litra` to convert `LightCommand` variants into proprietary HID report formats. This encoding layer is opaque to users—you write semantic commands, and the appropriate driver generates the correct byte sequences.

This architecture means new hardware support requires only a new encoder implementation, without changes to user configuration or the command-generation logic.

---

## Summary

- **Configuration is declarative**: Edit `[light]` in [`OpenLogi.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/OpenLogi.toml) with `enabled`, `brightness_percent`, and `temperature_kelvin`
- **Translation is automatic**: `commands_for_light_settings` in [`crates/openlogi-core/src/hid/light.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/hid/light.rs) filters by device capabilities
- **Control is flexible**: Use file editing, CLI (`openlogi light apply` or `openlogi light set`), or direct Rust API calls
- **Hardware is abstracted**: Device-specific encoders in `openlogi_hid::write` handle HID protocol details

---

## Frequently Asked Questions

### Does OpenLogi support RGB color lighting?

OpenLogi currently focuses on **color temperature** (Kelvin) rather than RGB color spaces. The `temperature_kelvin` field in `LightSettings` supports warm-to-cool white adjustments. Check your device's `LightCapabilities` to verify temperature range support—some hardware may only expose brightness and power controls.

### What happens if I set a brightness value my device doesn't support?

The `commands_for_light_settings` function automatically clamps or filters values based on reported capabilities. If a device reports `brightness: Some(0..=100)`, values outside this range are handled appropriately. The function returns only `LightCommand` variants the hardware explicitly supports, preventing protocol errors.

### Can I customize lighting for multiple devices simultaneously?

Yes. The agent maintains separate capability contexts for each connected device. When you run `openlogi light apply`, the core generates device-specific command sets for every connected light. Each driver encoder (`openlogi_hid::write::litra`, etc.) produces the correct HID reports for its respective hardware.

### Where is my lighting configuration saved?

OpenLogi follows XDG Base Directory standards. The [`OpenLogi.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/OpenLogi.toml) file resides at `$HOME/.config/OpenLogi/OpenLogi.toml` on Linux/macOS, or the equivalent platform-specific location. The config module in [`crates/openlogi-core/src/config/settings.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/config/settings.rs) handles persistence and loading of these values at agent startup.