Nehir — a tiling window manager for macOS
328
stars
345
commits
Swift
primary language
Aug 20, 2026
updated
A scrolling tiling window manager for macOS, built on the Niri column layout paradigm.
Nehir (Turkish for "river") — windows flow in columns, scrolling horizontally across your screen.
nehirctl~/.config/nehir/After the first release is published, Nehir can be distributed from the guria/tap Homebrew tap:
brew tap guria/tap
brew install --cask nehir
Nehir requires Accessibility permissions after installation:
System Settings > Privacy & Security > Accessibility
# Package the app bundle
mise run package:release
# User-local install (no sudo)
mkdir -p "$HOME/Applications" "$HOME/.local/bin"
rm -rf "$HOME/Applications/Nehir.app"
cp -R dist/Nehir.app "$HOME/Applications/Nehir.app"
install -m 755 .build/apple/Products/Release/nehirctl "$HOME/.local/bin/nehirctl"
Or use mise:
# User-local install
mise run install
# System-wide install
mise run install:system
# Run
Nehir
# CLI control (requires IPC enabled)
nehirctl command focus left
nehirctl command switch-workspace 2
nehirctl --help
Nehir restores parked/offscreen windows during a normal graceful quit. A force quit, crash, or kill -9 bypasses shutdown cleanup, so macOS may leave previously parked windows at the screen edge.
If that happens, use macOS's built-in window shortcuts to bring the selected Mission Control window back onscreen:
Control + Globe/Fn + FControl + Globe/Fn + CYou can also find these actions in the macOS Window menu. In Mission Control, selecting the stuck window and applying Fill or Centre/Center usually restores it to the visible desktop.
Trace capture and the other debug commands are gated behind Developer Mode. Enable it in the Diagnostics tab of Settings — this unlocks the Debug: … commands in the command palette and hotkey settings, enables the IPC debug endpoints, and reveals the Debug Actions, Background Trace Buffer, and Recent Traces panels in that same tab.
With Developer Mode on, you can start a trace capture from anywhere:
Ctrl+Option+Cmd+T)nehirctl command debug trace toggle; accepts an optional desiredState argument (active/inactive) for idempotent scripting, e.g. nehirctl command debug trace toggle active; while trace capture is running, nehirctl command debug capture-recent-trace exports a retained recent clipA clean trace covers only the misbehavior, with Nehir's own UI out of the way:
Enable Developer Mode once, in Settings → Diagnostics.
Start trace capture. A custom hotkey or the DebugBar is ideal here — they fire without the Settings window open.
Close the Settings window. Nehir-owned windows (Settings, Command Palette, App Rules) change focus and layout behavior, so reproducing with them closed matches how issues actually happen in normal use.
Reproduce the issue as you normally would.
Stop trace capture. A log bundle is written to:
${XDG_STATE_HOME:-$HOME/.local/state}/nehir/traces/
and its path is copied to your clipboard.
Share the trace file, not the path — a local path is only meaningful on your machine. Use Copy File in the Recent Traces list, or drag it out of the traces folder. The Recent Traces list in the Diagnostics tab keeps the last ten captures and lets you copy the path (handy for pasting into a terminal), copy the file, or reveal the folder.
Tip: start capture before you trigger the misbehavior and stop it immediately after, so the log isn't padded with unrelated activity.
The other debug commands in the same category:
For IPC/CLI usage, see docs/IPC-CLI.md.
Nehir uses a split-file config layout under ~/.config/nehir/:
~/.config/nehir/
├── settings.toml # core app behavior
├── hotkeys.toml # physical keybindings
├── workspaces.toml # workspace definitions
├── apprules.d/ # one file per app rule
│ ├── com-google-chrome.toml
│ └── pip-floating.toml.sample # inactive sample
└── monitors.d/ # per-monitor overrides
└── studio-display.toml
All files are watched for changes — edits are applied live without restarting.
See Configuration Principles for the design rationale.
Two settings interact here:
moveMouseToFocusedWindow moves the pointer after focus changes, but Nehir treats it primarily as a keyboard/command-navigation affordance. Pointer-originated focus changes do not warp the cursor: mouse hover/click, workspace bar clicks, tab overlay clicks, trackpad gestures, scroll animations, and floating-window clicks/drags all preserve pointer position.focusFollowsMouse is debounced and refreshes after scroll/swipe animations settle and after owned Nehir UI windows (Settings, App Rules, Command Palette) close, because those interactions may not generate a fresh mouse-move event.focusFollowsMouse enabled, swipe gesture end updates the viewport selection but does not commit focus to the snapped column; final focus follows the pointer after the gesture/animation settles.Nehir defaults are stored and shown as physical key chords.
For a lighter way to enter the base layer, see the Karabiner double-Command recipe.
The goal is a small set of predictable modifier patterns:
without Shift = go there
with Shift = move current window there
Hyper = reshape or move structure
# Build (debug)
mise run build
# Build and run
mise run dev
# Release build
mise run build:release
# Run tests (requires Xcode)
mise run test
# Clean
mise run clean
See CONTRIBUTING.md for setup details, changesets, the release flow, and Nehir's maintenance principles.
Nehir is the macOS embodiment of an idea with a clear family tree.
Nehir's interaction model — windows in horizontally scrolling columns — is a direct port of Niri's design language. Niri is a scrollable tiling Wayland compositor; Nehir brings that workflow to macOS.
Nehir is an opinionated fork of OmniWM, a general-purpose macOS tiling window manager by BarutSRB. We borrowed its macOS window-management engine and narrowed it to a single layout engine, dropping backward-compatibility baggage to do one thing well. Deeply grateful to the original author for the foundation — see NOTICE.md for full attribution.
animationsEnabled setting.~/.config/nehir/ with separate files for settings, hotkeys, workspaces, app rules, and monitor overrides.gestures.scrollSnap in settings.toml (default true).moveMouseToFocusedWindow jump the cursor, and hover focus is constrained around floating/unmanaged windows to fit the Niri layout model.${XDG_STATE_HOME:-$HOME/.local/state}/nehir/traces/.Nehir is one of several projects exploring this workflow:
GPL-2.0-only
Swift
99.1%
Nehir — a tiling window manager for macOS
328
stars
345
commits
Swift
primary language
Aug 20, 2026
updated
A scrolling tiling window manager for macOS, built on the Niri column layout paradigm.
Nehir (Turkish for "river") — windows flow in columns, scrolling horizontally across your screen.
nehirctl~/.config/nehir/After the first release is published, Nehir can be distributed from the guria/tap Homebrew tap:
brew tap guria/tap
brew install --cask nehir
Nehir requires Accessibility permissions after installation:
System Settings > Privacy & Security > Accessibility
# Package the app bundle
mise run package:release
# User-local install (no sudo)
mkdir -p "$HOME/Applications" "$HOME/.local/bin"
rm -rf "$HOME/Applications/Nehir.app"
cp -R dist/Nehir.app "$HOME/Applications/Nehir.app"
install -m 755 .build/apple/Products/Release/nehirctl "$HOME/.local/bin/nehirctl"
Or use mise:
# User-local install
mise run install
# System-wide install
mise run install:system
# Run
Nehir
# CLI control (requires IPC enabled)
nehirctl command focus left
nehirctl command switch-workspace 2
nehirctl --help
Nehir restores parked/offscreen windows during a normal graceful quit. A force quit, crash, or kill -9 bypasses shutdown cleanup, so macOS may leave previously parked windows at the screen edge.
If that happens, use macOS's built-in window shortcuts to bring the selected Mission Control window back onscreen:
Control + Globe/Fn + FControl + Globe/Fn + CYou can also find these actions in the macOS Window menu. In Mission Control, selecting the stuck window and applying Fill or Centre/Center usually restores it to the visible desktop.
Trace capture and the other debug commands are gated behind Developer Mode. Enable it in the Diagnostics tab of Settings — this unlocks the Debug: … commands in the command palette and hotkey settings, enables the IPC debug endpoints, and reveals the Debug Actions, Background Trace Buffer, and Recent Traces panels in that same tab.
With Developer Mode on, you can start a trace capture from anywhere:
Ctrl+Option+Cmd+T)nehirctl command debug trace toggle; accepts an optional desiredState argument (active/inactive) for idempotent scripting, e.g. nehirctl command debug trace toggle active; while trace capture is running, nehirctl command debug capture-recent-trace exports a retained recent clipA clean trace covers only the misbehavior, with Nehir's own UI out of the way:
Enable Developer Mode once, in Settings → Diagnostics.
Start trace capture. A custom hotkey or the DebugBar is ideal here — they fire without the Settings window open.
Close the Settings window. Nehir-owned windows (Settings, Command Palette, App Rules) change focus and layout behavior, so reproducing with them closed matches how issues actually happen in normal use.
Reproduce the issue as you normally would.
Stop trace capture. A log bundle is written to:
${XDG_STATE_HOME:-$HOME/.local/state}/nehir/traces/
and its path is copied to your clipboard.
Share the trace file, not the path — a local path is only meaningful on your machine. Use Copy File in the Recent Traces list, or drag it out of the traces folder. The Recent Traces list in the Diagnostics tab keeps the last ten captures and lets you copy the path (handy for pasting into a terminal), copy the file, or reveal the folder.
Tip: start capture before you trigger the misbehavior and stop it immediately after, so the log isn't padded with unrelated activity.
The other debug commands in the same category:
For IPC/CLI usage, see docs/IPC-CLI.md.
Nehir uses a split-file config layout under ~/.config/nehir/:
~/.config/nehir/
├── settings.toml # core app behavior
├── hotkeys.toml # physical keybindings
├── workspaces.toml # workspace definitions
├── apprules.d/ # one file per app rule
│ ├── com-google-chrome.toml
│ └── pip-floating.toml.sample # inactive sample
└── monitors.d/ # per-monitor overrides
└── studio-display.toml
All files are watched for changes — edits are applied live without restarting.
See Configuration Principles for the design rationale.
Two settings interact here:
moveMouseToFocusedWindow moves the pointer after focus changes, but Nehir treats it primarily as a keyboard/command-navigation affordance. Pointer-originated focus changes do not warp the cursor: mouse hover/click, workspace bar clicks, tab overlay clicks, trackpad gestures, scroll animations, and floating-window clicks/drags all preserve pointer position.focusFollowsMouse is debounced and refreshes after scroll/swipe animations settle and after owned Nehir UI windows (Settings, App Rules, Command Palette) close, because those interactions may not generate a fresh mouse-move event.focusFollowsMouse enabled, swipe gesture end updates the viewport selection but does not commit focus to the snapped column; final focus follows the pointer after the gesture/animation settles.Nehir defaults are stored and shown as physical key chords.
For a lighter way to enter the base layer, see the Karabiner double-Command recipe.
The goal is a small set of predictable modifier patterns:
without Shift = go there
with Shift = move current window there
Hyper = reshape or move structure
# Build (debug)
mise run build
# Build and run
mise run dev
# Release build
mise run build:release
# Run tests (requires Xcode)
mise run test
# Clean
mise run clean
See CONTRIBUTING.md for setup details, changesets, the release flow, and Nehir's maintenance principles.
Nehir is the macOS embodiment of an idea with a clear family tree.
Nehir's interaction model — windows in horizontally scrolling columns — is a direct port of Niri's design language. Niri is a scrollable tiling Wayland compositor; Nehir brings that workflow to macOS.
Nehir is an opinionated fork of OmniWM, a general-purpose macOS tiling window manager by BarutSRB. We borrowed its macOS window-management engine and narrowed it to a single layout engine, dropping backward-compatibility baggage to do one thing well. Deeply grateful to the original author for the foundation — see NOTICE.md for full attribution.
animationsEnabled setting.~/.config/nehir/ with separate files for settings, hotkeys, workspaces, app rules, and monitor overrides.gestures.scrollSnap in settings.toml (default true).moveMouseToFocusedWindow jump the cursor, and hover focus is constrained around floating/unmanaged windows to fit the Niri layout model.${XDG_STATE_HOME:-$HOME/.local/state}/nehir/traces/.Nehir is one of several projects exploring this workflow:
GPL-2.0-only
Swift
99.1%