A minimal, single-binary CLI for changing display resolution. No dependencies, no installer — just drop the binary in your PATH and go.
| Platform | Support |
|---|---|
| Windows 7 / 8 / 10 / 11 | ✅ via Win32 API |
| Linux amd64 (X11) | ✅ via xrandr |
| Linux amd64 (Wayland) | ✅ via zwlr-output-management protocol |
| Linux arm64 (X11 + Wayland) | ✅ Raspberry Pi 4/5, Asahi Linux, ARM VMs |
| macOS (Intel + Apple Silicon) | ✅ via CoreGraphics — universal binary |
-
Grab
resctl.exefrom the latest release. -
Optionally verify the download against
checksums.txt(also in the release assets):# PowerShell $hash = (Get-FileHash resctl.exe -Algorithm SHA256).Hash.ToLower() $expected = (Select-String resctl.exe checksums.txt).Line.Split()[0] if ($hash -eq $expected) { "OK" } else { "MISMATCH" }
-
Open a terminal in the folder containing the download and run:
.\resctl.exe installThis copies the binary to
%USERPROFILE%\bin\resctl.exeand adds that folder to your userPATH. -
Restart your terminal — you're done.
git clone https://github.com/dever-labs/resctl
cd resctl
.\build.ps1 # installs goversioninfo, embeds resources, builds resctl.exe
.\resctl.exe installX11 requires
xrandr(x11-xserver-utilson Debian/Ubuntu,xorg-xrandron Arch).
Wayland works out of the box — the binary speaks thezwlr-output-management-unstable-v1protocol directly. No extra packages needed. Requires a compositor that implements that protocol (e.g. sway, wayfire, labwc, or any wlroots-based compositor). GNOME (Mutter) and KDE (KWin) do not implement this protocol —resctldetects this and tells you to usegnome-randr/Settings on GNOME,kscreen-doctoron KDE, or anxrandr-based tool via XWayland elsewhere.
-
Grab the binary for your architecture from the latest release:
resctl— amd64 (most desktops/laptops)resctl-linux-arm64— arm64 (Raspberry Pi 4/5, Asahi Linux, ARM cloud VMs)
-
Optionally verify the download against
checksums.txt(also in the release assets):sha256sum -c checksums.txt --ignore-missing # resctl: OK -
Run:
chmod +x resctl ./resctl install
This copies the binary to
~/bin/resctland adds~/binto yourPATHin.bashrc,.zshrc, or.profile. -
Restart your terminal — you're done.
git clone https://github.com/dever-labs/resctl
cd resctl
go build -ldflags="-s -w" -o resctl .
./resctl install-
Grab
resctl-macosfrom the latest release. It's a universal binary (runs natively on both Intel and Apple Silicon Macs). -
Optionally verify the download against
checksums.txt(also in the release assets):sha256sum -c checksums.txt --ignore-missing # resctl-macos: OK -
Run:
mv resctl-macos resctl chmod +x resctl ./resctl install
This copies the binary to
~/bin/resctland adds~/binto yourPATHin.bash_profile,.zshrc,.config/fish/config.fish, or.profile. -
Restart your terminal — you're done.
git clone https://github.com/dever-labs/resctl
cd resctl
go build -ldflags="-s -w" -o resctl .
./resctl installresctl uninstall # prompts for confirmation
resctl uninstall --force # skip the confirmation prompt
resctl list List all supported resolutions (current marked with *)
resctl get Show the current resolution
resctl set <WxH[@Hz]> [--force] Change resolution (skips the change if already active, unless --force)
resctl toggle [res1 res2 ...] Cycle between resolutions
resctl toggle --list Show the saved toggle list and current position
resctl toggle --clear Delete the saved toggle list
resctl install Copy binary to ~/bin and add to PATH
resctl uninstall [--force] Remove binary from ~/bin (prompts for confirmation)
resctl completion <shell> Print a completion script (bash, zsh, fish)
resctl version Print the installed version
Resolution format: WxH or WxH@Hz — e.g. 1920x1080 or 2560x1440@144.
# See everything your monitor supports
resctl list
# What's active right now?
resctl get
# Switch to 1080p (keeps the current refresh rate if available)
resctl set 1920x1080
# Switch to 1440p at 144 Hz explicitly
resctl set 2560x1440@144
# No-op: already at 1920x1080, prints "Already at 1920x1080 @ 60Hz" and exits
resctl set 1920x1080
# Reapply the same resolution anyway (e.g. to force a mode re-negotiation)
resctl set 1920x1080 --force
# Set up a two-resolution toggle and switch immediately
resctl toggle 1920x1080 2560x1440
# After that, each call to `toggle` cycles to the next entry
resctl toggle
# Inspect the saved toggle list and current position
resctl toggle --list
# Toggle list:
# [0] 1920x1080
# [1] 2560x1440 ← current
# Delete the saved toggle list
resctl toggle --clear
# List all connected displays and their current resolution
resctl displays
# Connected displays:
# DP-1: 2560x1440 @ 144Hz
# HDMI-1: 1920x1080 @ 60Hz
# Enable shell completion
resctl completion bash > /etc/bash_completion.d/resctl
resctl completion zsh > "${fpath[1]}/_resctl"
resctl completion fish > ~/.config/fish/completions/resctl.fishToggle state is saved and persists across reboots:
- Windows:
%APPDATA%\resctl\state.json - Linux:
$XDG_CONFIG_HOME/resctl/state.json(defaults to~/.config/resctl/state.json) - macOS:
~/Library/Application Support/resctl/state.json
- Windows — calls
EnumDisplaySettingsWandChangeDisplaySettingsWdirectly. No admin rights required for the primary display. - Linux (X11) — shells out to
xrandr. Targets the primary connected output. Requires an X11 session. - Linux (Wayland) — connects to the Wayland compositor socket and speaks the
zwlr-output-management-unstable-v1protocol natively. No external tools required. The session is detected automatically viaWAYLAND_DISPLAYorXDG_SESSION_TYPE. - macOS — calls CoreGraphics (
CGDisplayCopyDisplayMode,CGDisplayCopyAllDisplayModes, andCGDisplaySetDisplayMode) directly for the main display. No external tools required.
The easiest way to get started is with the included Dev Container — open the repo in VS Code or GitHub Codespaces and everything is set up automatically.
- Go 1.26+
- Windows build:
goversioninfo(go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@latest) - Linux build:
xrandrfor smoke-testing - macOS build: Xcode Command Line Tools for cgo and CoreGraphics
Windows:
.\build.ps1Or manually:
go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@latest
goversioninfo -64 -o resource.syso # embed icon & version metadata
go build -ldflags="-s -w -X main.version=dev" -o resctl.exe .Linux:
go build -ldflags="-s -w -X main.version=dev" -o resctl .macOS:
go build -ldflags="-s -w -X main.version=dev" -o resctl .Cross-compile for Windows from Linux (Dev Container):
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w -X main.version=dev" -o resctl.exe .Tests run without resource.syso present (the test linker cannot handle Windows COFF resource objects):
# Windows
Remove-Item resource.syso -ErrorAction SilentlyContinue
go test ./...# Linux / Dev Container
go test ./...# macOS
go test ./...Unit test coverage focuses on pure/parsing logic (resolution parsing, xrandr output parsing, toggle-list state handling, JSON output, flag parsing, shell-completion script generation). Code that calls into platform display APIs directly (xrandr, the Wayland compositor protocol, Win32, CoreGraphics) isn't exercised by unit tests — it's verified on every PR by CI running the full build, vet, lint, and test suite natively on windows-2025-vs2026, ubuntu-latest, and macos-latest runners.
resctl follows Semantic Versioning. As of 1.0.0:
- The CLI's commands, flags, and output formats (including
--jsonschemas) are considered a stable public interface — breaking changes to them will only ship in a new major version. - The
state.jsonschema is versioned (see theversionfield) so future changes can migrate existing files forward instead of breaking them. - Pre-1.0.0 releases (
0.x.y) did not carry this guarantee.
Tag the commit you want to release, then create a release from the GitHub UI and attach the built binary as an asset:
$env:VERSION = "v1.0.0"
.\build.ps1See CONTRIBUTING.md for branch naming, commit conventions, and the local verification checklist expected before opening a PR.
xrandr: command not found / xrandr query failed
resctl shells out to xrandr on X11. Install it: sudo apt install x11-xserver-utils (Debian/Ubuntu) or sudo pacman -S xorg-xrandr (Arch). This error can also appear if you're actually in a Wayland session but xrandr (XWayland-aware) still fails — check echo $XDG_SESSION_TYPE / echo $WAYLAND_DISPLAY.
zwlr_output_manager_v1 not available on GNOME or KDE
GNOME (Mutter) and KDE (KWin) don't implement the zwlr-output-management protocol that resctl uses natively on Wayland. Use gnome-randr or Settings → Displays on GNOME, or kscreen-doctor on KDE. On other desktops, the error message suggests trying an xrandr-based tool via XWayland. See #7 for background.
cannot connect to Wayland socket / XDG_RUNTIME_DIR is not set
resctl needs XDG_RUNTIME_DIR and WAYLAND_DISPLAY set, which is normally done automatically by your session manager. This usually means you're running resctl from a context without a graphical session attached (e.g. an SSH session, a sudo-elevated shell that dropped the environment, or a cron job) — run it from within your graphical session instead.
resctl install updated PATH but resctl still isn't found
Restart your terminal (or re-source your shell rc file, e.g. source ~/.bashrc) — PATH changes only take effect in new shell sessions. If that doesn't help, check that your SHELL environment variable actually points at your real shell (echo $SHELL); resctl install picks the rc file to edit based on it, and an unusual/misconfigured SHELL can cause it to fall back to ~/.profile instead of ~/.bashrc/~/.zshrc/~/.config/fish/config.fish.
display "X" not found when using --display
Display names are platform-specific (e.g. DP-1, HDMI-1 on Linux; a numeric index on Windows/macOS). Run resctl list without --display first to see the primary display's modes, or check your compositor/X11 output name directly (xrandr --query on X11, or your Wayland compositor's own tooling).
MIT © Dever Labs