Dart (3.13) Module 1 – Getting started: the SDK, a first program and the tools
The dart command: analyze, format, test, compile
Run the dart command's check loop: dart analyze and dart fix, dart format, dart test and dart compile exe, with the exit status each returns.
What you will learn
- Use dart analyze, dart format and dart fix in an edit-check loop
- Run tests with dart test and read which test failed and why
- Build a native executable with dart compile exe and run it
- Find the right subcommand and flag with dart help and the official docs
Before you start
What you’ll learn · Before you start
What you will learn
- Use dart analyze, dart format and dart fix in an edit-check loop
- Run tests with dart test and read which test failed and why
- Build a native executable with dart compile exe and run it
- Find the right subcommand and flag with dart help and the official docs
Before you start
On this page
A five-line file typed in a hurry gave dart analyze 5 problems to report, and two dart fix commands repaired all
five without a single edit by hand. That is the dart command at work: one program that checks, repairs, lays out, tests
and builds your code, and ends every step with a status that a script can act on.
You will find any command and flag from dart help, run the loop of dart analyze, dart fix and dart format on a
messy file, run tests and read a failure, and build a native executable that runs on its own.
One dart command holds every tool, and help lists them
Everything in the SDK is a subcommand of dart. dart --help lists them in four groups, and dart help followed by
a command explains that command:
from session import run
# What the dart command offers, and the help of one of its commands.
run(
"""
dart --help
dart help compile
"""
) Output
$ dart --help
A command-line utility for Dart development.
Usage: dart <command|dart-file> [arguments]
Global options:
-v, --verbose Show additional command output.
--version Print the Dart SDK version.
--enable-analytics Enable analytics.
--disable-analytics Disable analytics.
--suppress-analytics Disallow analytics for this `dart *` run without changing the analytics configuration.
-h, --help Print this usage information.
Available commands:
Global
install Install or upgrade a Dart CLI tool for global use.
installed List globally installed Dart CLI tools.
uninstall Remove a globally installed Dart CLI tool.
Project
build Build a Dart application including code assets.
compile Compile Dart to various formats.
create Create a new Dart project.
pub Work with packages.
run Run a Dart program from a file or a local or remote package.
test Run tests for a project.
Source code
analyze Analyze Dart code in a directory.
doc Generate API documentation for Dart projects.
fix Apply automated fixes to Dart source code.
format Idiomatically format Dart source code.
Tools
devtools Open DevTools (optionally connecting to an existing application).
info Show diagnostic information about the installed tooling.
Run "dart help <command>" for more information about a command.
See https://dart.dev/tools/dart-tool for detailed documentation.
$ dart help compile
Compile Dart to various formats.
Usage: dart compile <subcommand> [arguments]
-h, --help Print this usage information.
Available subcommands:
js Compile Dart to JavaScript.
jit-snapshot Compile Dart to a JIT snapshot.
kernel Compile Dart to a kernel snapshot.
exe Compile Dart to a self-contained executable.
aot-snapshot Compile Dart to an AOT snapshot.
wasm Compile Dart to a WebAssembly/WasmGC module.
Run "dart help" to see global options.
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 help_session.py
Here are the four groups of that list, with what each one is for:
| Group | Commands | For |
|---|---|---|
| Global | install, installed, uninstall |
Command-line tools installed for use outside any one project, added in Dart 3.10 |
| Project | build, compile, create, pub, run, test |
Making, running and building a project |
| Source code | analyze, doc, fix, format |
Checking and tidying the code itself |
| Tools | devtools, info |
Debugging and performance tools, and the report for bug reports |
dart help compile went one level down and listed the six formats that dart compile produces, among them JavaScript,
WebAssembly and the self-contained executable that this lesson builds at the end. The last line of dart --help points
to the tool’s page on dart.dev, where each command has a page of its own. One more form is not in the list:
dart file.dart runs a file directly, and the tool page says to prefer dart run. Since Dart 3.10 the dart you type
is itself a compiled tool, and the virtual machine that runs your programs is a separate executable named dartvm,
which dart run and dart test start for you.
Help for one flag
Every command takes --help: dart format --help lists the formatter’s flags, and dart help pub outdated explains a
pub command. The tool’s help always matches the SDK you have, which a web page may not.
dart analyze finds problems, and dart fix repairs many
dart analyze runs static analysis: Checking source code for errors and likely mistakes without running it; dart analyze runs the same analysis an editor with Dart support runs as you type., the same checks an editor with Dart support
runs as you type, over every Dart file under the current folder. The console template turns on the recommended
lint rule: A named check of the analyzer for style or likely bugs, such as unused_import; lint rules are turned on in analysis_options.yaml, often through package:lints. of package:lints through its
analysis_options.yaml: The file in a package's root that configures dart analyze and the formatter: which lint rules apply, which files are left out, and settings such as the page width.. Here is the messy file, five lines as they were typed:
import 'dart:io';
import 'dart:math';
import 'package:hello_cli/hello_cli.dart';
label(String name) { return "Total for "+name; }
int total(List<int> amounts){var sum=0;for(var a in amounts){sum+=a;}return sum;} The session copies it into a new project, analyzes and fixes it step by step, and ends with a real error for comparison:
from session import files, run
# A file typed in a hurry: what dart analyze reports, what dart fix repairs, and an error for comparison.
files("loop/report.dart=report.dart", "loop/broken.dart=broken.dart")
run(
"""
dart create --no-pub -t console hello_cli > /dev/null
cd hello_cli
dart pub get --offline > /dev/null
cp ../report.dart lib/
!dart analyze
dart fix --apply --code=unused_import
dart analyze
!dart analyze --fatal-infos
dart fix --dry-run
dart fix --apply
dart analyze --fatal-infos
!dart analyze ../broken.dart
""",
pub=True,
) Output
$ dart create --no-pub -t console hello_cli > /dev/null $ cd hello_cli $ dart pub get --offline > /dev/null $ cp ../report.dart lib/ $ dart analyze Analyzing hello_cli... warning - lib/report.dart:1:8 - Unused import: 'dart:io'. Try removing the import directive. - unused_import warning - lib/report.dart:2:8 - Unused import: 'dart:math'. Try removing the import directive. - unused_import warning - lib/report.dart:3:8 - Unused import: 'package:hello_cli/hello_cli.dart'. Try removing the import directive. - unused_import info - lib/report.dart:4:3 - Missing type annotation. Try adding a type annotation. - strict_top_level_inference info - lib/report.dart:4:31 - Use interpolation to compose strings and values. Try using string interpolation to build the composite string. - prefer_interpolation_to_compose_strings 5 issues found. [exit status 2] $ dart fix --apply --code=unused_import Computing fixes in hello_cli... Applying fixes... lib/report.dart unused_import - 3 fixes 3 fixes made in 1 file. $ dart analyze Analyzing hello_cli... info - lib/report.dart:1:3 - Missing type annotation. Try adding a type annotation. - strict_top_level_inference info - lib/report.dart:1:31 - Use interpolation to compose strings and values. Try using string interpolation to build the composite string. - prefer_interpolation_to_compose_strings 2 issues found. $ dart analyze --fatal-infos Analyzing hello_cli... info - lib/report.dart:1:3 - Missing type annotation. Try adding a type annotation. - strict_top_level_inference info - lib/report.dart:1:31 - Use interpolation to compose strings and values. Try using string interpolation to build the composite string. - prefer_interpolation_to_compose_strings 2 issues found. [exit status 1] $ dart fix --dry-run Computing fixes in hello_cli (dry run)... 2 proposed fixes in 1 file. lib/report.dart prefer_interpolation_to_compose_strings - 1 fix strict_top_level_inference - 1 fix To fix an individual diagnostic, run one of: dart fix --apply --code=prefer_interpolation_to_compose_strings dart fix --apply --code=strict_top_level_inference To fix all diagnostics, run: dart fix --apply $ dart fix --apply Computing fixes in hello_cli... Applying fixes... lib/report.dart prefer_interpolation_to_compose_strings - 1 fix strict_top_level_inference - 1 fix 2 fixes made in 1 file. $ dart analyze --fatal-infos Analyzing hello_cli... No issues found! $ dart analyze ../broken.dart Analyzing broken.dart... error - broken.dart:1:13 - A value of type 'String' can't be assigned to a variable of type 'int'. Try changing the type of the variable, or casting the right-hand type to 'int'. - invalid_assignment 1 issue found. [exit status 3]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 analyze_session.py
Each line of the report gives the severity, the place, the message and the name of the rule. The severity decides the exit status, which is what a CI job reads:
| What the report held | Status in the session |
|---|---|
| Three warnings (unused imports) and two infos | 2 |
| Two infos only | 0, so a script sees success |
Two infos, with --fatal-infos |
1 |
| Nothing | 0, “No issues found!” |
An error (a String assigned to an int) |
3 |
dart fix --apply --code=unused_import repaired one rule’s problems; dart fix --dry-run then listed what was left
without changing anything, and dart fix --apply repaired the rest: an added return type and string interpolation in
place of +. dart fix applies fixes only for the diagnostics the analyzer reports, so a lint rule that is not turned
on is never fixed, and the dart fix page notes that not every diagnostic has a fix: the type error at the end is one
without, because only you know which value was meant.
Applying fixes without a preview
dart fix --apply changes every file of the project that has a fix, not only the file you have open. Run
dart fix --dry-run first, as the session did, to see which files and rules it will touch, and add --code when
you want one rule’s changes at a time.
Checkpoint
Check: Finding commands and flags · dart analyze and dart fix
dart format gives every file the same layout
Layout is not a choice in a Dart project: dart format decides it. The session formats the same messy file. First
--output=show prints the result without saving it, then the check that CI runs fails, then the files are rewritten
and the check passes:
from session import files, run
# dart format on the same file: show the result, check it the way CI does, then rewrite it.
files("loop/report.dart=report.dart")
run(
"""
dart create --no-pub -t console hello_cli > /dev/null
cd hello_cli
dart pub get --offline > /dev/null
cp ../report.dart lib/
dart format --output=show lib/report.dart
!dart format --output=none --set-exit-if-changed .
dart format .
dart format --output=none --set-exit-if-changed .
""",
pub=True,
) Output
$ dart create --no-pub -t console hello_cli > /dev/null
$ cd hello_cli
$ dart pub get --offline > /dev/null
$ cp ../report.dart lib/
$ dart format --output=show lib/report.dart
import 'dart:io';
import 'dart:math';
import 'package:hello_cli/hello_cli.dart';
label(String name) {
return "Total for " + name;
}
int total(List<int> amounts) {
var sum = 0;
for (var a in amounts) {
sum += a;
}
return sum;
}
Formatted 1 file (1 changed) in … seconds.
$ dart format --output=none --set-exit-if-changed .
Changed lib/report.dart
Formatted 4 files (1 changed) in … seconds.
[exit status 1]
$ dart format .
Formatted lib/report.dart
Formatted 4 files (1 changed) in … seconds.
$ dart format --output=none --set-exit-if-changed .
Formatted 4 files (0 changed) in … seconds.
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 format_session.py
The session used the formatter in three ways, and the table sets them side by side:
| Command | What it does | In the session |
|---|---|---|
dart format --output=show <file> |
Prints the formatted file, changes nothing | the file, laid out |
dart format --output=none --set-exit-if-changed . |
Lists the files it would change; status 1 if any | Changed lib/report.dart, status 1 |
dart format . |
Rewrites the files | Formatted lib/report.dart |
The formatter removed the stray spaces and put each statement on its own line; no line was longer than 80 characters,
the width at which it wraps by default. Two details come from the language version of the file. Since language 3.7 it uses the “tall” style, adding and removing trailing
commas in argument lists itself. And at language 3.13 it separates imports into sections: the blank line between
import 'dart:math'; and the package: import in the output. It reads the language version from the package
configuration that dart pub get writes, so run dart pub get before formatting.
The three tools make a loop that every change goes through before it ships. Step through it, with the status each step ends with:
The drawing shows the whole scene; its 6 steps are listed below.
Every step as text
- Edit. You change the code. Nothing checks it yet, though an editor with the Dart plugin runs the same analysis as you type.
- Format. dart format . rewrites every Dart file in the project to the one standard layout, so the next diff shows only what you meant to change.
- Analyze. dart analyze reports errors, warnings and infos. It ends with status 3 for an error and 2 for a warning, and with 0 for infos unless you pass --fatal-infos, which makes them 1.
- Back to the code. A problem sends you back to edit. dart fix --apply repairs the problems that have an automatic fix, such as an unused import; the rest you fix by hand.
- Test. dart test runs the files in test/ whose names end in _test.dart. One failing test makes it end with status 1 and name the test.
- Ship. When everything passes, dart compile exe turns the program into one native file for this system, which runs without the SDK.
Key idea
The layout of a Dart file follows from its code and its language version alone, so formatting is a command you run, never a style you choose.
dart test runs the tests and says which failed
dart test runs the tests in the test/ folder of the current project, in files whose names end in _test.dart,
with package:test. This session adds a function with a bug and two tests of it, runs them, fixes the function and
runs them again:
from session import files, run
# Two tests of total(): run them against a version with a bug, then against the fixed version.
files("tests/total.dart=total.dart", "tests/fixed/total.dart=fixed/total.dart", "tests/total_test.dart=total_test.dart")
run(
"""
dart create --no-pub -t console hello_cli > /dev/null
cd hello_cli
dart pub get --offline > /dev/null
cp ../total.dart lib/
cp ../total_test.dart test/
!dart test test/total_test.dart
cp ../fixed/total.dart lib/
dart test test/total_test.dart
dart test
""",
pub=True,
) Output
$ dart create --no-pub -t console hello_cli > /dev/null
$ cd hello_cli
$ dart pub get --offline > /dev/null
$ cp ../total.dart lib/
$ cp ../total_test.dart test/
$ dart test test/total_test.dart
--:-- +0: loading test/total_test.dart
--:-- +0: adds every amount
--:-- +0 -1: adds every amount [E]
Expected: <250>
Actual: <130>
package:matcher expect
test/total_test.dart 6:5 main.<fn>
--:-- +0 -1: an empty bill totals zero
--:-- +1 -1: Some tests failed.
Failing tests:
test/total_test.dart: adds every amount
Consider enabling the flag chain-stack-traces to receive more detailed exceptions.
For example, 'dart test --chain-stack-traces'.
[exit status 1]
$ cp ../fixed/total.dart lib/
$ dart test test/total_test.dart
--:-- +0: loading test/total_test.dart
--:-- +0: adds every amount
--:-- +1: an empty bill totals zero
--:-- +2: All tests passed!
$ dart test
--:-- +0: loading test/hello_cli_test.dart
--:-- +0: test/hello_cli_test.dart: calculate
--:-- +1: test/total_test.dart: adds every amount
--:-- +2: test/total_test.dart: an empty bill totals zero
--:-- +3: All tests passed!
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 test_session.py
Each line of the report starts with a clock, which the session shows as --:-- because it differs on every run, then
+ with the number of tests passed so far and - with the number failed. The failure names the test, what it expected
and what it got, Expected: <250> and Actual: <130>, and the line of the test that failed, test/total_test.dart 6:5.
130 is 80 + 50: the loop started at index 1 and skipped the first amount. After the fix both tests passed, and
dart test with no path ran every test file of the project, three tests in all. To run some of them only, add a path,
or --name with part of a test’s name.
Checkpoint
Check: dart format · Running and reading tests
dart compile exe builds one file that runs without the SDK
dart run compiles your program on the virtual machine every time it starts. dart compile exe compiles it once,
ahead of time, into a self-contained executable: One file of machine code with a small Dart runtime inside, made by dart compile exe; it runs without the Dart SDK, on the system and processor it was built for.: machine code plus a small
Dart runtime for garbage collection and type checks. The session first builds into a folder that does not exist
yet, then makes the folder, builds the template’s program again, measures the file and runs it:
from session import run
# The template's program as one native executable: a build into a folder that does not exist fails; then make the
# folder, build it, measure it and run it without dart.
run(
"""
dart create --no-pub -t console hello_cli > /dev/null
cd hello_cli
dart pub get --offline > /dev/null
!dart compile exe bin/hello_cli.dart -o build/hello_cli
mkdir -p build
dart compile exe bin/hello_cli.dart -o build/hello_cli
wc -c < build/hello_cli
file build/hello_cli
./build/hello_cli
""",
pub=True,
) Output
$ dart create --no-pub -t console hello_cli > /dev/null $ cd hello_cli $ dart pub get --offline > /dev/null $ dart compile exe bin/hello_cli.dart -o build/hello_cli Error: AOT compilation failed PathNotFoundException: Cannot open file, path = '~/demo/hello_cli/build/hello_cli' (OS Error: No such file or directory, errno = 2) [exit status 254] $ mkdir -p build $ dart compile exe bin/hello_cli.dart -o build/hello_cli Generated: ~/demo/hello_cli/build/hello_cli $ wc -c < build/hello_cli 5716304 $ file build/hello_cli build/hello_cli: Mach-O 64-bit executable arm64 $ ./build/hello_cli Hello world: 42!
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 compile_session.py
The file is 5,716,304 bytes, about 5.7 MB, for a program that prints one line: nearly all of it is the runtime and the
core libraries, which is why an empty program is not much smaller. file reports it as a 64-bit Mach-O executable for
arm64, a macOS program for Apple silicon, so it runs on those Macs and nowhere else. The first build ended with status 254
and a PathNotFoundException, because build/ did not exist yet: dart compile exe writes into the folder you name
but does not create it, so make the folder first. To debug or profile instead of shipping, run the program with
dart run --observe and open Dart DevTools.
Checkpoint
Check: Native executables
Practise: clean up a messy project
Make a project with dart create -t console tidy_me, then:
- Copy loop/report.dart, the messy file shown above, into
lib/. - Run
dart analyze, note its status withecho $?, and repair it withdart fix --apply. - Run
dart format --output=none --set-exit-if-changed .and note its status, then rundart format .and the check once more: now it ends with status 0. - Add a test of one function to
test/, make it fail once on purpose, then make it pass. - Build the program with
dart compile exeand run the file it writes.
The project is clean when dart analyze finds no issues, dart format has nothing left to change and every test
passes. Then check what stayed with you:
Practice that adapts to you
Practise this lesson
10 questions about 5 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Warm-up (fresher): What do dart analyze, dart fix and dart format each do?
dart analyze checks the code without running it: it reports errors, warnings and infos from the language and from the lint rules turned on in analysis_options.yaml, and ends with a non-zero status for errors and warnings, or for infos too with –fatal-infos. dart fix applies the automatic fixes that the analyzer’s diagnostics offer, such as removing an unused import; –dry-run lists them first, and –code limits it to one rule. dart format rewrites the layout of the code into the one standard style, without changing what it does; with –output=none –set-exit-if-changed it changes nothing and ends with status 1 when a file is not formatted.
The module’s bank holds two longer questions that build on this lesson:
Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.
-
Fresher to mid
A Dart command-line tool must run on 40 Linux servers, started by a scheduler every minute. Either install the Dart SDK on every server and use dart run, or build the tool with dart compile exe on a Mac laptop and copy the file. Which do you choose, and what do you check before you ship?
Flashcards · 7 cards
Recall it, then check
Say the answer to yourself before you look: recalling it is what makes it stick.
-
How do you find a dart subcommand and its flags for the SDK you have?
dart --help lists every tool as a subcommand, in four groups; dart help <command> explains one, and every command takes --help. The tool's help always matches the installed SDK, which a web page may not.
-
Which exit statuses does dart analyze end with?
3 when it reports errors, 2 for warnings and 0 when only infos are left. With --fatal-infos, infos fail the run with 1.
-
What should you run before dart fix --apply, and why?
dart fix --dry-run. --apply changes every file of the project that has a fix, not only the one you have open; the dry run lists the files and rules first, and --code limits the fixes to one rule.
-
How do you make dart format a check that changes nothing?
Run dart format --output=none --set-exit-if-changed: it rewrites nothing and ends with status 1 when a file is not formatted.
-
What decides the layout dart format gives a file?
The code, its language version and the formatter settings in analysis_options.yaml, such as the page width, 80 characters by default. There is one standard style, so formatting is a command you run, never a style you choose.
-
Which files does dart test run, and what does it report?
The _test.dart files in test/. It counts passes and failures and names each failed test with what it expected and what it got.
-
What does dart compile exe build?
One self-contained executable, 5,716,304 bytes for the console template's program, that runs without the SDK on the operating system and processor it was built for.
Key takeaways
- Every SDK tool is a subcommand of
dart, in four groups thatdart --helplists, anddart help <command>explains each one for the SDK you have. dart analyzereports errors, warnings and infos and ends with 3, 2 or 0 for them,--fatal-infosmakes infos fail with 1, anddart fixapplies the fixes those diagnostics offer, one rule at a time with--code.dart formatgives every file the standard layout of its language version, and--output=none --set-exit-if-changedturns it into a check that fails with 1 when a file is not formatted.dart testruns the_test.dartfiles intest/, counts passes and failures, and names each failed test with what it expected and what it got.dart compile exebuilds one self-contained executable, 5,716,304 bytes for the template’s program, that runs on its own on the system it was built for.
Terms in this lesson
- analysis_options.yaml
- The file in a package's root that configures dart analyze and the formatter: which lint rules apply, which files are left out, and settings such as the page width.
- lint rule
- A named check of the analyzer for style or likely bugs, such as unused_import; lint rules are turned on in analysis_options.yaml, often through package:lints.
- self-contained executable
- One file of machine code with a small Dart runtime inside, made by dart compile exe; it runs without the Dart SDK, on the system and processor it was built for.
- static analysis
- Checking source code for errors and likely mistakes without running it; dart analyze runs the same analysis an editor with Dart support runs as you type.
References
- dart: The Dart command-line tool (The Dart project (Google))
- dart analyze (The Dart project (Google))
- dart fix (The Dart project (Google))
- dart format (The Dart project (Google))
- dart test (The Dart project (Google))
- test: the package:test test runner (The Dart project (Google))
- dart compile (The Dart project (Google))
- dart run (The Dart project (Google))
- Dart SDK changelog (The Dart project (Google))
Report a problem with this lesson
Kept only in this browser. Your Learn progress