pixelcoords 0.7.7

Freeze your screen, mark regions, get pixel-exact coordinates and crops — a cross-platform screenshot and screen-capture CLI for macOS, Windows, and Linux (X11 and Wayland), HiDPI and multi-monitor aware
pixelcoords-0.7.7 is not a library.

Useful? A star is how other developers find it — ★ GitHub · pixelcoords.dev

Every screen tool that measures pixels ends at a human's eyeball: a ruler shows you a number, a screenshot app draws an arrow, a mouse tracker prints a position you copy by hand. pixelcoords starts from a different premise — the real consumer of a coordinate is a machine.

Freeze the screen so nothing moves while you measure, mark regions with real shapes, and what you marked becomes data, not a picture: versioned JSON in physical pixels with per-monitor DPI scale, labeled crops, and ready-to-paste click code for your automation stack.

Install

Route Command Worth knowing
Homebrew brew tap nolindnaidoo/tapbrew install pixelcoords macOS only. The formula has no Linux build — the Linux binary needs a capture stack (libxcb, libpipewire, libegl, libgbm) wired to system paths Homebrew does not own. Tap once; after that it installs like any formula.
winget winget install nolindnaidoo.pixelcoords Windows 10+. A portable install: winget unpacks the exe and registers a PATH alias, so there is nothing in Add/Remove Programs.
cargo cargo install pixelcoords Any platform, needs Rust 1.88+. It compiles the capture stack from source, so expect minutes rather than seconds. On Linux install the build dependencies below first.
Prebuilt binary releases page macOS (arm64 + x86_64), Windows, Linux. No toolchain needed — download, unpack, run. No auto-update: you come back here for the next version. Each release ships checksums.

Building on Linux needs the capture stack first:

sudo apt-get install -y libxcb1-dev libxcb-randr0-dev libpipewire-0.3-dev \
  libclang-dev libegl1-mesa-dev libgbm-dev pkg-config

macOS asks for Screen Recording permission on first run.

Sixty seconds

pixelcoords                        # freeze every screen; drag to mark, A labels, S saves
pixelcoords resolve --session ~/Downloads/pixelcoords-captures/<stamp>

resolve prints the click point for every label you marked, in the space and units your automation API speaks:

{ "label": "submit", "monitor": 0, "scale": 2.0, "units": "logical",
  "point": { "x": 812, "y": 440 } }

That is the whole loop: mark once, resolve forever. The session is a directory of JSON and PNGs you can commit.

Commands

Command What it does
pixelcoords Freeze every screen and open the marking overlay
resolve Where to click for each label, in your API's space and units
find Re-locate regions in a fresh capture — for when the UI moved
assert Did this point land in the right region? One point or a stream
diff Do the regions still look like they did?
wait Block until regions match again, or until one stops matching
emit Ready-to-paste click code for pyautogui, cliclick, xdotool, and more
shoot Plain scripted screenshot, no overlay, same DPI handling
resume Reopen a saved session and keep editing
rename Give a session a friendly name for the resume picker
windows List visible windows, for --target
doctor Check permissions, config, and the monitor setup
mcp Serve the agent surface over MCP on stdio

Full reference with every flag: docs/CLI.md

Things worth knowing early

Coordinates are physical pixels, and --units is the knob. A session records what the display actually has. --units auto converts to what your platform's input API expects — logical points on macOS, physical pixels on Windows and X11. Guessing wrong on a Retina display puts every click at half the intended position.

Exit codes are the API. Scripts branch on them:

Code Meaning
0 yes — resolved, matched, hit
1 a real answer, and it is no — not found, missed, timed out
2 the question was malformed — bad label, unreadable session

Wayland withholds window geometry. windows and --target refuse there and point you at --pick instead. That refusal is deliberate; a guessed window position would be worse than no answer.

--min-score and --tolerance are different quantities. The first is a correlation score in 0..=1; the second is a percentage of pixels in 0..=100. Both are bounds-checked, so a swapped value is refused rather than silently matching nothing.

Configure it

Colors, key bindings, snapping, and overlay behavior live in a config file you can also override per run:

pixelcoords --bind u=undo --config ./my-config.toml

Every setting and every bindable action: docs/CONFIGURATION.md

Platform support

Platform Capture Window targeting Verified by hand
macOS Yes --target overlay through 0.5.1; multi-monitor + mixed-DPI on real hardware
Windows 11 Yes --target through 0.4.0; multi-monitor test-only
Linux (X11) Yes --target through 0.4.0; multi-monitor test-only
Linux (Wayland) Yes, via portal --pick only through 0.4.0; windows/--target refuse by design

Fractional scaling is unverified everywhere. Claims here match runs — where a run has not happened it says so, and CONTRIBUTING.md carries the full record.

Performance

Measured on an Apple M5 Pro, --release, at 0.5.3. Reproduce with:

cargo run --release -p pixelcoords-core --example bench   # the math
scripts/bench-cli.sh <session-dir>                        # the round trip
Operation Size Median
resolve, all labels 400 selections 14.3 µs
assert, one point 400 selections 2.0 µs
diff, one region 160×90 crop 20.6 µs
find (full-frame NCC) 160×90 crop 198 ms
find (full-frame NCC) 400×300 crop 1.40 s

Resolving is free; matching is the expensive part, and it scales with crop area rather than screen size. Method and caveats: docs/PERFORMANCE.md

Testing

Layer What it covers
Unit + property tests pixelcoords-core, 90% line coverage floor per module
Contract tests every exit code, every command — no display needed
Scenario tests the binary driven against a real display, on macOS, Windows and Linux every push
Manual gates the overlay itself — tests cannot speak for it, so it is verified by hand and said so plainly

659 tests. CI runs fmt, clippy pedantic (-D warnings), the suite, MSRV, cargo audit, and a policy job that fails on any inline #[allow].

Non-goals

Not a screen recorder, not an OCR tool, not a UI-testing framework, and not an executor — pixelcoords never moves your mouse. It answers where, and stops. pixelactions is the other half of that loop.

Documentation

Also by nolindnaidoo

Rust

VS Code Extensions — every tool in the family, one page: letools.dev

  • String-LE - Extract string values for i18n from JSON, YAML, CSV, TOML, INI, and .env
  • Numbers-LE - Extract numeric values from JSON, YAML, CSV, TOML, INI, and .env
  • EnvSync-LE - Spot missing keys across your .env files, with a markdown report
  • Paths-LE - Extract file paths from JS/TS imports, JSON, HTML, CSS, TOML, CSV, and .env
  • Secrets-LE - Detect and sanitize credentials locally, before you commit
  • Scrape-LE - Check whether a page is scrapeable before you write the scraper
  • Colors-LE - Extract and analyze colors from CSS, SCSS, LESS, Stylus, HTML, JS/TS, and SVG
  • URLs-LE - Extract URLs from documentation, configs, and code
  • Regex-LE - Find, test, and validate the regex patterns in the current file
  • Dates-LE - Extract and analyze dates from logs, configs, and code

Contact DeveloperGitHub · LinkedIn

License

MIT — see LICENSE. Bundled: JetBrains Mono (OFL 1.1).