Skip to content

Commands inject

albertoodev edited this page Jul 25, 2026 · 4 revisions

inject: code transformation

The inject command instruments a target project so its State subclasses report runtime metrics. Driven by the JSONL manifest from analyze, it rewrites each target State class to extend SPM's SpmState base class, and a remove mode reverts every change.

Usage

spm inject --jsonl results.jsonl /path/to/project              # inject (default)
spm inject -j results.jsonl -m inject /path/to/project
spm inject -j results.jsonl -m remove /path/to/project         # revert

Options and flags

Flag / Option Short Description
--jsonl <path> -j Required. JSONL manifest from analyze.
--mode <mode> -m inject (default) or remove.
--verbose -v Print progress to stdout.
<repo_root> Path to the Flutter project root (exactly one).

--mode accepts only inject and remove. Passing any other value is a usage error.

What it rewrites

For each target State class listed in the manifest, inject mode:

  1. Inserts an instanceId getter right after the class's opening brace:
    @override
    String get instanceId => '<instanceId-from-manifest>';
  2. Replaces extends State<T> with extends SpmState<T> in the extends clause.
  3. Adds the SpmState import (package:spm/spm.dart) to the file. This is the only supported public import from SPM.

remove mode reverts all three: it deletes the instanceId getter, changes SpmState back to State, and removes the import.

How runtime metrics get selected

inject does not choose between performance and dataflow measurement. That happens at runtime, inside SpmState.setState, based on the Flutter build mode:

Build mode Runtime call Emitted event
--profile (kProfileMode) SpmProfiler.monitor(...) performance_metric
--debug (kDebugMode) SpmProfiler.monitorDataFlow(..., context: ...) dataflow-metric
release plain super.setState(fn) none (no instrumentation)

So the same injected code produces performance metrics under --profile and dataflow metrics under --debug. See Output Formats for both event schemas.

Notes

  • Always run --mode remove to restore the source once profiling is complete.
  • Injection is driven by the analyze manifest, so re-run analyze whenever the target source changes.

Related

  • run applies injection and launches the app (always in --profile) in one step.
  • Output Formats documents the runtime JSONL the instrumented app emits.

Clone this wiki locally