Help us shape the future of Go! Take the 2026 Go Developer Survey

neferwl

module
v0.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2026 License: AGPL-3.0

README

NeferWL

Last commit

A Wayland compositor that spends its frames on your apps, not on itself.

https://github.com/user-attachments/assets/1ff42ce5-47b3-4cf8-a3a7-5fc5abde4af1

Stash, overview and animations, recorded on the headless backend at 1080p.

[!WARNING] Early alpha, but stable enough for daily use. Developed and tested mostly on AMD CPUs and GPUs. Hybrid and multi-GPU setups are supported but not yet tested on NVIDIA hardware (contribs welcome). Expect bugs and breaking config changes.

Why NeferWL

  • Performance: allocation-free hot paths, no wasted CPU passes and no cgo; about 40–80 MB of RAM with two 4K monitors. On 4K HDR video, GC takes under 9% of a process using 13% of a core; see Architecture and Performance.
  • Games: direct scanout, VRR, tearing, explicit sync and HDR give games the whole GPU instead of spending it on composition; see Performance.
  • Overview: cmd+o or a four-finger swipe up shows live workspace previews. Select a window with the keyboard, touchpad or mouse; see Overview.
  • Stash: cmd+s toggles a floating strip of windows set aside for the current workspace; cmd+shift+s moves a window into or out of it. See Stash.
  • Hint mode: click what is on screen by typing its label, without reaching for the mouse; targets come from an ordered chain of accessibility, OCR and optional nefer-hints detection. Enable experimental hint.enable and add a bind; see Hint mode.
  • Animations: short, cheap and off by default. Opt in with experimental animations = on; see Configuration.

Written in Go, without cgo. Each piece of state has one owner goroutine, connected to the others by channels; hot paths reuse memory and client buffers stay off the Go heap. See Architecture for the concurrency model, the GC strategy and the reusable Go libraries.

Small on purpose, and staying small: no blur, shadows or themes. No built-in bar or wallpaper either: bring your own, any layer-shell client works.

Install

Arch Linux

paru -S neferwl-bin   # latest release, pre-built for x86_64 and aarch64
paru -S neferwl-git   # latest main, built from source

Or install from a checkout with Go 1.27:

make install   # build a package from HEAD and install it with pacman

make pkg builds the package without installing it.

Ubuntu 24.04 and later

Download the .deb for your architecture (amd64 or arm64) and checksums.txt from Releases, then install it with apt, which pulls the runtime dependencies:

sha256sum -c --ignore-missing checksums.txt
sudo apt install ./neferwl_<version>_amd64.deb
sudo apt install foot fuzzel xdg-desktop-portal-gtk xdg-desktop-portal-gnome

X11 apps need xwayland-satellite 0.7 or later, which you may have to build. The package is tested on Ubuntu 24.04 and 26.04; Debian with the same library packages should work but is untested.

The packages provide:

  • neferwl with CAP_SYS_NICE for real-time scheduling.
  • A NeferWL session for display managers such as Ly, GDM and SDDM.
  • neferwl-session, which starts neferwl.service and manages graphical-session.target so desktop services start and stop with the session.

Running neferwl --session directly also exports the display environment to D-Bus and systemd user services. See Desktop integration for session setup.

Copy /usr/share/doc/neferwl/config.example to ~/.config/neferwl/config to start from the example config.

Other distributions

Download a linux_amd64 or linux_arm64 archive from Releases and verify it against checksums.txt. To build locally, run make bin; the binary is bin/neferwl.

Configuration

The default file is $XDG_CONFIG_HOME/neferwl/config, or ~/.config/neferwl/config.

keyboard.layout = fr
terminal.auto-open = first
startup = waybar

output.DP-1 = 3840x2160@144
output.DP-1.scale = 1.5

layout.max-columns = 3

# Start and place an editor and terminal when this workspace is opened.
workspace.dev.monitor = DP-1
workspace.dev.column.1 = 67%, code --new-window
workspace.dev.column.2 = 33%, foot
bind.cmd+d = workspace dev
  • Use one key = value per line; # starts a comment.
  • Missing keys use defaults. Invalid lines warn and keep that key's default; other lines still apply.
  • Save to reload. The log lists changed keys.
  • Use neferwl --config <path> to select a file, or neferwl validate-config [path] to check it without starting the compositor.

