High-performance, async theme switching for Hyprland/Wayland desktops with Material You color schemes.
- ⚡ Blazing Fast: Async Rust implementation, modules run in parallel
- 🎨 Flexible Theming: Material You colors from wallpapers (via matugen), custom JSON colors, or built-in fallback themes
- 🔌 Modular: Supports 14+ applications (Waybar, Hyprland, VSCode, Wezterm, SwayNC, etc.)
- 🎯 Auto-Detection: Only applies themes to installed applications
- 🔧 Easy Setup: Auto-injects config includes with
lmtt setup - 🧹 Clean Uninstall:
lmtt cleanupremoves all injected config - ⚙️ Highly Configurable: TOML config at
~/.config/lmtt/config.toml - 🔔 Desktop Notifications: Optional notifications for theme changes
Add the [mason] repo to /etc/pacman.conf, then install:
[mason]
SigLevel = Optional TrustAll
Server = https://masonrhodesdev.github.io/arch-repo/x86_64sudo pacman -Sy lmttsudo dnf copr enable solaris765/lmtt
sudo dnf install lmtt- matugen - Optional, for wallpaper-based color generation
- If not installed, LMTT uses built-in Material You fallback themes
- Can also use custom JSON color files
- GTK 3/4 applications (optional, for
gsettingsintegration)
Requires Rust 1.70+ (rustup recommended):
git clone https://github.com/MasonRhodesDev/linux-multi-theme-toggle.git
cd linux-multi-theme-toggle
sudo make install PREFIX=/usrThis installs both binaries (lmtt, lmtt-config) plus the config example
and custom-module examples under /usr/share/lmtt/.
-
Initialize config:
lmtt init
-
Edit config at
~/.config/lmtt/config.toml:[general] wallpaper = "~/Pictures/your-wallpaper.png"
-
Run setup (auto-configures app config files):
lmtt setup
-
Switch theme:
lmtt switch # Toggle between light/dark lmtt switch dark # Switch to dark mode lmtt switch light # Switch to light mode
Launch the interactive configuration manager:
lmtt configEvery setting is editable from one screen:
The schema-driven TUI has three sections:
- General - wallpaper, default_mode, scheme_type, use_matugen, default color files, with Notifications / Performance / Cache / Logging as subsections
- Light Profile - GTK/icon/cursor themes, fonts, VSCode theme, opacity, blur for light mode
- Dark Profile - the same settings for dark mode
Modules are not toggled from the TUI — enable or disable one by editing
[modules.<name>] enabled = false in ~/.config/lmtt/config.toml (modules
are otherwise auto-skipped when their app isn't installed).
Controls:
Tab/←→/h/l- Switch between sections↑↓orj/k- Navigate itemsSpace/Enter- Toggle boolean valuese- Open full config in$EDITORq/Esc- Quit
Changes are saved immediately to ~/.config/lmtt/config.toml.
# Switch theme
lmtt switch # Toggle between light/dark
lmtt switch dark # Switch to dark mode
lmtt switch light # Switch to light mode
lmtt switch --no-notify # Toggle without notifications
# Interactive configuration
lmtt config # TUI for managing all settings
# Setup mode (configure app configs)
lmtt setup
lmtt setup --dry-run
# Cleanup mode (remove lmtt config injections)
lmtt cleanup
lmtt cleanup --module waybar # Cleanup specific module
lmtt cleanup --dry-run
# Status and info
lmtt status
lmtt list
lmtt list --allConfig file: ~/.config/lmtt/config.toml
[general]
wallpaper = "~/Pictures/forrest.png"
default_mode = "dark"
scheme_type = "scheme-tonal-spot"
use_matugen = true # Set to false to use fallback/custom colors
default_light_colors = "~/.config/lmtt/colors-light.json"
default_dark_colors = "~/.config/lmtt/colors-dark.json"
[notifications]
enabled = true
timeout = 5000
[modules.waybar]
enabled = true
[modules.hyprland]
enabled = trueKey features:
- Modules enabled by default: Apps are auto-detected and run if installed
- Disable modules: Set
enabled = falseto skip specific apps - Flexible color sources:
- matugen (default): Generate colors from wallpaper
- Custom JSON: Provide your own
colors-light.jsonandcolors-dark.json - Built-in fallback: Material You themes if matugen not available
Create your own color schemes by placing JSON files at ~/.config/lmtt/colors-light.json and ~/.config/lmtt/colors-dark.json:
{
"surface": "#fbf8ff",
"on_surface": "#1a1b23",
"primary": "#3a6a33",
"on_primary": "#ffffff",
"secondary": "#7d525f",
"error": "#ba1a1a",
"outline": "#74767f",
"surface_variant": "#e0e2ec",
"on_surface_variant": "#44464f"
}Set use_matugen = false in config to use custom colors instead of wallpaper-based generation.
LMTT supports user-defined custom modules in ~/.config/lmtt/modules/ - no recompilation needed!
1. Declarative (Template-based) - For simple config files:
# ~/.config/lmtt/modules/alacritty.toml
name = "alacritty"
binary = "alacritty"
[output]
path = "~/.config/alacritty/lmtt-colors.yml"
[template]
content = """
colors:
primary:
background: '{{surface}}'
foreground: '{{on_surface}}'
"""2. Script-based - For complex logic:
# ~/.config/lmtt/modules/spotify.toml
name = "spotify"
binary = "spotify"
[script]
path = "~/.config/lmtt/scripts/spotify.sh"
timeout = 10000Custom modules are automatically discovered and loaded. See examples/modules/ for working examples (Alacritty, Kitty, Discord, Spotify) and examples/README-modules.md for full documentation.
| Module | Config File | Auto-Setup |
|---|---|---|
| GTK | gsettings | ✓ |
| Waybar | style.css |
✓ |
| Hyprland | lmtt-colors.conf |
✓ |
| SwayNC | style.css |
✓ |
| Wezterm | lmtt-colors.lua |
✓ |
| Tmux | lmtt-colors.conf |
✓ |
| Neovim | lmtt-colors.lua |
✓ |
| VSCode | settings.json |
✓ |
| Wofi | style.css |
✓ |
| Fish | universal variables (set -U) |
— |
lmtt setup checks your installed applications and prompts to inject config includes:
$ lmtt setup
🔧 LMTT Setup Mode
================
✓ waybar detected
📄 /home/user/.config/waybar/style.css
Import lmtt colors into Waybar CSS
⚠ Include line missing:
@import url('../matugen/lmtt-colors.css');
Inject this line? [Y/n/q] y
✓ Injected successfully!Each module adds a marked block at the top of your config:
/* >>> lmtt managed block - do not edit manually >>> */
@import url('../matugen/lmtt-colors.css');
/* <<< lmtt managed block <<< */
/* Your existing config below */The marker comment syntax matches the file type: CSS uses /* */, Lua uses
--, and conf/ini files use #.
This allows clean removal with lmtt cleanup.
Remove all lmtt-injected config lines:
# Clean all modules
lmtt cleanup
# Clean specific module
lmtt cleanup --module waybar
# Dry run (see what would be removed)
lmtt cleanup --dry-runThis is completely non-intrusive - your original config files are restored.
Runtime pipeline for a theme switch:
flowchart TD
CMD["lmtt switch (mode)"] --> CFG["Load config from ~/.config/lmtt/"]
CFG --> RES{"Color resolution"}
RES -->|"use_matugen: matugen from wallpaper (cached — skipped if wallpaper unchanged)"| SCHEME["ColorScheme"]
RES -->|"else: custom colors-light.json / colors-dark.json"| SCHEME
RES -->|"else: built-in Material You fallback palette"| SCHEME
SCHEME --> REG["ModuleRegistry — inventory-discovered ThemeModule impls (17 built-ins + handlebars-templated custom modules)"]
subgraph PAR ["apply() for every enabled module, in parallel on Tokio — whole switch ~100-200ms"]
GTK["GTK: gsettings color-scheme + theme names"]
HYP["Hyprland: write lmtt-colors.conf include, hyprctl reload"]
XDG["xdg-desktop-portal: color-scheme via dbus-send"]
APPS["config writes: Waybar / SwayNC / Wofi CSS, Wezterm / Neovim Lua, Tmux conf, VSCode settings.json, ..."]
end
REG --> PAR
PAR --> NOTE["notify-send (optional)"]
lmtt/ # CLI binary
lmtt-core/ # Core types (Config, ColorScheme, Cache)
lmtt-modules/ # Theme modules (Waybar, Hyprland, etc.)
lmtt-platforms/ # Platform backends (GTK, XDG, Qt)
See lmtt-modules/src/waybar.rs for a template. Key points:
- Implement
ThemeModuletrait - Specify
binary_name()for auto-detection - Implement
apply()for theme switching - Implement
config_files()for setup mode - Add to
ModuleRegistryinregistry.rs
Typical theme switch: ~100-200ms
- Modules run in parallel (Tokio async)
- No blocking I/O
- Wallpaper color caching (skips regeneration if unchanged)
Performance warnings for slow modules (>250ms default).
Desktop notifications are shown when the theme changes (disable with
--no-notify, or [notifications] enabled = false in the config). Set
show_module_progress = true for a per-module notification as each applies.
# Check if app is installed
lmtt list --all
# Check config
lmtt status
# Verbose output
lmtt -v switch dark# Re-run setup
lmtt setup
# Verify config file includes lmtt block
cat ~/.config/waybar/style.cssConfig files must have the lmtt marker comments. If you manually edited them, you may need to manually remove the include lines.
The Rust version is a drop-in replacement with improved performance:
- Backup your current bash scripts
- Install lmtt
- Run
lmtt initandlmtt setup - Test with
lmtt switch dark
Your existing module configs should work without changes.
Contributions welcome! Areas needing help:
- Additional module support (Alacritty, Kitty, etc.)
- Platform backends (KDE Plasma integration)
- Documentation improvements
- Testing on different distros
MIT
- matugen - Material You color generation
- Original bash implementation by Mason
