Skip to content

v0.10.0

Choose a tag to compare

@noahkurz noahkurz released this 21 Sep 15:09
· 8 commits to main since this release

Cheaper screenshots, correct Android frames, and roughly half the tokens per reply — with the README's cost table now measured rather than estimated.

Screenshots

  • Half the point size by default — a quarter of the image tokens (144 vs 560 on an iPhone 17 Pro Max), still enough for layout, spacing and colour. scale:1 when you need to read rendered text.
  • target crops to one element at full detail with 12pt of context: 8–48 image tokens for a button or a full-width row.
  • Resized in-process with node:zlib — same output and cost on every platform, no sips.
  • Replies drop the timestamped path and say how to convert coordinates: Cropped to #11 Pressable "increment", 80px wide; 1px = 1pt, then add (216,331) for tap/swipe.

Fixes

  • Android frames are now screen points. measureInWindow answers relative to the window, which starts below the status bar unless the app is edge-to-edge; tap, swipe and crops were off by that height. Frames are moved onto the screen at the source, mirroring the inset React Native itself subtracts.
  • reload no longer kills the app in Expo Go on iOS. React Native's reload left the new runtime without Expo's native modules (Cannot find native module 'ExpoAsset'); the bridge now uses Expo's own reload on iOS when present. Android keeps React Native's, which is the one that works there.
  • Crop edges are rounded from point edges, so a fractional device scale cannot shave a pixel off the far side.

Token efficiency (measured with count_tokens against claude-opus-5, demo Home screen)

Call 0.9.0 0.10.0
nav_state 95 22
tree · interactive 301 184
tree (default) 504 382
tree · frames 870 602
screenshot · target (all-in) — 58–107
screenshot (default, all-in) ~1,000–1,600 175

How: shorter tool schemas (the why moved to the playbook, which loads once), whole-point frames, compact JSON, a two-line nav_state without the random route key, and a tree that collapses forwarded wrappers (BottomTabItem → Pressable, TextInput around its host input) and reads Animated(X) as X.

interactive:true now keeps a list row's text — #42 Pressable "#2 qui est esse" [press] instead of Pressable [press] ×N with no way to tell rows apart — so it is finally usable on lists, and press by that text climbs to the row.

Also

  • navState is typed in the protocol; pngWidth (unused outside tests) is gone.
  • 197 tests (was 145); verified end-to-end through the packed tarball in Expo Go on iOS and Android.

Full changelog: 45bdd58...v0.10.0