Target Audience: Power Users & Registry Maintainers
The Registry (~/.config/hypr/hypricer/catalog/registry/) is the database of building blocks. A Theme Developer cannot use a "CPU Watcher" or a "Neon Window Style" unless it is first defined here.
hypricer recursively reads all .toml files in this directory. You can organize them however you like (e.g., audio.toml, system.toml, visuals.toml).
Every entry in the registry falls into one of these four tables:
| Type | Table Name | Role |
|---|---|---|
| Static | [static] |
A fixed configuration file (e.g., a specific waybar config). |
| Tunable | [tunable] |
Reserved for v2.1. Currently acts like Static but intended for parametric configs. |
| Watcher | [watcher] |
An Async Trigger. Spawns a thread to listen for system events. |
| Provider | [provider] |
A Sync Enricher. Fetches data on-demand during an update cycle. |
These map a unique ID to a physical file. When a theme requests {{ apps }}, and the registry resolves it to apps_minimal, the content of the referenced file is injected.
# File: catalog/registry/apps.toml
[static.apps_minimal]
path = "catalog/static/apps/minimal.conf"
description = "Terminal-only setup for focus"
[static.apps_full]
path = "catalog/static/apps/full.conf"
description = "Full desktop suite with background apps"Fields:
path: Relative path from thehypricerroot.description: (Optional) Helpful text for UI tools.
This is where you define how hypricer talks to the OS.
Watchers run continuously in the background. They are responsible for saying "Something changed!"
Required Fields:
provider: The internal Rust module to use. Currently supports:"poll_cmd": Runs a command repeatedly. Triggers if output changes."stream_cmd": Runs a command once and listens to STDOUT line-by-line.
Example: Battery Monitor (Polling)
# File: catalog/registry/system.toml
[watcher.battery_status]
provider = "poll_cmd"
cmd = "cat /sys/class/power_supply/BAT0/status"
interval = 5000 # Check every 5000ms (5 seconds)
output = "string"Example: Music Monitor (Streaming)
# File: catalog/registry/media.toml
[watcher.music_metadata]
provider = "stream_cmd"
cmd = "playerctl metadata --format '{{ title }}' --follow"
output = "string"
check = "which playerctl" # Build fails if playerctl is missingProviders run only when a Watcher triggers. They gather extra context needed to make decisions. They must be fast.
Critical Rule: You MUST provide a default value. If the command fails or times out (200ms limit), the default value is used to prevent the desktop from freezing.
Example: Get Current Wallpaper
# File: catalog/registry/context.toml
[provider.current_wallpaper]
cmd = "swww query | grep 'currently displaying' | cut -d ' ' -f 8"
default = "unknown.png" # <--- REQUIREDTo prevent the daemon from crashing at runtime, you can define build-time checks for your components. hypricer will run these commands during the build. If any command fails (exit code != 0), the build will abort with a helpful error.
You can provide a single command or a list of commands.
Supported on: [watcher], [provider]
Examples:
# Single Check
[watcher.time]
provider = "poll_cmd"
cmd = "date +%S"
check = "which date"
# Multiple Checks (All must pass)
[provider.weather]
cmd = "curl -s 'wttr.in?format=1' | jq -r .text"
default = "offline"
check = ["which curl", "which jq"]- Modularize Files: Don't dump everything into one file. Use
system.tomlfor hardware,rice.tomlfor visual styles, etc. - Unique IDs: Keys must be globally unique. You cannot have
[static.my_bar]in two different files. - Safe Defaults: Always assume your command might fail. If your "Weather Provider" fails because of no internet, your default should be
"offline", not an empty string or crash. - Use
check: If your watcher relies on a tool likeplayerctlorjq, add acheck = "which tool"line. This helps users debug missing dependencies during the build process.
- Error: "Duplicate Key" -> You defined the same ID in two files.
- Error: "Path Not Found" -> Your
path = "..."does not point to a valid file relative to the config root. - Error: "Missing Default" -> A
[provider]is missing itsdefaultfield.