Loading...
Loading...
Entrypoint structure, exit codes, cross-platform scripts. Use when building command line utilities, scripts, or applications.
npx skill4agent add flutter/agent-plugins dart-build-cli-appdart create -t cli <project_name>main()bin/lib/src/lib/<project_name>.dartdart format . --set-exit-if-changedargsArgParseraddFlagaddOptiongitCommandRunnerCommandCommandRunner.argParserCommand.argParserUsageExceptioniostack_traceioExitCodeExitCode.success.codeExitCode.usage.codesharedStdInioChain.capture()stack_traceTrace.terseChain.tersestderrexit(1)UsageException[!IMPORTANT] All new commands and significant features must be covered by automated tests. Manual verification is not sufficient for testing logic. However, manual verification of help text and user experience (UX) is still required to ensure the interface is intuitive and correct.
test_processtest_descriptortest_descriptord.dird.fileawait d.Descriptor.create()TestProcess.start('dart', ['run', 'bin/cli.dart', ...args])StreamQueueemitsThroughemitsawait process.shouldExit(0)await d.Descriptor.validate()dart run bin/cli.dartdart build clibuild/cli/_/bundle/dart compile exe bin/cli.dart -o <output_path>dart compile aot-snapshot bin/cli.dart.aotdartaotruntime--target-os--target-archdart compile exedart compile aot-snapshot--target-os=linux--target-arch=arm64--target-arch=x64--target-arch=arm--target-arch=riscv64dart compile exe --target-os=linux --target-arch=arm64 bin/cli.dartCommandlib/src/commands/namedescriptionargParser.addFlag()argParser.addOption()run()CommandRunnerbin/cli.dartaddCommand()test/test_processdart run bin/cli.dart help <command_name>dart compile exe./bin/cli <command>dart format . --set-exit-if-changeddart analyzedart testdart compile exe bin/cli.dart -o build/cli-hostdart compile exe --target-os=linux --target-arch=x64 bin/cli.dart -o build/cli-linux-x64import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:stack_trace/stack_trace.dart';
class CommitCommand extends Command {
final String name = 'commit';
final String description = 'Record changes to the repository.';
CommitCommand() {
argParser.addFlag('all', abbr: 'a', help: 'Commit all changed files.');
}
Future<void> run() async {
final commitAll = argResults?['all'] as bool? ?? false;
print('Committing... (All: $commitAll)');
}
}
void main(List<String> args) {
Chain.capture(() async {
final runner = CommandRunner('dgit', 'Distributed version control.')
..addCommand(CommitCommand());
await runner.run(args);
}, onError: (error, chain) {
if (error is UsageException) {
stderr.writeln(error.message);
stderr.writeln(error.usage);
exit(64); // ExitCode.usage.code
} else {
stderr.writeln('Fatal error: $error');
stderr.writeln(chain.terse);
exit(1);
}
});
}import 'package:test/test.dart';
import 'package:test_process/test_process.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;
void main() {
test('CLI formats output correctly and modifies filesystem', () async {
// 1. Setup mock filesystem
await d.dir('project', [
d.file('config.json', '{"key": "value"}')
]).create();
// 2. Spawn the CLI process
final process = await TestProcess.start(
'dart',
['run', 'bin/cli.dart', 'process', '--path', '${d.sandbox}/project']
);
// 3. Validate stdout stream
await expectLater(process.stdout, emitsThrough('Processing complete.'));
// 4. Validate exit code
await process.shouldExit(0);
// 5. Validate filesystem mutations
await d.dir('project', [
d.file('config.json', '{"key": "value"}'),
d.file('output.log', 'Success')
]).validate();
});
}