Library / SDK
nwg-piotr/autotiling avatar
nwg-piotr/autotiling

autotiling: sway and i3 split orientation decided by window shape

Script for sway and i3 to automatically switch the horizontal / vertical window split orientation

1,150 stars40 forksPythonGPL-3.0

At a glance

What is it?
autotiling is a small Python script for the sway and i3 window managers that watches the focused window and switches the container between a horizontal and a vertical split when the window's height to width ratio crosses a threshold. It does one thing, it is careful to say that it does not do more, and its documentation is more honest about the limits than most window manager add-ons are.
Who is it for?
Adopt autotiling if you use sway or i3 with wide terminals and you keep re-splitting containers by hand because the new window is tall, and start with the --limit option so stacking and tabbed layouts stay usable. Do not adopt it if your workflow depends on stacking or tabbed layouts at the top level, because the README is explicit that those behave oddly and that no fix is coming.
Can I use it commercially?
Yes, with conditions. GPL-3.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 101 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

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

Editorial analysis

A script that does exactly one thing

The README opens with a section titled PLEASE DO READ THIS, and it is the most useful part of the document.

The script uses the i3ipc-python library to switch the layout between splitv and splith depending on the currently focused window's dimensions, and it works on both sway and i3. The description of what it does is deliberately minimal: it checks the window height to width ratio, and executes the equivalent of either swaymsg splitv or swaymsg splith. Nothing less, nothing more.

The script was inspired by an existing project, i3-alternating-layout, and the author is clear about the mechanism rather than the magic. The ratio is the whole decision. If the focused window is wider than it is tall, the container splits horizontally, side by side. If it is taller than wide, the container splits vertically, stacked. The -sr switch tunes the ratio at which the decision flips.

That is the entire behaviour, and the README says so, which is a rarity in this category of tool. There is no layout engine here, no rules engine, no configuration language. One measurement, one comparison, one command.

The consequence is that the tool does not know anything about your intentions. It sees a window shape and acts, which is exactly what makes it predictable and exactly what makes it wrong in some cases.

Why stacking and tabbed layouts misbehave

The README states the problem plainly. This may make stack and tabbed layouts behave oddly, and unfortunately there is nothing that can be done about it. Please do not submit issues about it.

The reason is not hard to reconstruct. A stacked layout puts several windows in the same space, so which window is focused does not tell you the shape of the space, and a tabbed layout keeps a container's size while its contents change. The script's input is the focused window's dimensions, and in those layouts that input no longer describes the container it is being asked to split.

The author offers two workarounds, and both are worth reading because they show the real shape of the problem.

The first is to enable autotiling on certain workspaces or outputs only. The README's example configures it on odd workspaces and not on even ones:

text
### Autostart
  exec_always autotiling -w 1 3 5 7 9

The second is to set --limit and only use stacking or tabbing on the lowest level. The suggested starting point is --limit 2, and the idea is to open four windows with the third and fourth in the same container as two, which might mimic a master-stack layout, so that switching to stacking or tabbed becomes possible. The warning is that the decision on how to split is still based on the height and width ratio.

So the honest summary is that autotiling works well in a flat layout and degrades in nested ones, and the configuration lets you limit where it applies.

The switches, and what the split ratio means

The usage output is short and every option earns its place:

text
$ autotiling -h
usage: main.py [-h] [-d] [-v] [-o [OUTPUTS ...]] [-w [WORKSPACES ...]]
               [-l LIMIT] [-sw SPLITWIDTH] [-sh SPLITHEIGHT] [-sr SPLITRATIO]
               [-e [EVENTS ...]]

The scoping options come first. -o restricts autotiling to certain outputs, with the example autotiling --output DP-1 HDMI-0, and -w restricts it to certain workspaces, with autotiling --workspaces 8 9. For anyone with a laptop and an external monitor, or a habit of keeping one workspace for terminal work, these are the options that make the script usable at all.

-l limits how often autotiling will split a container, and the help text suggests trying 2 if you like master-stack layouts, with the default of 0 meaning no limit. That is the single most useful switch for a real setup.

-sw and -sh set the width of the vertical split and the height of the horizontal split as factors, both defaulting to 1.0, so the container divides evenly unless you say otherwise.

-sr is the ratio itself. The help text describes it as the split direction ratio based on window height to width, defaulting to 1, and suggests trying 1.61 for the golden ratio, in which case the window has to be 61 percent wider for a left and right split. The help also says default 1.0 for the ratio, so the two statements in the upstream text disagree slightly, which is a fair warning about how carefully to read the numbers.

Events: WINDOW and MODE unless you say otherwise

The events section explains a change made in v1.6 and the reason for it. Changing event subscription had already been the objective of several pull requests, and to avoid doing this again and again, from v1.6 you may specify the events in the -e or --events argument.

If no value is given, the script subscribes to Event.WINDOW and Event.MODE, as if it had been run with autotiling -e WINDOW MODE. The README points at the event enumeration in the i3ipc-python project for the full list.

The two default events are the interesting part. WINDOW fires when a window changes, which is when the focused window's dimensions might have changed and a new decision is needed. MODE fires when the layout mode changes, which is when the container structure has been rebuilt and the script's previous assumption about the split is stale. Subscribing to both means the script re-evaluates whenever either could invalidate its decision.

