inkpal_bridge

The reliable execution path between your AI and your Flutter app.

pub package pub points GitHub stars

AI writes Flutter code. It can't run it. So it guesses — at the widget tree, at the state, at whether the change compiled. inkpal_bridge closes that loop.

The InkPal loop

  AI writes  →  hot-reloads  →  drives the UI  →  verifies  →  repeats

Every step is one MCP tool call over a loopback HTTP server your app opens on port 8767. No external CLI, no daemon, no ADB round-trip.

Install

# pubspec.yaml
dependencies:
  inkpal_bridge: ^8.0.0
// lib/main.dart
import 'package:inkpal_bridge/inkpal_bridge.dart';

void main() => inkpalRunApp(const MyApp());

Paste this into your editor's MCP config once:

{"mcpServers": {"inkpal": {"transport": "http",
  "url": "http://127.0.0.1:8767/mcp"}}}

Restart the editor. Done.

What's unique

  • Verified execution. Every mutating call returns a verification envelope — did the screen change, did errors fire, did the route move. verify: 'lite' | 'off' on the fast paths.
  • Runtime identity. Every response carries _meta.runtime with session_id, bridge_id, build_id, hot_reload_generation — agents catch stale reads without asking.
  • 79 tools. Inspection, interaction, wait/assert, state time-travel, HTTP memory, hot reload, recording → replay, runtime-health rollup, image cache — all in one Dart package.
  • Zero deps. Just flutter. No third-party runtime deps ever.

Android

The bridge binds inside the running app. Android emulators need one adb forward per flutter run:

adb forward tcp:8767 tcp:8767

The bridge's welcome banner prints this command when it detects Android. iOS simulator, macOS, Linux, and Windows share loopback — no forward required.

Platforms

Android, iOS, macOS, Linux, Windows. Flutter web is not currently supporteddart:io HttpServer is unavailable in the browser runtime. The bridge skips its HTTP server on web with a debugPrint and stays inert.

Bundled CLIs

dart run inkpal_bridge:inkpal tap "Save"
dart run inkpal_bridge:inkpal health
dart run inkpal_bridge:inkpal screenshot --out shot.png
dart run inkpal_bridge:doctor        # nine-check diagnostic
dart run inkpal_bridge:connect       # discover bridge + print editor config

Full release history

See CHANGELOG.md.


Advanced — routers, state adapters, hooks

go_router — pass your router; route tracking is automatic:

final router = GoRouter(routes: [...]);
inkpalRunApp(MyApp(router: router), router: router);

Other routers — pass an onNavigateToRoute callback:

inkpalRunApp(
  const MyApp(),
  onNavigateToRoute: (route) async => Get.toNamed(route),
);

Live app state — wire an InkPalStateAdapter so state_read, state_watch, state_override reach your Riverpod / Bloc / Provider / GetX / MobX store:

inkpalRunApp(
  const MyApp(),
  stateAdapter: InkPalStateAdapter(
    list: () async => [{'id': 'cart.count', 'kind': 'notifier'}],
    read: (id) async => {'value': cartNotifier.value},
    write: (id, v) async { cartNotifier.value = v as int; return {'success': true}; },
  ),
);

Custom widgets — teach the semantics walker to recognise them:

inkpalRunApp(
  const MyApp(),
  walkerHooks: InkPalWalkerHooks(
    isInteractiveWidget: (w) => w is BrandButton,
    extractTextFrom: (w) => w is BrandButton ? w.label : null,
  ),
);

Default verify mode — set once for every mutating tool:

inkpalRunApp(const MyApp(), defaultVerify: 'lite');

App identity — set once, echoed on every reply so cross-app orchestration can tell which bridge answered:

inkpalRunApp(const MyApp(), appIdentity: 'com.foo.mymapapp');

Emergency kill-switch — even in a debug build:

flutter run --dart-define=INKPAL_BRIDGE=off

MIT-licensed. Bug reports + PRs welcome at github.com/InkPalAI/inkpal_bridge.

Libraries

inkpal_bridge
InkPal Bridge — in-app intelligence for AI-powered Flutter development.