Mosaico
A cross-platform tiling window manager, written in Rust.
Mosaico automatically arranges your windows into a non-overlapping tiled layout. It ships three tiling algorithms (BSP, VerticalStack, ThreeColumn) that you can cycle per workspace at runtime, runs as a lightweight background daemon, and is controlled entirely from the command line or via global keyboard shortcuts.
Features
- Automatic tiling with three algorithms – BSP (default),
VerticalStack, and ThreeColumn. Cycle on the fly with
Alt + Nor pin a layout per workspace. - Vim-style navigation – focus and move windows with
Alt + H/J/K/L. - Workspaces – up to 8 workspaces, switching either per-monitor (default) or globally across every display, like Windows virtual desktops.
- Multi-monitor – each monitor is managed independently with cross-monitor navigation.
- Per-window borders – focused, monocle, and unfocused color states
under
[borders.colors]. - Monocle mode – full-screen single-window mode per monitor.
- Status bar – configurable per-monitor bar with workspace indicators, clock, CPU, RAM, focused window icon, pause indicator, and more.
- Three theme families – Catppuccin, Rosé Pine, and Tokyo Night with multiple flavors each.
- Pause / unpause hotkeys –
Alt + Shift + Preleases every Mosaico shortcut so full-screen applications can claim the same combinations. - Hot-reload – changes to
config.toml,bar.toml, anduser-rules.tomlare applied without restarting. - Window rules – community-maintained rules plus user overrides to exclude specific applications from tiling.
Quick Start
# Install on Windows
irm https://raw.githubusercontent.com/jmelosegui/mosaico/main/docs/install.ps1 | iex
# Create default config files
mosaico init
# Start the window manager
mosaico start
See Installation for more options or Getting Started for a walkthrough.
License
Mosaico is released under the MIT License.
Installation
Windows
Run the following command in PowerShell to download and install the latest release:
irm https://raw.githubusercontent.com/jmelosegui/mosaico/main/docs/install.ps1 | iex
The installer downloads the latest release from GitHub and places the binary
in %LOCALAPPDATA%\mosaico. It also adds that directory to your user PATH
so you can run mosaico from any terminal.
From Source
If you have the Rust toolchain installed, you can build and install directly:
cargo install --path .
Or build a release binary without installing:
cargo build --release
The binary will be at target/release/mosaico.exe.
Verifying the Installation
After installing, verify that Mosaico is available:
mosaico --version
You should see the version number printed to the terminal.
Getting Started
This guide walks you through your first session with Mosaico.
1. Generate Configuration Files
Create the default configuration files in ~/.config/mosaico/:
mosaico init
This generates the following files:
| File | Purpose |
|---|---|
config.toml | Layout, border, theme, and logging settings |
keybindings.toml | Keyboard shortcut mappings |
rules.toml | Community rules (auto-updated on daemon startup) |
user-rules.toml | Personal rule overrides (never overwritten) |
bar.toml | Status bar settings |
Existing files are never overwritten, so it is safe to run init again.
2. Start the Window Manager
mosaico start
Mosaico launches a background daemon that immediately tiles all visible windows on your desktop. You will see a startup banner with your config directory, the daemon PID, and a helpful tip.
3. Navigate with Keyboard Shortcuts
The default keybindings use vim-style motions:
| Shortcut | Action |
|---|---|
Alt + H/J/K/L | Focus left/down/up/right |
Alt + Shift + H/J/K/L | Move or swap the focused window |
Alt + 1 .. Alt + 8 | Switch to workspace 1-8 |
Alt + Shift + 1 .. Alt + Shift + 8 | Send focused window to workspace 1-8 |
Alt + N | Cycle layout (BSP / VerticalStack / ThreeColumn) |
Alt + T | Toggle monocle (full-screen) mode |
Alt + M | Minimize the focused window |
Alt + Q | Close the focused window |
Alt + Shift + R | Retile (re-apply the current layout) |
Alt + Shift + P | Pause / resume all Mosaico hotkeys |
The full reference card lives at the Cheatsheet. Edit
~/.config/mosaico/keybindings.toml to remap any shortcut.
4. Pick a Theme (optional)
Mosaico ships with three theme families that color the status bar and
the focus border. Set the active theme in ~/.config/mosaico/config.toml:
[theme]
name = "rose-pine" # catppuccin (default), rose-pine, tokyo-night
flavor = "main"
Save and the colors update live, no restart needed. See Theming for the full palette per family.
5. Check the Status
mosaico status
Reports whether the daemon is running and its PID.
6. Run the Doctor
mosaico doctor
Performs a health check on your configuration files, daemon status, and monitor setup. Any issues are reported with colored status tags.
7. Stop the Window Manager
mosaico stop
All windows are restored to their original state before the daemon exits.
Next Steps
- Cheatsheet – one-page reference card for every default shortcut
- CLI Commands – full command reference
- Configuration – customize layout, borders, and more
- Keyboard Bindings – change or add shortcuts
- Workspaces – per-monitor and global workspace modes
- Focus Borders – focused, monocle, and unfocused border colors
- Theming – Catppuccin, Rosé Pine, Tokyo Night palettes
Cheatsheet
A one-page reference for the default Mosaico keyboard shortcuts and CLI actions. Print it, pin it, or just keep this tab open.
Tip: every shortcut shown here can be remapped in
~/.config/mosaico/keybindings.toml. See Keyboard Bindings for the full configuration reference.
At a Glance
Alt + H/J/K/L focus left/down/up/right
Alt + Shift + H/J/K/L move/swap window left/down/up/right
Alt + 1 .. Alt + 8 switch to workspace N
Alt + Shift + 1 .. 8 send focused window to workspace N
Alt + N cycle layout (BSP -> VStack -> 3Col)
Alt + T toggle monocle (full-screen one window)
Alt + M minimize focused window
Alt + Q close focused window
Alt + Shift + R retile (re-apply current layout)
Alt + Shift + P pause / unpause all mosaico hotkeys
Focus
Move keyboard focus between tiled windows. Left and right cross monitors when no neighbor exists in that direction; up and down stay on the current monitor.
| Shortcut | Action | CLI |
|---|---|---|
Alt + H | Focus left | mosaico action focus left |
Alt + J | Focus down | mosaico action focus down |
Alt + K | Focus up | mosaico action focus up |
Alt + L | Focus right | mosaico action focus right |
Move
Swap the focused window with its neighbor in the given direction. Left and right can move a window between adjacent monitors; up and down swap within the same monitor.
| Shortcut | Action | CLI |
|---|---|---|
Alt + Shift + H | Move left | mosaico action move left |
Alt + Shift + J | Move down | mosaico action move down |
Alt + Shift + K | Move up | mosaico action move up |
Alt + Shift + L | Move right | mosaico action move right |
Workspaces
Each monitor has up to 8 workspaces. The default mode is per-monitor:
switching workspace only affects the focused monitor. Set
workspaces.mode = "global" in config.toml to flip every monitor in
lockstep, like Windows virtual desktops. See
Workspaces.
| Shortcut | Action | CLI |
|---|---|---|
Alt + 1 | Switch to workspace 1 | mosaico action goto-workspace-1 |
Alt + 2 | Switch to workspace 2 | mosaico action goto-workspace-2 |
| … | … | … |
Alt + 8 | Switch to workspace 8 | mosaico action goto-workspace-8 |
Alt + Shift + 1 | Send window to workspace 1 | mosaico action send-to-workspace-1 |
Alt + Shift + 2 | Send window to workspace 2 | mosaico action send-to-workspace-2 |
| … | … | … |
Alt + Shift + 8 | Send window to workspace 8 | mosaico action send-to-workspace-8 |
Layout
Cycle through Mosaico’s three tiling algorithms or switch the focused workspace into monocle mode (one window fills the work area). Retile forces a fresh re-application of the current layout.
| Shortcut | Action | CLI |
|---|---|---|
Alt + N | Cycle layout (BSP -> VerticalStack -> ThreeColumn -> …) | mosaico action cycle-layout |
Alt + T | Toggle monocle mode | mosaico action toggle-monocle |
Alt + Shift + R | Retile | mosaico action retile |
Per-workspace layout overrides are configured under
[workspaces.layouts] in config.toml. See
Tiling & Layouts.
Window
| Shortcut | Action | CLI |
|---|---|---|
Alt + Q | Close focused window | mosaico action close-focused |
Alt + M | Minimize focused window | mosaico action minimize-focused |
Daemon
Pause every Mosaico hotkey (including the pause hotkey itself stays
active so you can resume) when running a full-screen application that
needs to claim its own keybindings. The status bar shows a red PAUSED
pill while paused.
| Shortcut | Action | CLI |
|---|---|---|
Alt + Shift + P | Toggle pause / resume | mosaico pause / mosaico unpause |
| – | Start the daemon | mosaico start |
| – | Stop the daemon | mosaico stop |
| – | Check status | mosaico status |
| – | Reload config (automatic) | edit config.toml, save |
| – | Diagnose setup | mosaico doctor |
Modifier Keys
| Keyword | Key |
|---|---|
alt | Alt |
shift | Shift |
ctrl | Control |
win | Windows / Super |
Combine in keybindings.toml with
modifiers = ["alt", "shift"].
Recognised Key Names
| Type | Examples |
|---|---|
| Letters | A .. Z (case-insensitive) |
| Digits | 0 .. 9 |
| Function | F1 .. F12 |
| Named | Enter, Escape, Tab, Space, Backspace, Delete, Insert, Home, End, PageUp, PageDown, Up, Down, Left, Right |
Set them in ~/.config/mosaico/keybindings.toml like this:
[[keybinding]]
action = "focus-left"
key = "H"
modifiers = ["alt"]
[[keybinding]]
action = "send-to-workspace-3"
key = "3"
modifiers = ["alt", "shift"]
Themes at a Glance
[theme]
name = "catppuccin" # catppuccin, rose-pine, tokyo-night
flavor = "mocha" # depends on family (see below)
| Family | Flavors |
|---|---|
catppuccin | mocha, macchiato, frappe, latte |
rose-pine | main, moon, dawn |
tokyo-night | night, storm, day |
See Theming for palette colors per family.
Border Colors at a Glance
[borders]
width = 4 # 0 disables every border
corner_style = "small" # square / small / round
[borders.colors]
focused = "" # empty = theme default
monocle = "" # empty = theme default
unfocused = "" # empty = theme default; "none" disables unfocused borders
See Focus Borders for the full lifecycle.
See Also
- Configuration – every config field, all four files.
- Keyboard Bindings – full action reference and how to remap.
- CLI Commands – start, stop, status, action, doctor, …
CLI Commands
All interactions with Mosaico go through the command-line interface.
mosaico init
Creates default configuration files in ~/.config/mosaico/:
config.toml– layout, border, theme, and logging settingskeybindings.toml– keyboard shortcutsrules.toml– community window rules (auto-updated on daemon startup)user-rules.toml– personal rule overridesbar.toml– status bar settings
Files that already exist are skipped to preserve your customizations. On first run, you are prompted to enable automatic startup.
mosaico start
Launches the daemon as a detached background process. On success, a startup banner is printed showing the config directory, PID, and a usage tip. If a newer release is available on GitHub, an update notice is shown.
If the daemon is already running, the command reports the existing state instead of starting a second instance.
mosaico stop
Sends a stop command to the running daemon. All windows are restored to their original positions before the daemon exits. If the daemon is unresponsive, a fallback mechanism terminates the process directly.
mosaico status
Reports whether the daemon is running, along with its PID. Detects and cleans up stale PID files from crashed sessions.
mosaico doctor
Runs a comprehensive health check and prints colored status tags for each item:
| Tag | Meaning |
|---|---|
[ok] | Check passed |
[warn] | Non-critical issue |
[fail] | Critical problem |
[fixed] | Auto-remediated |
Checks performed:
- Config directory exists (creates it if missing)
config.tomlsyntax validation- Theme flavor validation
keybindings.tomlsyntax validation- Key names resolve to valid key codes
rules.tomlsyntax validation- Community rules cache age
user-rules.tomlsyntax validationbar.tomlsyntax validation- Autostart status
- Daemon status (IPC pipe, PID file, process liveness)
- Monitor enumeration and dimensions
mosaico autostart
Manages automatic startup when Windows boots.
mosaico autostart enable # Register to start on logon
mosaico autostart disable # Remove the startup entry
mosaico autostart status # Show current autostart state
This writes a value under the HKEY_CURRENT_USER registry Run key, so no
administrator rights are needed.
On first run, mosaico init also prompts to enable autostart.
mosaico update
Checks GitHub for a newer release and installs it automatically. If the daemon is running, it is stopped before the update and restarted afterward.
mosaico update # Update to the latest release
mosaico update --force # Reinstall even if already on the latest version
The --force flag is useful for recovering a corrupted binary.
mosaico action <verb> [direction]
Sends a tiling action to the running daemon. Available actions:
mosaico action focus left|right|up|down
mosaico action move left|right|up|down
mosaico action retile
mosaico action toggle-monocle
mosaico action close-focused
mosaico action goto-workspace <1-8>
mosaico action send-to-workspace <1-8>
These are the same actions triggered by keyboard shortcuts, useful for scripting or integration with other tools.
mosaico pause / mosaico unpause
Temporarily suspends all mosaico global hotkeys so another application can use those key combinations, then restores them.
mosaico pause # Unregister all hotkeys (releases them to the OS)
mosaico unpause # Re-register all hotkeys
While paused, the status bar shows a red PAUSED indicator. You can also
toggle pause from the keyboard by binding the toggle-pause action — the
toggle hotkey remains registered while paused so you can resume without opening
a terminal. See Keyboard Bindings for setup.
mosaico debug list
Displays a formatted table of all visible windows showing:
- HWND (hex)
- Managed status
- Monitor number
- Title and class name
- Position and dimensions
- Border offset
mosaico debug events
Streams real-time window events to stdout. Press Ctrl+C to stop. Useful
for understanding how Mosaico reacts to window changes.
mosaico debug move <hwnd> <x> <y> <width> <height>
Moves a specific window to exact pixel coordinates. The HWND can be provided
in decimal or 0x hex format. Useful for testing window positioning.
Configuration
Mosaico uses TOML configuration files stored in ~/.config/mosaico/. All
settings have sensible defaults, so configuration files are entirely optional.
Run mosaico init to generate fully-commented template files.
Configuration Files
| File | Purpose | Hot-Reload |
|---|---|---|
config.toml | Layout, borders, theme, logging | Yes |
keybindings.toml | Keyboard shortcuts | No (restart required) |
rules.toml | Community window rules (auto-downloaded) | On startup |
user-rules.toml | Personal window rule overrides | Yes |
bar.toml | Status bar settings | Yes |
config.toml
Controls layout, borders, logging, and theme:
[layout]
default = "bsp" # Default layout algorithm: "bsp", "vertical-stack", "three-column"
gap = 8 # Pixel gap between windows (0-200)
ratio = 0.5 # BSP split ratio (0.1-0.9)
hiding = "cloak" # How windows hide on workspace switch: "cloak", "hide", "minimize"
[workspaces]
# How a workspace switch is applied across monitors.
# "per-monitor" (default): only the focused monitor switches.
# "global": all monitors switch in lockstep, like Windows virtual desktops.
mode = "per-monitor"
[workspaces.layouts]
# Available: "bsp", "vertical-stack", "three-column"
1 = "three-column" # Override layout for workspace 1
3 = "vertical-stack" # Override layout for workspace 3
# Workspaces without an entry use [layout].default
[borders]
width = 4 # Border thickness in pixels (0-32)
corner_style = "small" # "square", "small", or "round"
[borders.colors]
focused = "#00b4d8" # Color of the focused window in tiled layouts
monocle = "#2d6a4f" # Color of the focused window in monocle mode
unfocused = "#6c7086" # Color drawn around unfocused tiled windows;
# set to "none" to disable unfocused borders
[theme]
name = "catppuccin" # catppuccin, rose-pine, tokyo-night
flavor = "mocha" # catppuccin: mocha | macchiato | frappe | latte
# rose-pine: main | moon | dawn
# tokyo-night: night | storm | day
[logging]
enabled = false # Enable file logging
level = "info" # Log level: debug, info, warn, error
max_file_mb = 10 # Max log file size before rotation
keybindings.toml
Maps key combinations to actions. See Keyboard Bindings for the full reference.
[[keybinding]]
action = "focus-down"
key = "J"
modifiers = ["alt"]
bar.toml
Configures the status bar. See Status Bar for details.
enabled = true
height = 28
monitor = "all" # "all", "primary", or 0-based index
[colors]
background = "base" # Named Catppuccin color
foreground = "text"
accent = "blue"
[[left]]
type = "workspaces"
[[center]]
type = "clock"
format = "%H:%M"
[[right]]
type = "cpu"
rules.toml and user-rules.toml
Window rules control which applications are tiled. Community rules are
downloaded automatically to rules.toml on daemon startup. Add personal
overrides in user-rules.toml (user rules take priority).
See Window Rules for details.
# user-rules.toml — your personal overrides
[[rule]]
match_title = "My Private Tool"
manage = false
Partial Files
All configuration fields have defaults. You only need to include the settings you want to change. A file containing only:
[layout]
gap = 12
will use defaults for everything else.
Validation
Out-of-range values are automatically clamped to safe boundaries rather than rejected:
| Setting | Valid Range |
|---|---|
gap | 0 – 200 |
ratio | 0.1 – 0.9 |
border width | 0 – 32 |
corner_style | "square", "small", "round" |
hiding | "cloak", "hide", "minimize" |
default | "bsp", "vertical-stack", "three-column" |
Hot-Reload
Changes to config.toml, user-rules.toml, and bar.toml are
automatically detected and applied while the daemon is running (polled
every 2 seconds).
- config.toml – layout gap/ratio, hiding behaviour, border settings, and theme are reloaded. Windows are retiled immediately. Hiding changes take effect on the next workspace switch.
- user-rules.toml – both rule sets are re-merged and existing windows are re-evaluated against the new rules.
- bar.toml – the status bar is recreated with updated settings and colors.
- rules.toml – community rules, updated only on daemon startup.
- keybindings.toml – not hot-reloaded. Changes require a daemon
restart (
mosaico stop && mosaico start).
Only valid configurations are applied. If a file change introduces a parse error, the current configuration is kept and a warning is logged.
Keyboard Bindings
Mosaico registers global system hotkeys that work regardless of which
application has focus. Keybindings are configured in
~/.config/mosaico/keybindings.toml.
Default Keybindings
The defaults use vim-style spatial navigation (H=left, J=down, K=up, L=right). For a printable one-page reference, see the Cheatsheet.
| Shortcut | Action |
|---|---|
Alt + H | Focus left |
Alt + J | Focus down |
Alt + K | Focus up |
Alt + L | Focus right |
Alt + Shift + H | Move left |
Alt + Shift + J | Move down |
Alt + Shift + K | Move up |
Alt + Shift + L | Move right |
Alt + Shift + R | Retile |
Alt + T | Toggle monocle |
Alt + N | Cycle layout |
Alt + M | Minimize focused window |
Alt + Q | Close focused window |
Alt + 1 .. Alt + 8 | Switch to workspace 1-8 |
Alt + Shift + 1 .. Alt + Shift + 8 | Send window to workspace 1-8 |
Alt + Shift + P | Toggle pause / resume |
Configuration Format
Each binding is a [[keybinding]] entry with three fields:
[[keybinding]]
action = "focus-left"
key = "H"
modifiers = ["alt"]
[[keybinding]]
action = "move-left"
key = "H"
modifiers = ["alt", "shift"]
Actions
| Action | Description |
|---|---|
focus-left | Focus the window to the left |
focus-right | Focus the window to the right |
focus-up | Focus the window above |
focus-down | Focus the window below |
move-left | Move window left (swap or cross-monitor) |
move-right | Move window right |
move-up | Move window up (swap on same monitor) |
move-down | Move window down |
retile | Re-apply the tiling layout |
toggle-monocle | Toggle monocle (full-screen) mode |
cycle-layout | Cycle to the next tiling layout (BSP -> VStack -> 3Col) |
close-focused | Close the focused window |
minimize-focused | Minimize the focused window |
goto-workspace-N | Switch to workspace N (1-8) |
send-to-workspace-N | Send focused window to workspace N (1-8) |
toggle-pause | Toggle hotkey pause on/off |
Modifiers
| Modifier | Key |
|---|---|
alt | Alt key |
shift | Shift key |
ctrl | Control key |
win | Windows key |
Supported Keys
| Key Type | Examples |
|---|---|
| Letters | A – Z (case-insensitive) |
| Digits | 0 – 9 |
| Function keys | F1 – F12 |
| Named keys | Enter, Tab, Escape, Space |
| Arrow keys | Left, Right, Up, Down |
| Punctuation | Minus, Plus, Comma, Period |
Unknown key names are skipped with a log message.
Pause / Unpause
If another application uses the same global shortcuts as mosaico, you can temporarily release mosaico’s hotkeys so that application can receive them:
[[keybinding]]
action = "toggle-pause"
key = "P"
modifiers = ["alt", "shift"]
Press Alt+Shift+P to pause — the status bar shows a red PAUSED indicator.
Press it again to resume. You can also use the CLI:
mosaico pause
mosaico unpause
The toggle-pause hotkey stays registered while paused so you can always
resume from the keyboard without opening a terminal.
Auto-merge
On each daemon start, any default keybinding actions not present in your
keybindings.toml are automatically appended to the file. This ensures you
pick up new shortcuts added in future versions without overwriting any of your
customizations. Actions you’ve already bound (even to different keys) are
never touched.
Reloading
Keybinding changes are not hot-reloaded. You must restart the daemon for changes to take effect:
mosaico stop && mosaico start
Window Rules
Window rules control which applications Mosaico manages. Rules are split into two files:
| File | Purpose |
|---|---|
rules.toml | Community rules, downloaded on daemon startup |
user-rules.toml | Your personal rules, never overwritten |
Both files live in ~/.config/mosaico/.
How It Works
When the daemon starts, it downloads the latest community rules from the
mosaico-rules repository
and saves them to rules.toml. Your personal rules in user-rules.toml
are never touched.
At runtime, both files are merged: user rules are evaluated first, so they take priority over community defaults. The first matching rule wins.
Rule Format
Each rule is a [[rule]] entry:
[[rule]]
match_class = "ApplicationFrameWindow"
manage = false
[[rule]]
match_title = "Calculator"
manage = false
[[rule]]
match_class = "Chrome_WidgetWin_1"
match_title = "Picture-in-Picture"
manage = false
Rule Fields
| Field | Type | Description |
|---|---|---|
match_class | string | Match by window class name (case-insensitive, exact) |
match_title | string | Match by window title (case-insensitive, substring) |
manage | bool | Whether to tile the window (true or false) |
Matching Behavior
- Class match: case-insensitive exact match against the window class name.
- Title match: case-insensitive substring match against the window title.
- If a rule specifies both
match_classandmatch_title, both must match. - If a rule specifies neither, it matches everything.
Evaluation Order
Rules are evaluated in order. User rules (user-rules.toml) come first,
followed by community rules (rules.toml). The first matching rule
wins. If no rule matches a window, it is managed by default.
This means you can override any community rule by adding a rule in
user-rules.toml. For example, to force-tile a window that community
rules exclude:
# user-rules.toml
[[rule]]
match_class = "Chrome_WidgetWin_1"
manage = true
Community Rules
Community rules are maintained at github.com/jmelosegui/mosaico-rules. They cover common exclusions like UWP apps, GPU overlays, system dialogs, and VPN clients.
If you find a window that should be excluded for all users, consider
contributing
the rule upstream instead of keeping it in user-rules.toml.
Hot-Reload
Changes to user-rules.toml are automatically detected and applied while
the daemon is running. When the file changes, both rule sets are re-merged
and existing windows are re-evaluated against the new rules.
Community rules (rules.toml) are only updated on daemon startup.
Finding Window Class Names
Use the debug list command to see the class names of all visible windows:
mosaico debug list
The output includes the class name for each window, which you can use in your rules.
Status Bar
Mosaico includes a configurable status bar that sits at the top of each
monitor. It is configured in ~/.config/mosaico/bar.toml.
Configuration
enabled = true
height = 28
monitor = "all" # "all", "primary", or 0-based index
[colors]
background = "base" # Named theme color or hex
foreground = "text"
accent = "blue"
[[left]]
type = "workspaces"
[[center]]
type = "clock"
format = "%H:%M"
[[right]]
type = "cpu"
General Settings
| Setting | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Show or hide the bar |
height | int | 28 | Bar height in pixels |
monitor | string | "all" | Which monitors show the bar |
The monitor field accepts:
"all"– show on every monitor"primary"– show only on the primary monitor- A number (e.g.
0,1) – show on a specific monitor by index
Colors
Colors can be specified as hex values ("#1e1e2e") or as named theme
colors ("blue", "green", "mauve", etc.). The named-color palette
depends on the active theme family (Catppuccin, Rosé Pine, Tokyo Night);
see Theming for the full list per family.
| Setting | Description |
|---|---|
background | Bar background color |
foreground | Default text color |
accent | Highlight color for active elements |
Widgets
Widgets are placed in [[left]], [[center]], or [[right]] arrays.
| Widget | Description | Options |
|---|---|---|
workspaces | Workspace indicator pills | – |
active_window | Icon of the focused window | – |
layout | Current layout mode | – |
clock | Current time | format (strftime) |
date | Current date | format (strftime) |
ram | RAM usage percentage | – |
cpu | CPU usage percentage | – |
update | Update indicator | – |
media | Currently playing track | max_length |
paused | Shown (in red) when hotkeys are paused | color |
The active_window widget displays the application icon of the currently
focused window. It extracts the icon from the running process and renders
it as a bitmap in the bar. When no window is focused or the icon cannot be
determined, the widget is hidden automatically.
The media widget shows the currently playing track (“Artist - Title”)
using the Windows media transport controls API (GSMTC). It works with
Spotify, browser media (YouTube, SoundCloud, etc.), VLC, and any app that
integrates with Windows media controls. When nothing is playing, the
widget is hidden automatically. Long titles are truncated to max_length
characters (default 40) with an ellipsis. Some third-party media apps
may not register with GSMTC and will not be detected.
[[right]]
type = "media"
icon = "\uF001" # music note icon
max_length = 40 # truncate long titles
Example: Full Bar
[[left]]
type = "workspaces"
[[left]]
type = "active_window"
[[left]]
type = "layout"
[[center]]
type = "clock"
format = "%H:%M"
[[right]]
type = "media"
icon = "\uF001"
max_length = 40
[[right]]
type = "cpu"
[[right]]
type = "ram"
[[right]]
type = "date"
format = "%a %d %b"
The paused widget is auto-hidden when hotkeys are active and shown in red
when they are paused. It is included in the default config and is added
automatically to existing bar.toml files on daemon startup (along with any
other new default widgets from future versions).
Work Area
The bar reserves space at the top of the monitor. The tiling layout automatically accounts for the bar height so windows do not overlap it.
Hot-Reload
Changes to bar.toml are automatically applied while the daemon is running.
The bar is recreated with the new settings and all monitors are retiled.
Theming
Mosaico ships with three built-in theme families: Catppuccin, Rosé Pine, and Tokyo Night. Each family has multiple flavors that share a common palette and only differ in shading, so the focus borders, monocle border, unfocused borders, and the status bar all stay coordinated.
Configuration
Set the theme name and flavor in config.toml:
[theme]
name = "catppuccin" # catppuccin, rose-pine, tokyo-night
flavor = "mocha"
Available Themes
Catppuccin
| Flavor | Style |
|---|---|
latte | Light |
frappe | Medium-dark |
macchiato | Dark |
mocha | Darkest (default) |
Rosé Pine (name = "rose-pine")
| Flavor | Style |
|---|---|
main | Dark, default |
moon | Slightly lighter dark |
dawn | Light |
Tokyo Night (name = "tokyo-night")
| Flavor | Style |
|---|---|
night | Dark, default |
storm | Dark with bluish tint |
day | Light |
Named Colors
When a theme is active, you can use named colors anywhere a color value is
expected (borders, bar colors). Each theme family exposes its own palette,
plus a small set of common aliases (red, green, blue, yellow) that
resolve under every theme so portable configs like focused = "blue" look
right regardless of which theme you pick.
Catppuccin (14 accent colors)
| Name | Description |
|---|---|
rosewater | Warm pink |
flamingo | Soft pink |
pink | Pink |
mauve | Purple |
red | Red |
maroon | Dark red |
peach | Orange |
yellow | Yellow |
green | Green |
teal | Teal |
sky | Light blue |
sapphire | Blue |
blue | Vivid blue |
lavender | Soft purple |
Rosé Pine
| Name | Description |
|---|---|
love | Red/pink accent (alias red) |
gold | Warm yellow (alias yellow) |
rose | Soft pink |
pine | Teal/blue accent (alias blue) |
foam | Cyan (alias green, teal) |
iris | Purple (alias mauve, purple, magenta) |
Tokyo Night
| Name | Description |
|---|---|
red | Red |
orange | Orange |
yellow | Yellow |
green | Green |
cyan | Cyan |
teal | Teal |
blue | Blue |
purple | Purple (alias mauve, magenta) |
Additional named colors for surfaces and text:
| Name | Description |
|---|---|
base | Base background |
mantle | Darker background |
crust | Darkest background |
surface0 | Surface layer 0 |
surface1 | Surface layer 1 |
surface2 | Surface layer 2 |
overlay0 | Overlay layer 0 |
overlay1 | Overlay layer 1 |
overlay2 | Overlay layer 2 |
subtext0 | Subdued text |
subtext1 | Slightly subdued text |
text | Primary text color |
Color Resolution
Colors are resolved in the following order:
- Hex value (
"#1e1e2e") – used as-is - Named color (
"blue") – looked up in the active theme palette - Empty string – falls back to the default for that setting
Existing hex color values in your configuration continue to work unchanged after enabling a theme. Named colors are optional.
Examples
Using named colors in bar.toml:
[colors]
background = "base"
foreground = "text"
accent = "blue"
Using named colors for borders in config.toml:
[borders.colors]
focused = "blue"
monocle = "green"
Hot-Reload
Theme changes in config.toml are hot-reloaded. When the flavor changes,
all named colors are re-resolved against the new palette and the bar is
updated without restarting.
Tiling & Layouts
Mosaico automatically arranges windows on each monitor using a tiling layout algorithm. Three layouts are available out of the box: BSP, VerticalStack, and ThreeColumn.
Layout Algorithms
BSP (Binary Space Partitioning)
The default layout. The algorithm recursively divides the available screen area:
- One window – fills the entire work area (minus gaps).
- Two or more windows – the area is split in half:
- Even depth: horizontal split (side by side)
- Odd depth: vertical split (stacked)
- The first window gets the primary partition (controlled by the
ratiosetting). - Remaining windows are recursively laid out in the second partition.
This produces a balanced, grid-like arrangement where each new window gets its own tile.
+-------+-------+
| | 2 |
| 1 +---+---+
| | 3 | 4 |
+-------+---+---+
VerticalStack
A classic master/stack layout. The first window occupies a large pane on the left (the “master”), and all remaining windows are stacked vertically on the right.
+-----------+-----------+
| | 2 |
| 1 +-----------+
| (master) | 3 |
+-----------+-----------+
This layout works well when you have one main window you want to keep visible (editor, browser) while referencing several smaller ones.
ThreeColumn
A centered-master layout. The first window sits in the center column, and additional windows alternate between stacks on the left and right sides.
+------+-----------+------+
| 2 | | 3 |
+------+ 1 +------+
| 4 | (master) | 5 |
+------+-----------+------+
With only two windows it behaves like a simple left/right split. Once a third window is added, the center master column appears and the side stacks begin filling up.
Cycling Layouts
Press Alt + N to cycle through layouts on the focused workspace:
BSP -> VerticalStack -> ThreeColumn -> BSP -> …
You can also run:
mosaico action cycle-layout
The layout change takes effect immediately and all windows are retiled.
Configuration
Layout settings are in config.toml:
[layout]
gap = 8 # Pixel gap between windows (0-200)
ratio = 0.5 # Split ratio for the primary partition (0.1-0.9)
default = "bsp" # Default layout for all workspaces
- gap – the pixel spacing between windows and around the edges of the
screen. Set to
0for no gaps. - ratio – controls how much space the first window in each split
receives.
0.5means equal halves;0.6gives 60% to the primary window. - default – the layout algorithm used for any workspace that does not
have an explicit override. Accepted values:
"bsp","vertical-stack","three-column".
Per-Workspace Layout
You can assign a specific layout to individual workspaces using the
[workspaces.layouts] section. Workspace numbers range from 1 to 8.
The available layout values are:
| Value | Layout |
|---|---|
"bsp" | Binary Space Partitioning (default) |
"vertical-stack" | Master pane left, vertical stack right |
"three-column" | Master pane center, stacks on both sides |
[layout]
default = "bsp"
[workspaces.layouts]
1 = "three-column" # Workspace 1 always uses ThreeColumn
3 = "vertical-stack" # Workspace 3 always uses VerticalStack
Workspaces without an entry in this table use the layout.default. You
can still cycle layouts at runtime with Alt + N – the per-workspace
config only controls the initial layout when the daemon starts.
Workspace Mode
workspaces.mode controls how a workspace switch propagates across
monitors:
[workspaces]
mode = "per-monitor" # default
# mode = "global"
- per-monitor (default) – a workspace switch only affects the focused monitor. Other monitors keep their current workspace, so you can flip one screen without disturbing the others.
- global – a workspace switch flips every monitor to the same workspace number in lockstep, mirroring Windows virtual desktops. Each monitor still owns its own window list per workspace; the mode just syncs which workspace number every monitor is showing.
The mode is hot-reloaded: edit config.toml and the next workspace
switch follows the new mode without restarting the daemon.
Monocle Mode
A per-monitor toggle that makes the focused window fill the entire work area. Other windows remain in the workspace but are not repositioned.
- Toggle with
Alt + Tormosaico action toggle-monocle - The focus border color changes to the configured monocle color
- Each monitor has its own independent monocle state
Retiling
Mosaico automatically retiles when windows are opened, closed, minimized, restored, or moved between monitors. You can also manually retile at any time:
- Press
Alt + Shift + R - Or run
mosaico action retile
Window Management
Mosaico tiles a window if it meets all of the following criteria:
- The window is visible
- The window has a title bar (
WS_CAPTIONstyle) - The window is not a tool window
- The window passes your window rules
Layout Changes Are Hot-Reloaded
Changes to gap, ratio, default, and workspaces in config.toml
are automatically applied while the daemon is running. All windows are
retiled immediately with the new settings.
Workspaces
Mosaico supports up to 8 workspaces. Each workspace maintains its own set of tiled windows. By default each monitor switches workspaces independently; you can opt into a global mode where every monitor switches in lockstep (see Workspace Mode below).
Switching Workspaces
| Shortcut | Action |
|---|---|
Alt + 1 – Alt + 8 | Switch to workspace 1-8 |
Alt + Shift + 1 – Alt + Shift + 8 | Send focused window to workspace 1-8 |
Or via the CLI:
mosaico action goto-workspace 3
mosaico action send-to-workspace 5
Behavior
Switching (goto-workspace)
When you switch to a different workspace:
- All windows on the current workspace are hidden using the configured hiding strategy
- All windows on the target workspace are shown
- The layout is reapplied
- Focus is set to the first window
If you are already on the target workspace, nothing happens.
Sending (send-to-workspace)
When you send a window to another workspace:
- The focused window is removed from the current workspace
- It is added to the target workspace
- The window is hidden (it is now on a non-active workspace)
- The current workspace is retiled
- Focus moves to the next window
Hiding Behaviour
The hiding setting in [layout] controls how windows are hidden during
workspace switches:
| Strategy | Taskbar Icon | Notes |
|---|---|---|
"cloak" (default) | Kept | Invisible via DWM. Same mechanism as Windows virtual desktops. |
"hide" | Removed | Legacy SW_HIDE. Simple but loses taskbar icons. |
"minimize" | Kept (minimized) | Some apps react to minimize (e.g. pause media). |
[layout]
hiding = "cloak" # "cloak", "hide", or "minimize"
Cloak is the recommended default. Windows become invisible but keep their taskbar icons, so you can still see all running apps. Clicking a cloaked window’s taskbar icon automatically switches to its workspace.
Workspace Mode
workspaces.mode in config.toml controls how a workspace switch
propagates across monitors:
[workspaces]
mode = "per-monitor" # default
# mode = "global"
| Mode | Behavior |
|---|---|
"per-monitor" (default) | Switching workspaces only affects the focused monitor. The other monitors keep showing whatever workspace they were on. |
"global" | Every monitor switches to the same workspace number in lockstep, mirroring Windows virtual desktops. |
In both modes each monitor still owns its own window list per workspace;
windows do not jump between displays. The mode only controls which
monitors flip when you press Alt + N or run mosaico action goto-workspace N.
send-to-workspace in global mode moves the window to the target
workspace on its current monitor, then flips every other monitor to the
same workspace number so the view stays in sync.
The mode is hot-reloaded: change it in config.toml and the next
workspace switch follows the new mode without restarting the daemon.
Status Bar Integration
If the status bar is enabled with a workspaces widget, it displays
pill-shaped indicators showing which workspace is active and which
workspaces contain windows.
Multi-Monitor
Mosaico manages each monitor independently with its own workspaces, layout, and monocle state. Windows can be navigated and moved across monitors seamlessly.
By default, switching workspaces only flips the focused monitor (per-monitor
mode). Set workspaces.mode = "global" in config.toml to make every
monitor switch to the same workspace number in lockstep, like Windows
virtual desktops. See Workspaces -> Workspace Mode.
Monitor Detection
Monitors are automatically enumerated and sorted left-to-right by their x-coordinate. Each monitor’s work area excludes the Windows taskbar and the Mosaico status bar (if enabled).
Cross-Monitor Navigation
Focus navigation with Alt + H/L (left/right) can cross monitor
boundaries. When there is no window in the requested direction on the
current monitor, focus moves to the nearest window on the adjacent monitor.
Up/Down navigation (Alt + J/K) stays within the current monitor.
Moving Windows Across Monitors
Move actions with Alt + Shift + H/L transfer windows between monitors:
- Moving right – the window is placed at the leftmost position in the target monitor’s BSP layout.
- Moving left – the window is placed at the rightmost position.
Both the source and target monitors are retiled after the move.
Up/Down move actions (Alt + Shift + J/K) swap windows within the same
monitor.
Manual Dragging
If you manually drag a window to a different monitor, Mosaico detects the monitor change and reassigns the window automatically. Both monitors are retiled.
DPI Awareness
Mosaico uses per-monitor DPI awareness (V2) to ensure accurate pixel positioning on mixed-DPI multi-monitor setups. This is handled automatically and requires no configuration.
Window Borders
Mosaico draws a colored border overlay around every visible tiled window. The focused window is highlighted with the focused (or monocle) color; every other tiled window on the active workspace gets a muted unfocused border so tile boundaries stay readable – especially with small gaps. Unfocused borders can be disabled if you prefer a minimal look.
Configuration
Border settings are in config.toml:
[borders]
width = 4 # Border thickness in pixels (0-32)
corner_style = "small" # "square", "small", or "round"
[borders.colors]
focused = "#00b4d8" # Color for focused window in tiled layouts
monocle = "#2d6a4f" # Color for focused window in monocle mode
unfocused = "#6c7086" # Color drawn around unfocused tiled windows
-
width – thickness of the border in pixels. Set to
0to disable every border. -
corner_style – controls both the border overlay shape and the DWM corner preference for tiled windows (Windows 11 only; ignored on Windows 10).
Value Border overlay DWM (Windows 11) "square"Sharp corners (0 px) DONOTROUND"small"Subtle rounding (8 px) ROUNDSMALL(~4 px)"round"Standard rounding (16 px) ROUND(~8 px) -
borders.colors.focused – the border color for the focused window during normal tiling. Accepts hex colors or named theme colors (see Theming).
-
borders.colors.monocle – the border color when monocle mode is active.
-
borders.colors.unfocused – the border color drawn around every unfocused tiled window. Set to
"none"to disable unfocused borders entirely (only the focused window will have a border in that case). An empty string falls back to the active theme’s muted-gray default.
Behavior
- Every tiled window on every monitor’s active workspace gets its own border overlay.
- Changing focus recolors the previously focused border to the unfocused color and the new focused border to the focused color, in one update.
- Switching workspaces hides the outgoing windows’ borders and shows the incoming windows’ borders.
- In monocle mode only the focused window’s border renders; all other tiled borders on that monitor are hidden until monocle is toggled off.
- When the focused window is maximized, its border is hidden so it does not overflow off-screen, and unfocused borders on the same monitor are also hidden because they are visually covered.
- Borders are click-through (
WS_EX_TRANSPARENT) and never interfere with mouse interaction.
Using Named Colors
With a theme active, you can use named colors:
[borders.colors]
focused = "blue"
monocle = "green"
unfocused = "mauve"
Empty values fall back to the theme’s defaults: blue for focused, green for monocle, and a muted gray (Catppuccin Overlay0) for unfocused.
Disabling Unfocused Borders Only
If you want the focus highlight without borders on every other window:
[borders.colors]
unfocused = "none"
This keeps focused and monocle rendering as before and skips
unfocused borders entirely. Use width = 0 instead if you want every
border off.
Hot-Reload
Border settings are hot-reloaded. Changes to width, corner_style,
and any [borders.colors] entry take effect immediately, including
flipping unfocused = "none" on or off.
Logging
Mosaico includes a built-in file logger with automatic rotation. Logging is disabled by default.
Configuration
Enable logging in config.toml:
[logging]
enabled = true
level = "info" # debug, info, warn, error
max_file_mb = 10 # Max file size before rotation
Log Levels
| Level | Description |
|---|---|
debug | Verbose output for troubleshooting |
info | General operational messages |
warn | Potential issues |
error | Failures that affect functionality |
Log Location
Logs are written to:
~/.config/mosaico/logs/mosaico.log
Rotation
When the log file exceeds max_file_mb, it is rotated:
- The current file is renamed to
mosaico.log.1 - A new
mosaico.logis created - Only one backup file is kept
When to Enable Logging
Logging is most useful when:
- Debugging why a window is not being tiled
- Investigating unexpected behavior
- Reporting issues on GitHub
For general use, logging can remain disabled to avoid unnecessary disk writes.
Debugging
Mosaico provides several tools for inspecting and troubleshooting the window manager.
mosaico doctor
The doctor command performs a comprehensive health check:
mosaico doctor
It checks:
- Config directory exists
- All configuration files are valid TOML
- All keybinding key names resolve to valid key codes
- Daemon status (running, stopped, or stale)
- Monitor enumeration and dimensions
Issues are reported with colored tags: [ok], [warn], [fail], or
[fixed].
mosaico debug list
Lists all visible windows on the desktop:
mosaico debug list
The output is a formatted table showing:
| Column | Description |
|---|---|
| HWND | Window handle in hex |
| Managed | Whether the window is tiled |
| Monitor | Which monitor the window is on |
| Title | Window title |
| Class | Window class name |
| Position | X, Y coordinates |
| Size | Width and height |
| Border Offset | Invisible frame compensation values |
This is useful for finding window class names when writing window rules.
mosaico debug events
Streams window events in real time:
mosaico debug events
Shows events like window creation, destruction, focus changes, moves,
minimize/restore, and title changes. Press Ctrl+C to stop.
This is useful for understanding how Mosaico reacts to window changes and diagnosing timing issues.
mosaico debug move
Moves a specific window to exact coordinates:
mosaico debug move 0x1A2B3C 100 200 800 600
Arguments: <hwnd> <x> <y> <width> <height>. The HWND can be in decimal
or 0x hex format (use debug list to find it).