Tauri 2 system-tray app for managing dnsmasq, Caddy, AeroSpace, and SketchyBar with nom parser-combinators and 63 tests

I have been into system ricing since Windows 7. Custom wallpapers on KLWP with KLCK and KWGT, a Hyprland rice with an embedded AI chatbot, SketchyBar replacing the macOS menu bar with something that actually shows me information I want. Ricing is fundamentally about asking whether the default is optimal — usually it is not — and then replacing it with something you built.
The configuration management that comes with ricing is less fun. By early 2026, after finishing the Prachyam infrastructure work, my local development environment ran on four config files that all touched the network stack: dnsmasq.conf for private DNS, a Caddyfile for HTTPS reverse-proxying local services, an AeroSpace config for window management, and a SketchyBar config for the menu bar display. Changing anything in dnsmasq required creating a resolver file in /etc/resolver/ with sudo, then restarting the service, then verifying it actually restarted, then checking that the DNS entry resolved correctly. Five steps. Two of them needed elevated privileges. The whole ritual took three to five minutes and demanded my full attention each time.
I was doing this ten times a day.
The default — manual terminal edits plus service restarts — was not optimal for someone managing four interconnected config surfaces that frequently needed simultaneous changes. I had accepted that default without examining it because each individual step felt small. The accumulated cost was not small.
ConfigPilot started as a weekend scratch project to collapse that ritual into a single form submission.
The core abstraction is a ConfigProvider trait. Each config file — dnsmasq, Caddy, AeroSpace, SketchyBar — is a struct that implements six methods: parse, validate, apply, reload, rollback, and health-check. React has no visibility into which providers exist. Adding a new config tool means writing one Rust struct; the frontend updates automatically because the provider list is dynamic.
The parsing layer is where the project got interesting. dnsmasq and Caddy use their own bespoke text formats, which means I needed actual parsers rather than regex substitution. I wrote nom parser-combinator grammars for both — nom lets you build parsers from composable primitives in a way that produces typed ASTs rather than strings with holes in them. The result: when ConfigPilot writes a dnsmasq entry back to disk, it knows the structure of the file, not just the position of a pattern. Edits are surgical.
AeroSpace and SketchyBar use TOML, which is more tractable, but they have a specific requirement: the config files often contain user comments that explain layout decisions, keyboard shortcut rationale, or widget configuration logic. Comments are not part of the TOML data model; a naive round-trip parse-and-serialize pass destroys them. I used toml_edit instead, which operates on the concrete syntax tree rather than the semantic AST. User comments survive every ConfigPilot write.
The diagnostics engine runs nine cross-provider checks: DNS resolution against configured entries, Caddy TLS certificate validity, service process health, port conflict detection, filesystem permission checks, config syntax validation, reload latency measurement, and two inter-provider consistency checks (for example: does every Caddy upstream have a corresponding dnsmasq entry?). Each check returns a score component; the engine aggregates to a 0–100 health number with specific failure explanations when something goes wrong.
SQLite in WAL mode stores config history and health timeseries. Every apply operation is recorded. Rolling back to any previous state is a single click. The timeseries means I can see whether the health score degraded after a specific change.
For the macOS integration: NSVisualEffectView via cocoa/objc Rust FFI gives the panel authentic vibrancy blur — the same visual treatment that native macOS apps use. Tauri 2 provides the system-tray entry point and native file access. React 19 with Tailwind CSS v4 and shadcn/ui builds the frontend. Zustand handles local state without the ceremony that Redux would have added for what is ultimately a dashboard-shaped UI.
The shell-script plugin system is the escape hatch: any tool whose config format is too idiosyncratic to warrant a full Rust provider can be wrapped in a shell script. ConfigPilot invokes it, captures the output, and displays it in the standard panel. I added this on day two when I realised that the abstraction needed a floor — a way to extend coverage without the overhead of writing Rust for every niche tool.
The project took two days of focused work during the early March 2026 personal sprint that came after finishing the Prachyam infrastructure phase. I kept a commit-per-logical-unit discipline throughout: 47 commits, each representing a complete and testable piece of behaviour rather than a checkpoint snapshot.
17,565 lines of code at close of the sprint. 63 passing tests covering the parser grammars, the provider trait implementations, the diagnostics engine checks, and the apply/rollback cycle. The parser tests are the ones I trust most — nom grammars are easy to over-engineer and easy to under-test, so I wrote tests for every edge case in the dnsmasq format that had ever surprised me in manual editing.
What I did not build: a settings sync mechanism, multi-machine support, or any concept of profiles beyond the current active config. Those were conscious scope cuts. The goal was to eliminate the five-step ritual from my own workflow. That goal is met.
The same logic that produced the Prachyam infrastructure work applies here at a smaller scale: understand what runs under you, own the variable rather than rent it.
In the infrastructure context, the variable was cloud service cost. Here, the variable is developer attention — the cognitive overhead of managing configuration files manually, the context-switch cost of a three-to-five-minute service restart sequence, the risk of typos in a config format that gives you no immediate feedback when you get it wrong.
Ricing culture has a useful discipline built in. You cannot rice a system you do not understand. Every wallpaper compositor, every window-manager keybind, every menu-bar widget is a small assertion about how your environment should behave and why. ConfigPilot is that same assertion applied to the infrastructure layer underneath the rice — the layer that actually determines whether your local services are reachable.
The recurring thesis that I find myself applying: look at the default, ask whether it is optimal for your situation, build the evidence, then do the work. Here the evidence was ten manual rituals per day across four config files over several months. The work was two days. The ratio holds.
Rust + Tauri
passing
nom parsers
Tauri 2 system-tray Docker manager with force-directed canvas graph, NSVisualEffectView vibrancy, and 19 commits
33-panel Tauri v2 + Svelte 5 macOS developer HUD with Rust sysinfo metrics, Docker management, and an embedded webhook server
Global-hotkey Tauri popup for Docker management with frecency ranking, Rust bollard, and Unix socket IPC
Did this resonate?