When you need cross-cutting concerns like logging, timing, or authentication across all commands without duplicating code, implement a command interceptor. The interceptor runs before and after every command, keeping individual commands focused on their core logic.
What We're Building
A timing interceptor wrapping every command, reporting execution duration automatically—no timing code in the commands themselves:
Create an Interceptor
Implement ICommandInterceptor with two methods: Intercept runs before execution, InterceptResult runs after. The same instance handles both, so you can store state between them.
public class TimingInterceptor : ICommandInterceptor
{
private Stopwatch? _stopwatch;
public void Intercept(CommandContext context, CommandSettings settings)
{
// Runs before command execution
_stopwatch = Stopwatch.StartNew();
System.Console.WriteLine($"Starting command: {context.Name}");
}
public void InterceptResult(CommandContext context, CommandSettings settings, ref int result)
{
// Runs after command execution
_stopwatch?.Stop();
System.Console.WriteLine($"Command completed in {_stopwatch?.ElapsedMilliseconds}ms (exit code: {result})");
}
}
Register the Interceptor
Use SetInterceptor in your configuration:
var app = new CommandApp();
app.Configure(config =>
{
config.SetInterceptor(new TimingInterceptor());
config.AddCommand<ProcessCommand>("process")
.WithDescription("Process files");
});
return await app.RunAsync(args);
Common Use Cases
- Logging: Configure log scopes in
Intercept, flush logs inInterceptResult - Timing: Start a stopwatch before, report duration after
- Authentication: Validate credentials before any command runs
- Resource management: Initialize connections before, clean up after
- Exit code adjustment: Modify the result based on post-execution checks
The InterceptResult method receives the exit code by reference (ref int result), allowing you to modify it based on the command outcome.
See Also
- Dependency Injection in CLI Apps - Inject services into interceptors
- Handling Errors and Exit Codes - Custom error handling