Skip to content

Releases

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 12 Nov 15:16

appdyno 1.0.0 is the first public release: an MCP server, a command line and a Mac app that drive, test and measure iOS and Android apps on simulators, emulators and real phones. Each of its 48 tools is also a command and a call in the library; coming from 0.6.0, read Changed first.

Added

  • The Mac app, Appdyno.app, from a disk image or a Homebrew cask, signed and notarized: it carries its own Node, the Android agent, the device viewer and Perfetto's trace processor, lives in the menu bar, and looks for a newer release when it opens and once a day, which it installs only when you say so. Google's terms keep adb out of it, and appdyno tools install adb --accept-license fetches it.
  • appdyno install adds the server to the MCP clients on this Mac, changing only its own entry after a backup, with --dry-run to see the change and --remove to take it out. appdyno path puts the app's command on every shell's PATH.
  • appdyno update moves to the latest release only once it is verified, by npm's provenance for the package and a signed appcast for the app, and --check changes nothing. appdyno doctor says the version and how it was installed.
  • appdyno mcp --http 127.0.0.1:PORT serves the same tools over Streamable HTTP, for a client that cannot start a program on this Mac: on this Mac's loopback alone, behind a token, to one client at a time.
  • appdyno hub shows every device of this Mac in one window, to start, stop, create and watch, with Connect a Phone, which takes a phone from its cable to ready, a page that adds and tests each MCP client, Tools and Help, in English and Turkish.
  • appdyno mirror opens a live window of a simulator, an emulator, an Android phone or an iPhone on iOS 27 by USB, driven by mouse, trackpad and keyboard while an MCP client drives the same device. appdyno pair lets a window reach a phone by Wi-Fi.
  • A window's Inspector has ten panes, Performance, Flows, Apps, Activity, Logs, Network, Accessibility, Device, Links and Push, which do by hand what the tools do, live numbers and launch and scroll measures among them.
  • Record Flow writes what a person does in a window as a flow, by selector, with a password kept as a secret's name. Show Beside This One, or appdyno mirror with two --device and --pair, puts two devices side by side, and a touch goes to both.
  • The mirror tool opens and closes a window from a client, and hand_off asks the person to do what a tool cannot, such as Face ID, and waits. --silent keeps it quiet, for CI and a shared Mac.
  • push sends an app a push notification of seven types: by simctl on a simulator, by FCM's own message on Android with no Firebase project, and by APNs or FCM once a person has stored its credentials with appdyno push setup.
  • open_link settings opens Settings at a named page, and links lists the schemes and domains an installed app opens.
  • press_key takes control_center, notification_center, spotlight, escape, space, the arrows, mute and siri, a letter or digit with keys held, as command+a, and a count.
  • screenshot saves a file and sizes its image by points or width, and with watchMs says in words what moved on the screen. assert check: moves holds something to moving.
  • A screen whose tree has no words, such as a game or a canvas, is read from its picture by the Mac's own text recognition, and find, tap, wait_for and assert take what it reads.
  • swipe exact moves the content by its distance and stops, gesture drag takes holdMs to press before it moves, and set_location clear ends a fixed location.
  • simulator create makes and boots a new iOS simulator. app installs an .ipa, builds and runs a project with build_and_run, and copies an app's data out and back with download_data and replace_data.
  • device_setting takes increase_contrast, reduce_transparency, airplane, wifi, mobile_data, thermal and keychain. On Android it slows a phone's network too, folds a device from API 31, sets a language below API 33 and enrolls a fingerprint on an emulator.
  • list_devices says what blocks each device and how to fix it, and use_device takes a device by its serial, a simulator's or an AVD's name, or its model.
  • On an iPhone, clipboard works with no runner, and inspector lists and presses what is on the screen with no signing identity.
  • crashes symbols names a release build's stack, from its dSYM on iOS and its libraries with symbols on Android.
  • appdyno perf why, or perf_compare action: why, finds the likeliest cause of a regression with what shows it: a function, a phase of a start, a frame's cause or a hang. perf reference, perf functions and perf comment go with it.
  • A journey is measured and gated: appdyno test --measure, or flow run with iterations, keeps each step's numbers, and perf compare names the step that got slower. perf_launch baseline keeps a baseline in one call, and perf_compare budget sets a budget.
  • On Android, perf_snapshot also reads surface, startInfo, anonMemory and battery, numbers are set against Google Play's definitions, perf_trace says why slow frames were slow, and perf_launch baselineProfile measures a Baseline Profile.
  • On an iPhone, a window's numbers come each second with no runner, and perf_trace what: hangs says whether each hang was busy or blocked and in which function, which dsym names.
  • Kept traces stay under a limit, 10 GB by default (--trace-limit-gb), and appdyno perf prune lists what goes. Perfetto's trace processor, pinned and checked, is fetched the first time an Android trace needs it.
  • report timeline (appdyno timeline) puts a journey's video, touches, steps, frames, requests, log and memory on one clock, in one HTML file to send. report flight (appdyno flight), once turned on, keeps an app's last 30 s and saves them on a crash or a stall.
  • Flows take parameters as ${NAME}, run another flow with run and carry tags, and appdyno test takes --tag, --env-file and --retries, which reports a file that passed on a retry as flaky. flow export to writes Maestro YAML to a file.

