Window Rules
Window rules let you match newly opened windows and automatically apply actions: force floating, assign to a workspace, or set initial geometry.
Defining rules
gar.rule(match_table, actions_table)
Both arguments are Lua tables.
Match criteria
| Key | Type | Description |
|---|---|---|
app_name |
string | Application name (e.g., "Calculator", "Firefox") |
app_bundle |
string | Bundle identifier (e.g., "com.apple.calculator") |
title |
string | Window title |
If multiple criteria are specified, all must match (AND logic).
Finding app names and bundle IDs
Use the IPC to inspect running windows:
tarmacctl get-windows | jq '.data[] | {app_name, app_bundle: .app_bundle, title}'
Or check with macOS tools:
# Bundle ID
mdls -name kMDItemCFBundleIdentifier /Applications/Safari.app
# App name (usually the .app filename without .app)
Actions
| Key | Type | Description |
|---|---|---|
floating |
bool | Force into floating state |
workspace |
number/string | Assign to workspace. Number (1-10) or "special:name". |
geometry |
table | Set initial position and size: {x, y, width, height} |
Examples
Float specific apps
gar.rule({ app_name = "Calculator" }, { floating = true })
gar.rule({ app_name = "System Settings" }, { floating = true })
gar.rule({ app_name = "Finder" }, { floating = true })
gar.rule({ app_name = "Archive Utility" }, { floating = true })
gar.rule({ title = "Picture in Picture" }, { floating = true })
Assign apps to workspaces
gar.rule({ app_bundle = "com.apple.Safari" }, { workspace = 2 })
gar.rule({ app_name = "Slack" }, { workspace = 3 })
gar.rule({ app_name = "Mail" }, { workspace = 4 })
gar.rule({ app_name = "Spotify" }, { workspace = "special:music" })
Set initial geometry for floating windows
gar.rule(
{ app_name = "Music" },
{ floating = true, geometry = { 200, 200, 800, 600 } }
)
The geometry table is {x, y, width, height} in pixels.
Combine criteria
-- Only match Safari windows with a specific title
gar.rule(
{ app_bundle = "com.apple.Safari", title = "Developer Tools" },
{ floating = true }
)
Rule evaluation
Rules are evaluated in the order they're defined in the config. When a new window appears, tarmac checks each rule against the window's properties. The first matching rule wins — subsequent rules are not checked.
Rules are checked when:
- A new window is detected during polling
- An existing window changes its title (re-evaluated)
Rules and config reload
On config reload, all rules are replaced by the new config's rules. Existing windows are not re-evaluated against the new rules — they only apply to newly opened windows.
Debugging rules
Use RUST_LOG=tarmac=debug to see which rules match:
RUST_LOG=tarmac=debug tarmac
You'll see log lines like:
DEBUG tarmac: rule matched: app_name="Calculator" → floating=true