# How to Add Custom Actions and Icons to the OpenLogi Actions Ring

> Learn to add custom actions and icons to your OpenLogi Actions Ring. Configure actions in TOML and add icons to the assets directory for a personalized overlay experience.

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

---

**Define custom actions in your TOML profile's `action_ring` table, place SVG or PNG icons in the `assets/action_ring/` directory, and the desktop client automatically forwards the configuration to the overlay via IPC using the `ActionRingPresentation` struct.**

The Actions Ring in the AprilNEA/OpenLogi repository provides a radial quick-access interface for executing contextual commands. You can extend its default capabilities by adding custom actions and icons to the OpenLogi Actions Ring through declarative configuration and asset management, without modifying the core overlay source code.

## Understanding the Actions Ring Architecture

The Actions Ring is rendered by the `openlogi-overlay` process and receives its data over the IPC channel defined in `openlogi-ipc`. Each slot in the ring is described by the `ActionRingPresentation` struct located in [`crates/openlogi-core/src/binding/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/action_ring.rs).

This struct contains two critical fields for customization:

- **`icon: ActionRingIcon`** – Selects a built-in glyph or denotes a custom asset
- **`literal: Option<String>`** – Available starting with protocol version v15, this field supplies the custom filename or label for user-defined icons

The desktop client (`openlogi-desktop`) watches your configuration files and translates TOML definitions into `ActionRingInvocation` messages that it sends to the overlay via tarpc-based IPC.

## Configuring Custom Actions via TOML

### Editing the Profile Configuration

Each OpenLogi profile can contain an `action_ring` table that maps directional slots to specific actions. Create or edit your configuration file at `~/.config/openlogi/config.toml` (or the platform-equivalent path) to define custom behavior.

```toml
[profile.my_app.action_ring]
top = { action = "LaunchTerminal", icon = "my_terminal_icon" }
right = { action = "ToggleMute", icon = "my_mic_icon" }
bottom = { action = "ShowClipboard", icon = "custom_clipboard" }
left = { action = "LockScreen", icon = "my_lock" }

```

The `action` key specifies the command identifier, while the `icon` key references the asset filename (without extension) that the overlay should render for that slot.

## Installing Custom Icon Assets

### Supported Formats and Location

Custom icons are loaded by the `ActionIcons` asset source defined in [`crates/openlogi-ui/src/action_icons.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ui/src/action_icons.rs). The system supports **SVG** and **PNG** formats for crisp scaling at different ring sizes.

Place your icon files in the `assets/action_ring/` directory relative to the OpenLogi installation or configuration root. The asset source automatically discovers any files placed in this location during the overlay startup or refresh cycle.

### Naming Conventions

The filename must exactly match the value specified in the TOML `icon` field. For example, if your configuration specifies `icon = "my_terminal_icon"`, the file system should contain:

```

assets/action_ring/
├── my_terminal_icon.svg
├── my_mic_icon.svg
└── custom_clipboard.png

```

The `ActionIcons` loader in [`crates/openlogi-ui/src/action_icons.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ui/src/action_icons.rs) strips the extension when indexing, allowing you to reference the base name consistently across different supported formats.

## Advanced Customization via Rust

### Constructing ActionRingPresentation Programmatically

When building custom integrations or plugins, you construct the `ActionRingPresentation` struct directly to pass custom literals and labels. This approach is used internally by [`crates/openlogi-desktop/src/state/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/state/action_ring.rs) when mapping user configuration to IPC messages.

```rust
use openlogi_core::binding::{
    ActionRingPresentation, 
    ActionRingSlot, 
    ActionRingIcon
};
use std::collections::BTreeMap;

let mut slots = BTreeMap::new();
slots.insert(
    ActionRingSlot::Top,
    ActionRingPresentation {
        icon: ActionRingIcon::Custom,               // Signals custom asset usage
        literal: Some("my_terminal_icon".into()),     // Matches filename in assets/
        label: Some("Terminal".into()),              // Displayed in UI editors
    },
);

```

