Tomacco

Docs Operation reference screen operations

screen operations#

8 operations. Generated from assets/operations.json; all areas.

On this page (8)

screen.marks#

Mark tappable elements

Take a screenshot with numbered boxes over what can be tapped, and a list that says what each number is (label, text, description, resource id, class, bounds, centre), so a vision-capable agent can answer "tap 7" and call screen.tap. On Android the marks are the enabled clickable, long-clickable, checkable and editable elements of the UI hierarchy, in document order; content an app draws itself (a canvas, a game, much of a WebView) is not in it. On the virtual iPhone, which has no UI hierarchy, they are the lines of text Tesseract reads off the screenshot, each with its confidence (source ocr, which Android can use too): an icon without a label gets no mark, and text it misreads or misses is wrong or absent. The numbers belong to this look at the device; screen.tap checks the screen still matches before it taps. The result's path is the marked PNG, which MCP returns inline. Needs tesseract only for source ocr.

Annotations: writes, idempotent, open world.

ArgumentTypeRequiredDefaultDetails
devicestringyesnon-empty; Android serial from device.list, or virtual-iphone for the running virtual iPhone
pathstringyesnon-empty; Absolute path of the marked PNG to write; an existing file is replaced
sourcestring"auto"one of auto, hierarchy, ocr; hierarchy reads the UI hierarchy (Android); ocr reads text off the screenshot with Tesseract (any screen, and the only way on the virtual iPhone); auto takes the hierarchy where there is one
max_marksinteger601 to 200; Most marks; the first ones in reading order are kept and truncated says so
xml_pathstringnon-empty; Also keep the UI hierarchy as UIAutomator XML at this absolute path, for screen.diff
min_confidencenumber400 to 100; Leave out words Tesseract reads with less confidence than this (0 to 100)
languagestring"eng"matching ^[A-Za-z0-9_+]+$; Tesseract language code, such as eng or eng+deu; its data must be installed
regionobjectRead only this part of the screen, in pixels. Tesseract reads a screen with both light and dark areas as one and can miss the minority area; a region reads it alone
region.xintegeryesat least 0
region.yintegeryesat least 0
region.widthintegeryesat least 1
region.heightintegeryesat least 1
tomaccoctl call screen.marks '{"device":"<device>","path":"<path>"}'

screen.tap#

Tap a mark

Tap the centre of a numbered mark from the last screen.marks (or screen.tree) of this device. First it checks the screen still has what the mark was made from: on Android the same element (class, resource id, text and bounds) in the UI hierarchy; for a mark read by OCR, the pixels where it was, unchanged. If not it answers mark_stale and taps nothing, so a number never lands on another element after the screen moved on. Pass duration for a long press.

Annotations: writes, not idempotent, open world.

ArgumentTypeRequiredDefaultDetails
devicestringyesnon-empty; Android serial from device.list, or virtual-iphone for the running virtual iPhone
markintegeryes1 to 200; The mark's number in the last screen.marks result for this device
durationinteger100 to 5000; Hold for this many milliseconds (a long press) instead of tapping
verifybooleantrueCheck the screen still matches the mark before tapping; false taps where the mark was whatever is there now
tomaccoctl call screen.tap '{"device":"<device>","mark":1}'

screen.tree#

Read UI tree as text

Read the Android UI hierarchy as a short indented text for a model's context: only the elements that carry text or a description, can be pressed or scroll, each with its class, text, id, bounds and state (checked, disabled, focused, editable), and #N on those screen.tap can tap. The first line says the screen size and the app's package. The text stops at max_chars with a last line that says how many nodes are missing. Android only: the virtual iPhone has no UI hierarchy (ui_hierarchy_unavailable); use screen.marks with source ocr there.

Annotations: writes, idempotent, open world.

ArgumentTypeRequiredDefaultDetails
devicestringyesnon-empty; Android serial from device.list, or virtual-iphone for the running virtual iPhone
max_charsinteger6000500 to 100000; Longest text, in characters
only_interactivebooleanfalseLeave out text that cannot be pressed
xml_pathstringnon-empty; Also keep the UI hierarchy as UIAutomator XML at this absolute path, for screen.diff
tomaccoctl call screen.tree '{"device":"<device>"}'

screen.ocr#

Read text on screen

Read the text on a device's screen or in a PNG with Tesseract, for screens that have no UI hierarchy: the virtual iPhone, games, WebViews. Answers every word and line with its box and Tesseract's confidence (0 to 100), and with text (whole words, any letter case) or text_contains (part of a word or line), the matches with their centre, ready to tap. The recognition is of pixels, not of controls: small, low-contrast or decorative text can be misread or missed, a space can be lost ("Signin"), and a picture with light and dark areas may need region. A dark theme is handled by also reading the inverted picture. Needs tesseract (capabilities.ocr says whether it is installed).

Annotations: read-only, idempotent, open world.

