diff --git a/bread-theme/Cargo.toml b/bread-theme/Cargo.toml
index 39930a1..8dc41e7 100644
--- a/bread-theme/Cargo.toml
+++ b/bread-theme/Cargo.toml
@@ -18,3 +18,9 @@ gtk4 = { version = "0.11", features = ["v4_12"], optional = true }
# Enable GTK4 CSS provider helpers (breadbar, breadbox, breadpad use this).
# bread (daemon) and breadcrumbs (CLI) depend on this crate without the feature.
gtk = ["dep:gtk4"]
+
+# The generator CLI. It only touches the gtk-free lib API (render + write), so
+# it builds without the gtk feature and stays light.
+[[bin]]
+name = "bread-theme"
+path = "src/bin/bread-theme.rs"
diff --git a/bread-theme/src/bin/bread-theme.rs b/bread-theme/src/bin/bread-theme.rs
new file mode 100644
index 0000000..e79d5c0
--- /dev/null
+++ b/bread-theme/src/bin/bread-theme.rs
@@ -0,0 +1,50 @@
+//! `bread-theme` — generates the ecosystem's shared GTK stylesheet from the
+//! current pywal palette and writes it to the canonical path that every bread
+//! GUI loads. Run it at session start, and again after the wallpaper/palette
+//! changes (e.g. from a pywal hook); apps watch the file and recolour live.
+//!
+//! bread-theme # same as `generate`
+//! bread-theme generate # render + write the shared stylesheet
+//! bread-theme path # print the stylesheet path
+//! bread-theme print # render to stdout (no write)
+
+use std::process::ExitCode;
+
+fn main() -> ExitCode {
+ let cmd = std::env::args().nth(1).unwrap_or_else(|| "generate".into());
+ match cmd.as_str() {
+ "path" => {
+ println!("{}", bread_theme::shared_css_path().display());
+ ExitCode::SUCCESS
+ }
+ "print" => {
+ print!("{}", bread_theme::render());
+ ExitCode::SUCCESS
+ }
+ "generate" => match bread_theme::write_shared_css() {
+ Ok(path) => {
+ eprintln!("bread-theme: wrote {}", path.display());
+ ExitCode::SUCCESS
+ }
+ Err(e) => {
+ eprintln!("bread-theme: failed to write stylesheet: {e}");
+ ExitCode::FAILURE
+ }
+ },
+ "-h" | "--help" | "help" => {
+ eprintln!(
+ "bread-theme — shared stylesheet generator\n\n\
+ USAGE:\n bread-theme [generate|path|print]\n\n\
+ generate render the pywal palette to the shared stylesheet (default)\n\
+ path print the stylesheet path ({})\n\
+ print render to stdout without writing",
+ bread_theme::shared_css_path().display()
+ );
+ ExitCode::SUCCESS
+ }
+ other => {
+ eprintln!("bread-theme: unknown command '{other}' (try generate|path|print)");
+ ExitCode::FAILURE
+ }
+ }
+}
diff --git a/bread-theme/src/gtk.rs b/bread-theme/src/gtk.rs
index 6e62cb4..71f5306 100644
--- a/bread-theme/src/gtk.rs
+++ b/bread-theme/src/gtk.rs
@@ -1,7 +1,41 @@
+use gtk4::gio;
+use gtk4::prelude::*;
use gtk4::CssProvider;
use std::cell::RefCell;
use std::path::Path;
+thread_local! {
+ static SHARED_PROVIDER: RefCell