CLI tool
OmniNull/OmniWM avatar
OmniNull/OmniWM

OmniWM: two Linux layout models per workspace, a build hard coded to arm64, and tool versions verified before every lint

Free, open-source tiling window manager for Apple Silicon Macs, with Niri-style scrolling containers and Hyprland-style Dwindle BSP.

3,618 stars182 forksSwiftGPL-2.0

At a glance

What is it?
A tiling window manager for recent Apple Silicon Macs that borrows its scrolling containers from one Linux compositor and its binary space partitioner from another, and lets you pick between them per workspace. Its build checks its pinned formatter and linter versions before running either, and its localization scripts are Python that require a completed build first.
Who is it for?
OmniWM fits a Mac user on current hardware who wants tiling with a scrolling option and does not mind a project that borrows its layout vocabulary from Linux. It does not fit an Intel Mac, an older macOS, or a user who expects an Intel build.
Can I use it commercially?
Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • OmniNull/OmniWM3,618 ★ · +603
Star history
Repository2026-09-252026-11-14
OmniNull/OmniWM3k3.6k

603 Stars in the last 50 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Two layout models borrowed from two Linux compositors, chosen per workspace

The distinguishing design decision is that this is not one tiling algorithm but two, and the choice is per workspace rather than global. One is orientation-aware scrolling containers, credited in the README to a Linux compositor by name, where windows stack in a direction that can follow the monitor's orientation. The other is a Dwindle binary space partition layout, credited to a different Linux window manager, which splits the screen recursively instead of tiling it. Making the choice per workspace means a user can keep a scrolling stack on one space and a partitioned layout on another, which is why the README leads with both names rather than picking one. It also means keybindings and muscle memory have to cover two models, and the documentation's job is larger than it would be for a single layout. Everything else in the feature sentence is smaller: multi-monitor routing and optional local command line and IPC automation.

The platform floor is Apple Silicon on a recent macOS, and the build says arm64

The first sentence of the README states three constraints at once: Apple Silicon Macs, macOS 26 or later, and a specific signing status. The repository agrees with the first two and makes the architecture explicit. The build target in the Makefile compiles for the arm64 architecture and nothing else, and the Makefile does not offer an alternate target for Intel. So the floor is not a preference in the documentation; it is the only thing the build system produces. Two things follow for an adopter. There is no fallback path if you are on an Intel Mac other than running the sources under translation, which the repository does not claim to support. And the project links a page titled known limitations on its own site, which is the right place to look for what a tiling window manager on a closed platform cannot do, since the README itself only states the requirements.

Developer ID signed and notarized, stated in the opening line

Distribution is part of the product description here, which is unusual for a window manager and decisive for whether a user can install it at all. The README says the builds are Developer ID signed and Apple notarized, both in the first sentence and in the repository description. On macOS, an unnotarized application with any form of code signature still triggers a gatekeeper warning, and clearing it means either disabling the check system-wide or removing the quarantine attribute on the downloaded application by hand. A notarized build removes that step. It also means there is a signing identity in the release process, and that a build produced locally from a clone is not the same artefact as a release: the local build path in the Makefile installs a development build rather than a signed one. The entitlements file at the repository root is the other half of that story, since a window manager needs accessibility and screen recording permissions declared somewhere, and that file is where they are declared.

Tool versions are pinned in a file and verified before every format and lint run

The Makefile is unusually strict about its own tooling, and the mechanism is worth copying. It includes an environment file from the scripts directory that holds the required versions of the formatter and the linter. Every target that uses either tool first runs a version check target, and each check invokes the tool asking for its version, compares the answer against the pinned string, and exits with an error naming both the required and the found version if they differ. The formatting and linting targets depend on those checks rather than repeating the comparison, so there is one implementation. The tools themselves are not expected on the developer's machine: both paths point into a cache directory inside the repository, which is where the setup target installs them. The result is that a contributor cannot silently format with a different formatter version than the project agreed on, at the cost of a target failing on a machine whose cache is out of date.

The lint fix target ignores its own first failure, then verifies again

One target is worth reading twice because of what it tolerates. The lint fix target first depends on the version checks, then runs the formatter, then runs the linter with its fix flag followed by a shell operator that discards the result, then runs the formatter again, and finally runs the linter without the fix flag. Discarding the result of the fix pass is defensible, since a linter that cannot fix something exits non-zero and you do not want that to stop the target before the verification pass runs. The sequence is also expensive: two full formatting passes and two lint passes over the tree on every invocation, with the tools launched from a cache directory rather than from a system install. If you are wondering why formatting this project feels slow, this is the target that does it, and the second pass is the one that decides whether the fix worked.