Common settings

Key Default Meaning
keyboard.layout system xkb layout, e.g. fr
keyboard.cmd super Modifier used as cmd
terminal $TERMINAL, then foot Terminal command
terminal.auto-open first Open on initial numbered workspace; also all or off
startup none Session-start commands, separated by ;
layout.max-columns 2 Columns sharing the screen
layout.overflow cascade Overflow layout: cascade, scroll, fixed
layout.gaps 0 Space between windows
output.<name> preferred Mode: WxH@Hz, preferred or off
output.<name>.scale 1 Fractional scale, 1 to 4
output.<name>.hdr off HDR on capable displays
touchpad.natural-scroll off Content follows fingers
stash.width 80 Selected stash window width, percent
hint.enable off Experimental keyboard clicking; restart required
animations off Experimental layout and swipe animations

Default key bindings

cmd means Super by default. Hint mode has no default binding.

Keys Action
cmd+return Open terminal
ctrl+cmd+space Launch fuzzel
cmd+q Close window
cmd+arrows / cmd+h/j/k/l Focus columns and windows
cmd+shift+arrows Move columns and windows
cmd+o Toggle overview
cmd+s Show/hide stash
cmd+shift+s Move window into/out of stash
cmd+shift+f Toggle fullscreen
cmd+shift+space Toggle floating
cmd+1…9 (physical digit keys) Focus numbered workspace
cmd+pageup/pagedown Previous/next workspace

See Configuration for all keys, actions, bindings and automatic-terminal behavior, or examples/config for commented defaults.

Features

Display and games

  • Eligible fullscreen buffers use direct scanout; VRR and tearing are on by default for supported fullscreen use (render.vrr, render.tearing). Tearing requires direct scanout and a client request.
  • Explicit sync carries client fences to the GPU and KMS, enabled by default with no flag. HDR10 on capable displays includes configurable SDR brightness.
  • Separate workspaces and fractional scale per output; workspaces move when a monitor is unplugged and return when it reconnects.
  • Hidden apps get frame callbacks once per second and the suspended state, whether on another workspace, in a hidden stash, off screen or under fullscreen. Captured windows keep their output's refresh rate.
  • Steam and other X11 clients run through xwayland-satellite; Wine can run natively on Wayland.

Windows and workspaces

  • Cascade tiling is the default; horizontal scrolling (as in PaperWM and niri) and fixed spiral layouts are available per output or workspace.
  • Numbered workspaces appear as needed; named workspaces can start commands and place windows in predefined columns.
  • Overview and stash keep workspaces and set-aside windows close at hand, with keyboard, pointer and touchpad navigation.

Desktop integration

Bring your own layer-shell UI, such as Noctalia or Waybar. For capture and idle management, see nefercap and neferafk.

Configuration is a flat key = value file that reloads on save. A JSON state file exposes outputs, workspaces and windows to scripts; see Desktop integration.

Hardware support

NeferWL requires Linux, atomic KMS and a Vulkan 1.3 device that can export images as dmabufs. It reports an error at startup if these requirements are not met.

GPU Status
AMD Developed and tested on radv
NVIDIA Untested; explicit sync and multi-GPU output are implemented
Intel Untested

Reports from NVIDIA and Intel users are welcome.

Documentation

Contributing

Issues are welcome, including NVIDIA and Intel reports. Please open an issue before a large pull request; small fixes are fine directly.

Before submitting, run make check, make race, make mocks-check and staticcheck ./.... See AGENTS.md for repository rules.

License

GNU Affero General Public License v3.0.

Directories

