pixelcoords 0.5.0

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
<h1 align="center">pixelcoords</h1>

<p align="center">
  <b>Freeze your screen, mark regions, get pixel-exact coordinates and crops</b><br/>
  <i>Rectangles, ellipses, triangles, N-gons, freehand, rulers — rotate, label, verify, regenerate</i>
</p>

<p align="center">
  <a href="https://github.com/nolindnaidoo/pixelcoords/actions/workflows/ci.yml">
    <img src="https://github.com/nolindnaidoo/pixelcoords/actions/workflows/ci.yml/badge.svg" alt="Build Status" />
  </a>
  <a href="https://docs.rs/pixelcoords-core">
    <img src="https://img.shields.io/docsrs/pixelcoords-core.svg" alt="docs.rs" />
  </a>
  <a href="https://crates.io/crates/pixelcoords">
    <img src="https://img.shields.io/crates/v/pixelcoords.svg" alt="crates.io" />
  </a>
  <img src="https://img.shields.io/badge/rustc-1.88+-93450a.svg" alt="MSRV: Rust 1.88+" />
  <a href="https://github.com/nolindnaidoo/pixelcoords/blob/main/LICENSE">
    <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT" />
  </a>
  <a href="https://pixelcoords.dev">
    <img src="https://img.shields.io/badge/web-pixelcoords.dev-00A0FF.svg" alt="pixelcoords.dev" />
  </a>
</p>

<p align="center">
  <img src="https://github.com/nolindnaidoo/pixelcoords/raw/main/docs/assets/demo.gif" alt="pixelcoords demo: freeze a window, mark shapes, save machine-readable coordinates" style="max-width: 100%; height: auto;" />
</p>

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.**

It freezes your screen so nothing moves while you measure, then lets you
mark regions with real shapes — rectangles, ellipses, triangles, N-gons,
freehand — rotated, labeled, and placed to the exact pixel with a loupe
and arrow-key nudging, plus rulers that report distance and angle between
any two points. Marks snap to the UI edges already in the frozen image,
so a rect around a button lands on the button. What you mark becomes
data, not a picture: versioned JSON in physical pixels with per-monitor
DPI scale, the color under each click point, labeled crops and
frame-sized cutouts, and ready-to-paste click code for your automation
stack.

Then it answers the questions a machine actually asks about that data —
each with an exit code and one JSON shape, so CI and computer-use agents
can script them. Did this click land in the right region, for one point
or a whole trajectory. Where do I click *now*, in the units my input API
wants, on the display it's actually on. Wait until this dialog is back.
Do these regions still look right. Where did this region move to when the
UI drifted out from under my coordinates. Sessions reopen and edit like
documents.

No account, no network, no toolkit — one small native binary for macOS,
Windows, and Linux. MIT-licensed, because the aim was to build the best
tool in this category and give it away.

## Install

