DevTools Profiler CLI
devtools_profiler_cli is the terminal and MCP front end for the pure-Dart
profiler package set.
Use it when you want to profile a Dart or Flutter VM command without opening the DevTools UI. It can capture the whole run, capture marked regions emitted by the target program, print readable terminal output, write JSON for automation, and serve the same capabilities to AI agents over stdio MCP.
For the full CLI guide, see the profiler README.
Install And Run
Install the CLI once:
dart pub global activate devtools_profiler_cli
devtools-profiler help
When testing an unpublished checkout, activate the local package instead:
dart pub global activate --source path packages/devtools_profiler_cli
devtools-profiler help
Profile the bundled fixture app:
devtools-profiler run \
--hide-sdk \
--hide-runtime-helpers \
--call-tree \
--method-table \
--cwd packages/devtools_profiler_core/test/fixtures/profiled_app \
-- dart run bin/profiled_app.dart
Profile your own app:
devtools-profiler run \
--cwd /path/to/app \
bin/main.dart
For full Dart or Flutter commands, put profiler options before the target
command. Use -- when the target command has its own options:
devtools-profiler run \
--json \
--duration 15s \
--hide-sdk \
--hide-runtime-helpers \
--call-tree \
--bottom-up \
--method-table \
--cwd /path/to/app \
-- dart run bin/main.dart
Bare Dart files are expanded to dart run <file>. Dart launches are held at
isolate exit long enough for final CPU and memory snapshots, so short scripts
can still produce a whole-session profile.
Profile the bundled terminal UI fixture:
devtools-profiler run \
--terminal \
--cwd packages/devtools_profiler_core/test/fixtures/profiled_app \
-- dart run bin/artisanal_widget_app.dart
Use --terminal when the target needs direct stdin, raw-mode input, mouse
tracking, or alternate-screen rendering. It cannot be combined with --json
because the target writes directly to the terminal. If you press Ctrl+C while
the CLI is running, the profiler writes the diagnostics captured so far before
printing the session summary.
Profile a Flutter test:
devtools-profiler run \
--json \
--duration 15s \
--hide-sdk \
--hide-runtime-helpers \
--call-tree \
--method-table \
--cwd /path/to/flutter/app \
-- flutter test test/widget_test.dart
Profile a Flutter app run:
devtools-profiler run \
--json \
--hide-sdk \
--hide-runtime-helpers \
--call-tree \
--method-table \
--cwd /path/to/flutter/app \
-- flutter run -d linux
--duration starts after the VM service is available. Flutter builds can take
longer than Dart scripts before a VM service URI is printed, so use
--vm-service-timeout 5m when profiling a cold build.
Attach to an already-running VM service:
devtools-profiler attach \
--json \
--duration 15s \
--hide-sdk \
--hide-runtime-helpers \
--call-tree \
--method-table \
--cwd /path/to/flutter/app \
http://127.0.0.1:8181/abcd/
Use attach mode when flutter run is already active and you want repeated
profiling windows without rebuilding. Start Flutter with a host VM-service port
when needed:
flutter run -d linux -t lib/main_relic_breach.dart --host-vmservice-port=0
The attach command clears the VM's existing CPU samples, captures the
whole-session VM service view for a bounded duration, and does not stop the
target process. It defaults to 15s, and attach sessions skip DTD by default
because explicit region markers are unavailable in attach mode.
If exactly one app is running, attach can auto-discover its VM service URI.
Live Flutter Analysis
The CLI includes commands that connect directly to a running Flutter or Dart
application via its VM service URI. Use discover to find available URIs on
this machine, then run the live-analysis commands.
Discover running apps:
devtools-profiler discover
This scans OS processes for Flutter/Dart development services and lists their
VM service WebSocket URIs. Pass --json for machine-readable output.
All flutter commands below auto-discover the VM service URI when omitted. Just run them while your app is running and they connect automatically:
devtools-profiler timeline # auto-discovers URI
devtools-profiler flutter:timeline # compatibility alias
devtools-profiler flutter:screenshot # same
When multiple apps are running, the command lists them and asks you to pick one by passing the URI explicitly.
Profile frame timing and detect jank:
devtools-profiler flutter:timeline \
--duration 5 \
ws://127.0.0.1:8181/abc123/ws
Returns frame timing metrics including total/janky frame counts, average, P90,
P99, and max frame times, plus a breakdown of build, layout, and paint phases.
Auto-detects display refresh rate and shader compilation events.
flutter:timeline and flutter:frame-profile are available as
compatibility aliases.
Capture a memory snapshot:
devtools-profiler flutter:memory-snapshot \
--name before-optimization \
--save \
--no-gc \
ws://127.0.0.1:8181/abc123/ws
Returns top allocation classes sorted by current heap size. Omit --no-gc to
force garbage collection before the capture. Use --save to persist the
snapshot under .dart_tool/devtools_profiler/sessions for later comparison.
Capture the widget tree:
devtools-profiler flutter:widget-tree \
--depth 15 \
--summary \
ws://127.0.0.1:8181/abc123/ws
Use --summary for a condensed Flutter-only view. Use --project-only to
filter framework widgets and show only project code in either tree shape.
Query widget inspector RPCs:
devtools-profiler flutter:inspector \
--method getSelectedWidget \
ws://127.0.0.1:8181/abc123/ws
Supported methods include getSelectedWidget, getSelectedSummaryWidget,
getParentChain, getProperties, getChildren, getChildrenSummaryTree,
getChildrenDetailsSubtree, getDetailsSubtree, and
getLayoutExplorerNode.
Capture a screenshot:
devtools-profiler flutter:screenshot \
--output app.png --width 1920 \
ws://127.0.0.1:8181/abc123/ws
Uses the Flutter inspector screenshot service extension.
Dump diagnostic information:
devtools-profiler flutter:debug-dump --kind render \
ws://127.0.0.1:8181/abc123/ws
Available kinds: app, render, layer, focus, semantics.
Capture log and output streams:
devtools-profiler flutter:logs \
--duration 30 --output session.log \
ws://127.0.0.1:8181/abc123/ws
Captures Logging, Stdout, and Stderr streams. Use --follow for continuous
streaming until interrupted.
What You Get Back
Each run or attach writes a session directory:
.dart_tool/devtools_profiler/sessions/<session-id>/
A session can contain:
overall: the whole process profile.regions: profiles for marked regions emitted bydevtools_region_profiler.- CPU summaries: top self frames, top total frames, top-down call trees, bottom-up call trees, and method tables.
- Memory summaries when memory capture was available.
- Warnings and artifact paths needed by later commands.
If the target app has no marked regions, the CLI still captures the whole session.
JSON responses include a cliCommand field for the command that can reproduce
the same analysis selection.
Read Existing Artifacts
List stored profiling sessions:
devtools-profiler profiles
By default this shows a compact listing of session id, modified time, and
command. Use --extended for the full table with working directory, exit
code, region count, and warnings. Use --limit to control how many sessions
are shown; --limit 0 shows all stored sessions.
Almost every analysis command below works without a path when at least one
stored session exists — it falls back to the latest session automatically.
Use --session-id latest, --session-id previous, or --session-id <id>
to pick a different stored session explicitly.
Positional arguments accept session ids in addition to file paths, so you can pass a session id directly instead of its on-disk path:
devtools-profiler summarize 0712060003-8c410
devtools-profiler compare 0712060003-8c410 0711235455-ebfb3
devtools-profiler trends session-a session-b session-c
devtools-profiler inspect --method Parser.parseFile 0712060003-8c410
devtools-profiler inspect-classes --class String 0712060003-8c410
Summarize a session:
devtools-profiler summarize \
--hide-sdk \
--hide-runtime-helpers \
--call-tree \
--method-table \
/path/to/session
Explain likely hotspots:
devtools-profiler explain \
--json \
--profile-id overall \
/path/to/session
Search for methods:
devtools-profiler search-methods \
--json \
--query Parser \
--sort total \
/path/to/session
Inspect one method:
devtools-profiler inspect \
--json \
--method Parser.parseFile \
--profile-id overall \
/path/to/session
Inspect memory classes:
devtools-profiler inspect-classes \
--json \
--class String \
--min-live-bytes 1048576 \
/path/to/session
Use --limit 0 for an unlimited class list. The command can read a session
directory, a region summary.json, or a raw memory_profile.json artifact.
Compare two sessions:
devtools-profiler compare \
--json \
--method-table \
/path/to/baseline-session \
/path/to/current-session
Analyze a series oldest to newest:
devtools-profiler trends \
--json \
/path/to/session-1 \
/path/to/session-2 \
/path/to/session-3
# Or use the N most recent stored sessions:
devtools-profiler trends --last 5
Check for regressions against a known-good baseline (useful in CI):
devtools-profiler regress path/to/baseline-session
devtools-profiler regress 0712060003-8c410 0711235455-ebfb3
Exits with code 1 when regressions are found. Use --warn-only to exit 0.
Compare three or more sessions with an aligned hotspot table:
devtools-profiler compare session-a session-b session-c
devtools-profiler compare --csv session-a session-b session-c
Important Flags
--jsonemits machine-readable JSON.--csvoutputs compact CSV tables instead of formatted terminal output.--call-treeincludes the top-down call tree.--bottom-upincludes the bottom-up caller tree.--method-tableincludes DevTools-style caller and callee context.--hide-sdkhides Dart and Flutter SDK frames.--hide-runtime-helpershides profiler transport and runtime helper frames.--collapse-asynccategorizesdart:asyncframes by type (normal completions, error completions, listener dispatch, microtask scheduling, zone overhead) and attributes async cost to the calling function when raw CPU samples are available (e.g.async (await _executeFrame)).--include-package <prefix>keeps only matching package prefixes.--exclude-package <prefix>removes matching package prefixes.--full-locationskeeps full source locations instead of compact labels.--frame-limit 0,--tree-depth 0,--tree-children 0, and--method-limit 0disable the corresponding output limits.--duration <duration>stops long-running targets after profiling for that duration. Examples:15s,2m,500ms.--warm-up <duration>waits this long after VM service connection before starting the profiling timer. Useful for Flutter apps to skip startup and first-frame rendering. Examples:5s,30s.--fluttersets--warm-up 3s,--hide-sdk, and--hide-runtime-helperstogether as Flutter-friendly defaults.--vm-service-timeout <duration>controls startup wait time before the VM service is available. Examples:3m,300s.--terminalgives the launched process direct terminal access for TUI and alternate-screen apps. It cannot be combined with--json.--min-live-bytes <n>filters memory class rows forcompareandinspect-classes.--memory-class-limit <n>controls compared memory class rows forcompare.0means unlimited.--last <n>ontrendsuses thenmost recent stored sessions. Example:devtools-profiler trends --last 5.
Commands that operate on one profile use --profile-id overall for the
whole-session profile or a generated region id for a marked region. Region names
are labels; region ids are printed in session summaries and exposed by MCP.
Use --session-id latest, --session-id previous, or --session-id <id>
instead of a path to reference stored sessions directly. The profiles command
lists available session ids.
The profiles command accepts --extended, --limit, and --json:
devtools-profiler profiles # compact list (default limit 12)
devtools-profiler profiles --extended # full table
devtools-profiler profiles --limit 0 # all stored sessions
devtools-profiler profiles --json # machine-readable output
MCP Server
Start the local stdio MCP server:
devtools-profiler mcp
Example client configuration:
{
"command": "devtools-profiler",
"args": ["mcp"]
}
Agent-facing tools include:
profile_runprofile_attachprofile_summarizeprofile_read_artifactprofile_list_sessionsprofile_latest_sessionprofile_get_sessionprofile_list_regionsprofile_get_regionprofile_explain_hotspotsprofile_search_methodsprofile_inspect_methodprofile_inspect_classesprofile_discover_appsprofile_frame_profiletimelineprofile_memory_snapshotprofile_widget_treeprofile_widget_inspector_queryprofile_screenshotprofile_debug_dumpprofile_stream_logsprofile_compareprofile_compare_methodprofile_find_regressionsprofile_analyze_trends
Limits
- Attach mode captures a fixed whole-session VM-service window from an existing process, but explicit region markers normally require launch mode.
- Dart and Flutter VM-service commands only.
- Supported Flutter subcommands are
flutter run,flutter attach,flutter drive, andflutter test. - Flutter release mode, AOT profiling, and
dart compile ...targets are not supported. - Flutter region markers require the target process to reach the profiler's local DTD URI. This works for host-side Flutter tests and desktop runs, but device runs may need additional networking.
- MCP transport is local stdio.
- If an MCP client does not inherit the Pub global executable path, configure
the client with the resolved
devtools-profilerexecutable path.
Libraries
- devtools_profiler_cli
- CLI and MCP entrypoints for the DevTools profiler backend.