The TOML config layer four macOS apps share — warden
(terminals), curator (browser tabs),
lector (local doc sites) and
flotilla (document workspaces): the
window → group → tab shape, its validation, edits that keep your comments, and the fmt
formatter behind warden fmt, curator fmt and lector fmt.
It is not a generic config framework: each app keeps its own leaf tab type (curator:
url/session; warden: dir/shell/probe; lector: dir; flotilla: url), validation, and
the rules for how window and group settings pass down to each tab.
[dependencies]
config-core = { git = "https://github.com/lockyc/config-core", rev = "<commit>" }A config in the shared shape, with the app's own keys on its tabs:
[[window]]
title = "work"
colour = "#0f8a8a"
[[window.group]]
name = "services"
[[window.group.tab]]
title = "api"
url = "https://api.example.com/"Load it with your leaf tab type, check the shared keys, and format it in house style:
use config_core::{format_file, resolve_config_path, validate_windows, Window};
use serde::Deserialize;
#[derive(Deserialize)]
struct Tab { title: String, url: String }
#[derive(Deserialize)]
struct Config { #[serde(rename = "window")] windows: Vec<Window<Tab>> }
let path = resolve_config_path("MYAPP_CONFIG", "myapp"); // $MYAPP_CONFIG, else ~/.config/myapp/config.toml
let config: Config = toml::from_str(&std::fs::read_to_string(&path)?)?;
validate_windows(&config.windows)?; // titles, sizes, colours, group names
format_file(&path)?; // rewrites only when bytes changeA key outside the common set lands in the window's or group's extras type (NoExtras when an app
has none), so an unknown key is reported by name, inside the window, group and tab it sits in.
window—Window<T, X, G>/Group<T, G>with the common keys,validate_windows, andretitle_windowfor a rename made in place.edit— comment-preserving, atomic edits of windows, groups, tabs and keys viatoml_edit(re-exported, so callers need no dependency of their own).fmt— the house-style formatter (format_str,format_file) andfmt_cli, thefmtsubcommand behindwarden fmt,curator fmtandlector fmt.roots— finding every git repo under a[[window.root]]directory (warden and lector).paths,seed,colour,model— config-path resolution, a starter config written only when nothing is there,#rgb/#rrggbbcolours, and the sharedDensity,TabDigitKeysandWarningtypes.
Every function and its contract: the crate's rustdoc (cargo doc --open).
In use by all four apps, each pinned to a commit rev; there are no tags or crates.io releases.
chrome-core (the sidebar) and shell-core (app shell and release tooling) are the other two cores the apps share.
git clone https://github.com/lockyc/config-core && cd config-core
just gate # cargo fmt --check, clippy -D warnings, tests
cargo test # the quick loop: unit + golden formatter testsConventions: CLAUDE.md.
MIT — see LICENSE.