Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Stdin/stdout/stderr patterns and machine-readable output
Testing CLI applications via in-process invocation
Out of scope
System.CommandLine API details (RootCommand, Option, SetAction) -- see [skill:dotnet-system-commandline]
Native AOT compilation and publish pipeline -- see [skill:dotnet-native-aot]
CLI distribution and packaging -- see [skill:dotnet-cli-distribution] and [skill:dotnet-cli-packaging]
General CI/CD patterns -- see [skill:dotnet-gha-patterns] and [skill:dotnet-ado-patterns]
DI container internals -- see [skill:dotnet-csharp-dependency-injection]
General testing strategies -- see [skill:dotnet-testing-strategy]
Cross-references: [skill:dotnet-system-commandline] for System.CommandLine 2.0 API, [skill:dotnet-native-aot] for AOT
publishing CLI tools, [skill:dotnet-csharp-dependency-injection] for DI patterns, [skill:dotnet-csharp-configuration]
for configuration integration, [skill:dotnet-testing-strategy] for general testing patterns.
clig.dev Principles for .NET CLI Tools
The Command Line Interface Guidelines provide language-agnostic principles for well-behaved CLI
tools. These translate directly to .NET patterns.
Core Principles
Principle
Implementation
Human-first output by default
Use Console.Out for data, Console.Error for diagnostics
Machine-readable output with --json
Add a --json global option that switches output format
Stderr for status/diagnostics
Logging, progress bars, and prompts go to stderr
Stdout for data only
Piped output (mycli list | jq .) must not contain log noise
Non-zero exit on failure
Return specific exit codes (see conventions below)
publicasync Task<SyncResult> SyncAsync(
Uri source, bool dryRun, CancellationToken ct)
// Pure business logic -- testable without CLI infrastructure
var
await
// ...
return
new
## Configuration Precedence
CLI tools use a specific configuration precedence (lowest to highest priority):
1. **Compiled defaults** -- hardcoded fallback values
2. **appsettings.json** -- shipped with the tool
3. **appsettings.
4.
set
by
or
5.
explicit user input (highest priority)
### Implementation with Generic Host
```csharp
var builder
new
args
// Layers 2-3 handled by CreateDefaultBuilder:
// appsettings.json, appsettings.{env}.json, env vars
// Layer 4: User-specific config file
var
".mycli"
"config.json"
if
true
// Layer 5: CLI args override everything
// System.CommandLine options take precedence via handler binding
### User-Level Configuration
level config (e.g., `~/.mycli/config.json`, `~/.config/mycli/config.yaml`). Follow platform
conventions:
| Platform | Location |
| ------------- | --------------------------------- |
| Linux/macOS | `~/.config/mycli/` or `~/.mycli/` |
| Windows | `%APPDATA%\mycli\` |
| XDG-compliant | `$XDG_CONFIG_HOME/mycli/` |
---
## Structured Logging in CLI Context
### Configuring Logging for CLI
CLI tools need different logging than web apps: logs go to stderr, and verbosity is controlled by flags.
```csharp
host.ConfigureLogging((ctx, logging)
// xUnit: just call it -- if it throws, the test fails
var
// Stderr contains diagnostic output
"Connected to"
## Agent Gotchas
1.
not
and
is
for
into
2.
not
1
for
Use distinct exit codes for different failure categories (I/O,
network, auth, validation). Callers and scripts rely on exit codes to determine what went wrong.
3. **Do not put business logic in command handlers.** Handlers should orchestrate calls to injected services and format
output. Business logic in handlers cannot be reused or unit-tested independently.
4. **Do not test CLI tools only via process spawning.** Use in-process invocation with `CommandLineBuilder` and
`TestConsole` for fast, reliable tests. Reserve process-level tests for smoke testing the published binary.
5. **Do not ignore `Console.IsInputRedirected` when accepting stdin.** Without checking, the tool may hang waiting for
input when invoked without piped data.
6. **Do not use exit codes above 125.** Codes 126-255 have special meanings in Unix shells (126 = not executable, 127 =
not found, 128+N = killed by signal N). Tool-specific codes should be in the 1-125 range.
---
## Code Navigation (Serena MCP)
**Primary approach:** Use Serena symbol operations for efficient code navigation:
1. **Find definitions**: `serena_find_symbol` instead of text search
2. **Understand structure**: `serena_get_symbols_overview` forfile organization
3. **Track references**: `serena_find_referencing_symbols` for impact analysis
4. **Precise edits**: `serena_replace_symbol_body` for clean modifications
**When to use Serena vs traditional tools:**
- ✅ **Use Serena**: Navigation, refactoring, dependency analysis, precise edits
- ✅ **Use Read/Grep**: Reading full files, pattern matching, simple text operations
- ✅ **Fallback**: If Serena unavailable, traditional tools work fine
**Example workflow:**
```text
# Instead of:
Read: src/Services/OrderService.cs
Grep: "publicvoid ProcessOrder"
# Use:
serena_find_symbol: "OrderService/ProcessOrder"
serena_get_symbols_overview: "src/Services/OrderService.cs"
```
## References
- [Command Line Interface Guidelines (clig.dev)](https://clig.dev/)
- [System.CommandLine overview](https://learn.microsoft.com/en-us/dotnet/standard/commandline/)
- [12 Factor CLI Apps](https://medium.com/@jdxcode/12-factor-cli-apps-dd3c227a0e46)
- [Generic Host in .NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host)
- [Console logging in .NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/console-log-formatter)