Changed

  • app has no launch: launch_app takes restart, args and env and starts the app fresh with them, takes an app by its name as well as its id, and says whether it started the app or brought it to the front.
  • find, wait_for and assert take their target in selector, as every touch does. A selector's words at the top of a tool or a step are refused, with the call in that shape in the hint.
  • On iOS the on-screen keyboard is one element, @keyboard keyboard, as on Android, and a touch on it is refused. type_text with no target, where nothing has the focus, is refused with NO_FOCUS.
  • Every answer's structuredContent holds its whole text as text, and leaves done out where the text holds it. A refusal's text starts with its code and ends with its hint.
  • press_key reads a key's name whatever its case, return as enter, and a letter in a shortcut is a small one.
  • logs takes contains, reads from when the last action began where no since is given, and on a simulator keeps to the app's own lines and the errors of Apple's frameworks.
  • Protocol 2: the host checks every request against its schema before it reaches a device, a dark screen is SCREEN_OFF, device_info lists no capabilities, and a runner or agent of another version is refused at its first answer.
  • push is a tool of its own, out of device_setting, and takes alert, background, rich, live_activity, tapped, voip and widgets.
  • set_orientation takes landscape_left, landscape_right and upside_down where it took landscape, and answers once the screen has turned.
  • device_setting says changed only when the device reads otherwise after the change, dark_mode reads on or off, and text_size on iOS takes iOS's own named sizes.
  • locale on a simulator, with an app given or selected, holds that app in the language and leaves the simulator alone, which app "" sets whole. launch_app language on iOS is for that launch alone.
  • appdyno mcp is the one way to start the server, as appdyno-mcp is gone, bench takes no --driver, and the library exports one function, connect.
  • A client's calls that act run one at a time, in the order they came, and say waiting its turn while they wait; calls that only read run beside them.
  • A wait_for that runs out is refused with TIMEOUT, and an alert with no alert with NOT_FOUND, so on the command line both exit 1.
  • The performance gate fails on noisy, few-samples and refused as on a regression, and perf baseline exits 1 until it holds the 3 runs a comparison needs.
  • Several numbers are measured anew, so take a baseline kept with 0.6.0 again: exit counts are per run, every percentile has one definition, a step that never settled keeps no time, and an iOS step leaves out the runner's wait for an alert.
  • perf_scroll reads one round, and three under a scenario. perf_profile and perf_compare are no longer marked read-only, as either can swipe or restart the app.
  • The command line keeps its selected device per working directory, a condition it changes stays until restore, and downloaded tools are kept in ~/Library/Caches/appdyno/tools.

Fixed

  • An answer no longer claims what did not happen: typing whose field reads back other text presses no Enter and says submitted: false, and a touch that may have gone out is answered TIMEOUT or dispatched: "unknown" and never made twice.
  • An action whose app dies under it is refused at once with APP_NOT_RUNNING, the crash report's reason and the app's last log lines, in steps and flows too, and behind Android's crash dialog as well.
  • The settle no longer calls a screen still while it slides slowly or while an alert comes up late, nor busy...
Read more