ArgumentTypeRequiredDefaultDetails
devicestringnon-empty; Android serial from device.list, or virtual-iphone for the running virtual iPhone
imagestringnon-empty; Absolute path of a PNG to read, instead of a device
textstringnon-empty; Find these words, in this order, as whole words in one line
text_containsstringnon-empty; Find this text inside a line, also as part of a word
indexinteger0 to 10000; Keep only the nth match, top to bottom
fuzzybooleanfalseLet a word of five or more letters match with one letter misread
min_confidencenumber400 to 100; Leave out words Tesseract reads with less confidence than this (0 to 100)
languagestring"eng"matching ^[A-Za-z0-9_+]+$; Tesseract language code, such as eng or eng+deu; its data must be installed
regionobjectRead only this part of the screen, in pixels. Tesseract reads a screen with both light and dark areas as one and can miss the minority area; a region reads it alone
region.xintegeryesat least 0
region.yintegeryesat least 0
region.widthintegeryesat least 1
region.heightintegeryesat least 1
invertstring"auto"one of auto, never, always; auto reads the picture as it is and with its colours inverted, and merges the words (twice the time, finds light text on dark ground); never reads it once; always reads only the inverted picture
max_wordsinteger4001 to 5000; Most words and lines to list
tomaccoctl call screen.ocr

screen.diff#

Compare two screens

Describe what changed between two screens in structured form. before and after are both UIAutomator XML files (hierarchies: elements added, removed and changed in text, state or position, or a different screen, from screen.tree or screen.marks with xml_path) or both PNG screenshots (the regions where pixels changed, each with its box, size, share of changed pixels and position, and a summary; status bar regions are marked). Leave after out and give device to compare before with the screen now. With text:true the screenshots are also read with Tesseract and the lines added and removed are listed. Screens of different sizes (a rotation) answer size_changed. before and after can also both be export bundles from screen.export (the directory or its screen.json): the answer then lists the metadata that changed (device, display, theme, locale, app), the element difference and the pixel regions.

Annotations: read-only, idempotent, open world.

ArgumentTypeRequiredDefaultDetails
beforestringyesnon-empty; Absolute path of a .xml hierarchy, a .png screenshot, or a screen.export bundle (its directory or screen.json)
afterstringnon-empty; Absolute path of the second one, the same kind
devicestringnon-empty; Android serial from device.list, or virtual-iphone for the running virtual iPhone
toleranceinteger240 to 255; A pixel counts as changed when a colour channel differs by more than this (screenshots)
ignorearray of objectup to 100 items; Regions in screen pixels that are not compared, such as the status bar clock
ignore[].xintegeryesat least 0
ignore[].yintegeryesat least 0
ignore[].widthintegeryesat least 1
ignore[].heightintegeryesat least 1
max_regionsinteger121 to 100; Most regions, or elements per list, to describe
textbooleanfalseAlso list the lines of text added and removed, read with Tesseract (screenshots)
min_confidencenumber400 to 100; Leave out words Tesseract reads with less confidence than this (0 to 100)
languagestring"eng"matching ^[A-Za-z0-9_+]+$; Tesseract language code, such as eng or eng+deu; its data must be installed
tomaccoctl call screen.diff '{"before":"<before>"}'

screen.wait#

Wait for text or a steady screen

Wait until text is on the screen, is gone, or the screen has stopped changing, polling every interval_ms. text and text_gone look in the UI hierarchy's text and descriptions where there is one (Android, case-insensitive, part of a text) and otherwise read the screenshot with Tesseract; source forces one. stable takes screenshots until stable_ms pass with at most threshold of the pixels (outside ignore) changed from one to the next, and answers screen_unstable with the last changed fraction when a video, animation or spinner keeps going. A timeout answers text_timeout or screen_unstable with what was seen. The same waits are the wait_text and wait_stable steps of testing.run scenarios.

Annotations: read-only, idempotent, open world.

ArgumentTypeRequiredDefaultDetails
devicestringyesnon-empty; Android serial from device.list, or virtual-iphone for the running virtual iPhone
untilstringyesone of text, text_gone, stable; text: wait for it to appear; text_gone: wait for it to go; stable: wait for the screen to stop changing
textstringnon-empty; The text, for text and text_gone
sourcestring"auto"one of auto, hierarchy, ocr; hierarchy reads the UI hierarchy (Android); ocr reads text off the screenshot with Tesseract (any screen, and the only way on the virtual iPhone); auto takes the hierarchy where there is one
timeoutinteger300 to 300; Seconds
interval_msinteger50050 to 10000; Milliseconds between looks
stable_msinteger1000100 to 60000; For stable: how long the screen must stay unchanged
thresholdnumber0.0010 to 1; For stable: the largest changed fraction of the pixels still counted as unchanged
toleranceinteger240 to 255; For stable: a pixel counts as changed when a colour channel differs by more than this
ignorearray of objectup to 100 items; Regions in screen pixels that are not compared, such as the status bar clock
ignore[].xintegeryesat least 0
ignore[].yintegeryesat least 0
ignore[].widthintegeryesat least 1
ignore[].heightintegeryesat least 1
fuzzybooleanfalseFor text read by OCR: let a word of five or more letters match with one letter misread
min_confidencenumber400 to 100; Leave out words Tesseract reads with less confidence than this (0 to 100)
languagestring"eng"matching ^[A-Za-z0-9_+]+$; Tesseract language code, such as eng or eng+deu; its data must be installed
regionobjectRead only this part of the screen, in pixels. Tesseract reads a screen with both light and dark areas as one and can miss the minority area; a region reads it alone
region.xintegeryesat least 0
region.yintegeryesat least 0
region.widthintegeryesat least 1
region.heightintegeryesat least 1
tomaccoctl call screen.wait '{"device":"<device>","until":"text"}'

