cli-conventions.md
1 # CLI Conventions 2 3 This document describes the conventions for implementing command-line interfaces (CLI) in PowerToys modules. 4 5 ## Library 6 7 Use the **System.CommandLine** library for CLI argument parsing. This is already defined in `Directory.Packages.props`: 8 9 ```xml 10 <PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" /> 11 ``` 12 13 Add the reference to your project: 14 15 ```xml 16 <PackageReference Include="System.CommandLine" /> 17 ``` 18 19 ## Option Naming and Definition 20 21 - Use `--kebab-case` for long form (e.g., `--shrink-only`). 22 - Use single `-x` for short form (e.g., `-s`, `-w`). 23 - Define aliases as static readonly arrays: `["--silent", "-s"]`. 24 - Create options using `Option<T>` with descriptive help text. 25 - Add validators for options that require range or format checking. 26 27 ## RootCommand Setup 28 29 - Create a `RootCommand` with a brief description. 30 - Add all options and arguments to the command. 31 32 ## Parsing 33 34 - Use `Parser(rootCommand).Parse(args)` to parse CLI arguments. 35 - Extract option values using `parseResult.GetValueForOption()`. 36 - Note: Use `Parser` directly; `RootCommand.Parse()` may not be available with the pinned System.CommandLine version. 37 38 ### Parse/Validation Errors 39 40 - On parse/validation errors, print error messages and usage, then exit with non-zero code. 41 42 ## Examples 43 44 Reference implementations: 45 - Awake: `src/modules/Awake/Awake/Program.cs` 46 - ImageResizer: `src/modules/imageresizer/ui/Cli/` 47 48 ## Help Output 49 50 - Provide a `PrintUsage()` method for custom help formatting if needed. 51 52 ## Best Practices 53 54 1. **Consistency**: Follow existing module patterns. 55 2. **Documentation**: Always provide help text for each option. 56 3. **Validation**: Validate input and provide clear error messages. 57 4. **Atomicity**: Make one logical change per PR; avoid drive-by refactors. 58 5. **Build/Test Discipline**: Build and test synchronously, one terminal per operation. 59 6. **Style**: Follow repo analyzers (`.editorconfig`, StyleCop) and formatting rules. 60 61 ## Logging Requirements 62 63 - Use `ManagedCommon.Logger` for consistent logging. 64 - Initialize logging early in `Main()`. 65 - Use dual output (console + log file) for errors and warnings to ensure visibility. 66 - Reference: `src/modules/imageresizer/ui/Cli/CliLogger.cs` 67 68 ## Error Handling 69 70 ### Exit Codes 71 72 - `0`: Success 73 - `1`: General error (parsing, validation, runtime) 74 - `2`: Invalid arguments (optional) 75 76 ### Exception Handling 77 78 - Always wrap `Main()` in try-catch for unhandled exceptions. 79 - Log exceptions before exiting with non-zero code. 80 - Display user-friendly error messages to stderr. 81 - Preserve detailed stack traces in log files only. 82 83 ## Testing Requirements 84 85 - Include tests for argument parsing, validation, and edge cases. 86 - Place CLI tests in module-specific test projects (e.g., `src/modules/[module]/tests/*CliTests.cs`). 87 88 ## Signing and Deployment 89 90 - CLI executables are signed automatically in CI/CD. 91 - **New CLI tools**: Add your executable and dll to `.pipelines/ESRPSigning_core.json` in the signing list. 92 - CLI executables are deployed alongside their parent module (e.g., `C:\Program Files\PowerToys\modules\[ModuleName]\`). 93 - Use self-contained deployment (import `Common.SelfContained.props`).