dart-cli-app-best-practices
Original:🇺🇸 English
Translated
Best practices for creating high-quality, executable Dart CLI applications. Covers entrypoint structure, exit code handling, and recommended packages.
7installs
Sourcekevmoo/dash_skills
Added on
NPX Install
npx skill4agent add kevmoo/dash_skills dart-cli-app-best-practicesTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Dart CLI Application Best Practices
1. When to use this skill
Use this skill when:
- Creating a new Dart CLI application.
- Refactoring an existing CLI entrypoint ().
bin/ - Reviewing CLI code for quality and standards.
- Setting up executable scripts for Linux/Mac.
2. Best Practices
Entrypoint Structure (bin/
)
bin/Keep the contents of your entrypoint file (e.g., ) minimal. This improves testability by decoupling logic from the process runner.
bin/my_app.dartDO:
dart
// bin/my_app.dart
import 'package:my_app/src/entry_point.dart';
Future<void> main(List<String> arguments) async {
await runApp(arguments);
}DON'T:
- Put complex logic directly in .
bin/my_app.dart - Define classes or heavy functions in the entrypoint.
Executable Scripts
For CLI tools intended to be run directly on Linux and Mac, add a shebang and ensure the file is executable.
DO:
- Add to the first line.
#!/usr/bin/env dart - Run to make it executable.
chmod +x bin/my_script.dart
dart
#!/usr/bin/env dart
void main() => print('Ready to run!');Process Termination (exitCode
)
exitCodeProperly handle process termination to allow for debugging and correct status reporting.
DO:
- Use the setter to report failure.
exitCode - Allow to complete naturally.
main - Use standard exit codes (sysexits) for clarity (e.g., for bad usage,
64for configuration errors).78- See
package:ioclass or FreeBSD sysexits man page.ExitCode
- See
dart
import 'dart:io';
void main() {
if (someFailure) {
exitCode = 64; // DO!
return;
}
}AVOID:
- Calling directly, as it terminates the VM immediately, preventing "pause on exit" debugging and
exit(code)blocks from running.finally
Exception Handling
Uncaught exceptions automatically set a non-zero exit code, but you should handle expected errors gracefully.
Example:
dart
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
}
}3. Recommended Packages
Use these community-standard packages to solve common CLI problems:
| Category | Recommended Package | Usage |
|---|---|---|
| Stack Traces | | detailed, cleaner stack traces |
| Version Info | | automatic version injection |
| Arg Parsing | | standard flag/option parsing |
| CLI Generation | | generate arg parsers from classes |
| Configuration | | precise YAML parsing with line numbers |
| Configuration | | strongly typed config objects |
| Testing | | integration testing for CLI apps |
| Testing | | file system fixtures for tests |
| Networking | | standard HTTP client (remember user-agent!) |
4. Conventions
- File Caching: Write cached files to .
.dart_tool/[pkg_name]/ - User-Agent: Always set a User-Agent header in HTTP requests, including version info.
- ANSI Output: Use for handling ANSI colors and styles.
package:io