Path Synopsis
cmd
neferwl command
Command neferwl is the NeferWL Wayland compositor.
Command neferwl is the NeferWL Wayland compositor.
examples
testime command
Command testime is a minimal zwp_input_method_v2 client for testing text input.
Command testime is a minimal zwp_input_method_v2 client for testing text input.
testpattern command
Command testpattern is a minimal Wayland client that shows a grid of known colours, to check by eye or by screenshot that NeferWL renders them correctly:
Command testpattern is a minimal Wayland client that shows a grid of known colours, to check by eye or by screenshot that NeferWL renders them correctly:
testpattern/pattern
Package pattern defines the colour patches of the testpattern client and the transfer functions that say what each patch must look like.
Package pattern defines the colour patches of the testpattern client and the transfer functions that say what each patch must look like.
internal
adapters/atspi
Package atspi finds hint targets in the accessibility tree of the apps on screen.
Package atspi finds hint targets in the accessibility tree of the apps on screen.
adapters/busretry
Package busretry keeps a D-Bus service running across bus restarts and busy names: it runs an attempt again after a growing delay until the context ends.
Package busretry keeps a D-Bus service running across bus restarts and busy names: it runs an attempt again after a growing delay until the context ends.
adapters/captureallow
Package captureallow reads the screen-capture allowlist: the executables that may capture the screen.
Package captureallow reads the screen-capture allowlist: the executables that may capture the screen.
adapters/clock
Package clock is the wall clock behind ports.Clock.
Package clock is the wall clock behind ports.Clock.
adapters/drm
Package drm drives KMS outputs with raw ioctls and atomic commits.
Package drm drives KMS outputs with raw ioctls and atomic commits.
adapters/drm/gbm
Package gbm allocates dmabuf images with libgbm, loaded at runtime with purego.
Package gbm allocates dmabuf images with libgbm, loaded at runtime with purego.
adapters/drm/supervisor
Package supervisor owns DRM cards, readers and timers and executes synchronous core policy decisions.
Package supervisor owns DRM cards, readers and timers and executes synchronous core policy decisions.
adapters/fdwait
Package fdwait parks descriptor waits in Go's netpoller.
Package fdwait parks descriptor waits in Go's netpoller.
adapters/hdrcursor
Package hdrcursor converts cursor images to the HDR10 output encoding (BT.2020 PQ) for cursor planes, whichever adapter owns the image memory.
Package hdrcursor converts cursor images to the HDR10 output encoding (BT.2020 PQ) for cursor planes, whichever adapter owns the image memory.
adapters/headless
Package headless owns virtual output I/O and rendering for the headless backend.
Package headless owns virtual output I/O and rendering for the headless backend.
adapters/headlessinput
Package headlessinput converts scripted text into keyboard events.
Package headlessinput converts scripted text into keyboard events.
adapters/hints
detector sources, capturing pixels only when a listed source needs them.
detector sources, capturing pixels only when a listed source needs them.
adapters/logging
Package logging configures component-scoped zerowrap logging.
Package logging configures component-scoped zerowrap logging.
adapters/outputkit/capture
Package capture transfers each request to an output: the output closes its destination fd exactly once and attempts one reply, never blocking after its context is done.
Package capture transfers each request to an output: the output closes its destination fd exactly once and attempts one reply, never blocking after its context is done.
adapters/outputkit/corewake
Package corewake is how an output asks core for the next frame of a running animation.
Package corewake is how an output asks core for the next frame of a running animation.
adapters/outputkit/cursors
Package cursors delivers cursor updates and owns hide timing through ports.Clock.
Package cursors delivers cursor updates and owns hide timing through ports.Clock.
adapters/outputkit/presented
to wayland: what the output read, held and flipped.
to wayland: what the output read, held and flipped.
adapters/outputkit/routing
Package routing delivers scenes, content and leases to output owners without adding a channel hop to latency-critical output paths.
Package routing delivers scenes, content and leases to output owners without adding a channel hop to latency-critical output paths.
adapters/outputkit/surfaces
renderer, and the last content of a window that closed while the scene still draws it.
renderer, and the last content of a window that closed while the scene still draws it.
adapters/overlaydraw
Package overlaydraw rasterizes compositor overlays (such as keyboard hint labels) on the CPU as premultiplied BGRA pixels for the renderer to upload and draw.
Package overlaydraw rasterizes compositor overlays (such as keyboard hint labels) on the CPU as premultiplied BGRA pixels for the renderer to upload and draw.
adapters/peerexe
Package peerexe names the executable behind a process through a pidfd.
Package peerexe names the executable behind a process through a pidfd.
adapters/powerkey
Package powerkey takes logind's inhibitor locks for the power, suspend, hibernate and reboot keys, so pressing one no longer powers the machine off or to sleep by itself: the key reaches the compositor as a key event (XF86PowerOff, XF86Sleep, ...) and only a bind acts on it.
Package powerkey takes logind's inhibitor locks for the power, suspend, hibernate and reboot keys, so pressing one no longer powers the machine off or to sleep by itself: the key reaches the compositor as a key event (XF86PowerOff, XF86Sleep, ...) and only a bind acts on it.
adapters/sched
Package sched configures latency-sensitive compositor threads.
Package sched configures latency-sensitive compositor threads.
adapters/screencast
interfaces (org.gnome.Mutter.ScreenCast, org.gnome.Mutter.DisplayConfig, org.gnome.Shell.Introspect, org.gnome.Shell.Screenshot) so that xdg-desktop-portal-gnome can offer monitor and window sharing and screenshots.
interfaces (org.gnome.Mutter.ScreenCast, org.gnome.Mutter.DisplayConfig, org.gnome.Shell.Introspect, org.gnome.Shell.Screenshot) so that xdg-desktop-portal-gnome can offer monitor and window sharing and screenshots.
adapters/screensaver
Package screensaver serves org.freedesktop.ScreenSaver idle inhibition.
Package screensaver serves org.freedesktop.ScreenSaver idle inhibition.
adapters/seat
Package seat opens a libseat session (logind or seatd) and hands out device fds.
Package seat opens a libseat session (logind or seatd) and hands out device fds.
adapters/sessionsecurity
Package sessionsecurity supplies a coherent defensive session gate to boundaries outside the Wayland display goroutine.
Package sessionsecurity supplies a coherent defensive session gate to boundaries outside the Wayland display goroutine.
adapters/statefile
Package statefile publishes core's state as JSON for scripts, and reads it back for the `neferwl state` command.
Package statefile publishes core's state as JSON for scripts, and reads it back for the `neferwl state` command.
adapters/syncfile
Package syncfile waits for Linux sync files (dma-fence fds), such as the GPU fence a frame render returns.
Package syncfile waits for Linux sync files (dma-fence fds), such as the GPU fence a frame render returns.
adapters/watchdog
Package watchdog writes every goroutine stack to a file when a probed owner loop stops answering, so a frozen session leaves the exact place it is stuck on disk.
Package watchdog writes every goroutine stack to a file when a probed owner loop stops answering, so a frozen session leaves the exact place it is stuck on disk.
adapters/workspaceid
Package workspaceid names workspaces for programs outside the compositor: the `id` of ext_workspace_handle_v1 and the `workspace_id` of the state file are the same string.
Package workspaceid names workspaces for programs outside the compositor: the `id` of ext_workspace_handle_v1 and the `workspace_id` of the state file are the same string.
adapters/xcursor
Package xcursor loads cursor themes and prepares images for output adapters.
Package xcursor loads cursor themes and prepares images for output adapters.
adapters/xwayland
Package xwayland runs X11 clients through xwayland-satellite, started on demand: neferwl owns the X11 display sockets and starts the satellite when the first X11 client connects, and again after it exits.
Package xwayland runs X11 clients through xwayland-satellite, started on demand: neferwl owns the X11 display sockets and starts the satellite when the first X11 client connects, and again after it exits.
app
Package app coordinates the application lifecycle.
Package app coordinates the application lifecycle.
cli
Package cli parses the neferwl command line and runs the selected command.
Package cli parses the neferwl command line and runs the selected command.
core
Package core is the compositor's application service.
Package core is the compositor's application service.
core/geom
Package geom holds the placement values and pure geometry helpers shared by the core domain packages: window placements, output scale steps and border zones.
Package geom holds the placement values and pure geometry helpers shared by the core domain packages: window placements, output scale steps and border zones.
core/layout
Package layout owns column geometry, lane state and layout engine hooks.
Package layout owns column geometry, lane state and layout engine hooks.
core/motion
Package motion provides value-based springs, gesture tracking, snap swipes, and presentation slides.
Package motion provides value-based springs, gesture tracking, snap swipes, and presentation slides.
core/workspace
Package workspace is the Workspace model: columns, floats, the stash, focus and MRU order, fullscreen and maximization, drag and drop, overview stacks and the pure part of action handling.
Package workspace is the Workspace model: columns, floats, the stash, focus and MRU order, fullscreen and maximization, drag and drop, overview stacks and the pure part of action handling.
domain
Package domain defines compositor entities and value types.
Package domain defines compositor entities and value types.
ports
Package ports defines boundary interfaces and sealed channel messages carrying internal/domain entities and value types.
Package ports defines boundary interfaces and sealed channel messages carrying internal/domain entities and value types.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL