Flarness is an AI-friendly tool designed to let AI Agents (like coding assistants) drive the complete Flutter development loop. Unlike traditional CLI tools built for humans, Flarness provides structured JSON responses for every operation, allowing agents to understand, interact with, and automate Flutter applications with pinpoint precision.
AI agents are rewriting the development flow. To effectively manage a Flutter app, an agent needs more than just raw shell output; it needs structured state, machine-readable logs, and programmatic control over terminal-based interactions. Flarness provides this bridge.
- JSON-First: Every command outputs valid JSON, suitable for immediate parsing.
- Daemon Management: Run a background flarness daemon to keep the Flutter VM service alive and responsive.
- Full Control: Start, stop, restart, and hot-reload Flutter apps programmatically.
- State Inspection: Capture screenshots, inspect UI structure, and analyze project health in real-time.
- UI Automation: Drive taps, typing, waits, scrolling, swipes, and long presses through grouped interaction subcommands.
- AI-Friendly Help: A built-in
helpcommand that outputs command specifications in JSON.
Option 1: install a published release on Darwin/Linux
curl -fsSL https://raw.githubusercontent.com/canaanyjn/flarness/main/release/install.sh | bashOption 2: build from source
Required: Go 1.22+
git clone https://github.com/canaanyjn/flarness.git
cd flarness
make build
# Optional: install to /usr/local/bin
sudo make installThis repo also exposes a Codex-compatible skill at skills/flarness.
With vercel-labs/skills, install it from the repo directly:
npx skills add canaanyjn/flarness --skill flarnessAfter that, the installed skill can guide an agent through the Flarness workflow without needing the subdirectory URL.
Note:
skills/flarness/is the canonical install path for external skill installers.
All commands return a JSON object with a status field.
flarness app start --project /path/to/flutter_project --device chromeEvery project gets one daemon, addressed by a session id derived from the
project's absolute path. You rarely need to pass it: when --session is
omitted, flarness resolves the session from the Flutter app root containing
your current working directory — it walks up to the nearest pubspec.yaml
that has a lib/main.dart (or a platform directory), skipping nested package
pubspecs in a monorepo.
cd /path/to/worktree/apps/mobile # or any subdirectory of it
flarness app status # targets this worktree's daemon
flarness observe screenshot # no --session neededThis makes flarness git-worktree friendly: commands run from inside a
worktree always target that worktree's daemon, never another checkout's,
because each path hashes to a different session. Pass --session <id> (or
--project <path|alias>) only to target a project other than the one you are
standing in — but note a remembered --session can point at a stale or wrong
worktree, so prefer the cwd default or verify with flarness app status.
If your project needs a wrapper instead of calling flutter directly, add it to ~/.flarness/config.yaml:
defaults:
flutter_command:
- /absolute/path/to/apps/mobile/scripts/dev.sh
extra_args:
- --flavor
- devFlarness will then execute the configured wrapper and append run --machine, the selected device, and any extra args.
flarness sessions listflarness app status --session <session>flarness observe screenshot --session <session>On macOS, screenshot support is limited to Flutter-rendered content and
requires the app to initialize
flarness_plugin
in debug mode. It does not capture the desktop, window frame, or native
platform views.
On other non-web platforms, Flarness still tries flutter screenshot first and
uses the same plugin-based Flutter-content capture as a fallback when the
native Flutter path fails.
flarness observe inspect --session <session>observe inspect = structure/debugging view (widget tree or render tree)
observe semantics = automation/interaction view (labels, actions, focus, bounds)
flarness interact tap --text "Login"
flarness interact tap --id 21 # target a node by its 'observe semantics' id
flarness interact type --value "hello@example.com"
flarness interact wait --text "Success"Targets can be found by --text, --type, --id (the numeric node id from
observe semantics), or --x/--y coordinates. --id is the most reliable way
to hit icon-only controls and text fields that have no stable label. The rects
in observe semantics are absolute (global, logical) coordinates, so a node's
center is directly tappable. tap, swipe, scroll, and longpress all
accept --id.
flarness help [command]app: Start, stop, inspect status, reload, and restart the running Flutter app.observe: Capture screenshots, inspect UI structure, and dump semantics.interact: Group UI interaction subcommands such astap,type,wait,scroll,swipe, andlongpress.diagnose: Query logs and run analyzer checks.sessions: List known daemon sessions.config: Manage named Flutter project configuration.help: Get structural information about these commands.
Interactive commands require the Flutter app to register ext.flarness.*
service extensions in debug mode.
Use the bundled Flutter integration package:
Recommended dependency for external apps:
dependencies:
flarness_plugin:
git:
url: https://github.com/canaanyjn/flarness.git
path: packages/flarness_plugin
ref: v0.2.0