Hydrogen Desktop (macOS / Lima)
Public Made by Adomby adom
The macOS platform layer for Hydrogen Desktop.
name: hd-self-screenshot-mac
description: >
macOS platform companion to hd-self-screenshot — the Apple-specific half of HD
screenshotting its own window, PLUS the token-efficient capture flow (shot — one
call, prints a PNG path, never floods context with base64). The tool ladder, the
POST /screenshot CDP endpoint, selector region-clips, the sharing gate, and the
during-a-recording contention matrix live in hd-self-screenshot (adom/hd-bootstrap);
THIS skill carries the shot helper doctrine and the macOS capture internals: the
screencapture CLI / CoreGraphics window path, the CDP Page.captureScreenshot
content grab, how the per-panel selector crop resolves the rect via dom.measure
(WKWebView has no CDP) and crops with the image crate, and the Screen Recording TCC
grant. Mirror of hd-self-screenshot-windows (Win32 PrintWindow/BitBlt). Trigger
words — screenshot hd mac, shot helper, token efficient screenshot, screencapture
cli, coregraphics screenshot, wkwebview no cdp, dom.measure crop,
page.capturescreenshot mac, screen recording permission screenshot, tcc screenshot
grant.
hd-self-screenshot (macOS) — screencapture / CoreGraphics + the CDP content path
This is the macOS half of hd-self-screenshot. The default flow — adom-cli hydrogen screenshot panel|workspace|screen saving a PNG into the container's
screenshots/ to Read, the POST /screenshot {target,selector,b64,silent} CDP
power-path, the sharing gate, and the multi-thread capture_busy / coexistence matrix
— is cross-platform and lives in the generic hd-self-screenshot skill. Read that
first; this skill documents the token-efficient capture flow and what's Apple-specific
about how the bytes are grabbed.
⭐ ALWAYS capture with shot — 2 tool calls, ~20 bytes of output
Never run adom-cli hydrogen screenshot ... bare. It prints the capture as a
~300 KB base64 dataUrl JSON on stdout — that's ~85k tokens of noise in your context
per capture, plus a second decode step you'd have to improvise. This bootstrap installs
a wrapper that does the whole thing in one call and prints ONLY the PNG path:
shot # whole workspace (all panels) → /tmp/shot-workspace-<ts>.png
shot screen # entire screen (desktop, other apps)
shot panel --name "KiCad" # one panel's content
shot workspace --reason "verify the flow viewer rendered" # flags pass through
Then Read the printed path — the Read tool attaches images efficiently. Total flow: one Bash call + one Read. That's the floor; don't add steps.
- If no image comes back,
shotexits 1 and prints the CLI's own JSON to stderr — usually the sharing gate (capture needs the user's sharing approval; pass--reason "…"so the approval dialog says why). Read the error, don't blind-retry. SHOT_OUT=/path/out.png shot ...overrides the output path if you need a stable name.- If
shotis missing (pre-0.1.3 workspace), re-converge:adom-wiki pkg install adom/hd-mac-bootstrap— or inline the same pipe:adom-cli hydrogen screenshot workspace 2>/dev/null | python3 -c "import sys,json,base64;d=json.load(sys.stdin);open('/tmp/ws.png','wb').write(base64.b64decode(d['dataUrl'].split(',',1)[1]));print('/tmp/ws.png')"
How HD grabs its own window on macOS
- Whole-window / desktop: HD uses the macOS
screencaptureCLI (and CoreGraphics window capture) to grab the HD window or the full screen — the macOS analog of the WindowsPrintWindow/BitBltpath. - Webview / panel content: the canonical content grab is CDP
Page.captureScreenshot(the/capture/viewport·/shotpath) — a one-shot, wake-lock-free capture of the rendered surface. This is the samePOST /screenshotendpoint as everywhere; on macOS it backs thetarget/panel content capture.
⭐ The per-panel selector crop — dom.measure, not CDP
On Windows the selector region-clip can lean on CDP against the webview. On macOS the
HD shell uses WKWebView, which exposes no CDP to drive the page directly. So a
per-panel / per-selector crop resolves the rect a different way:
- Resolve the element's rectangle via the
dom.measureui-action RPC (the UI-command bus measures the selector in the live DOM and returns its bounds). - Capture the content area (CDP
Page.captureScreenshot/screencapture). - Crop the captured image to that rect with the Rust
imagecrate.
So {selector:".resource-bars"} still clips to just that element — but the rect comes
from dom.measure and the crop is server-side in Rust, because WKWebView can't be
CDP-shot to a selector the way a Chromium webview can.
macOS gotcha — the Screen Recording TCC grant
The OS-level capture (screencapture / CoreGraphics) is gated by macOS TCC: System
Settings → Privacy & Security → Screen Recording must allow Hydrogen Desktop. Without
that grant a window/screen capture comes back black or empty even though the call
"succeeds." If screenshots are blank, check the Screen Recording grant first — it's the
same grant the desktop recording paths need ([hd-recording-mac]).
NOT here (lives in the Windows companion)
The Win32 capture primitives — PrintWindow (per-window, works for backgrounded
windows) and BitBlt — are the Windows self-screenshot mechanics; see
hd-self-screenshot-windows. On macOS it's screencapture/CoreGraphics + CDP
Page.captureScreenshot, with dom.measure-driven cropping for selectors.
---
name: hd-self-screenshot-mac
description: >
macOS platform companion to hd-self-screenshot — the Apple-specific half of HD
screenshotting its own window, PLUS the token-efficient capture flow (`shot` — one
call, prints a PNG path, never floods context with base64). The tool ladder, the
`POST /screenshot` CDP endpoint, selector region-clips, the sharing gate, and the
during-a-recording contention matrix live in hd-self-screenshot (adom/hd-bootstrap);
THIS skill carries the `shot` helper doctrine and the macOS capture internals: the
`screencapture` CLI / CoreGraphics window path, the CDP `Page.captureScreenshot`
content grab, how the per-panel selector crop resolves the rect via `dom.measure`
(WKWebView has no CDP) and crops with the image crate, and the Screen Recording TCC
grant. Mirror of hd-self-screenshot-windows (Win32 PrintWindow/BitBlt). Trigger
words — screenshot hd mac, shot helper, token efficient screenshot, screencapture
cli, coregraphics screenshot, wkwebview no cdp, dom.measure crop,
page.capturescreenshot mac, screen recording permission screenshot, tcc screenshot
grant.
---
# hd-self-screenshot (macOS) — screencapture / CoreGraphics + the CDP content path
This is the **macOS half** of `hd-self-screenshot`. The default flow — `adom-cli
hydrogen screenshot panel|workspace|screen` saving a PNG into the container's
`screenshots/` to `Read`, the `POST /screenshot {target,selector,b64,silent}` CDP
power-path, the sharing gate, and the multi-thread `capture_busy` / coexistence matrix
— is cross-platform and lives in the generic **hd-self-screenshot** skill. Read that
first; this skill documents the token-efficient capture flow and what's Apple-specific
about how the bytes are grabbed.
## ⭐ ALWAYS capture with `shot` — 2 tool calls, ~20 bytes of output
**Never run `adom-cli hydrogen screenshot ...` bare.** It prints the capture as a
~300 KB base64 `dataUrl` JSON on stdout — that's ~85k tokens of noise in your context
per capture, plus a second decode step you'd have to improvise. This bootstrap installs
a wrapper that does the whole thing in one call and prints ONLY the PNG path:
```bash
shot # whole workspace (all panels) → /tmp/shot-workspace-<ts>.png
shot screen # entire screen (desktop, other apps)
shot panel --name "KiCad" # one panel's content
shot workspace --reason "verify the flow viewer rendered" # flags pass through
```
Then **Read** the printed path — the Read tool attaches images efficiently. Total flow:
one Bash call + one Read. That's the floor; don't add steps.
- If no image comes back, `shot` exits 1 and prints the CLI's own JSON to stderr —
usually the **sharing gate** (capture needs the user's sharing approval; pass
`--reason "…"` so the approval dialog says why). Read the error, don't blind-retry.
- `SHOT_OUT=/path/out.png shot ...` overrides the output path if you need a stable name.
- If `shot` is missing (pre-0.1.3 workspace), re-converge: `adom-wiki pkg install
adom/hd-mac-bootstrap` — or inline the same pipe:
`adom-cli hydrogen screenshot workspace 2>/dev/null | python3 -c "import sys,json,base64;d=json.load(sys.stdin);open('/tmp/ws.png','wb').write(base64.b64decode(d['dataUrl'].split(',',1)[1]));print('/tmp/ws.png')"`
## How HD grabs its own window on macOS
- **Whole-window / desktop:** HD uses the macOS **`screencapture` CLI** (and
CoreGraphics window capture) to grab the HD window or the full screen — the macOS
analog of the Windows `PrintWindow`/`BitBlt` path.
- **Webview / panel content:** the canonical content grab is **CDP
`Page.captureScreenshot`** (the `/capture/viewport` · `/shot` path) — a one-shot,
wake-lock-free capture of the rendered surface. This is the same `POST /screenshot`
endpoint as everywhere; on macOS it backs the `target`/panel content capture.
## ⭐ The per-panel selector crop — `dom.measure`, not CDP
On Windows the `selector` region-clip can lean on CDP against the webview. On macOS the
HD shell uses **WKWebView, which exposes no CDP** to drive the page directly. So a
per-panel / per-selector crop resolves the rect a different way:
1. Resolve the element's rectangle via the **`dom.measure` ui-action RPC** (the
UI-command bus measures the selector in the live DOM and returns its bounds).
2. Capture the content area (CDP `Page.captureScreenshot` / `screencapture`).
3. **Crop the captured image to that rect with the Rust `image` crate.**
So `{selector:".resource-bars"}` still clips to just that element — but the rect comes
from `dom.measure` and the crop is server-side in Rust, because WKWebView can't be
CDP-shot to a selector the way a Chromium webview can.
## macOS gotcha — the Screen Recording TCC grant
The OS-level capture (`screencapture` / CoreGraphics) is gated by macOS **TCC: System
Settings → Privacy & Security → Screen Recording** must allow Hydrogen Desktop. Without
that grant a window/screen capture comes back **black or empty** even though the call
"succeeds." If screenshots are blank, check the Screen Recording grant first — it's the
same grant the desktop recording paths need ([hd-recording-mac]).
## NOT here (lives in the Windows companion)
The Win32 capture primitives — **`PrintWindow`** (per-window, works for backgrounded
windows) and **`BitBlt`** — are the Windows self-screenshot mechanics; see
`hd-self-screenshot-windows`. On macOS it's `screencapture`/CoreGraphics + CDP
`Page.captureScreenshot`, with `dom.measure`-driven cropping for selectors.