SimUtil: a terminal UI for launching and controlling Android emulators and iOS simulators
It's not just a cross-platform TUI app that quickly opens Android & iOS emulators/simulators
At a glance
- What is it?
- SimUtil is a Dart command line and terminal UI tool that lists your emulators and simulators, launches them with custom options, streams Logcat and connects to physical Android devices wirelessly, with a Flutter desktop app in preview that does the same across many devices at once and exposes an MCP server for AI agents. The CLI is built on the Nocterm terminal UI framework.
- Who is it for?
- SimUtil fits a mobile developer who wants to start a device, read Logcat and drive a physical Android phone from the keyboard instead of opening Android Studio or Xcode, and who wants to script that with plugins or YAML scenarios. It is the wrong choice on Linux or Windows if you need iOS simulators, since that support requires macOS, and the wrong choice if you want a stable tool, because the desktop app is explicitly a preview and carries its own scrcpy server.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Dart, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two products in one repository, with different release tags
SimUtil comes in two forms, and the distinction matters because they are versioned separately.
The CLI and TUI is the simutil binary in your terminal, used to launch and shut down devices, run ADB wireless tools, view Logcat and run custom plugins. It is built with Nocterm, a terminal UI framework for Dart with similar syntax to Flutter.
The desktop app is in preview, a Flutter app that streams and controls many Android emulators, devices and iOS simulators side by side, records them, runs scenarios across devices, and exposes an MCP server for AI agents. Its own README lives at app/README.md in the repository.
The versioning reflects the split. The releases are tagged separately, with v prefixed tags for the CLI and app-v prefixed tags for the desktop app, and the README links to both filters. The recent releases are v1.1.0 for the CLI on 2026-10-13, SimUtil Desktop 0.3.0 also on 2026-10-13, and SimUtil Desktop 0.2.0 earlier the same day. The desktop app and the CLI shipped three releases in one day, which tells you both lines are moving fast and that the preview numbering has not yet stabilised.
The stated job of the tool is to browse your available emulators and simulators side by side, launch with custom options and connect to physical devices wirelessly. The one-key launch framing is the pitch: start any device with Enter, with no need to open Android Studio or Xcode.
Both forms run on macOS, Linux and Windows, with one hard constraint. iOS Simulator support requires macOS, because it goes through Xcode and simctl, and on Linux and Windows the tools focus on Android emulators and devices.
The primary language is Dart, the licence is MIT, and the repository is organised as a pub workspace, with a packages/ directory, an app/ directory for the Flutter desktop app, a root pubspec.yaml, docs/ and art/ directories, and an AGENTS.md.
Installing the CLI, five different ways
The CLI has five documented install routes, and the difference between them is the update story more than the install itself.
A binary install on macOS and Linux pipes the install script straight into bash:
curl -fsSL https://raw.githubusercontent.com/dungngminh/simutil/main/install.sh | bashOn Windows PowerShell the equivalent is:
powershell -ExecutionPolicy Bypass -Command "iwr -useb https://raw.githubusercontent.com/dungngminh/simutil/main/install.ps1 | iex"Homebrew works on both macOS and Linux, and the tap is the project's own:
brew tap dungngminh/simutil
brew install simutilPub.dev is the route for people already in the Dart ecosystem:
dart pub global activate simutilAnd from source, which is the only route that tells you something about the repository layout. The clone is followed by a pub get and a path activation, with a comment explaining why:
git clone https://github.com/dungngminh/simutil.git
cd simutil
flutter pub get # the workspace includes the Flutter desktop app
dart pub global activate --source path packages/simutilThat comment is the useful part. The root of the repository is a Dart pub workspace, the Flutter desktop app is a member of it, and the CLI itself lives in packages/simutil. So the CLI and the desktop app share one workspace, which is why a plain Dart user needs flutter pub get at the root, and why the project can ship both from one repository while versioning them separately.
The desktop app is a separate install, and the macOS route is a Homebrew cask:
brew update
brew tap dungngminh/simutil
brew install --cask simutil-desktopThe brew update step is called out specifically so the tap sees the latest cask. The macOS app requires Monterey or later and pulls in adb and ffmpeg, or you can download SimUtil-macos.dmg and drag SimUtil into Applications. On Windows you download SimUtil-windows-x64-setup.exe from the latest desktop release, and the installer offers to install Android platform-tools and FFmpeg. On Linux, an x86_64 AppImage is installed by a script that also installs adb, ffmpeg and FUSE with your package manager, and you re-run it to update.
The TUI feature set: launch, logcat, wireless ADB and plugins
The CLI and TUI feature list is where the actual utility is, and it is worth reading item by item because each one removes a specific tool from your workflow.
One-key launch starts any device with Enter, with no need to open Android Studio or Xcode. Android launch options cover Normal, Cold Boot, No Audio, or Cold Boot plus No Audio and more, which are the emulator start options you would otherwise set in the Android Studio AVD editor. There is also a shutdown device command for simulators and emulators.
Logcat viewing is built in, with filtering supported, which removes the adb logcat invocation from your muscle memory.
The ADB tools are the part that goes beyond a launcher. You can connect to physical Android devices wirelessly three ways: by IP address, by pairing with a 6-digit code on Android 11 and later, or by QR code pairing, also Android 11 and later. So you can drop the USB cable and still get at a phone on the same network.
Custom plugins are the extensibility story. You add your own external tools, scrcpy or Maestro for example, via a YAML file with no code changes needed, and then press p to pick a plugin and a command to run on the selected device. That is a sensible design, because the set of tools you want alongside a device varies while the device list does not.
Two conveniences are keyboard-driven and worth knowing. Press e to open ~/.simutil/settings.yaml in your default editor on macOS, Linux or Windows, so the configuration file is edited the way you edit everything else. Press x on macOS to clear Xcode Derived Data, and the README is careful to say this happens after a size preview and a confirmation, because deleting derived data is a slow rebuild for whoever runs it next.
The settings file at ~/.simutil/settings.yaml opens in your editor with e, and custom plugins are added through a YAML file, so the YAML approach runs through both.
The desktop app: streaming many devices and an MCP server
The preview desktop app is the more ambitious half, and it is where the project's direction points.
Multi-device streaming is the centrepiece. Stream and control many Android emulators, devices and iOS simulators side by side, in a grid or a spotlight layout, with touch, swipe and navigation buttons on every stream. The spotlight layout is the answer to the problem that a grid of eight phones is unreadable, since it promotes one device to prominence without losing the others.
Headless devices are supported, meaning you start a device without the emulator window or the Simulator app, and Android emulators can be launched with Cold Boot or No Audio from the context menu.
Slim mode is a specific memory claim. iOS simulators with background services off use about 1 GB of memory instead of 4 GB. For a grid of many simulators on one laptop, that is the difference between running four devices and running a dozen, so it is a more consequential feature than its position in the list suggests.
Recording works at the device level or across the whole grid, and the README states it is native at 60 fps on macOS.
The scenario studio is the scripting layer. You write YAML scenarios with tap by label, swipe, type and assertions, then run them on many devices at once while watching each step's status live. Tap by label in particular is the right primitive, since it survives a UI change that would break coordinate based scripts.
The MCP server for agents is the most novel piece. It lets Claude Code, Codex, Cursor and others list, start, stream, tap, swipe, screenshot and record devices. That is a device farm exposed as a tool interface, and it is a differentiator for anyone running agent driven testing against mobile apps. The README points at a specific anchor in app/README.md for the details.
One implementation note saves a dependency. The app ships its own scrcpy server, so no scrcpy install is needed. That matters on the Windows path, where the installer offers to add platform-tools and FFmpeg, and on Linux, where the AppImage handles the same.
Updates, version checks and where the project stands
SimUtil has an update mechanism worth knowing about, because it is polite about it and it is opt-out.
The tool checks for a new release at most once a day, and when it finds one it shows Version X available! Run: simutil upgrade. Setting SIMUTIL_NO_UPDATE_CHECK=1 turns it off. The daily cap and the environment variable are both sensible: a CLI that phones home on every invocation is unpleasant, and a CI machine that runs it in a loop should not have to be told about it each time.
The upgrade command dispatches on how you installed. It runs the upgrade for your install method, which the README gives as examples: brew upgrade dungngminh/simutil/simutil, dart pub global activate simutil, or re-running the install script. On Windows, or when running from source, it prints the command or the releases link instead, because there is no single correct upgrade for those cases.
The repository layout supports the two-product story. There is a root pubspec.yaml and pubspec.lock for the workspace, a packages/ directory holding the CLI package, an app/ directory for the Flutter desktop app including its own packaging directory with a linux install.sh, a docs/ directory, an art/ directory with the logo and showcase images, install.sh and install.ps1 at the root for the binary installers, an analysis_options.yaml for the Dart analyzer, and an AGENTS.md.
The maintenance picture is a date rather than an adjective. The repository is not archived and the last push was on 2026-10-14, one day after the v1.1.0 CLI release and the desktop 0.3.0. The release cadence around the preview is fast, and the versioning split means a CLI user and a desktop user are on completely independent release trains.
The practical question for anyone evaluating this is which half they need. The CLI is the finished product: a small, focused tool with a documented keybinding set and a YAML configuration file. The desktop app is a preview with a lot of surface area, a bundled scrcpy server, a scenario runner and an MCP server, and a preview label that tells you the interface and behaviours may still move.
Editorial conclusion
SimUtil fits a mobile developer who wants to start a device, read Logcat and drive a physical Android phone from the keyboard instead of opening Android Studio or Xcode, and who wants to script that with plugins or YAML scenarios. It is the wrong choice on Linux or Windows if you need iOS simulators, since that support requires macOS, and the wrong choice if you want a stable tool, because the desktop app is explicitly a preview and carries its own scrcpy server. Before adopting, install the CLI rather than the desktop app, and check the supported platforms section for the simulators and emulators your project actually uses.
Frequently asked questions
How do I install the SimUtil CLI?
Five routes are documented. The install script piped to bash on macOS and Linux, the PowerShell equivalent on Windows, Homebrew with brew tap dungngminh/simutil then brew install simutil, dart pub global activate simutil from pub.dev, or from source with a clone, flutter pub get and dart pub global activate --source path packages/simutil.
Does SimUtil work with iOS simulators on Linux and Windows?
No. iOS Simulator support requires macOS with Xcode and simctl, and on Linux and Windows the tools focus on Android emulators and devices. The tool itself runs on macOS, Linux and Windows.
How do I connect to a physical Android device wirelessly with SimUtil?
The built-in ADB tools support connecting by IP address, pairing with a 6-digit code on Android 11 and later, and QR code pairing on Android 11 and later. You can also add external tools such as scrcpy or Maestro as plugins through a YAML file.
What is the MCP server in the SimUtil desktop app?
It exposes the device fleet to AI agents. The README says it lets Claude Code, Codex, Cursor and others list, start, stream, tap, swipe, screenshot and record devices. The desktop app itself is labelled a preview.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dungngminh-simutil)Was this useful?