npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

flutter-axi

v0.1.2

Published

AXI-compliant Flutter app automation: widget-tree snapshots, driver interactions, native device control, TOON output, contextual suggestions

Downloads

289

Readme

flutter-axi wraps the Dart MCP server with an AXI-compliant CLI, plus a native device layer (adb / xcrun simctl) for everything the Flutter tooling can't reach.

  • Token-efficient: TOON-encoded output and pre-rendered widget-tree snapshots cut input tokens ~70% vs raw MCP
  • Combined operations: one command launches, connects, snapshots, and suggests next steps
  • Contextual suggestions: every response includes actionable next-step hints
  • Beyond the widget tree: GPS mocking, permissions, deep links, push notifications, app lifecycle
  • Performance profiling: frame timings with jank stats, memory, CPU, timeline traces
  • Multi-app native: named sessions and a script runner drive two apps at once (e.g. a user app and an operator app)

Benchmarks

Agent ergonomics is measurable. The benchmark harness in bench/ replicates the axi methodology: 13 real app-automation tasks (launch-and-read, interaction flows, hot reload, log investigation, screenshots, GPS/permissions/push/lifecycle) run through both interfaces, 3 repeats each, with claude-sonnet-4-6 as the agent and an LLM judge scoring task success against the live app.

flutter-axi posts the lowest input tokens, cost, duration, and turn count, with 100% task success:

| Condition | Avg Input Tokens | Avg Cost/Task | Avg Duration | Avg Turns | Success | | -------------------- | ---------------- | ------------- | ------------ | --------- | -------- | | flutter-axi | 99,588 | $0.082 | 32.4s | 4.6 | 100% | | dart-mcp (raw MCP) | 336,667 | $0.160 | 52.6s | 8.1 | 100% |

Against the raw Dart MCP server, the very server this CLI wraps, that is 70% fewer input tokens, 49% lower cost, and 43% fewer agent turns on the 8 tasks both can perform. The other 5 tasks (GPS, permissions, deep links, push, lifecycle) are outside the Dart MCP server's capability entirely; flutter-axi passed all of them and they are reported N/A for MCP rather than counted as wins.

The gap widens with interaction count. Screenshots are the pathological case (4.7x cost for MCP, which has no save-to-file path):

| Task | flutter-axi | dart-mcp | Cost ratio | | ---- | ----------- | -------- | ---------- | | read counter (launch + 1 read) | $0.050 / 3 turns | $0.073 / 5 turns | 1.5x | | inspect tree (launch + 2 reads) | $0.061 / 3 turns | $0.168 / 5 turns | 2.7x | | tap increment x5 | $0.099 / 5 turns | $0.203 / 11 turns | 2.0x | | screenshot to file | $0.071 / 4 turns | $0.330 / 14 turns | 4.7x |

Full analysis, per-task tables, methodology, and fairness caveats: bench/published-results/STUDY.md.

Quick Start

Install the flutter-axi skill in the Agent Skills format with npx skills:

npx skills add ammar00sheikh/flutter-axi --skill flutter-axi -g

