What Is Qtile?

Updated

Qtile is a full-featured, hackable tiling window manager written and configured in Python. It is aimed at users who want their window management logic expressed as Python code rather than a separate configuration language. The current release listed on the project site is v0.37.0 (Aug 7, 2026).

What "tiling window manager" means here

A tiling window manager arranges windows automatically so they fill the screen without overlapping, instead of letting you drag and resize floating windows by hand. Qtile applies this model and exposes the controls as key bindings and Python objects.

The project's own framing emphasizes the benefits of a tiling window manager, and Qtile's distinguishing feature is that both the window manager and its configuration are Python. That means your config is a real program: you can import modules, write loops, define functions, and compute bindings rather than only declaring static values.

How configuration works

Qtile's default configuration is a Python file. Key bindings are declared as Key objects, and actions are wrapped in lazy calls so they run when the key is pressed rather than at load time.

A representative excerpt from the documented default config:

Key([mod, "shift"], "k", lazy.layout.shuffle_up(), desc="Move window up"),
Key([mod, "control"], "h", lazy.layout.grow_left(), desc="Grow window to the left"),
Key([mod], "n", lazy.layout.normalize(), desc="Reset all window sizes"),
Key([mod], "Return", lazy.spawn(terminal), desc="Launch terminal"),
Key([mod], "Tab", lazy.next_layout(), desc="Toggle between layouts"),
Key([mod], "w", lazy.window.kill(), desc="Kill focused window"),
Key([mod], "f", lazy.window.toggle_fullscreen(), desc="Toggle fullscreen on the focused window"),
Key([mod], "t", lazy.window.toggle_floating(), desc="Toggle floating on the focused window"),
Key([mod, "control"], "r", lazy.reload_config(), desc="Reload the config"),
Key([mod, "control"], "q", lazy.shutdown(), desc="Shutdown Qtile"),

Two things are worth noting for anyone evaluating Qtile:

  • Layout actions are first-class. Commands like shuffle_up, grow_left, normalize, and toggle_split are layout methods, so window behavior is scriptable in the same language as everything else.
  • Config can be reloaded without restarting. lazy.reload_config() is bound by default, which shortens the edit-test loop while you tune bindings.

Groups, layouts, and display servers

The default config builds workspaces as Group objects and generates bindings for them in a loop:

groups = [Group(i) for i in "123456789"]

for i in groups:
    keys.extend([
        Key([mod], i.name, lazy.group[i.name].toscreen(), desc=f"Switch to group {i.name}"),
    ])

This is a small but telling example: because the config is Python, a list comprehension and a for loop replace what would otherwise be nine near-identical declarations.

Qtile also supports switching between layouts at runtime (lazy.next_layout()), and the default config includes Wayland-specific virtual terminal bindings. Those bindings are guarded so they only take effect on Wayland:

lazy.core.change_vt(vt).when(func=lambda: qtile.core.name == "wayland")

The comment in the config explains why: the core name can't be checked while the default config is being loaded, because Qtile hasn't started yet, so the check is deferred until the binding actually runs. If you write your own conditional bindings, this is the pattern to copy.

Who Qtile suits

Qtile is a reasonable choice if:

  • You are comfortable in Python and would rather configure a window manager in a language you already use.
  • You want window behavior that depends on logic — computed bindings, loops over groups, conditional actions — rather than a fixed set of options.
  • You want to reload configuration changes without restarting the session.

It is a weaker fit if you don't want to read or write Python to change how your windows behave, or if you prefer a configuration format that is purely declarative.

Where to go next

The project site (qtile.org) links to screenshots, videos, documentation, the issue tracker, and GitHub, plus a download link, release notes, and an install guide for the current v0.37.0 release. The install guide is the right starting point for setup; the documentation covers layouts, widgets, and the configuration API referenced by the default config above.