The reason the switch exists is the pull request fatigue the README describes, and it is a good example of a project absorbing a request properly: the capability was generalised, so later requesters did not have to patch anything.

Installing it in sway and i3

The script is packaged for a range of distributions, with a Repology badge showing where, and it is on PyPI. The manual route is three steps.

First install the python-i3ipc package at version 2.0.1 or newer, or whatever the equivalent is called in your Linux distribution. Second, save the main.py file anywhere, rename it to autotiling, make it executable and move it into your bin folder. Third, add it to your window manager's startup configuration, with exec_always autotiling in the sway config at ~/.config/sway/config, and exec_always --no-startup-id autotiling in the i3 config at ~/.config/i3/config.

The i3 flag is not cosmetic. The --no-startup-id option tells i3 not to assign a startup id to the command, which matters because i3's exec_always runs on every reload.

The exec_always form rather than exec is deliberate in both cases. The script needs to be running whenever the window manager reloads, because the layout decision has to be re-evaluated as the session continues, and a script started once with exec would not survive a configuration reload.

Where autotiling is the wrong choice

The first wrong-tool case is a workflow built around stacked or tabbed containers. The README is unambiguous that those behave oddly and that there is no fix, so a server that lives in a stacked layout should not install this, and the two workarounds are mitigations rather than solutions.

The second is a window manager that is not sway or i3. The script talks to the compositor over the i3 IPC socket through i3ipc-python, which means the two window managers that implement that protocol. There is no fallback path, and the script's split commands are the sway ones, so on a different manager nothing happens at all rather than something slightly wrong.

The third is a setup where the split direction is already what you want. Some people open one window and never touch the split, and for them the script is a background process that occasionally re-splits a container they had arranged deliberately. The -w and -o switches exist for exactly this, and a user who does not set them gets the script acting everywhere.

There is also the case of a mixed DPI or multi-monitor arrangement, where a window's reported dimensions in the i3 IPC stream may not correspond to what the user sees, and the ratio decision then disagrees with the eye. The README does not discuss that case, so it is worth testing on your own hardware before enabling it everywhere.

GPL-3.0, version 1.9.4, and a small tool with a long tail

The project is licensed under GPL-3.0, with the LICENSE file at the repository root. The default branch is master, and the last push was on 2026-07-13, the same day as the release v1.9.4.

The release history shows the long tail of a small utility. The versions are v1.9.4 from 2026-07-13, v1.9.3 from 2024-05-21 and v1.9.2 from 2024-04-26, so a two-year gap followed by a patch release, which is what you would expect from a script that solves a problem most people have or do not have.

The repository layout is small and honest about the scope. There is an autotiling/ package with the script, a pyproject.toml and a setup.py, and a setup.cfg which holds the version, since the Makefile reads the version out of it with a configparser one-liner before tagging. The Makefile is a release script rather than a build script: it refuses to run unless the current branch is master, it builds with pep517, uploads with twine, and creates the release tag through the GitHub API using a token read from the home directory. There are also format and lint targets running isort, black and flake8, a .flake8 configuration, and a CHANGELOG.md.

What makes it worth a reviewer's attention is the documentation rather than the code. The README explains exactly what the script does, names the failure case, tells you not to file issues about it, and offers two workarounds. That is rare, and it is why a small script has survived this long with users still configuring it.

Editorial conclusion

Adopt autotiling if you use sway or i3 with wide terminals and you keep re-splitting containers by hand because the new window is tall, and start with the --limit option so stacking and tabbed layouts stay usable. Do not adopt it if your workflow depends on stacking or tabbed layouts at the top level, because the README is explicit that those behave oddly and that no fix is coming. Before you install, read the limitation notes in the README, decide whether you want it on every workspace or only some, and note that the script needs a current i3ipc-python, since the manual instructions ask for python-i3ipc 2.0.1 or newer.

Frequently asked questions

What does autotiling do in sway and i3?

It checks the height to width ratio of the currently focused window and executes the equivalent of swaymsg splitv or swaymsg splith, so a wide window produces a side by side split and a tall one a stacked split. The README is explicit that the script does one thing and nothing more.

How do I install autotiling?

Install the python-i3ipc package at 2.0.1 or newer, save main.py renamed to autotiling, make it executable and put it in your bin folder, then add exec_always autotiling to the sway config or exec_always --no-startup-id autotiling to the i3 config. The script is also packaged for several distributions and published on PyPI.

How do I stop autotiling from breaking stacked and tabbed layouts?

The README offers two workarounds. Enable it on chosen workspaces or outputs only, for example exec_always autotiling -w 1 3 5 7 9, or set --limit, with 2 suggested, and only use stacking or tabbing at the lowest level. It notes there is no fix for the underlying behaviour.

What is the --splitratio option in autotiling?

It sets the split direction ratio based on the window height to width, with the default at 1. The help text suggests trying 1.61 for the golden ratio, in which case a window has to be 61 percent wider for a left and right split.

Which events does autotiling subscribe to?

From v1.6 you can choose them with the -e or --events argument, and if you give no value the script subscribes to Event.WINDOW and Event.MODE, as if it had been run with autotiling -e WINDOW MODE.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. nwg-piotr/autotiling on GitHub
  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/nwg-piotr-autotiling.svg)](https://hysenlabs.com/projects/nwg-piotr-autotiling)

Was this useful?