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/ ) 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: 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
!/usr/bin/env dart
to the first line. Run chmod +x bin/my_script.dart to make it executable.
- !
- /
- usr
- /
- bin
- /
- env dart
- void
- main
- (
- )
- =
- >
- (
- 'Ready to run!'
- )
- ;
- Process Termination (
- exitCode
- )
- Properly handle process termination to allow for debugging and correct status
- reporting.
- DO:
- Use the
- exitCode
- setter to report failure.
- Allow
- main
- to complete naturally.
- Use standard exit codes (sysexits) for clarity (e.g.,
- 64
- for bad usage,
- 78
- for configuration errors).
- See
- package:io
- ExitCode
- class or FreeBSD sysexits man page.
- import
- 'dart:io'
- ;
- void
- main
- (
- )
- {
- if
- (
- someFailure
- )
- {
- exitCode
- =
- 64
- ;
- // DO!
- return
- ;
- }
- }
- AVOID:
- Calling
- exit(code)
- directly, as it terminates the VM immediately,
- preventing "pause on exit" debugging and
- finally
- blocks from running.
- Exception Handling
- 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
- )
- {
- (
- 'App crashed!'
- )
- ;
- (
- e
- )
- ;
- (
- stack
- )
- ;
- exitCode
- =
- 1
- ;
- // Explicitly fail
- }
- }
- 3. Recommended Packages
- 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
- 4. Interesting community packages
- 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
- 5. 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.