Prebuilt binaries for macOS, Windows, and Linux are on the
[releases page](https://github.com/nolindnaidoo/pixelcoords/releases) —
download, unpack, run. Or build it with cargo:

```bash
cargo install pixelcoords
```

Rust 1.88+ for the cargo route. On Linux it needs build dependencies
first:

```bash
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 —
[docs/TROUBLESHOOTING.md](https://github.com/nolindnaidoo/pixelcoords/blob/main/docs/TROUBLESHOOTING.md) covers it.

## Sixty seconds

```bash
pixelcoords                      # screen freezes; drag shapes, A labels, S saves
# → Downloads/pixelcoords-captures/<timestamp>/
#   session.json  screenshot-0.png  cutout-primary-0.png  cutout-inverse-0.png  crop-0-submit.png

pixelcoords assert --session <dir> --point 812,440 --expect submit
# exit 0: that point is inside the region you labeled "submit"
# --stdin scores a whole trajectory in one process, one point per line

pixelcoords resolve --session <dir> --label submit --units auto
# where to click, right now, in the units your input API actually wants

pixelcoords emit --session <dir> --format pyautogui
# ready-to-paste click code, coordinate conventions already handled

pixelcoords wait --session <dir> --label dialog --for match
# block until that region is back on screen; exit 1 if it never arrives

pixelcoords diff --session <dir> --against baseline/
# did those regions still look right? visual regression, per region

pixelcoords find --session <dir>
# the UI moved? every region re-located by its saved crop, deltas included

pixelcoords resume                # pick any saved session, keep editing it

pixelcoords --monitor primary     # freeze one display instead of all of them
# also an index, or part of a display's name: --monitor 0,DELL
```

Window-attached sessions with `--target "Title"` (macOS/Windows/X11)
or `--pick` (Wayland): drawing is locked to the window, and every mark
records `window_px` alongside the usual coordinates so the session stays
valid when the window moves. Freezing every screen stays the default;
`--monitor` narrows it, `[capture] monitors` makes that permanent for a
double-clicked launch, and `R` releases one display mid-session while the
rest stay frozen. Every command speaks exit codes and JSON where a
script would care — the complete reference with every flag is
[docs/CLI.md](https://github.com/nolindnaidoo/pixelcoords/blob/main/docs/CLI.md).

## Controls

Drag draws; the on-screen panel teaches everything else. The ones that
matter: `W` cycles the tool, `A` labels, `S` saves, `Z` undoes, `X` turns
edge snapping off when you want a placement left exactly where you put
it, hold `M` for a pixel loupe, `Esc` backs out / quits. Full table in
[docs/CLI.md](https://github.com/nolindnaidoo/pixelcoords/blob/main/docs/CLI.md); every key is rebindable via
[docs/CONFIGURATION.md](https://github.com/nolindnaidoo/pixelcoords/blob/main/docs/CONFIGURATION.md).

## Platform status

| Platform | State |
|----------|-------|
| macOS | Supported — primary development platform |
| Windows | Supported — verified by hand on Windows 11 |
| Linux (X11) | Supported — verified by hand on GNOME 46; every feature works |
| Linux (Wayland) | Screen coordinates + `--pick` window marking — verified by hand on GNOME 46; no `windows` / `--target` (the protocol withholds window geometry) |

**Multi-monitor and mixed-DPI are verified on real hardware**, on macOS:
two displays at different scales (a 2x built-in and a 1x external sitting
at a negative desktop origin), marks placed on both, and every coordinate
recorded exactly where it was drawn. `find` relocated a region on the
second display at a perfect score, and releasing one display left the
other frozen and markable. Linux and Windows multi-monitor remain
test-only.

Hand-verification is per platform *and* per release, so the table above
is not a blanket claim. **macOS covers everything through 0.5.0**,
including the color readout, the measure tool, and edge snapping.
**Windows and Linux were verified by hand through 0.4.0**; 0.5.0's
overlay additions pass CI on both but have not had a human run there. CI
runs the full suite on all three platforms every push, and the overlay is
the part tests cannot speak for. This table is kept honest — claims match
runs.

## Acting on what you marked

pixelcoords answers *where is this thing, exactly*. It deliberately stops
there — it never moves your mouse or types for you.

**[pixelactions](https://github.com/nolindnaidoo/pixelactions)** is the
other half of that loop: it reads a session, performs the interaction —
click, type, chord, drag, scroll — and confirms it landed, refusing to act
on any region it cannot still find unambiguously.

```bash
pixelactions run --session ~/captures/checkout \
  click:email type:"a@b.com" click:submit wait:confirmed --yes
```

Driven from a chained command, a reviewable flow file, or a line protocol
any language can speak. Its logic layer is
[pixelactions-core](https://github.com/nolindnaidoo/pixelactions), the way
[pixelcoords-core](https://crates.io/crates/pixelcoords-core) is this
tool's. Separate binary, separate repository, one-way dependency: this
project does not know it exists.

## Non-goals

Knowing what a tool is means knowing what it isn't. These are settled:

- **OCR** — text extraction is a different product; platform tools and
  Shottr own it.
- **Live (unfrozen) measurement** — the freeze *is* the thesis: nothing
  moves between look and click.
- **Annotation** — arrows, blur, and highlights are a screenshot
  editor's job; labels here exist for machines, not slides.
- **Recording / GIF capture** — the product is the frozen instant, not
  the timeline; ShareX exists.
- **Cloud upload, sharing, accounts** — offline by design, permanently.
- **Performing the interaction** — clicking and typing is a different
  threat model and a different tool; see
  [pixelactions]https://github.com/nolindnaidoo/pixelactions above.

## Documentation

- [pixelcoords.dev]https://pixelcoords.dev — the website: demo, comparisons, how-to
- [docs/CLI.md]https://github.com/nolindnaidoo/pixelcoords/blob/main/docs/CLI.md — every command, flag, control, and exit code
- [docs/OUTPUT.md]https://github.com/nolindnaidoo/pixelcoords/blob/main/docs/OUTPUT.md — session.json schema, crops, cutouts, jq recipes
- [docs/CONFIGURATION.md]https://github.com/nolindnaidoo/pixelcoords/blob/main/docs/CONFIGURATION.md — colors, key bindings, config file
- [docs/TROUBLESHOOTING.md]https://github.com/nolindnaidoo/pixelcoords/blob/main/docs/TROUBLESHOOTING.md — fixes, behaviors, FAQ
- [docs/DEVELOPMENT.md]https://github.com/nolindnaidoo/pixelcoords/blob/main/docs/DEVELOPMENT.md — building from source, CI gates, tests, releases
- [CHANGELOG.md]https://github.com/nolindnaidoo/pixelcoords/blob/main/CHANGELOG.md — what changed and why
- [CONTRIBUTING.md]https://github.com/nolindnaidoo/pixelcoords/blob/main/CONTRIBUTING.md — bug reports and pull requests
- [pixelactions]https://github.com/nolindnaidoo/pixelactions — the executor half: act on a session, and confirm it landed

## License

MIT — see [LICENSE](https://github.com/nolindnaidoo/pixelcoords/blob/main/LICENSE). Bundled: JetBrains Mono (OFL 1.1).

Built by [nolindnaidoo](https://github.com/nolindnaidoo).