Text · 3044 bytes Raw Blame History
1 # Window Rules
2
3 Window rules let you match newly opened windows and automatically apply actions: force floating, assign to a workspace, or set initial geometry.
4
5 ## Defining rules
6
7 ```lua
8 gar.rule(match_table, actions_table)
9 ```
10
11 Both arguments are Lua tables.
12
13 ## Match criteria
14
15 | Key | Type | Description |
16 |-----|------|-------------|
17 | `app_name` | string | Application name (e.g., `"Calculator"`, `"Firefox"`) |
18 | `app_bundle` | string | Bundle identifier (e.g., `"com.apple.calculator"`) |
19 | `title` | string | Window title |
20
21 If multiple criteria are specified, all must match (AND logic).
22
23 ### Finding app names and bundle IDs
24
25 Use the IPC to inspect running windows:
26
27 ```bash
28 tarmacctl get-windows | jq '.data[] | {app_name, app_bundle: .app_bundle, title}'
29 ```
30
31 Or check with macOS tools:
32
33 ```bash
34 # Bundle ID
35 mdls -name kMDItemCFBundleIdentifier /Applications/Safari.app
36
37 # App name (usually the .app filename without .app)
38 ```
39
40 ## Actions
41
42 | Key | Type | Description |
43 |-----|------|-------------|
44 | `floating` | bool | Force into floating state |
45 | `workspace` | number/string | Assign to workspace. Number (1-10) or `"special:name"`. |
46 | `geometry` | table | Set initial position and size: `{x, y, width, height}` |
47
48 ## Examples
49
50 ### Float specific apps
51
52 ```lua
53 gar.rule({ app_name = "Calculator" }, { floating = true })
54 gar.rule({ app_name = "System Settings" }, { floating = true })
55 gar.rule({ app_name = "Finder" }, { floating = true })
56 gar.rule({ app_name = "Archive Utility" }, { floating = true })
57 gar.rule({ title = "Picture in Picture" }, { floating = true })
58 ```
59
60 ### Assign apps to workspaces
61
62 ```lua
63 gar.rule({ app_bundle = "com.apple.Safari" }, { workspace = 2 })
64 gar.rule({ app_name = "Slack" }, { workspace = 3 })
65 gar.rule({ app_name = "Mail" }, { workspace = 4 })
66 gar.rule({ app_name = "Spotify" }, { workspace = "special:music" })
67 ```
68
69 ### Set initial geometry for floating windows
70
71 ```lua
72 gar.rule(
73 { app_name = "Music" },
74 { floating = true, geometry = { 200, 200, 800, 600 } }
75 )
76 ```
77
78 The geometry table is `{x, y, width, height}` in pixels.
79
80 ### Combine criteria
81
82 ```lua
83 -- Only match Safari windows with a specific title
84 gar.rule(
85 { app_bundle = "com.apple.Safari", title = "Developer Tools" },
86 { floating = true }
87 )
88 ```
89
90 ## Rule evaluation
91
92 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.
93
94 Rules are checked when:
95 - A new window is detected during polling
96 - An existing window changes its title (re-evaluated)
97
98 ## Rules and config reload
99
100 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.
101
102 ## Debugging rules
103
104 Use `RUST_LOG=tarmac=debug` to see which rules match:
105
106 ```bash
107 RUST_LOG=tarmac=debug tarmac
108 ```
109
110 You'll see log lines like:
111
112 ```
113 DEBUG tarmac: rule matched: app_name="Calculator" floating=true
114 ```