screen.export#

Export a screen

Write one screen of a device as a bundle other tools can read: screen.png at full resolution and screen.json, a documented, versioned format (format "tomacco.screen", version 1; docs/screen-export.md and assets/schemas/screen-export-v1.schema.json). screen.json has the capture time, the device (platform, id, model, OS version, form factor), the display (pixels, density, size in dp or pt, orientation, rotation), the insets of the status bar, navigation bar and cutout where the platform reports them, the theme (dark or light), the locale, the foreground app, and every element of the screen as a flat list with ids and parent ids: role, class, text, description, resource id, bounds in pixels and in dp or pt, enabled, clickable, focusable, checked and selected, and the mark number screen.marks gives it. On Android the elements are the UI hierarchy. The virtual iPhone and USB iPhones (platform ios) have none, so there the elements are lines of text read off the screenshot with Tesseract (source ocr, state flags null) and hierarchy says unavailable. A field the platform does not report is null, never guessed. The marks are kept for screen.tap as after screen.marks. The directory must be new or empty. The result summarises the export; read screen.json for the elements.

Annotations: writes, not idempotent, open world.

ArgumentTypeRequiredDefaultDetails
devicestringyesnon-empty; Android serial from device.list, virtual-iphone for the running virtual iPhone, or a USB iPhone's UDID with platform ios
directorystringyesnon-empty; Absolute path of the bundle directory to create; it must not exist or must be empty
platformstring"android"one of android, ios; ios for a USB iPhone (screenshot and device info, no hierarchy); virtual-iphone needs no platform
sourcestring"auto"one of auto, hierarchy, ocr; hierarchy reads the UI hierarchy (Android); ocr reads text off the screenshot with Tesseract; auto takes the hierarchy where the platform has one and OCR where it has not
max_marksinteger2001 to 500; Most mark numbers; the first ones in reading order are numbered, as screen.marks numbers them, and marks.truncated says if more were left out. Every element is still listed
markedbooleanfalseAlso write marked.png, the screenshot with the numbered boxes of screen.marks
min_confidencenumber400 to 100; For OCR: leave out words Tesseract reads with less confidence than this (0 to 100)
languagestring"eng"matching ^[A-Za-z0-9_+]+$; For OCR: Tesseract language code, such as eng or eng+deu; its data must be installed
tomaccoctl call screen.export '{"device":"<device>","directory":"<directory>"}'

screen.export_batch#

Export screens of several devices

Export the screen now of several devices (Android serials and virtual-iphone) in one call, each as a screen.export bundle in NN-device/ inside one directory, with index.json (format "tomacco.screen-index", version 1) listing each screen's device, model, size, orientation, theme, locale, app, element count and files. A device that cannot be read is listed with its error and the others still run; ok is false then. It takes the current screen of each device, not a matrix of languages and themes: android.store_screenshots does that for store screenshots. The directory must be new or empty.

Annotations: writes, not idempotent, open world.

ArgumentTypeRequiredDefaultDetails
devicesarray of stringyes1 to 16 items; Android serials from device.list, or virtual-iphone
directorystringyesnon-empty; Absolute path of the directory to create; it must not exist or must be empty
sourcestring"auto"one of auto, hierarchy, ocr; hierarchy reads the UI hierarchy (Android); ocr reads text off the screenshot with Tesseract; auto takes the hierarchy where the platform has one and OCR where it has not
max_marksinteger2001 to 500; Most mark numbers; the first ones in reading order are numbered, as screen.marks numbers them, and marks.truncated says if more were left out. Every element is still listed
markedbooleanfalseAlso write marked.png, the screenshot with the numbered boxes of screen.marks
min_confidencenumber400 to 100; For OCR: leave out words Tesseract reads with less confidence than this (0 to 100)
languagestring"eng"matching ^[A-Za-z0-9_+]+$; For OCR: Tesseract language code, such as eng or eng+deu; its data must be installed
tomaccoctl call screen.export_batch '{"devices":["<device>"],"directory":"<directory>"}'

View this page as Markdown on GitHub