Best practices for creating high-quality, executable Dart CLI applications. Covers entrypoint structure, exit code handling, and recommended packages.
Use this skill when:
bin/).bin/)Keep the contents of your entrypoint file (e.g., bin/my_app.dart) minimal.
This improves testability by decoupling logic from the process runner.
DO:
// bin/my_app.dart
import 'package:my_app/src/entry_point.dart';
Future<void> main(List<String> arguments) async {
await runApp(arguments);
}
DON'T:
bin/my_app.dart.For CLI tools intended to be run directly on Linux and Mac, add a shebang and ensure the file is executable.
DO:
#!/usr/bin/env dart to the first line.chmod +x bin/my_script.dart to make it executable.#!/usr/bin/env dart
void main() => print('Ready to run!');
exitCode)Properly handle process termination to allow for debugging and correct status reporting.
DO:
exitCode setter to report failure.main to complete naturally.64 for bad usage,
78 for configuration errors).
package:io ExitCode class or FreeBSD sysexits man page.import 'dart:io';
void main() {
if (someFailure) {
exitCode = 64; // DO!
return;
}
}
AVOID:
exit(code) directly, as it terminates the VM immediately,
preventing "pause on exit" debugging and finally blocks from running.Uncaught exceptions automatically set a non-zero exit code, but you should handle expected errors gracefully.
Example:
Future<void> main(List<String> arguments) async {
try {
await runApp(arguments);
} catch (e, stack) {
print('App crashed!');
print(e);
print(stack);
exitCode = 1; // Explicitly fail
}
}
When writing CLI applications and tests, ensure compatibility with Windows:
/. Use package:path's
p.join or p.normalize to construct paths portably.chmod is not available on Windows. Use icacls on Windows or appropriate
mock libraries. Never skip tests on Windows simply because of permission
commands if a Windows equivalent exists.Use these community-standard packages owned by the Dart team to solve common CLI problems:
| Category | Recommended Package | Usage |
|---|---|---|
| Stack Traces | package:stack_trace | detailed, cleaner stack traces |
| Arg Parsing | package:args | standard flag/option parsing |
| Testing | package:test_process | integration testing for CLI apps |
| Testing | package:test_descriptor | file system fixtures for tests |
| Networking | package:http | standard HTTP client (remember user-agent!) |
| ANSI Output | package:io | handling ANSI colors and styles |
| Category | Recommended Package | Usage |
|---|---|---|
| Configuration | package:json_serializable | strongly typed config objects |
| CLI Generation | package:build_cli | generate arg parsers from classes |
| Version Info | package:build_version | automatic version injection |
| Configuration | package:checked_yaml | precise YAML parsing with line numbers |
.dart_tool/[pkg_name]/.