Getting started
Dartmole has two parts: the Dartmole app on your Mac, which shows the traffic, and dartmole_plugin in your Flutter app, which sends the traffic there. This page sets up both and gets the first call on screen.
You need:
- a Mac with Apple silicon, on macOS 12 or later;
- a Flutter app on Flutter 3.29 or later, running on a phone or simulator;
- the phone and the Mac on the same network.
1. Install Dartmole
Download Dartmole, open the DMG, and drag Dartmole to Applications. When you open it, it starts its proxy on port 8080. If something else has that port, Settings → Proxy says what, and lets you pick another.
Dartmole updates itself: it checks for a new version once a day, and Dartmole → Check for Updates… checks right away.
2. Add the plugin
In your app's pubspec.yaml:
dependencies:
dartmole_plugin: ^0.1.0Or run flutter pub add dartmole_plugin.
iOS
Pairing scans a QR code, so the app needs the camera, and it reaches your Mac
over the local network. Add both keys to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Scans the QR code in Dartmole to pair with it.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Connects to Dartmole on this network to inspect the app's traffic.</string>Without the camera key, iOS closes the app as soon as the scanner opens.
Android
Debug builds can already reach the network. For a release build that should
pair too, such as an internal build for testers, add this to
android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>3. Send your HTTP through it
Dartmole().createHttpClient() returns a dart:io HttpClient. Until the
app is paired and interception is on, it is an ordinary client, so it is safe
to use everywhere.
HTTP libraries create their client once and keep it, so swap it when the
pairing changes: Dartmole() is a ChangeNotifier.
With Dio:
import 'package:dartmole_plugin/dartmole_plugin.dart';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/widgets.dart';
final dio = Dio();
void main() {
WidgetsFlutterBinding.ensureInitialized();
_useDartmole();
Dartmole().addListener(_useDartmole);
runApp(const MyApp());
}
void _useDartmole() {
dio.httpClientAdapter = IOHttpClientAdapter(
createHttpClient: Dartmole().createHttpClient,
);
}With package:http:
import 'package:dartmole_plugin/dartmole_plugin.dart';
import 'package:flutter/widgets.dart';
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart';
http.Client client = IOClient(Dartmole().createHttpClient());
void main() {
WidgetsFlutterBinding.ensureInitialized();
Dartmole().addListener(() {
client.close();
client = IOClient(Dartmole().createHttpClient());
});
runApp(const MyApp());
}Read client at the moment of each call rather than keeping a copy, so calls
pick up the new one. With a plain HttpClient, create one with
Dartmole().createHttpClient() wherever you would write HttpClient().
4. Add the pairing panel
DartmoleSettings pairs the device, shows which Mac it is paired with, and
switches interception on and off. Put it where testers can reach it and store
users cannot, such as a debug menu:
Scaffold(
appBar: AppBar(title: const Text('Dartmole')),
body: const SingleChildScrollView(
padding: EdgeInsets.all(24),
child: DartmoleSettings(),
),
);5. Pair and watch
- In Dartmole, open the Devices tab. It shows a QR code.
- In your app, open the pairing panel and tap Scan QR code. On a simulator, or a device without a camera, type the host and port Dartmole shows instead.
- Use your app. Every call it makes appears on Dartmole's Proxy tab, with its headers and body.
TLS stays on throughout: the plugin trusts Dartmole's certificate authority for its own client only, and never switches certificate checks off.
Next: mock a call
Mocks are files in the repository of the app you are debugging, in
.dartmole/mocks/, so they are reviewed and shared like the rest of your
code.
- On the Mocks tab, choose Import project and pick your app's folder.
- On the Proxy tab, select a call and choose Save as mock. Change the response, the status or a delay, and save.
- Switch the mock on. The next matching call gets the mock's response, and the backend never sees it.
Mocks arrive switched off. Whether one is on is remembered on your Mac and never changes the files, so pulling someone's mocks cannot change your traffic by surprise.
When nothing shows up
- No calls on the Proxy tab. Check that the pairing panel says paired and interception is on, and that the phone and the Mac are on the same network. A client created before pairing keeps bypassing Dartmole; swap it as in step 3.
- The proxy does not start. Settings → Proxy shows its state and, if the port is taken, by what. Pick another port there; paired devices then pair again.
- Calls from native code are missing. The plugin covers Dart's
HttpClient. ForURLSession, OkHttp or WebViews, the pairing panel offers Also intercept native traffic, with steps for the device.
The dartmole_plugin page on pub.dev has the full reference: remembering a pairing across launches, native traffic, and checking that interception works.