turbo_bridge_client
Pure Dart client library for connecting to a running Flutter app via Turbo Bridge. Designed for tool builders, CI pipelines, and anyone who needs programmatic access to a Flutter app's UI.
Installation
dependencies:
turbo_bridge_client: ^0.3.0
Or use the CLI:
dart pub add turbo_bridge_client
Quick Start
import 'package:turbo_bridge_client/turbo_bridge_client.dart';
void main() async {
final client = TurboBridgeClient(host: '127.0.0.1', port: 8888);
// Check connection
if (!await client.isConnected()) {
print('App not running or bridge not started');
return;
}
// Take a screenshot
final screenshot = await client.screenshot();
File('screenshot.png').writeAsBytesSync(screenshot.bytes);
print('Screenshot: ${screenshot.width}x${screenshot.height} in ${screenshot.captureTimeMs}ms');
// Inspect the widget tree
final tree = await client.widgetTree(depth: 15);
print('Root: ${tree.type}');
for (final child in tree.children) {
print(' ${child.type} ${child.text ?? ""}');
}
// Find and tap a button
await client.tapByText('Submit');
// Or tap by key
await client.tapByKey('login_button');
// Or tap exact coordinates
await client.tap(195, 422);
// Get app info
final info = await client.appInfo();
print('Screen: ${info.screenWidth}x${info.screenHeight}');
print('Platform: ${info.platform}');
await client.dispose();
}
API Reference
TurboBridgeClient
The main entry point. Connects to the bridge HTTP server.
// Bridge-only connection
final client = TurboBridgeClient(host: '127.0.0.1', port: 8888);
// Bridge + VM Service (for Dart expression evaluation)
final client = TurboBridgeClient.withVmService(
host: '127.0.0.1',
port: 8888,
vmServiceUri: 'ws://127.0.0.1:5678/ws',
);
Screenshots
final result = await client.screenshot(pixelRatio: 2.0);
final settled = await client.screenshot(pixelRatio: 1.0, delayMs: 75);
result.bytes; // Uint8List (PNG)
result.width; // int
result.height; // int
result.captureTimeMs; // int (server-side capture time)
result.roundTripMs; // int (full HTTP round trip)
Use delayMs when you need to let the UI settle after a tap, swipe, or route transition. The client default stays 0 so direct callers keep full control over latency.
Widget Tree
final tree = await client.widgetTree(depth: 10);
tree.type; // 'MaterialApp'
tree.key; // String? widget key
tree.text; // String? text content
tree.rect; // {x, y, width, height}? layout bounds
tree.children; // List<WidgetNode>
// Search utilities
tree.findByText('Hello'); // List<WidgetNode>
tree.findByKey('my_button'); // WidgetNode?
tree.findByType('ElevatedButton'); // List<WidgetNode>
Gestures
// Tap coordinates
final result = await client.tap(100.0, 200.0);
result.success; // bool
result.durationMs; // int
// Find widget by text and tap its center
final result = await client.tapByText('Login');
// Find widget by key and tap its center
final result = await client.tapByKey('submit_btn');
// Swipe between two points
await client.swipe(200, 600, 200, 200); // startX, startY, endX, endY
// Scroll at a position
await client.scroll(200, 400, dy: 200); // scroll up
// Enter text into focused field
await client.enterText('hello@example.com');
await client.enterText('new value', replace: true); // replace existing text
Find Widgets (Server-Side)
// Search by text content
final results = await client.find(text: 'Login');
results.found; // bool
results.count; // int
for (final widget in results.results) {
print('${widget.type} at (${widget.center.$1}, ${widget.center.$2})');
}
// Search by key
final results = await client.find(key: 'submit_button');
// Search by type
final results = await client.find(type: 'ElevatedButton');
App Info
final info = await client.appInfo();
info.screenWidth; // double
info.screenHeight; // double
info.pixelRatio; // double
info.platform; // String
info.darkMode; // bool
info.bridgeVersion; // String
VM Service (Optional)
final client = TurboBridgeClient.withVmService(
host: '127.0.0.1',
port: 8888,
vmServiceUri: 'ws://127.0.0.1:5678/ws',
);
await client.connectVmService();
// Evaluate Dart expressions in the running app
final result = await client.evaluate('DateTime.now().toString()');
Use Cases
- Benchmark tools — Measure Flutter rendering performance
- Integration test harnesses — Drive UI tests from outside the app
- CI screenshot pipelines — Capture app states for visual regression
- Custom developer tools — Build your own Flutter inspector
- Bot frameworks — Programmatic app interaction for automation
Error Handling
try {
final screenshot = await client.screenshot();
} on BridgeException catch (e) {
print('Bridge error: ${e.message} (status: ${e.statusCode})');
}
All methods throw BridgeException when the bridge returns an error response (4xx/5xx). Connection failures throw standard http package exceptions.
Libraries
- turbo_bridge_client
- Flutter Turbo Bridge Client — High-speed client for AI-Flutter interaction.