The skill (generated from the CLI's own guidance) teaches your agent when and how to use flutter-axi; it loads on demand when the agent recognizes a mobile-app task. -g installs the skill for all projects (~/.claude/skills/, for example); drop it to install for the current project only.

Until flutter-axi is published to npm, also install the CLI itself (one line, see below):

curl -fsSL https://raw.githubusercontent.com/ammar00sheikh/flutter-axi/main/install.sh | bash

Then, once per Flutter project, enable driver input:

flutter-axi setup driver ~/my-app && (cd ~/my-app && flutter pub get)

And drive the app:

flutter-axi devices
flutter-axi launch ~/my-app --device <id>     # first launch compiles, be patient

Requirements: Node >= 20, Dart SDK >= 3.9 (dart on PATH, or set FLUTTER_AXI_DART_BIN), a booted iOS simulator or Android emulator.

What Agent Sees

$ flutter-axi launch bench/fixtures/counter_app --device 00920CD6-...
app:
  pid: 83714
  device: 00920CD6-2DFD-4A6F-9339-709459BBEE60
  platform: ios
  appId: dev.flutteraxi.counterApp
  driver: enabled
app:
  title: Flutter Demo Home Page
  refs: 8
tree:
uid=g1:1 MyApp
  MaterialApp
    uid=g1:3 MyHomePage
      Scaffold
        Center
          Column
            uid=g1:11 Text "You have pushed the button this many times:"
            uid=g1:12 Text "0"
        uid=g1:6 AppBar
          uid=g1:9 Text "Flutter Demo Home Page"
        uid=g1:7 FloatingActionButton
          uid=g1:10 Icon
help[2]:
  Run `flutter-axi tap @g1:7` to tap the FloatingActionButton
  Widgets without a uid can be targeted directly: `flutter-axi tap text:<visible text>` (also key:, type:, tooltip:, label:)

$ flutter-axi tap @g1:7
app:
  title: Flutter Demo Home Page
  refs: 8
tree:
...
            uid=g2:12 Text "1"
...

Refs carry a g<N>: generation prefix that bumps on every fresh snapshot. Pass refs back exactly as printed. If the tree re-rendered between snapshot and action, the action fails loudly with STALE_REF instead of silently acting on a stale tree, so the agent re-snapshots and retries. Widgets without a uid can be targeted with finder strings: text:, key:, type:, tooltip:, label:.

Other Ways to Install

The skill plus the curl installer is the recommended path, but it is not the only one.

Curl installer

curl -fsSL https://raw.githubusercontent.com/ammar00sheikh/flutter-axi/main/install.sh | bash

Clones into ~/.flutter-axi/cli (override with FLUTTER_AXI_HOME), builds, and links flutter-axi onto PATH. Re-running updates the install.

From source

git clone https://github.com/ammar00sheikh/flutter-axi.git
cd flutter-axi
npm install
npm run build
npm link        # puts `flutter-axi` on PATH

Session hook

Want ambient app-session context fed into every agent session instead of loading on demand?

flutter-axi setup hooks

This installs a SessionStart hook for Claude Code, Codex, and OpenCode that surfaces the active app session (device, screen title, ref count) and usage guidance at the start of each session. Restart your agent session after running this. Development entrypoints (npm run dev) are guarded from accidental hook installation.

How It Works

flutter-axi CLI  (axi-sdk-js: TOON output, structured errors, suggestions)
  ├─► HTTP bridge (one per session)  ─►  dart mcp-server  ─►  running Flutter app
  └─► native layer (adb / xcrun simctl)  ─►  emulator / simulator

Every CLI invocation is a short-lived process; a detached per-session bridge holds the persistent MCP connection to dart mcp-server, which drives the app through the Dart Tooling Daemon and the flutter_driver extension. Because the Dart MCP driver addresses widgets with finders rather than uids, flutter-axi mints its own generation-stamped uids at snapshot time and keeps a uid-to-finder registry per session. Native commands (GPS, permissions, deep links, push, lifecycle, OS screenshots) go straight to adb / xcrun simctl with no bridge involved.

Does it use MCP?

Yes, as its backend protocol, not its agent interface.

  • MCP inside: each session's bridge spawns the official Dart MCP server (dart mcp-server, ships with Dart SDK >= 3.9) and holds one persistent MCP stdio session to it. Every Flutter-tooling operation, from launch_app and get_widget_tree to flutter_driver, hot_reload, get_app_logs, and get_runtime_errors, is an MCP tool call made by the bridge on the agent's behalf.
  • No MCP outside: flutter-axi is not an MCP server and needs no MCP configuration in your agent. Agents use it through plain shell commands. That is the AXI thesis, and what the benchmark measures: the same MCP server consumed through this CLI costs 49% less and 43% fewer turns than consumed directly as MCP tools.
  • Two subsystems bypass MCP entirely: the native device layer talks straight to adb / xcrun simctl, and the performance layer (perf) talks straight to the app's Dart VM service over WebSocket, because the Dart MCP server exposes neither capability.

Native Device Control

flutter-axi gps 33.5138 36.2765               # mock location (or --route file.jsonl)
flutter-axi permission grant location         # no OS permission dialogs
flutter-axi deeplink myapp://item/42
flutter-axi push --title "New message" --body "You have a new message"   # real APNs on iOS sims
flutter-axi applifecycle force-stop           # install/uninstall/clear/background/foreground
flutter-axi screenshot ./screen.png --os      # OS-level capture (system UI included)

Performance Monitoring

Profiling goes straight to the app's Dart VM service (discovered automatically from the run logs). Every result is a pre-aggregated, decision-ready summary:

flutter-axi perf                                          # memory: heap/external per isolate + process RSS
flutter-axi perf frames --duration 5000 --scroll type:ListView
# frames: {count: 230, fps: 57.5, jank: "1 (0.4% over 16.7ms budget)",
#          build: "avg 2.2ms, p95 3.7ms, max 34.2ms", raster: "avg 0.8ms, ..."}
flutter-axi perf trace start && flutter-axi tap @g1:7 && flutter-axi perf trace stop --file ./trace.json
# timeline JSON loadable in https://ui.perfetto.dev
flutter-axi perf cpu --duration 3000                      # top functions by exclusive samples

perf frames measures frames rendered during the window. Pass --tap <ref> or --scroll <ref> and the CLI generates the load itself (e.g. jank-test a list with one command). Use --budget 8.3 for 120Hz displays.

Multi-App Orchestration

One session = one app + device. Add --app <name> to any command, or script several apps at once:

flutter-axi --app user     launch ~/user-app     --device <sim-1>
flutter-axi --app operator launch ~/operator-app --device <sim-2>

flutter-axi run <<'EOF'
const user = apps.user, operator = apps.operator;
await operator.gps(37.7749, -122.4194);
await user.tap("text:Submit Request");
await operator.waitFor("New request", { timeout: 30000 });
await operator.tap("text:Accept");
await user.waitFor("Request accepted");
console.log("two-app flow OK");
EOF

See examples/two-app-flow.mjs for a full two-app E2E example.

Development

npm install
npm test          # unit suite (no devices needed)
npm run test:e2e  # live suite, needs a booted simulator (two for multi-app tests)
npm run build     # compile to dist/

Architecture notes for coding agents: AGENTS.md. Contribution conventions: CONTRIBUTING.md.

Limitations

  • Driver input requires the app to be launched by flutter-axi through the driver shim (setup driver); attach --dtd <uri> is inspection-only.
  • Android needs adb (ANDROID_HOME); iOS simulators need Xcode CLI tools; physical iOS devices are not supported in v1.
  • Android push is a local-notification approximation (no FCM injection on stock emulators); iOS simctl push delivers real APNs payloads.