The build verifies another application is present, then extends its library path

The whole build target is short enough to quote:

code
./Scripts/ghostty-preflight.sh verify
swift build --arch arm64

(with the library path variable set from the same preflight script before the compile runs). The build target is three lines and the first one is a preflight script that verifies something external. The second sets a shell variable holding a library search path, built by running the preflight script in a mode that prints a library directory and appending whatever the existing path already was, so it does not clobber it. The third is the actual compile, for the arm64 architecture, with that variable in front. So the build has a hard external prerequisite, it is discovered by asking a script where it lives rather than by a fixed path, and the answer is folded into the compiler's search path. For a user this only matters if they build from source, and the developer install path is a separate script that installs the built product rather than running it from the build directory.

Localization scripts are Python, and both require a finished build

Two targets run a Python script, and both declare the build as a prerequisite, so checking or syncing the localized strings compiles the whole application first. There is no Python dependency in the manifest or in the package definition, which means the script relies on whatever interpreter the developer happens to have and on the standard library alone. For a repository whose product language is Swift, that is a reasonable trade for a maintenance script, and the alternative, a Swift tool, would cost a target. What it costs is a slower feedback loop for the most common localization change and one more runtime to document. The Makefile also declares targets for checking tool versions, profiling energy use, a live test against the window server, a release check and a general verification target, which suggests the project has a fairly complete local verification story beyond the tests.

Contributors are listed by employer, with fourteen companies named

The contributors section is arranged by employer rather than by person, which is unusual and has a practical effect on the page: the visible portion names at least fourteen organisations, including several large technology companies, alongside individual contributors who appear to be listed under the company they were employed by when they contributed. The section is generated between marker comments, so it is maintained by a tool rather than by hand. For a reader trying to work out who actually maintains the project, that is the weak point: the by-employer view shows breadth of participation and nothing about current ownership. The repository itself does not name a maintainer anywhere in the visible text. There is also a dot directory at the top level whose purpose the listing does not say, and a scripts directory that the Makefile treats as the home of both its tooling versions and its build logic.

Editorial conclusion

OmniWM fits a Mac user on current hardware who wants tiling with a scrolling option and does not mind a project that borrows its layout vocabulary from Linux. It does not fit an Intel Mac, an older macOS, or a user who expects an Intel build. Four things to check. The platform floor is narrow: Apple Silicon only, a recent macOS only, and the build target compiled for one architecture. The layout models come from two different Linux projects, so keyboard habits and expectations will differ between workspaces. The build depends on another application being present, verified by a preflight script before compilation. And the developer tooling is version-locked and checked before every format and lint run, which is strict, and will refuse to work on a machine whose cached tools are a different version.

Frequently asked questions

What is OmniWM?

A tiling window manager for Apple Silicon Macs running macOS 26 or later. It combines orientation-aware scrolling containers in the style of one Linux compositor with a Dwindle binary space partition layout in the style of another, selectable per workspace, plus multi-monitor routing and optional local command line and IPC automation.

Does OmniWM run on Intel Macs?

The README states it targets Apple Silicon Macs and requires macOS 26 or later, and the repository's build target compiles for the arm64 architecture with no alternate target. The project also links a known limitations page on its own site for what the platform constrains.

How are OmniWM builds signed and distributed?

The README states the builds are Developer ID signed and Apple notarized, which removes the gatekeeper workarounds an unsigned application needs on macOS. A local build from a clone is a development install performed by a script rather than a signed release, and an entitlements file at the repository root is where the permissions a window manager needs are declared.

How does the OmniWM build check its own tools?

The Makefile reads required versions from an environment file in the scripts directory and, before any format or lint target, asks the locally cached formatter and linter for their versions and fails with an error naming both if they differ. The tools live in a cache directory inside the repository rather than on the system.

Why does building OmniWM require another application?

The build target first runs a preflight script that verifies the other application, then sets a library search path by asking the script to print a library directory and appending any existing path, then compiles for the arm64 architecture with that variable in front of the compiler.

What does the OmniWM Makefile cover beyond build and test?

Beyond setup, build, lint and format it declares targets for checking pinned tool versions, running a Python localization script in check and sync modes, an energy profile, a live test against the window server, a release check and a general verification target, and installing either a development or a release build through a script.

Official sources

  1. License: GPL-2.0
  2. OmniNull/OmniWM on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/omninull-omniwm.svg)](https://hysenlabs.com/projects/omninull-omniwm)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/omninull-omniwm.svg)](https://hysenlabs.com/projects/omninull-omniwm)

Was this useful?