### Loading Icons with the ActionIcons Source

To verify asset availability programmatically, interact with the `ActionIcons` struct from `openlogi-ui`:

```rust
use openlogi_ui::action_icons::ActionIcons;

let icons = ActionIcons;
let my_icon = icons.load("my_terminal_icon.svg")?;
assert_eq!(my_icon.asset_path(), "my_terminal_icon.svg");

```

### Sending Invocations via IPC

The desktop client emits the ring configuration to the overlay using the `ActionRingInvocation` RPC. You can trigger this manually when building custom automation:

```rust
use openlogi_ipc::{AgentClient, ActionRingInvocation};

// Assume `client` is an established tarpc client to the overlay
let invocation = ActionRingInvocation {
    slots, // BTreeMap<ActionRingSlot, ActionRingPresentation>
    // Additional fields: position, radius, etc.
};

client.invoke_action_ring(invocation).await?;

```

## Modifying the Ring Layout

If you require non-standard slot positioning or a custom radius, edit the `ActionRingLayout` in [`crates/openlogi-core/src/binding/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/action_ring.rs). The layout defines the angular arrangement of slots (Top, Right, Bottom, Left) and their visual spacing.

Changes to the layout structure require restarting the overlay process, as the layout is read once at startup in [`crates/openlogi-overlay/src/ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-overlay/src/ring.rs). However, content changes (new icons or actions) propagate immediately via the file-watching mechanism in [`crates/openlogi-desktop/src/features/action_ring/editor.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-desktop/src/features/action_ring/editor.rs).

## Summary

- **Configure actions** in the TOML `action_ring` table to map directional slots to command identifiers and icon names.
- **Place custom icons** (SVG or PNG) in `assets/action_ring/`; the `ActionIcons` source in [`crates/openlogi-ui/src/action_icons.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ui/src/action_icons.rs) discovers them automatically.
- **Use the `ActionRingPresentation` struct** to pass custom metadata, including the `literal` field for user-defined icon filenames (protocol v15+).
- **Leverage IPC** via `ActionRingInvocation` to dynamically update the ring without restarting the entire OpenLogi stack.

## Frequently Asked Questions

### What image formats are supported for custom ring icons?

OpenLogi supports **SVG** and **PNG** files for custom icons placed in the `assets/action_ring/` directory. The `ActionIcons` asset source in [`crates/openlogi-ui/src/action_icons.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-ui/src/action_icons.rs) indexes these formats automatically and scales them appropriately for the ring's radial layout.

### Do I need to restart OpenLogi after adding new custom actions?

No. The desktop client (`openlogi-desktop`) implements file watching on the configuration directory. When you save changes to [`config.toml`](https://github.com/AprilNEA/OpenLogi/blob/main/config.toml) or add new files to `assets/action_ring/`, the client automatically rebuilds the `ActionRingInvocation` and pushes it to the overlay via IPC, refreshing the ring on the next invocation.

### Can I add more than four slots to the Actions Ring?

The default implementation in [`crates/openlogi-core/src/binding/action_ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/action_ring.rs) defines slots as an enum variant (Top, Right, Bottom, Left). To add additional positions such as diagonal slots, you must modify the `ActionRingSlot` enum and update the rendering logic in [`crates/openlogi-overlay/src/ring.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-overlay/src/ring.rs) to handle the new angular positions.

### Why doesn't my custom icon appear in the ring?

Verify three specific items: first, confirm the filename matches the `icon` value in your TOML configuration exactly (case-sensitive); second, ensure the file resides in the correct `assets/action_ring/` directory that the `ActionIcons` source monitors; third, check that you are running protocol version v15 or later if using the `literal` field for custom asset references, as defined in [`crates/openlogi-core/src/binding/action_ring/icon.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-core/src/binding/action_ring/icon.rs).