OpenRiot Architecture
Comprehensive reference for OpenRiot project structure and configuration.
π PROJECT STRUCTURE
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β REPOSITORY (~/Code/OpenRiot) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββββββββββββββ β
β β source/ β β config/ β β install/ β β
β β β β β β β β
β β main.go β β i3/ β β packages.yaml β Package β β
β β polybar/ β β polybar/ β β definitions β β
β β backgrounds/ β β rofi/ β β β β
β β wireguard/ β β alacritty/ β β openriot β Built binary β β
β β crypto/ β β fastfetch/ β β motd β β
β β audio/ β β dunst/ β β β β
β β display/ β β fish/ β β β β
β β installer/ β β helix/ β β β β
β β ... β β ... β β β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββββββββββββββ β
β β
β backgrounds/ config/bin/ install/openriot β
β (16 wallpapers) (scripts) (binary) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π KEY LOCATIONS
| What | Location |
|---|---|
| Repo | ~/Code/OpenRiot/ |
| Installed | ~/.local/share/openriot/ |
| XDG configs | ~/.config/ |
| Binary | ~/.local/share/openriot/install/openriot |
| Logs | ~/.cache/openriot/ |
| Lock script | ~/.local/share/openriot/config/bin/openriot-lock.sh |
| Rofi apps | ~/.config/rofi/apps.txt |
| Crypto config | ~/.config/crypto.toml |
Deployment Flow
config/fish/* β ~/.config/fish/
config/i3/* β ~/.config/i3/
config/polybar/* β ~/.config/polybar/config.ini (config only)
config/polybar/scripts/* β ~/.local/share/openriot/config/polybar/scripts/
config/bin/* β ~/.local/share/openriot/config/bin/
config/rofi/* β ~/.config/rofi/
config/fonts/* β ~/.local/share/fonts/
config/Xresources β ~/.Xresources
config/xsession/* β ~/.xsession (ALWAYS overwrite)
config/picom.conf β ~/.config/picom.conf
config/alacritty/* β ~/.config/alacritty/
install/openriot β ~/.local/share/openriot/install/openriot
Polybar scripts are special: They deploy to ~/.local/share/openriot/... NOT ~/.config/polybar/
π COMPLETE CLI REFERENCE
Binary location: ~/.local/share/openriot/install/openriot
Installation Commands
| Flag | Description |
|---|---|
--install |
Deploy configs, run commands, build source (no packages) |
--install-packages |
Install packages from packages.yaml (safe one-by-one) |
--source-builds |
Build software from source (crush, fonts, cursors) |
--packages |
List packages from packages.yaml |
--check-packages |
Verify packages.yaml versions against installed/available |
--sync-packages |
Update packages.yaml to latest available versions |
--version-check |
Check if remote version is newer |
Package Version Workflow
After doas pkg_add -u (system upgrade):
openriot --check-packages # See what's outdated
openriot --sync-packages # Update packages.yaml to match installed
git add packages.yaml && git push # Distribute to users
Users run:
./setup.sh # Calls --install-packages using yaml from repo
Key points:
--sync-packagesonly updatespackages.yaml, NOT the system- Creates backup:
packages.yaml.bak - Uses
pkg_info -afor fast local lookup (no network needed)
Wallpaper Commands
| Flag | Description |
|---|---|
--wallpaper-next |
Rotate to next wallpaper, save to ~/.current-background |
--wallpaper-load |
Load saved wallpaper from ~/.current-background |
Power Commands
| Flag | Description |
|---|---|
--lock |
Lock screen via openriot-lock.sh |
--suspend |
Suspend system (zzz) |
--power-menu |
Rofi menu: Lock/Suspend/Reboot/Shutdown/Logout |
--suspend-if-undocked |
Auto-suspend when undocked |
Volume/Brightness Commands
| Flag | Description |
|---|---|
--volume inc |
Increase volume |
--volume dec |
Decrease volume |
--volume toggle |
Toggle mute |
--brightness [args] |
Adjust brightness |
Polybar Modules
| Flag | Output | Used By |
|---|---|---|
--polybar-metrics |
CPU + RAM % | polybar cpu module |
--polybar-volume |
Volume icon + % | polybar volume module |
--polybar-memory |
RAM icon + % | polybar memory module |
--wireguard-status |
σ°³/σ° /σ°± | polybar wireguard module |
Notification Commands
| Flag | Description |
|---|---|
--notify "title" "body" |
Send notification |
--notify "title" "body" --urgency critical |
Critical notification |
--notify-dismiss [id] |
Dismiss notification |
--notify-clear |
Clear all notifications |
--notify-dunst |
Show dunst status |
--mem-notify |
Memory usage notification |
--cpu-notify |
CPU usage notification |
Network Commands
| Flag | Description |
|---|---|
--wireguard |
Toggle WireGuard VPN |
Crypto Commands
| Flag | Description |
|---|---|
--crypto [BTC|ZEC|XMR|LTC] |
Show crypto price |
--crypto-refresh |
Clear cache, fetch fresh prices |
Other Commands
| Flag | Description |
|---|---|
--share-log [file] |
Upload log to catbox.moe |
--version |
Show version |
π§ BUILD & TEST
make build # DEPRECATED - use 'make' or 'make install'
make # Dev build (no install)
make install # Build + deploy to ~/.local/share/openriot/install/
make verify # Build + smoke test
make test # Go tests
make deps # Tidy Go dependencies
Testing Workflow
Config files:
cp repo/path ~/.config/path # Copy to local
# Restart relevant daemon
pkill -HUP polybar # Polybar restart
# Test changes
Go binary:
make
# Test from install/openriot
./install/openriot --version
# Deploy when ready
make install
NEVER copy files without explicit approval.
Version System
Version is in VERSION file (e.g., β1.4β). Injected at build time via ldflags:
-X main.version=$(cat VERSION)
π οΈ TECHNOLOGY STACK
Platform
- OpenBSD 7.9+ (x86_64)
- i3 window manager (NOT sway/wayland)
- X11 (NOT Wayland)
- Minimum resolution: 1920x1080
Languages
- Go - CLI binary (
source/*.go) - YAML - Package definitions (
install/packages.yaml) - Fish - Shell configuration
- ini - Polybar, i3, dunst configs
Key Packages
| Package | Purpose |
|---|---|
polybar |
Status bar |
rofi |
App launcher |
i3 + i3lock |
Window manager |
alacritty |
Terminal |
dunst |
Notifications |
picom |
Compositor |
redshift |
Night light |
xautolock |
Screen lock trigger |
clipmenu |
Clipboard manager |
π¦ PACKAGES.YAML STRUCTURE
core:
base:
packages: ["pkg-1"]
configs: [{pattern: "source/*", target: "~/.config/dest"}]
commands: [{desc: "Desc", cmd: "shell command"}]
type: "Package"
critical: true
desktop:
i3:
packages: ["i3", "polybar", "rofi"]
configs:
- pattern: "i3/*"
preserve_if_exists: [keybindings.conf, monitors.conf]
depends: [core.base, fonts.fira-code]
type: "Package"
source:
crush:
type: "Source"
build: ["curl ... && install"]
depends: []
fonts:
fira-code:
type: "Source"
build: ["curl ... && unzip"]
depends: []
Module Categories
| Category | Examples |
|---|---|
core |
base, shell |
desktop |
i3, i3-auto-layout, rofi-calc, apps, media |
source |
crush, bibata-cursor, stormy |
fonts |
fira-code |
system |
tools, services |
Module Types
| Type | Meaning |
|---|---|
Package |
Install via pkg_add |
Source |
Build from source |
Config Pattern Types
| Pattern | Behavior |
|---|---|
dir/* |
Glob: copy all files in directory |
dir/file |
Single file |
bin/* |
Glob to ~/.local/bin |
Preserve Behavior
preserve_if_exists: [file]= Only deploy if missing- No preserve = Always overwrite
- Exception:
~/.xsessionALWAYS overwrites (system config)
π₯οΈ POLYBAR MODULE REFERENCE
See also: docs/polybar-state-architecture.md, docs/polybar-performance.md
Module Definition Template
[module/NAME]
type = custom/script
exec = $HOME/.local/share/openriot/install/openriot --flag
format-padding = 1
click-left = $HOME/.local/share/openriot/install/openriot --flag
All Modules (left to right)
modules-left = launcher workspaces workspaces2 workspaces3 workspaces4 window-title
modules-center = date
modules-right = crypto night-light cpu memory volume network-wifi network-eth wireguard battery openriot-update power lock
Module Details
| Module | Icon | Click Action | Scroll |
|---|---|---|---|
| launcher | ο¨ | launcher.sh |
- |
| workspaces | 1-4 | Switch workspace | - |
| window-title | text | Show window name | - |
| date | text | Next wallpaper | - |
| volume | ε©’ | Toggle mute | Volume adjust |
| network-wifi | 󰀨/󰀯 | WiFi details | - |
| network-eth | σ°/σ° | ETH details | - |
| battery | ο | - | - |
| crypto | ο | crypto-notify.sh | - |
| night-light | ο«/σ°΅ | Toggle redshift | - |
| cpu | ιΎ | CPU notification | - |
| memory | ν | Memory notification | - |
| wireguard | σ°³/σ° /σ°± | Toggle VPN | - |
| openriot-update | σ°’/σ°· | Check updates | - |
| power | β» | Power menu | - |
| lock | σ°Ύ | Lock screen | - |
Key Polybar Rules
- ALL modules-right MUST have
format-padding = 1 - Text icons: NO spaces -
"icon"works," icon "is broken - Font sizes: T1=10, T2=18
- Date format:
%A β’ %B %d β’ %I:%M %p
π APP LAUNCHER (ROFI)
apps.txt Format
Name|Command|Icon
Example:
Terminal|alacritty|σ°·
Firefox|firefox|σ°Ή
Telegram|tdesktop.desktop|σ°¦
Helix|alacritty -e hx|σ°
Media Player|mpv --player-operation-mode=pseudo-gui|ο¬
Desktop Files
Desktop files go to ~/.local/share/applications/. Commands ending in .desktop are executed via:
grep '^Exec=' ~/.local/share/applications/$CMD | cut -d= -f2-
Launcher Script Flow
- Read
apps.txt - Filter comments (
#) and empty lines - Build rofi input:
Icon Name - Run rofi with selected theme
- Get command for selected index
- Execute command
- Send βLaunchingβ¦β notification
π¨ FASTFETCH CONFIG
Valid Colors
| Valid | Invalid |
|---|---|
magenta |
darkpurple |
cyan |
lightblue |
green |
purple |
yellow |
orange |
blue |
lightgreen |
white |
Β |
black |
Β |
Config Location
~/.config/fastfetch/config.jsonc
Box Drawing
Uses ASCII box-drawing characters for section headers:
βββββββββββββββββββββHardwareβββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key widths must match box width (40 chars inside).
π LOCK SCREEN
Script: config/bin/openriot-lock.sh
Flow:
- Find
locked.jpgin install dir or repo - Get screen resolution via
xdpyinfo - Convert JPG to PNG at screen resolution
- Run
i3lock -i <png> - Delete temp PNG
i3lock on OpenBSD:
- Standard i3lock (no color) - uses bsd_auth
- i3lock-color does NOT work - requires PAM which OpenBSD doesnβt use
- Supports:
-i image.png,-c "#rrggbb" - Does NOT support:
--circle-color
π₯οΈ XSESSION SETUP
File: config/xsession/openriot-xsession
Order Matters
# 1. Locale
export LC_CTYPE=en_US.UTF-8
# 2. Cursor theme (X11 looks in ~/.icons/, NOT ~/.local/share/icons/)
export XCURSOR_THEME=Bibata-Modern-Ice
export XCURSOR_SIZE=24
# 3. Create dirs
mkdir -p ~/Screenshots
# 4. Load Xresources
[ -f ~/.Xresources ] && xrdb -merge ~/.Xresources
# 5. Disable DPMS
xset -dpms
# 6. Screensaver (10 min)
xset s 600
# 7. xautolock (OpenBSD doesn't have xss-lock)
xautolock -time 10 -locker "$HOME/.local/share/openriot/config/bin/openriot-lock.sh" &
xset s on
# 8. Start i3
exec i3
Screen Lock on OpenBSD
OpenBSD does NOT have xss-lock - use xautolock instead.
# Package: xautololock-2.2
xautolock -time 10 -locker "lock-script.sh" &
π‘ LESSONS LEARNED
Process Discipline (CRITICAL)
- ALWAYS PAUSE AND ASK when confused - donβt run amuck debugging
- Follow the exact workflow: PROPOSE β WAIT FOR CONFIRM β IMPLEMENT β TEST β COPY (only after user tests)
- Donβt implement complex solutions when user suggests simpler ones - theyβre smarter
- If stuck on logic, ask questions instead of implementing wrong approach
Version Comparison Logic
compareVersions(local, remote) < 0= update available (local < remote)compareVersions(local, remote) <= 0= local is same or older (wrong!)- Cache remote version in
~/.cache/openriot/remote.versionfor instant click response
Workspace Switching
- Binary does the switch via
i3-msgso it knows current before/after - If
current == target, exit early (already on that workspace, no-op) - Donβt rely on i3βs
workspace_auto_back_and_forth- control it in binary
Notifications
- When implementing a feature that needs notifications, ADD notify-send call
- Donβt forget:
exec.Command("/usr/local/bin/notify-send", ...).Start()
Script Deletion Checklist
- Before deleting scripts, grep polybar config for references
- Update i3 config if it references deleted scripts
- Add cleanup commands to packages.yaml for stale files during upgrades
WireGuard on OpenBSD
- Config at
/etc/wireguard/wg0.confrequires root to read - Use
doas test -fNOTos.Stat()for permission check
Makefile Changes
- Test Makefile targets after editing - donβt break build commands
- Especially
make release- verify it works before considering done
fastfetch
- Valid colors:
magenta,cyan,green,yellow,blue,white,black - NOT valid:
darkpurple,lightblue, etc. mountPointsmay show β/β instead of actual mount point- Headers need matching width with box-drawing chars
Memory Reporting
- Use
hw.usermemNOThw.physmemfor accurate user-available percentage hw.physmemincludes reserved kernel memory- Polybar memory:
--polybar-memoryoutputs icon + % - Memory notification:
GetMemDetails()shows βX.XX GiB of Y.YY GiB\nTotal Used: Z%β
Atheros WiFi (athn)
- AR9271 firmware NOT in OpenBSD base (licensing)
- Install via:
fw_update -v athnor download fromfirmware.openbsd.org - Error
failed loadfirmware of file athn-open-ar9271 (error 2)= firmware missing
Fish Shell Colors
- ALWAYS omit
#prefix for hex colors - fish treats#as comment! - CORRECT:
set_color bb9af7 - WRONG:
set_color #bb9af7 - Named colors work fine:
set_color purple,set_color cyan
Polybar Double Launch (setup.sh)
- Use
pkill polybarNOTpkill -HUP polybar -HUPonly signals reload, but if config changed it may not restart properlypkillkills and allows clean restart- Polybar does NOT auto-start from i3 - must manually restart:
pkill polybar && nohup polybar 2>/dev/null & disown
Polybar Script Paths (CRITICAL)
- CANONICAL location:
~/.local/share/openriot/config/polybar/scripts/ - Config points to:
~/.local/share/openriot/config/polybar/scripts/*.sh - NEVER copy scripts to
~/.config/polybar/scripts/ - NEVER point config to
~/.config/polybar/scripts/
Correct workflow for testing changes:
- Edit script in repo:
config/polybar/scripts/workspaces.sh - Copy to canonical:
cp config/polybar/scripts/workspaces.sh ~/.local/share/openriot/config/polybar/scripts/ - Restart polybar
- Test
If local polybar config has wrong paths (points to ~/.config/polybar/scripts/):
- Fix paths:
sed -i 's|\$HOME/.config/polybar/scripts/|$HOME/.local/share/openriot/config/polybar/scripts/|g' ~/.config/polybar/config.ini - OR copy repo config:
cp config/polybar/config.ini ~/.config/polybar/config.ini
Font Names (fontconfig)
- Font names from
fc-listmay differ from filename fc-list | grep Papershows:Paper Mono:style=Regular- Using
PaperMono Regular(filename-style) fails silently
Polybar Click Coordinates (%lx)
%lxdoes NOT work forcustom/scriptmodules - only forinternal/*modules- Solution: Pass workspace number directly in config, or use
internal/i3module - OLD (broken):
click-left = script.sh %lx- polybar ignores %lx - NEW (works):
click-left = i3-msg workspace 1- direct i3 command
notify-send Path
- Always use full path
/usr/local/bin/notify-sendfor reliability - Donβt rely on PATH being set correctly in all contexts
Dunst Restart - MUST Force Kill
- NEVER use
pkill dunst(SIGTERM) - leaves dunst in bad state - ALWAYS use
pkill -9 dunst- SIGKILL force kills and ensures clean restart - Stale dunst process causes generic βXβ icons even when code is correct
Git Status Confusion
- Staged files + deleted files can coexist showing βnew fileβ + βdeletedβ
- Clarify actual file state before making changes
- NEVER run git commands (add, rm, restore, checkout, etc.)
XSession Setup (CRITICAL)
- Must export
LC_CTYPE=en_US.UTF-8for proper locale - Cursor theme:
XCURSOR_THEME=Bibata-Modern-Ice,XCURSOR_SIZE=24 - X11 looks in
~/.icons/NOT~/.local/share/icons/for cursor themes - DPMS:
xset -dpmsto disable,xset s 600for 10min screensaver - OpenBSD needs
xautolock- xss-lock not available
Weather Module
- Config at
~/.config/weather.cfgwith[DEFAULT]section - Cache at
~/.cache/openriot-weather.json - If no API key in config, weather module hidden automatically
- Polybar format:
weather-font = 10;3(T1=10, T2=3)
Proton Drive (rclone)
- Requires
rclonepackage + config at~/.config/rclone/rclone.conf - Use
rclone bisyncfor two-way sync with local folder - Example:
rclone bisync Proton:Drive ~/ProtonDrive --progress
GTK Theme for Text Editor
- Gnome Text Editor uses GTK3
- Configs:
config/gtk-3.0/gtk.css+config/gtk-3.0/settings.ini - Deploy to
~/.config/gtk-3.0/ - Tokyo Night theme works well for dark mode editors
Polybar Performance
exec-intervalcontrols refresh rate (default often 30s)- Too frequent updates drain CPU
tail -f /dev/nulltrick to prevent module from exiting
π¨ OPENBSD SPECIFIC
| Issue | Solution |
|---|---|
| xss-lock | NOT available - use xautolock |
| i3lock-color | Doesnβt work - requires PAM, OpenBSD uses bsd_auth |
| tar -J | Not supported - use xz -d first |
| WireGuard | Use wg-quick, NOT manual ifconfig |
| Cursor theme | X11 looks in ~/.icons/, NOT ~/.local/share/icons/ |
| Bluetooth | NO native support - donβt even try |
| NVIDIA | Not supported - use Intel iGPU |
| Secure Boot | Must be disabled in BIOS |
| SATA Mode | Must be AHCI, not RAID |
WireGuard on OpenBSD
# Connect
doas wg-quick up /etc/wireguard/wg0.conf
# Disconnect
doas wg-quick down /etc/wireguard/wg0.conf
# Verify
curl https://am.i.mullvad.net/json
WiFi on OpenBSD
Only Intel iwm and USB Atheros athn work reliably.
# Check WiFi
ifconfig | grep -E "^iwm"
# Connect via hostname.if
doas vi /etc/hostname.iwn0
# Add: nwid "NetworkName" wpakey "password" dhcp
doas sh /etc/netstart iwn0
π CRYPTO CONFIG
File: ~/.config/crypto.toml
Format
api_key = "" # Optional CoinGecko API key
# Inline array MUST come before inline table
pairs = [
{ sym = "BTC", coin = "bitcoin", held = 0, entry = 0 },
{ sym = "ZEC", coin = "zcash", held = 0, entry = 0 },
{ sym = "XMR", coin = "monero", held = 0, entry = 0 },
{ sym = "LTC", coin = "litecoin", held = 0, entry = 0 },
]
[indicators]
rsi_period = 14
oversold = 30
overbought = 70
[display]
show_totals = false
Crypto Defaults
- Default coins: BTC, ZEC, XMR, LTC
- CoinGecko IDs: bitcoin, zcash, monero, litecoin
- No API key = rate limited queries
π ICON REFERENCE
See: docs/Icons.md
π POLYBAR REFERENCE
See: docs/polybar-state-architecture.md, docs/polybar-performance.md
π PROTON DRIVE REFERENCE
See: docs/proton-drive-module.md