Nomos
A window manager for Macs with more than one monitor. You mark out zones — the places windows should live in — on every screen you have, and from then on one key puts any window in any zone. Windows stay ordinary windows; you just stop dragging them.
The idea
Tiling when you want it, ordinary windows the rest of the time
There are two schools of window management, and neither is much fun on its own. A tiling manager gives the screen to the computer: nothing overlaps, everything runs from the keyboard, and every new window makes the whole screen rearrange itself around it. Ordinary windows — the ones your Mac comes with — give the screen to you: they float, they overlap, they go wherever you drag them, and dragging them is what you end up doing all day. Nomos takes the half of each that people actually like.
What it borrows from tiling
The screen is divided into zones you decide once and then keep. A window sent to one fills it exactly — no dragging, no nudging to line it up with the window beside it — and every command is a key press, so your hands stay where they already are.
What it keeps from ordinary windows
Nothing moves unless you ask. Windows still overlap, several can share one zone, and you can still shove one aside to see what is behind it — with a single key to put it back. Opening an app doesn’t rearrange the windows already on screen. And when your hand is already on the mouse, you can simply drag a window into a zone instead of naming it.
The ring
Move windows across multiple monitors with one key
Every zone on every screen gets a number, and the numbers run in one sequence across the whole desk instead of starting over on each monitor: 1, 2 and 3 on the wide screen, 4 and 5 on the portrait one beside it. Hold your shortcut key, press a number, and the window in front of you is there. Which monitor it was on a moment ago never comes into it — you think “put this in 4”, not “move this right, then right again”.
The order is yours to set, so the numbers follow the way you actually look at your desk rather than the order your Mac happens to list the screens in. Past the last zone the numbering comes back round to the first — which is why it is a ring. And the zones always fit together: each one is made by cutting a screen in two and then cutting the halves again, so a sliver of wasted screen between two of them, or one quietly overlapping another, cannot happen.
Geometry
Portrait and landscape monitors: the window takes the zone’s shape
A window takes the shape of wherever it lands. A terminal moved onto a portrait monitor becomes wide and short there, instead of dragging along the tall, narrow shape it had on a landscape one. This is the difference from dragging a window across a monitor boundary by hand, where it keeps its old proportions and you resize it again at the other end.
Measured on a two-monitor desk, the discrepancy between the frame Nomos asks for and the frame the window ends up with was half a point or less.
The keys
Every command starts with the hyper key, a
combination of modifiers you choose — it defaults to
⇧⌘⌃⌥, what a Space Cadet keyboard called Hyper. While it
is held, what you press reads as a phrase: a digit or an arrow is a
target on its own, and a few letters are verbs that wait for one, so
hyper + G + 5 gives focus to
zone 5. The phrase ends the moment you let go.
| Press, while holding hyper | Does |
|---|---|
| 1…9, or two digits up to 99 | move the focused window to the zone with that number |
| ← → ↑ ↓ | move the focused window to the neighbouring zone on that side — across monitors too |
| M + digit or arrow | the same move, spelled out in full |
| G + digit | give focus to that zone’s top window; nothing moves |
| S + digit | swap the focused window with that zone’s top window |
| E + arrow | grow the focused window into the row of zones on that side |
| C + arrow | give up the window’s outermost row of zones on that side |
| Z + arrow | nudge the boundary of the window’s own zone that way — this moves the wall, not the window |
| T | tidy: lay out the current display’s windows across its zones |
| F | fill the display with the focused window |
| A | snap the focused window back into the zone it is in — or, after F or E, back to the zone it grew from |
| ⇥ | cycle the windows of the zone the focused window is in |
| L | open the zone editor |
| P | switch to the next profile that suits the connected displays |
| R | place every window that has a rule into its zone |
| B | pin the focused application to the zones its window covers |
Every key above except the digits can be changed, from the settings window or by hand in the config file. The digits stay reserved on purpose: letting a command and a zone number land on the same combination would mean one of them wins silently. Walking the ring one zone at a time is still there too, as next and previous zone — it just has no key until you give it one.
Growing a window
hyper + E + an arrow grows the focused window
into the neighbouring zones on that side — one row of zones, exactly
as wide or as tall as the side it grows from.
hyper + C + an arrow gives the outermost row
on that side back. Both stay rectangular by construction: zones tile
the screen without gaps, so the row an edge touches is well defined,
and pulling it in or giving it up never leaves an L behind.
Neither remembers anything between presses. Each reads the window’s zones fresh from wherever it actually is, so a window dragged or resized by hand is picked up as it stands rather than argued with. With nowhere to grow into, or nothing left to give up, the press does nothing.
The older form, which asks for no direction, is still a command you can give a key: it grows the window to the smallest rectangle of zones larger than the one it fills now, one step per press, never leaving its monitor. The step is a set of zones, not a level of the layout tree — a set counts only if the rectangle drawn around it touches no zone outside it — so a zone spanning the full width or height of its screen grows in one press straight to the whole display: between the two there is no rectangle to stop at.
Putting a window back
A window drifts — dragged aside to see what is behind it, resized by
an application with its own ideas, left in place while the layout
around it changed. hyper + A puts it back
into the zone it is already in, without having to recall that zone’s
number or walk the ring forwards and back again.
It puts the window back into the zone’s own rectangle, not wherever a drag or another app’s resize left it.
Several windows in one zone
A zone is a place, not a window, and several collect in one: two
browser windows, a terminal under an editor. hyper +
⇥ cycles through the windows of the zone the focused
window is in — that zone, not the one under the pointer, because
your hand is on the keyboard and the mouse is wherever you left it.
The first press selects the window before the current one, so pressing and letting go returns you to where you just were, and Esc drops the whole thing without raising anything. A panel appears in the zone showing applications and window titles — titles are there for the case this exists for, two windows of the same browser being identical by icon and by name. The order comes from the stacking order rather than a remembered list, so it is right from the first press after a restart.
Moving a wall
hyper + Z + an arrow moves the boundary of
the zone the focused window is in, sixteen points at a time; hold the
arrow and it repeats. This one is not a window command at all — it
edits the layout itself, from wherever you are, without opening the
editor, and every window standing against that wall moves with it.
The whole burst counts as one step to undo.
Only the arrows that lead somewhere are offered: a zone whose edge is the edge of the screen has no wall to move that way. A window standing across a whole row moves that row’s wall, not one column of it — and where the layout has no single wall to move, nothing happens rather than half an edge sliding.
Seeing the zones
Hold the modifiers for a moment without pressing anything else and the zones appear on every screen, each with the number that sends a window there. Release any of them and they disappear. Nothing is clicked and nothing is consumed — it is a hint, not a mode. A broken config reports its error there too, which is the moment you are most likely to be looking.
How long that moment lasts, and how the zones look while it does, are
yours to set — in the settings window’s Overlay section or in the
config file. The wait before they appear defaults to a third of a
second, which is the compromise between flashing up on every hotkey
and making you wait for it; delay = 0 shows them at once.
The shading, the size of the numbers and their colour are settings for
the same reason: what reads clearly on dark wallpaper disappears on
bright.
Seeing the commands
Beside the zones, a small panel says what you can press. While you have pressed nothing it has two columns: the keys that start a phrase and wait for you to say where, and the keys that act the moment they are pressed. Press one of the first kind and the panel narrows to the ways of finishing it — the zones you could send this window to, the window’s current zone left out because sending it there would do nothing, and only the arrows that actually lead somewhere from where it stands.
Zones can be named — Mail, Reference, whatever the corner is for — and the name is shown beside the number, on the zones and in the panel both. The number still does the work; the name is for recognising the place without counting.
The menu bar icon is the third hint and the only one with no pause before it: it lights up the moment the modifiers go down, and shows the letter of the verb the moment you press one. Each of the three can be switched off on its own, and a phrase works exactly the same with all three off — they tell you what is happening, they are not how it happens.
Mouse
Or drag it there with the mouse
The keyboard is the quick way, not the only way. Hold the same modifiers and drag a window by its title bar as you always have: the zone under the cursor lights up, and letting go of the button drops the window into it, resized to fit. No target to aim at and no number to remember — you are already pointing at the place.
Only the zone you are over is drawn, not the whole numbered map: a cursor needs an edge to aim at, a typed number needs the numbers. Nothing waits, either — the moment a window is in your hand the mark is there, without the short pause the numbers have. Drag somewhere with no zone under it, the menu bar or the strip between two monitors, and nothing lights up and nothing moves.
The moment the button comes up is what decides, and nothing else. Let the modifiers go before you let go of the window and it was an ordinary drag all along: the window stays where you dropped it.
While you are dragging, the modifiers don’t reach the application underneath, so the gesture can’t turn into one of the things macOS does with a modified click — hiding the app you came from, or opening a context menu.
Configuration
Draw custom zones on each screen
Zones are edited on the real screens, not on a map of them.
hyper + L — or the button in the settings
window, which steps out of the way — draws the layout full-size on
every monitor and puts a small panel at the bottom of the screen your
pointer is on. Hover a zone to split or remove it; drag the boundary
between two and both resize together, snapping to halves, thirds and
quarters, with ⌥ for the exact position instead. Windows
standing in those zones follow the boundary as it moves, so you are
looking at the result rather than at a diagram of it.
The panel carries the profile being edited, the presets for each
monitor, undo and redo, a way to tidy the windows into what you just
drew, and a reset back to how the layout looked when you entered.
Drag it anywhere, including onto another screen. Esc or
the same hotkey leaves.
Underneath it is plain TOML in
~/.config/nomos/config.toml, picked up automatically —
no restart:
[hotkeys]
modifiers = ["control", "option"]
[overlay] # every field optional; these are the defaults
delay = 0.3 # seconds of holding before the zones appear
backgroundOpacity = 0.18 # how much a zone darkens what is under it
numberSize = 64 # the zone number, in points
color = "#FFFFFF" # borders and numbers
[[display]]
name = "XG32UCWG"
orientation = "landscape"
[display.split]
axis = "vertical" # top-to-bottom cut, divides width
at = 0.5
[display.split.first]
[display.split.second]
A broken config doesn’t crash anything: Nomos keeps the last valid layout and reports the error from the menu bar icon, so window placement stays usable while the file is being fixed.
Profiles
One desk is never the only desk
Home is two monitors. The train is the laptop screen on its own. A call takes half of the big screen for someone else’s slides. Each of those wants its own set of zones — a layout — so Nomos lets you keep as many as you need. A layout plus the list of screens it belongs on is a profile.
Unplug the monitors and the laptop’s own profile comes back; plug them in again at the end of the day and so does the profile you were last using there. It is a memory of what you chose, not a guess at what you might have wanted.
Switching between them never moves a window. It changes where the
next key press will send things; what is on screen right
now stays exactly as it is. Switch from the menu bar icon, or with
hyper + P.
Rules: an app that always opens in the same zone
Give an application a zone and its windows go there by themselves, a fraction of a second after they appear — late enough that an app restoring last session’s position finishes first, so you never watch a window land and then jump. Only the window that just opened is touched; whatever you moved by hand earlier is left where you left it. A rule lives inside a profile, the same way the zones do, because zone 1 at home and zone 1 on the road are different corners of different screens.
Gaps between windows
Zones sit flush against each other — that is what keeps the numbers honest — but the windows in them don’t have to. Two gaps say how much air you want: one for the space between neighbouring windows, one for the space around the edge of the screen. Everything that places a window respects them, and the zones you see when you hold the modifiers are drawn with the gaps included, so what you aim at is what you land in.
Settings
A window, a menu bar icon, and nothing in the Dock
Nomos has no window of its own until you open one. It lives in the menu bar, and that icon is both where the settings are and where it tells you something is wrong — a config file it cannot read, a screen it cannot bind zones to, a key combination another application already took. The profile list is there too, and so is the update.
The settings window has five pages, and everything on them is the same file you could edit by hand: General — start at login, automatic updates, the permission, where the config file is; Shortcuts; Appearance — the three hints, the look of the zones, the gaps; Layout — the zone editor and the ring; Profiles.
Changing the keys
Record a new combination for the hyper key, and a new key for any command, by pressing it — the commands are grouped the way they behave: the ones that act at once, the ones that start a phrase, the ones that finish it, and the ones with no key yet, waiting for you to give them one. If another application already holds a combination, the row says so rather than leaving you to wonder why nothing happens.
Changing the order
The ring is a list you can drag: move a row and the numbers follow, so the order matches the way you look at your desk. Each row also takes the zone’s name. A screen nobody has cut into zones is listed too, with the number it has for now — one whole-screen zone is still a zone, and the hotkeys already reach it.
Starting and updating
One tick starts Nomos at login; turning it off in System Settings wins, and Nomos reads the live answer rather than its own copy of it. Updates check quietly in the background: a new version is a dot on the menu bar icon and a menu item reading Update to…, never a dialog that interrupts you. You open it when you feel like it.
From a script or a Stream Deck
Commands can also arrive as an address —
nomos://zone?number=3,
nomos://profile?name=Road — which is enough for a
Raycast command, a Stream Deck button or a Shortcuts step. It is
off until you switch it on, because a registered address is also a
way for a web page to move your windows. It can do what the keys
can do and nothing more: it reads nothing, shows nothing and
answers nothing.
Requirements
What it asks of your Mac
- macOS 26 or newer, on Apple silicon. There is no Intel build: Nomos is compiled for arm64 alone, and an Intel Mac will refuse to open it rather than run it slowly.
- Accessibility permission, and nothing else. No Input Monitoring, no screen recording. Nomos goes online for one thing only: checking for updates, once you allow it. No telemetry, no analytics.
- A hyper key of at least two modifiers. One modifier alone would take ordinary keys away from every application, so Nomos won’t accept it.
- Displays that report a name. Zones bind to a display by name, so a nameless one has nothing to bind to — the menu bar marks those unusable.
If you want one convenient key rather than a four-finger chord, map Caps Lock onto all four modifiers with Hyperkey — a small free app that does exactly this and nothing else. That is the usual way Caps Lock becomes Hyper, and it is how Nomos is used day to day on the machine it is built on.
Price
All of it is free
Every feature on this page is free, including the three that used to be paid: profiles — several layouts for home, the road, a call; application rules — an editor that always opens in the first zone; and gaps — air between neighbouring windows and around the edges of the screen.
Nothing to buy, no key to enter, no trial running out and no reminder on launch. Nomos is a hobby project, and the point right now is that people find it and use it.
Download
Signed with a Developer ID and notarized by Apple, so it opens without a warning and without a trip to System Settings to unblock it.
Download NomosThe first launch is two launches
Drag Nomos to Applications and open it. It asks for the Accessibility permission — the one that lets it move windows — and then quits rather than waiting around. Grant it in System Settings → Privacy & Security → Accessibility, then open Nomos again. That second launch is needed once and never again.
Nomos has no window of its own: it lives in the menu bar, and that icon is where the settings, the display list and any configuration errors are.
Early access
Verified on a two-monitor desk: a window walks the ring across both monitors and wraps, and a terminal moved to the portrait monitor comes out wide and short. Every other desk is new ground, so how it behaves on yours is exactly what shapes the next release — hi@tauvin.dev.
Credits
The trickier parts of driving the Accessibility API — notably the size-then-position-then-size sequence needed to reliably resize a window, and the fallback to the focused window when the target can’t be found directly — are adapted from Rectangle by Ryan Hanson (MIT) — the app this one is indebted to, for the idea as much as for the code. Rectangle’s licence text ships inside the Nomos bundle, because MIT asks for the text itself to travel with the software, not merely for the source to name where it came from.
Nomos is proprietary software. Third-party code it adapts keeps its own terms.