On this page21 sections
- Prerequisites
- Connection With Previous Lectures
- Learning Objectives
- 1. One Tool, Many Commands
- 2. dart create and Its Templates
- 3. Reading Arguments in main
- 4. Exit Codes with exit
- 5. Reading Input with stdin.readLineSync()
- 6. dart compile exe
- 7. Other Compile Targets
- 8. The Rest of the Toolbox
- 9. A Real-World Example
- Code Examples
- Common Beginner Mistakes
- Best Practices
- Mini Challenge
- Practice Questions
- Practice Answers
- Quick Revision
- Key Takeaways
- What's Next?
Lecture 113 — Dart CLI
| Category | 19 — Dart Developer Tools |
| Lecture | 113 of 140 |
| Estimated video length | 8 min |
| Target | Dart 3.12.2 |
| Level | Advanced |
So far our programs ran only through
dart runand always did the same thing. Thedarttool can also pass them input, report success or failure, and build them into standalone programs that run without Dart installed.
Contents
Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways
Every output and error message in this lecture is real. Each one was produced by running the command shown on Dart 3.12. Folder paths are replaced with
<project>, and the user name withuser.
Prerequisites
Students should already understand, from Lectures 001–112:
dart createanddart run(Lecture 002)- lists,
for-inloops,int.tryParseand null checks dart:ioandstdout.write(Lectures 101 and 106)- packages,
pubspec.yamlanddart pub(Lectures 103–105)
Connection With Previous Lectures
Every project from Lecture 002 on started with this line, and we never used its parameter:
void main(List<String> arguments) {Our marks program had Ali's marks written inside the code. To grade Sara, we edited the file.
And to share the program, the other person needed the Dart SDK. A real command-line tool
takes its input when it starts, tells the terminal whether it succeeded, and runs as a
program of its own. That is what the dart tool gives us.
Learning Objectives
By the end of this lecture you will be able to:
- Find any
dartcommand's options with--help - Create projects from the
console,cliandpackagetemplates - Read command-line arguments in
main(List<String> args) - Report success or failure with
exitandexitCode - Read a line the user types with
stdin.readLineSync() - Build a standalone executable with
dart compile exe - Recognize
aot-snapshotandjsas other compile targets - Name what
test,format,analyze,fix,pub,docandinfodo
1. One Tool, Many Commands
CLI means command-line interface: a program you use by typing commands. dart is
itself a CLI, and every task is a subcommand after it — dart create, dart run,
dart compile. Lecture 002 listed them with dart help.
Analogy — the
darttool is a toolbox with one handle. The word afterdartpicks the tool.
Every subcommand explains itself with --help:
dart compile --helpCompile 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.--help works one level deeper too: dart compile exe --help, dart create --help.
2. dart create and Its Templates
dart create copies a template. dart create --help lists them:
[cli] A command-line application with basic argument parsing.
[console] (default) A command-line application.
[package] A package containing shared Dart libraries.
[server-shelf] A server app using package:shelf.
[web] A web app that uses only core Dart libraries.Choose one with -t:
dart create -t package grade_utilsCreating grade_utils using template package...
.gitignore
analysis_options.yaml
CHANGELOG.md
pubspec.yaml
README.md
example/grade_utils_example.dart
lib/grade_utils.dart
lib/src/grade_utils_base.dart
test/grade_utils_test.dart
...| Template | Main code | Use it for |
|---|---|---|
console | bin/, lib/, test/ | a program to run (Lecture 002) |
cli | bin/ only, plus package:args | a tool with flags such as --help |
package | lib/src/, example/ | code other projects import (Lecture 103) |
The cli starter already answers --help:
dart create -t cli marks_cli
cd marks_cli
dart run bin/marks_cli.dart --helpUsage: dart marks_cli.dart <flags> [arguments]
-h, --help Print this usage information.
-v, --verbose Show additional command output.
--version Print the tool version.3. Reading Arguments in main
Words typed after the file name arrive in main's list, as strings, in order:
void main(List<String> args) {
print('You passed ${args.length} arguments: $args');
}dart run bin/marks.dart Ali 80 75
dart run bin/marks.dart "Sara Khan" 90
dart run bin/marks.dartYou passed 3 arguments: [Ali, 80, 75]
You passed 2 arguments: [Sara Khan, 90]
You passed 0 arguments: []Spaces separate arguments; quotes keep Sara Khan together. 80 arrives as the
string '80' — convert it with int.tryParse before doing maths. Any name works for
the parameter; args is the usual short one.
4. Exit Codes with exit
When a program ends, it hands the terminal a number called the exit code. 0 means
success; anything else means failure. Scripts and other tools read it to decide what to do
next. exit(code) from dart:io stops the program at once with that code:
import 'dart:io';
void main(List<String> args) {
if (args.isEmpty) {
print('Please give a name.');
exit(1);
}
print('Welcome, ${args.first}!');
}dart run welcome.dart
echo "exit: $?"
dart run welcome.dart Zayan
echo "exit: $?"Please give a name.
exit: 1
Welcome, Zayan!
exit: 0$? is the terminal's way of showing the last exit code (on Windows PowerShell, use
$LASTEXITCODE). When a program reaches the end of main normally, the code is 0.
To record a failure but keep running, set the top-level exitCode instead; the program
finishes and then reports it. Example 5 shows this.
5. Reading Input with stdin.readLineSync()
Arguments are given up front. To ask a question while running, read a line from stdin, the
keyboard input:
import 'dart:io';
void main() {
stdout.write('Your name: ');
var name = stdin.readLineSync() ?? '';
print('Hello, $name!');
}Your name: Sara
Hello, Sara!The program pauses until the user presses Enter; here the user typed Sara.
readLineSync() returns String? — null when there is no more input — so ?? '' gives a
safe default.
6. dart compile exe
dart run compiles your code every time it starts (JIT, Lecture 001). dart compile exe
compiles it ahead of time (AOT) into one file that runs without the Dart SDK:
dart compile exe bin/marks.dart -o marks
ls -lh marks
./marks Sara 90 85 88Generated: <project>/marks
-rwxr-xr-x 1 user staff 5.5M marks
Student: Sara
Total: 263
Average: 87.7-o names the output file (on Windows, use marks.exe). The binary is about 5.5 MB
because it carries the Dart runtime inside. On our machine, ./marks finished in 0.016
seconds; dart run bin/marks.dart took about 0.5 seconds. The executable is built for your
operating system — --target-os (see dart compile exe --help) builds for another.
7. Other Compile Targets
aot-snapshot builds the same machine code without the runtime, so the file is smaller
but needs dartaotruntime, which ships with the SDK:
dart compile aot-snapshot bin/marks.dart
dartaotruntime bin/marks.aot Sara 90 85 88Generated: <project>/bin/marks.aot
Student: Sara
Total: 263
Average: 87.7marks.aot is 1.0 MB. js turns Dart into JavaScript for browsers and Node.js:
void main() {
var celsius = 25.0;
var fahrenheit = celsius * 9 / 5 + 32;
print('$celsius °C = $fahrenheit °F');
}dart compile js web/hello.dart -o hello.js
node hello.jsCompiled 10,324,736 input bytes (5,274,524 characters source) to 12,106 characters JavaScript in 0.21 seconds
25 °C = 77 °Fdart run prints 25.0 °C = 77.0 °F; JavaScript has one number type and drops the .0.
Code that imports dart:io (files, stdin, exit) cannot run in a browser.
8. The Rest of the Toolbox
| Command | What it does | Studied in |
|---|---|---|
dart test | runs the tests in test/ | Lecture 118 |
dart format | rewrites code in the standard layout | Lecture 114 |
dart analyze | finds errors, warnings and style issues without running | Lecture 114 |
dart fix --apply | applies the fixes analyze suggests | Lecture 114 |
dart pub | add, get, upgrade, outdated, deps | Lectures 103–105 |
dart doc | builds HTML documentation from /// comments into doc/api | Lecture 125 |
dart info | prints your Dart version, OS and project facts for bug reports | — |
A quick preview of two of them on the console starter project:
dart test
dart analyze00:00 +0: loading test/marks_test.dart
00:00 +0: test/marks_test.dart: calculate
00:00 +1: All tests passed!
Analyzing marks...
No issues found!And dart info begins like this (trimmed):
#### General info
- Dart 3.12.1 (stable) (Tue May 26 01:02:21 2026 -0700) on "macos_arm64"
- on macos / Version 26.5.1 (Build 25F80)
- locale is en-PK
#### Project info
- sdk constraint: '^3.12.1'
- dependencies: path
- dev_dependencies: lints, test9. A Real-World Example
A marks tool that takes a name and marks, checks them, and uses exit codes: 1 for missing
input, 2 for a bad mark.
import 'dart:io';
void main(List<String> args) {
if (args.length < 2) {
stderr.writeln('Usage: marks <name> <mark> [mark...]');
exit(1);
}
var name = args.first;
var marks = <int>[];
for (var text in args.skip(1)) {
var mark = int.tryParse(text);
if (mark == null) {
stderr.writeln('Not a number: $text');
exit(2);
}
marks.add(mark);
}
var total = marks.reduce((a, b) => a + b);
var average = total / marks.length;
print('Student: $name');
print('Total: $total');
print('Average: ${average.toStringAsFixed(1)}');
}dart run bin/marks.dart Ali 80 75 85; echo "exit: $?"
dart run bin/marks.dart Ali; echo "exit: $?"
dart run bin/marks.dart Ali eighty; echo "exit: $?"Student: Ali
Total: 240
Average: 80.0
exit: 0
Usage: marks <name> <mark> [mark...]
exit: 1
Not a number: eighty
exit: 2stderr is the terminal's error channel: it shows on screen like stdout, but tools can
keep errors apart from normal output. Compiled with dart compile exe (section 6), the same
file becomes the ./marks program.
Code Examples
Run each with dart run <file> <arguments>.
Example 1 — Counting Arguments
void main(List<String> args) {
print('Count: ${args.length}');
print('Arguments: $args');
}dart run e1.dart Ali Sara Zayan
Count: 3
Arguments: [Ali, Sara, Zayan]Example 2 — A Default When Nothing Is Given
void main(List<String> args) {
var name = args.isEmpty ? 'friend' : args.first;
print('Hello, $name!');
}dart run e2.dart Sara, then dart run e2.dart
Hello, Sara!
Hello, friend!Example 3 — Looping Over Arguments
void main(List<String> args) {
for (var arg in args) {
print('- $arg');
}
}dart run e3.dart milk bread eggs
- milk
- bread
- eggsExample 4 — Failing with exit
import 'dart:io';
void main(List<String> args) {
if (args.isEmpty) {
print('Please give a name.');
exit(1);
}
print('Welcome, ${args.first}!');
}dart run e4.dart; echo "exit: $?"
Please give a name.
exit: 1Example 5 — Recording Failure with exitCode
import 'dart:io';
void main(List<String> args) {
for (var arg in args) {
if (int.tryParse(arg) == null) {
print('Skipping $arg');
exitCode = 1;
} else {
print('Mark: $arg');
}
}
}dart run e5.dart 80 abc 75; echo "exit: $?"
Mark: 80
Skipping abc
Mark: 75
exit: 1Unlike exit(1), setting exitCode lets the loop finish.
Example 6 — Asking for a Name
import 'dart:io';
void main() {
stdout.write('Your name: ');
var name = stdin.readLineSync() ?? '';
print('Hello, $name!');
}Your name: Sara
Hello, Sara!Example 7 — Student Marks
void main(List<String> args) {
var total = 0;
for (var arg in args) {
total += int.parse(arg);
}
print('Total: $total');
}dart run e7.dart 80 75 85
Total: 240Example 8 — Shopping Total
void main(List<String> args) {
var price = double.parse(args[0]);
var quantity = int.parse(args[1]);
print('Total: ${(price * quantity).toStringAsFixed(2)}');
}dart run e8.dart 250.5 3
Total: 751.50Example 9 — Bank Deposit
import 'dart:io';
void main() {
var balance = 1000.0;
stdout.write('Deposit amount: ');
var amount = double.tryParse(stdin.readLineSync() ?? '');
if (amount == null || amount <= 0) {
print('Invalid amount.');
exit(1);
}
balance += amount;
print('New balance: $balance');
}Typing 500, then running again and typing abc:
Deposit amount: 500
New balance: 1500.0
Deposit amount: abc
Invalid amount.Example 10 — A Compiled Temperature Converter
void main(List<String> args) {
for (var arg in args) {
var celsius = double.parse(arg);
var fahrenheit = celsius * 9 / 5 + 32;
print('$celsius °C = $fahrenheit °F');
}
}dart compile exe e10.dart -o temp
./temp 25 37 -40Generated: <project>/temp
25.0 °C = 77.0 °F
37.0 °C = 98.6 °F
-40.0 °C = -40.0 °FCommon Beginner Mistakes
1. Giving dart run arguments but no file
dart run Ali 80Could not find package `Ali` or file `Ali`Inside a project, a bare dart run takes its first word as the thing to run. Name the file
first: dart run bin/marks.dart Ali 80.
2. Using exit without importing dart:io
void main(List<String> args) {
if (args.isEmpty) {
// exit(1); // ✗ no import 'dart:io'
}
}Error: Method not found: 'exit'.3. Reading args[0] when no argument was given
Running Example 8 with no arguments crashes:
Unhandled exception:
RangeError (length): Invalid value: Valid value range is empty: 0Check args.length first, as the real-world example does.
4. Using int.parse on user input
int.parse('eighty') throws FormatException: Invalid radix-10 number. For input you don't
control, use int.tryParse and handle null.
5. Treating readLineSync() as String
import 'dart:io';
void main() {
// String name = stdin.readLineSync(); // ✗
}Error: A value of type 'String?' can't be assigned to a variable of type 'String'.Add ?? '' or check for null.
6. Sending a compiled program to another operating system
A file built on macOS will not run on Windows. Build on each system, or use --target-os.
Best Practices
- Check
args.lengthbefore reading arguments; print a usage line when it is wrong. - Exit with
0on success and a non-zero code on failure; write error messages tostderr. - Prefer
exitCodewhen the program should finish its work first. - Parse every argument and typed line with
tryParse. - Use
dart runwhile developing anddart compile exewhen you share the tool. - When unsure of an option, ask the command:
dart <command> --help.
Mini Challenge
Write cart.dart for Sara's shopping. It takes item prices as arguments and prints the
number of items and the total. With no arguments, it writes a usage line to stderr and exits
with code 1.
$ dart run cart.dart 120 80 50
Items: 3
Total: 250Try it yourself before opening the solution.
Show solution
import 'dart:io';
void main(List<String> args) {
if (args.isEmpty) {
stderr.writeln('Usage: cart <price> [price...]');
exit(1);
}
var total = 0;
for (var arg in args) {
total += int.parse(arg);
}
print('Items: ${args.length}');
print('Total: $total');
}$ dart run cart.dart 120 80 50
Items: 3
Total: 250
$ dart run cart.dart; echo "exit: $?"
Usage: cart <price> [price...]
exit: 1Practice Questions
Beginner
- Which command creates a package project called
grade_utils? - Write a program that prints
You gave N arguments.Run it witha b c d. - Which exit code means success? What does
$?show?
Application
- Write a program that prints its arguments in reverse order, separated by spaces. Run it
with
Zayan Sara Ali. - Write a program that adds exactly two whole numbers given as arguments. With any other
count, print
Give exactly two numbers.and exit with1. - Which command builds
bin/grades.dartinto a standalone program namedgrades? - Inside a project,
dart run Sara 90fails. Why, and what is the fix? - Write a program that asks
Celsius:, reads a number and prints the Fahrenheit value. If the input is not a number, printNot a number.and exit with1.
Challenge
- Write a grade tool: one mark as an argument prints
Mark 72: grade B(A ≥ 80, B ≥ 60, C ≥ 40, else F). A missing, non-numeric or out-of-range mark writesGive a mark from 0 to 100.tostderrand exits with2. - Write a program that prints the highest mark from its arguments. Skip anything that is
not a number, but finish with exit code
1if anything was skipped.
Practice Answers
Question 1 — Solution
dart create -t package grade_utils
Question 2 — Solution
void main(List<String> args) {
print('You gave ${args.length} arguments.');
}You gave 4 arguments.Question 3 — Solution
0 means success. echo $? shows the exit code of the last command.
Question 4 — Solution
void main(List<String> args) {
print(args.reversed.join(' '));
}Ali Sara ZayanQuestion 5 — Solution
import 'dart:io';
void main(List<String> args) {
if (args.length != 2) {
print('Give exactly two numbers.');
exit(1);
}
var sum = int.parse(args[0]) + int.parse(args[1]);
print('Sum: $sum');
}7 5 prints Sum: 12 (exit 0); 7 alone prints Give exactly two numbers. (exit 1).
Question 6 — Solution
dart compile exe bin/grades.dart -o grades
Question 7 — Solution
dart run treats Sara as the package or file to run and reports
Could not find package `Sara` or file `Sara` . Name the file first:
dart run bin/grades.dart Sara 90.
Question 8 — Solution
import 'dart:io';
void main() {
stdout.write('Celsius: ');
var celsius = double.tryParse(stdin.readLineSync() ?? '');
if (celsius == null) {
print('Not a number.');
exit(1);
}
print('Fahrenheit: ${celsius * 9 / 5 + 32}');
}Celsius: 30
Fahrenheit: 86.0Question 9 — Solution
import 'dart:io';
void main(List<String> args) {
var mark = args.isEmpty ? null : int.tryParse(args.first);
if (mark == null || mark < 0 || mark > 100) {
stderr.writeln('Give a mark from 0 to 100.');
exit(2);
}
var grade = switch (mark) {
>= 80 => 'A',
>= 60 => 'B',
>= 40 => 'C',
_ => 'F',
};
print('Mark $mark: grade $grade');
}$ dart run grade.dart 72; echo "exit: $?"
Mark 72: grade B
exit: 0
$ dart run grade.dart 120; echo "exit: $?"
Give a mark from 0 to 100.
exit: 2Question 10 — Solution
import 'dart:io';
void main(List<String> args) {
var marks = <int>[];
for (var arg in args) {
var mark = int.tryParse(arg);
if (mark == null) {
exitCode = 1;
} else {
marks.add(mark);
}
}
if (marks.isEmpty) {
print('No marks.');
} else {
var highest = marks.reduce((a, b) => a > b ? a : b);
print('Highest: $highest');
}
}$ dart run highest.dart 80 x 95 70; echo "exit: $?"
Highest: 95
exit: 1Quick Revision
- How do you see the options of
dart compile exe? - Which three templates did we use, and what is each for?
- What type are command-line arguments, and how do you get an
intfrom one? - What is the difference between
exit(1)andexitCode = 1? - Why does
readLineSync()returnString?? - Why is a compiled executable about 5.5 MB, and an AOT snapshot much smaller?
- Which commands will Lecture 114 study in depth?
Key Takeaways
dartis a CLI; every task is a subcommand, and--helpexplains each one.dart create -t console|cli|packagepicks a starter template.- Arguments arrive in
main(List<String> args)as strings — parse withtryParse. exit(code)stops now;exitCodereports a code whenmainends.0is success.stdin.readLineSync()reads a typed line and may returnnull.dart compile exebuilds a standalone AOT program for your OS;aot-snapshotneedsdartaotruntime;jstargets JavaScript.test,format,analyze,fix,pub,docandinfocomplete the toolbox.
What's Next?
Lecture 114 — Dart Formatter & Analyzer. We met dart format, dart analyze and
dart fix only in passing. Next we will use them properly: how the formatter decides a
layout, how to read the analyzer's errors, warnings and infos, and how dart fix repairs
code for you.