agentleFS
parawandererparawanderer/OpenTagViewer/.claude/skills/device-screenshots/SKILL.md

device-screenshots

Skill455 starsChanged 32 days agoMITView on GitHub

Render app UI on the Gradle managed device and look at the result without spending a fortune in vision tokens. Use whenever a change is visual - colours, themes, drawables, layout - or when a screenshot needs comparing before and after, light and dark.

  • Installs packages

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Run them through the sheet tool first:

    line 17
  2. Distinctive:

    Run it on the managed device, which provisions and tears down its own emulator:

    line 74
  3. Very specific:

    No activity is needed for most of this.

    line 80

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Looking at the app's UI

Two halves: getting a screenshot off the device, and reading it cheaply. The second is the part that is easy to get wrong.

Never Read a raw screenshot

A device screenshot is ~1080px wide and mostly whitespace. Reading one costs a lot of vision tokens for a picture whose informative part is a few hundred pixels, and reading a before/after pair separately doubles it for a comparison that wants to be side by side anyway.

Run them through the sheet tool first:

python .claude/skills/device-screenshots/sheet.py \
    app/build/outputs/managed_device_android_test_additional_output/debug/testEmulator \
    <scratchpad>/shots

Then Read the sheets it prints. One subject, all its variants, one image, a few hundred pixels wide.

Files are grouped on the part before the last hyphen; the part after is the variant label:

my_device_list_item-fixed.png       ->  subject my_device_list_item, variant "fixed"
my_device_list_item-wallpaper.png                                    variant "wallpaper"
FlagDefaultFor
--width420target width per panel
--max-height420cap, so a tall image cannot produce a 2000px sheet
--darkdark,wallpaper_dark,nightvariants composited over black rather than white

Needs Pillow (python -m pip install pillow).

Screenshots that go somewhere public

A capture destined for the wiki or an issue is a screenshot of a real build on a real device, and some of what is on it belongs to whoever took it. The AMap key dialog is the worked example: it prints the package name and signing fingerprint, because that is exactly what AMap's console asks you to paste — correct behaviour, and not something to publish.

py -3 .claude/skills/device-screenshots/blur.py shot.png --band 0.42 0.55

--band takes fractions of the height, so it survives a change of device resolution; repeat it for more than one strip. Blur rather than crop — a cropped dialog looks like it has fewer fields than it does, and the next person wonders what was removed. It pixelates before blurring, so the characters are gone rather than merely soft.

Worth a look before publishing any capture: a signed-in email address, a real street name from the geocoder, a XXXX-XXXX-XXXX bundle passcode, coordinates. The capture classes fabricate all of those on purpose; a hand-taken screenshot does not.

Getting the screenshots

SystemColorsLayoutTest is the working example. Inflate a layout — or load a drawable — against a themed context, draw it to a Bitmap, and write it to the directory AGP passes as the additionalTestOutputDir instrumentation argument. AGP copies that back to the host after the run:

app/build/outputs/managed_device_android_test_additional_output/debug/testEmulator/

Run it on the managed device, which provisions and tears down its own emulator:

JAVA_HOME='C:\Program Files\Android\Android Studio\jbr' ./gradlew :app:testEmulatorDebugAndroidTest

No activity is needed for most of this. Inflating the layout against a ContextThemeWrapper(context, R.style.Theme_OpenTagViewer) on the main thread is enough, and it avoids every problem that comes with launching one.

Two traps, both hit here already

Transparency. Several layouts have no background of their own. Converting them straight to RGB renders every transparent pixel black, and the result looks like a catastrophic bug that is not there. The tool composites over a background; do the same anywhere else.

Images are not assertions. A screenshot proves what one configuration looked like once. Whatever the change is, assert it as well — a resolved colour, a contrast ratio, a measured height. SystemColorsLayoutTest requires the timeline tiles to clear WCAG 3:1 against their background, which is what actually fails the build; the images are what explain why.

And be careful what the assertion is about. That same test renders drawables through a themed context, so it kept passing while the history timeline was invisible in the app — the app was loading them with a null theme. The test proved the drawable could render, not that the app asked for it correctly. ThemedDrawableLoadingTest covers the call site instead.

Dark mode

Rendering the day theme only is the usual mistake — the app has a full values-night palette. A themed context can be forced to night without changing the device:

Configuration night = new Configuration(context.getResources().getConfiguration());
night.uiMode = (night.uiMode & ~Configuration.UI_MODE_NIGHT_MASK)
        | Configuration.UI_MODE_NIGHT_YES;
Context darkContext = context.createConfigurationContext(night);
// then wrap in ContextThemeWrapper(darkContext, R.style.Theme_OpenTagViewer)

Name those outputs -dark so the sheet tool composites them over black.

Related

  • AGENTS.md rule 2 — do not claim something works if you have not run it. A rendered sheet is evidence; "it should look right" is not.
  • CONTRIBUTING.md for how the managed device is configured.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.