/ doc / devdocs / cli-conventions.md
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`).