JWM is a Rust window manager and compositor with native X11 and Wayland backends. It combines tag-based tiling, multiple layouts, multi-monitor control, animations and compositor effects with a JSON IPC control plane. The project is under active development and supports both direct DRM/KMS sessions and nested development backends.
- X11RB and XCB window-manager backends with an integrated X11 compositor.
- Direct Wayland DRM/KMS, nested X11, and nested winit backends with XWayland.
- Tile, monocle, floating, scrolling, grid, deck, fibonacci, centered-master, bstack, three-column, tatami, fullscreen, and vertical-stack layouts.
- Tags, per-monitor state, overview/expose, display layout UI, screenshots, screen/audio recording, session restore, gestures, accessibility filters, HDR/VRR/color-management plumbing, and direct-scanout diagnostics.
- Full-screen WaterLily.jl simulation frames on the X11RB/XCB compositor, produced externally on CPU, CUDA, or ROCm.
- Live configuration reload and a newline-delimited JSON IPC API exposed through
jwm-tool. - Read-only startup health checks, semantic configuration diagnostics, and privacy-aware support bundles.
JWM requires the normal Linux X11, Wayland, DRM/GBM, libinput, libseat, EGL/GL,
ALSA, D-Bus, and font/rendering development packages for your distribution.
The minimum supported Rust version with the committed Cargo.lock is 1.89;
it is declared in Cargo.toml and checked in CI.
On a fresh Debian/Ubuntu machine, scripts/bootstrap_deps.sh installs every
native dependency plus the Rust toolchain (via rustup, since distro packages are
older than the 1.89 floor) in one step:
bash scripts/bootstrap_deps.sh # apt packages + rustup toolchain
JWM_CN_MIRROR=1 bash scripts/bootstrap_deps.sh # China: rustup + cargo via rsproxy.cn
bash scripts/bootstrap_deps.sh --help # options include --with-portal, --with-tauri, --cn--with-portal (or JWM_WITH_PORTAL=1) adds the PipeWire headers needed by the
screencast portal. On non-Debian distros the script prints the required library
groups to map to your package manager. Then build:
cargo build --locked --release
cargo test --locked --lib --bins --testsThe release build produces jwm, jwm-tool, and jwm-support. Before starting
a display backend, inspect the environment and configuration:
target/release/jwm --backend x11rb --doctor
target/release/jwm --backend wayland-udev --doctor --jsonX11 and Wayland use separate files under ~/.config/jwm:
target/release/jwm --gen-config
target/release/jwm --backend x11rb --check-config
target/release/jwm --backend wayland --check-config
target/release/jwm --backend x11rb
# Direct DRM/KMS session:
target/release/jwm --backend wayland-udevSupported backend names are x11rb, xcb, wayland-udev, wayland-x11, and
wayland-winit. See startup and configuration for aliases,
logging, benchmarking, restart behavior, and doctor output.
The installation helper builds JWM and one selectable status bar, installs the
session files, and keeps existing configuration unless --gen-config is used:
scripts/install_jwm_scripts.sh --helpNative bars need only the default bootstrap dependencies. Selecting a Tauri web
bar also needs the Tauri 2 Linux libraries (bootstrap_deps.sh --with-tauri) and
builds its frontend: React/Solid/Svelte/Vue variants require Node.js plus
pnpm; Leptos/Yew variants require trunk, Tauri CLI 2, and the
wasm32-unknown-unknown Rust target. The helper checks these prerequisites up
front and prints the exact install command for anything missing.
jwm-tool sends typed JSON commands and queries over JWM's private Unix socket:
jwm-tool msg get_windows
jwm-tool msg view --args '{"tag":2}'
jwm-tool msg setlayout --args '{"layout":"scrolling"}'
jwm-tool msg spawn --args '{"cmd":["alacritty"]}'
jwm-tool msg '' --subscribe 'window,tag,layout'
jwm-tool health
jwm-tool health --json
jwm-tool capabilities --jsonMalformed JSON, invalid argument types, overflow, empty spawn commands, unknown
commands, and { "success": false } responses produce a non-zero exit status,
so the tool is safe to use from scripts.
health is a backend-neutral live snapshot of the running JWM instance. Its
versioned JSON includes the actual selected backend, uptime, configuration
health, window/monitor/workspace counts, active features, and compositor metrics
when the backend exposes them. capabilities discovers the supported IPC
commands, queries, and subscription topics. The older jwm-tool status command
retains its existing meaning: it reports the optional process supervisor rather
than querying JWM's live IPC socket.
save_session writes a private, atomic snapshot under
$XDG_STATE_HOME/jwm/session.json (normally
~/.local/state/jwm/session.json); restore also recognizes the legacy cache
location. restore_session reapplies monitor, tag, and floating-window state.
jwm-support combines the offline startup doctor with optional live health and
capability queries in a versioned JSON document:
jwm-support --backend x11rb --output jwm-support.json
jwm-support --backend wayland-udev --offline --output jwm-support.json
jwm-support --strict --compact > jwm-support.jsonFile output is private (0600) and atomically replaced. The collector uses a
small environment allowlist and redacts configuration, executable, runtime,
and IPC error details; it excludes HOME, PATH, D-Bus addresses, process command
lines, window titles, and arbitrary environment variables. Review
support bundles before attaching a
report to a public issue.
The default modifier is Alt (Mod1). Useful built-in bindings include:
| Binding | Action |
|---|---|
| Alt+Shift+Return | Launch terminal |
| Alt+R | Application launcher (type / for open windows) |
| Alt+Control+Escape | Lock screen |
| Alt+Control+O | Display layout |
| Alt+S / Alt+Shift+S | Interactive / immediate desktop screenshot |
| Alt+Control+R | Interactively choose a source and start/stop screen recording |
| Alt+Control+Shift+R | Move, resize, or replace the active recording source |
| Alt+Shift+C | Close focused client |
| Alt+Control+C | Calculator scratchpad |
| Alt+Control+S | Toggle sticky window |
| Alt+Shift+F11 | Toggle the WaterLily simulation |
| Alt+Shift+F10 | Cycle the WaterLily simulation case |
| Alt+Shift+F9 | Cycle the WaterLily render palette |
| Alt+Shift+/ | Show all bindings |
During interactive screenshot or recording selection, press G, W, M, or
D to choose a dragged region, a window, the monitor under the pointer, or the
entire desktop. Tab and Shift+Tab cycle the same choices. Window capture
shows a hover preview and is confirmed with the left mouse button; Enter
saves a screenshot or starts/commits recording. Arrow keys nudge a committed
selection (Shift uses 10-pixel steps), while Escape, right-click, or the
recording shortcut again cancels safely.
Once a screenshot region is committed the selection becomes an editor, and a toolbar floats just outside it — below the selection, or above when there is no room below. Every tool has both a button and a key, so neither the mouse nor the keyboard is required:
| Tool | Key | Draws |
|---|---|---|
| Pencil | P / F |
Freehand stroke |
| Line | L |
Straight line |
| Arrow | A |
Line with a head |
| Rectangle | R |
Hollow rectangle |
| Filled rectangle | B |
Solid redaction bar |
| Ellipse | C / O |
Hollow ellipse |
| Marker | H |
Translucent highlighter |
| Text | T |
Typed label — click, then type |
| Counter | N |
Auto-numbered bubble; click to place the next one |
| Pixelate | X |
Drag a region down to blocks |
| Invert | I |
Invert a region's colors |
The rest of the strip is the selection's pixel size, the stroke controls, the ink swatch, and the four ways out:
| Control | Key |
|---|---|
| Thinner / thicker stroke | - / +, Ctrl+Down / Ctrl+Up, or the wheel |
| Ink (8-colour ring) | 1…8, or click the swatch to step |
| Undo / redo | Ctrl+Z, Backspace / Ctrl+Shift+Z, Ctrl+Y |
| Save to file | Enter or Ctrl+S |
| Copy to clipboard | Ctrl+C |
| Cancel | Escape |
While a text label is open every key is text; Enter commits it, Escape
drops it, and switching tools commits it. A control with nothing to do — undo
with an empty history, thinner at the minimum width — is dimmed rather than
removed, so the row never reflows under the pointer.
The status bars' screenshot pill drives exactly this editor over the control
socket (the take_screenshot IPC command) rather than launching an external
grabber, so it works identically under X11 and Wayland and needs nothing
installed. take_screenshot_fullscreen captures the whole desktop with no
interaction.
The optional portal/ crate provides JWM's screencast portal backend. Its
installer builds the independent manifest, installs a per-user D-Bus activation
service with the correct home path, and restarts an older activated backend:
scripts/install-portal.sh
scripts/test-portal.shPortal builds require PipeWire 1.2 development files, pkg-config, and libclang.
System installations are discovered automatically. For a private PipeWire
prefix, set JWM_PIPEWIRE_PREFIX; the installer derives the pkg-config search
path and runtime rpath, and it also honors CARGO_TARGET_DIR:
JWM_PIPEWIRE_PREFIX=/opt/pipewire-1.2 scripts/install-portal.shThe built-in shell — the control center, native
notifications with a freedesktop D-Bus service,
media controls driven from MPRIS, the
calendar, the application launcher,
the wallpaper picker and its colour theming,
clipboard history, the idle policy,
the resource rows, and the
session menu and night light — is documented per
feature. Every status bar in bars/ carries an entry that opens the
same Shell Hub,
so a pointer-driven session reaches it without Alt+F10. Every panel key is a
toggle: Alt+F10, Alt+F11, Alt+F12, Alt+F9 and the rest each take their
own surface back down, so nobody has to reach for Esc.
The Alt+Ctrl+Tab window switcher and the cube tag-switch transition are both
the Compiz-style lit prism documented in cube effects.
Alt+Space cycles layouts over a film strip of live thumbnails; see
the layout picker.
Minimized windows fold into the bar, expose a magnifying Dock shelf and show a
compositor-owned hover preview; the cross-process lifecycle is documented in
the minimized-window Dock.
The compositor's live counters are on Alt+Shift+F12; see
the debug HUD.
Additional operational tools are documented in tools/README.md.
The external Julia simulation worker and frame protocol are documented in
docs/waterlily.md.
Architecture boundaries and the incremental migration plan are in
docs/architecture.md. The delivery sequence for larger
changes is tracked in the evolution roadmap.
Before opening a pull request, read CONTRIBUTING.md. Please report security-sensitive problems through the private process described in SECURITY.md, not a public issue.
jwm is distributed under the MIT License. The portal/ crate
(the xdg-desktop-portal ScreenCast backend) is covered by the same license,
as already declared in its manifest.