5,008
stars
+0+-1+6
285
forks
46
watchers
93
prs
138
issues
15
releases
–
discussions
README
CliWrap
Development of this project is entirely funded by the community. Consider donating to support!
Made in 🇺🇦 Ukraine — despite Russia's best efforts.
Using this project or its source code comes with the implicit agreement that you condemn Russia's war of aggression against Ukraine, recognize Russia as a terrorist state, and support Ukraine's territorial integrity.
CliWrap is a library for interacting with command-line interfaces.
It provides a convenient model for launching processes, redirecting input and output streams, awaiting completion, handling cancellation, and more.
Install
- 📦 NuGet: dotnet add package CliWrap
Features
- Airtight abstraction over System.Diagnostics.Process
- Fluent configuration interface
- Flexible support for piping
- Fully asynchronous and cancellation-aware API
- Graceful cancellation using interrupt signals
- Designed with strict immutability in mind
- Complete ownership of the underlying process's lifetime
- Provides safety against typical deadlock scenarios
- Tested on Windows, Linux, and macOS
- Targets .NET Standard 2.0+, .NET Core 3.0+, .NET Framework 4.6.2+
- No external dependencies
Usage
Video guides
You can watch one of these videos to learn how to use the library:
- OSS Power-Ups: CliWrap by Oleksii Holub
- Stop using the Process class for CLI interactions in .NET by Nick Chapsas
Quick overview
Similarly to a shell, CliWrap's base unit of work is a command — an object that encapsulates instructions for running a process.
To build a command, start by calling Cli.Wrap(...) with the executable path, and then use the provided fluent interface to configure arguments, working directory, or other options.
Once the command is configured, you can run it by calling ExecuteAsync():
csharp
using CliWrap;
var result = await Cli.Wrap("/path/to/cli")
.WithArguments(["--foo", "bar"])
.WithWorkingDirectory("/work/dir/path")
.ExecuteAsync();
// Result contains:
// -- result.ExitCode (int)
// -- result.IsSuccess (bool)
// -- result.StartTime (DateTimeOffset)
// -- result.ExitTime (DateTimeOffset)
// -- result.RunTime (TimeSpan)
The code above spawns a child process with the configured command-line arguments and working directory, and then asynchronously waits for it to exit.
After the task has completed, it resolves to a CommandResult object that contains the process exit code and other relevant information.
[!WARNING]
CliWrap will throw an exception if the underlying process returns a non-zero exit code, as it usually indicates an error.
You can override this behavior by disabling result validation using WithValidation(CommandResultValidation.None).
By default, the process's standard input, output and error streams are routed to CliWrap's equivalent of a _null device_, which represents an empty source and a target that discards all data.
You can change this by calling WithStandardInputPipe(...), WithStan