How dungngminh/simutil works
1. What this repo is
- SimUtil is a cross-platform Dart terminal application for managing mobile devices from the command line: Android emulators, iOS simulators, and some Android physical-device workflows.
- The runtime boundary is the local machine; the app acts as an orchestration layer over platform/device tooling rather than hosting network services.
2. Startup and command-line entry
- The executable entrypoint is bin/simutil.dart.
- CLI parsing and command registration live under lib/cli, with a command runner (simutil_command_runner.dart) and commands such as simutil and version.
- This is the thin outer shell that starts the terminal UI app and exposes version/help-style behavior.
3. Terminal UI layer
- The main interactive experience is built in lib/simutil_app.dart using Nocterm, a Flutter-like terminal UI framework for Dart.
- Reusable UI pieces are in lib/components and include device lists, detail panels, status bars, dialogs, input fields, overlays, and themed styling.
- The UI is split into feature-oriented dialogs and components rather than a single monolithic screen.
4. Core domain model
- Shared state and data contracts live in lib/models.
- The model set covers devices, device OS/type/state, Android launch options, wireless pairing/connect flows, app settings, and isolate messaging.
- These models form the boundary between the UI and the platform-specific services.
5. Device management services
- lib/services/device_service.dart is the abstraction for device operations.
- Platform-specific implementations are split into android_device_service.dart and ios_device_service.dart.
- This service layer is the main bridge from UI intent (“launch this device”, “shut it down”, “connect wirelessly”) to platform commands.
6. External command execution boundary
- lib/services/command_exec.dart centralizes shell/process execution.
- This is the critical integration point with external tooling such as Android emulator/ADB utilities and iOS simulator tooling.
- Architecturally, most “real work” is delegated through this boundary, keeping the UI and models mostly tool-agnostic.
7. Android-specific feature modules
- Android tooling is grouped under lib/plugins/adb_tools.
- It includes dialogs for ADB operations, QR pairing, wireless pairing, and connect flows.
- Logcat support lives under lib/plugins/logcat, with its own dialog, filter bar, and helper logic, indicating a dedicated streaming/log-processing subsystem.
- lib/plugins/scrcpy exists as an integration point, but the tree suggests it is currently only a placeholder for that feature area.
8. Connectivity and discovery
- lib/services/wifi_discovery_service.dart supports discovering devices on the local network for wireless connection workflows.
- The pairing/connect models (wireless_connect_request, wireless_pairing_info, wifi_pairing_device, adb_connect_result) show that wireless ADB is a first-class flow, not an ad hoc UI action.
9. Concurrency and background work
- lib/services/isolate_runner.dart and lib/models/isolate_message.dart indicate that longer-running tasks or streaming operations are moved off the main UI thread via isolates.
- This is likely used for operations such as logcat streaming, device enumeration, and discovery so the terminal UI remains responsive.
10. Application state and dependency wiring
- lib/services/settings_service.dart persists app-level preferences using the app_settings model.
- lib/services/service_locator.dart wires together shared services, suggesting a lightweight dependency-injection pattern rather than direct construction throughout the UI.
- This keeps feature modules decoupled from concrete service implementations.
11. Shared utilities
- lib/utils contains constants, string/iterable extensions, and version helpers.
- These are support layers only; they do not own core behavior but reduce duplication across UI and service code.
12. Build, distribution, and release architecture
- The repo is set up for multi-channel distribution: pub.dev, Homebrew, and Windows winget, plus binary installers (install.sh, install.ps1).
- GitHub Actions workflows handle CI and release publishing, so packaging is part of the project’s architecture, not an afterthought.
- This matters because the app is meant to be installed as a local CLI tool across macOS, Linux, and Windows.
13. Overall data flow
- User action in the terminal UI → command/UI component → feature dialog or controller → domain model → service layer → external device tooling/processes → result back through models/isolate messages → UI update.
- The main architectural boundaries are therefore: UI, domain/models, device/platform services, and external command/tooling integration.
Main entry points: simutil_app.dart Simutil app · service_locator.dart Service locator · device_service.dart Device service · command_exec.dart Command exec
Components 25
CLI
Entry commands and startup shell
- simutil.dart · Dart executable entrypoint
bin/simutil.dart - Command runner · Registers commands and dispatches CLI behavior
lib/cli/simutil_command_runner.dart - Simutil command · Primary command surface for the terminal app
lib/cli/commands/simutil_command.dart - Version command · Version/help-style command
lib/cli/commands/version_command.dart
Terminal UI
Interactive Nocterm application and components
- Simutil app · Main interactive Nocterm application
lib/simutil_app.dart - Device list · Primary device browsing view
lib/components/device_list_component.dart - Detail panel · Shows selected device details and actions
lib/components/device_detail_panel.dart - Dialogs · Reusable dialogs, overlays, inputs, and status UI
lib/components - Theme · Shared terminal styling and icons
lib/components/simutil_theme.dart
Domain
Shared models and state contracts
- Devices · Device identity, type, OS, and state contracts
lib/models/device.dart - Wireless flows · Pairing and wireless connect request/result models
lib/models/wireless_connect_request.dart - App settings · Persisted user preferences and app configuration
lib/models/app_settings.dart - Isolate messages · Message contracts for background work
lib/models/isolate_message.dart
Services
Device orchestration, execution, discovery, and settings
- Device service · Abstraction for device operations
lib/services/device_service.dart - Android service · Android device and emulator workflows
lib/services/android_device_service.dart - iOS service · iOS simulator workflows
lib/services/ios_device_service.dart - Command exec · Shell and process execution for external tooling
lib/services/command_exec.dart - Wi‑Fi discovery · Network discovery for wireless connection flows
lib/services/wifi_discovery_service.dart - Isolate runner · Runs long-lived or blocking work off the UI thread
lib/services/isolate_runner.dart - Settings service · Persists and loads app settings
lib/services/settings_service.dart - Service locator · Central dependency wiring for shared services
lib/services/service_locator.dart
Plugins
Feature modules for Android tooling and log streaming
Distribution
Packaging and release automation
- Release flows · CI and distribution pipelines for package and installer publishing
.github/workflows/release.yaml
Connections 26
- simutil.dart → Command runner: starts · Entrypoint hands off to CLI parsing and dispatch
- Command runner → Simutil command: registers · Main command surface is registered with the runner
- Command runner → Version command: registers · Version command is exposed through the runner
- Simutil command → Simutil app: launches · CLI command starts the interactive terminal app
- Simutil app → Device list: renders · Main screen presents the device list
- Simutil app → Detail panel: renders · Selected device details flow into the detail panel
- Simutil app → Dialogs: uses · Feature dialogs and overlays drive interactions
- Simutil app → Theme: styles · Shared theme and iconography shape the UI
- Simutil app → Devices: binds · UI reads and updates device state models
- Simutil app → Device service: orchestrates · User intent is translated into device operations
- Device service → Android service: implements · Android-specific device workflows
- Device service → iOS service: implements · iOS-specific simulator workflows
- Android service → Command exec: executes · Android work is delegated to external tools and processes
- iOS service → Command exec: executes · iOS simulator work is delegated to external tools and processes
- ADB tools → Android service: drives · ADB dialogs and pairing flows invoke Android operations
- Logcat → Isolate runner: streams via · Logcat processing is isolated from the UI thread
- Logcat → Command exec: reads · Log streaming depends on external process execution
- Wi‑Fi discovery → Wireless flows: produces · Discovery supports wireless connect and pairing models
- Wi‑Fi discovery → Isolate runner: runs via · Network discovery can be offloaded to background work
- Settings service → App settings: persists · Settings service loads and saves app preferences
- Service locator → Device service: wires · Shared service graph exposes device operations
- Service locator → Settings service: wires · Shared service graph exposes persistence
- Service locator → Wi‑Fi discovery: wires · Shared service graph exposes discovery
- Service locator → Isolate runner: wires · Shared service graph exposes concurrency helpers
- Service locator → Command exec: wires · Shared service graph exposes process execution
- Release flows → simutil.dart: packages · Release automation builds and publishes the CLI tool