Sharprompt: interactive prompts for C# console applications
Interactive command-line based application framework for C#
At a glance
- What is it?
- Sharprompt is a .NET library for interactive command line prompts in C#, offering input, password, confirm, select, multi-select and list prompts, model-bound prompts that generate a form from a class, validators for required values, length limits and regular expressions, configurable symbols and colours, and cancellation through both Ctrl-C and a CancellationToken.
- Who is it for?
- Adopt Sharprompt if you are building a C# console tool that needs to ask the user things and want the prompts to look and behave like a proper application rather than a series of Console.ReadLine calls. Do not expect it to work in a non-interactive context, since every prompt blocks on the terminal.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Sharprompt is and how it differs from reading the console
Sharprompt is an interactive command-line based application framework for C#, published on NuGet as Sharprompt under the MIT licence.
The problem it solves is small and familiar. A console application that needs to ask the user something has three options, all bad: read a line and parse it yourself, which means no validation and no reprompt on bad input; use ReadLine with a loop, which is the same work with extra lines; or write your own console handling, which is what most people end up doing badly.
Sharprompt gives you the third option as a library. The feature list is multi-platform support, support for the popular prompts such as Input, Password and Select, support for model-based prompts, validation of input value, automatic generation of data source using Enum type, customizable symbols and colour schema, and Unicode support for multi-byte characters and emoji.
The design is worth noting because of what it does not include. There is no application model, no command routing, no configuration system, no dependency injection. The word framework in the description is generous. What you get is a set of prompt types and the machinery around them: validation, styling, cancellation and the model binding that turns a class into a form.
That narrowness is the appeal. It is a library you can add to a tool that already does something else, and it does not ask to own your program's structure.
The release history shows steady maintenance: v3.1.3 on 2026-09-30, v3.1.2 on 2026-07-05 and v3.1.1 on 2026-04-14, with the last push on 2026-10-15. The 3.x line suggests the API has settled.
The prompt types and their signatures
The prompt set is small and each one solves a distinct input shape.
Input takes a generic type parameter and performs type conversion as appropriate, so Prompt.Input<int>("Enter any number") gives you an int rather than a string to parse. The default-value behaviour is documented in detail: when a default value is provided, pressing Enter with nothing typed accepts the default, pressing Tab inserts the default value for editing, and pressing Backspace dismisses the default so the prompt behaves as if no default had been provided, which lets an empty value be submitted subject to the usual required check for non-nullable types and any validators.
That three-key arrangement is a small piece of interface design that takes thought. Tab to edit the default and Backspace to clear it are different intentions, and the fact that Backspace falls back to an empty prompt rather than to the default is the behaviour a user would expect.
Confirm takes a message and an optional default value, returning a bool. Password takes a message and does not echo the input. Select takes a message and an array of choices and returns the chosen one:
var city = Prompt.Select("Select your city", new[] { "Seattle", "London", "Tokyo" });MultiSelect is the checkbox variant and takes a pageSize, so a long list is navigable rather than scrolled off the top of the terminal. List is the free-form variant, letting the user add items rather than choose from a fixed set.
The samples live in a project called samples/Sharprompt.Example, and the README points you at it with dotnet run --project samples/Sharprompt.Example, which is the fastest way to see the rendering in a real terminal.
Model-based prompts and enum data sources
The Bind prompt is the feature that takes Sharprompt beyond a set of interactive widgets, and it is the closest thing in the library to a form builder.
You define a plain class with data annotations, and the library renders it as a sequence of prompts:
public class MyFormModel
{
[Display(Name = "What's your name?")]
[Required]
public string Name { get; set; }
[Display(Name = "Select your city")]
[Required]
[InlineItems("Seattle", "London", "Tokyo")]
public string City { get; set; }
[Display(Name = "Are you ready?")]
public bool? Ready { get; set; }
}Then Prompt.Bind<MyFormModel>() returns an instance populated from the answers. The mapping is done with standard .NET attributes: Display for the prompt text, Required for the non-empty check, DataType with DataType.Password for masked entry, MinLength for the length rule, and InlineItems for the choices of a string property.
The nullable bool is a small detail that shows the design. Ready is declared as bool? rather than bool, because a yes-or-no question that the user skipped should be distinguishable from a question they answered no, and the type carries that distinction.
Enums get their own treatment. The library generates the data source from the enum type automatically, and the Display attribute on each member sets the text shown:
public enum MyEnum
{
[Display(Name = "First value")]
First,
[Display(Name = "Second value")]
Second
}That means a Select<MyEnum>("Select enum value") call presents the members by their display names, with no separate list of strings to keep in sync with the enum. The feature list calls this automatic generation of data source using Enum type, and it removes a class of bug where the choices and the type drift apart.
Validators, styling and cancellation
Validation is a parameter on the prompt rather than a separate pass, and the built-in validators are four.
Validators.Required() ensures the input is not empty. Validators.MinLength(length) ensures at least that many characters. Validators.MaxLength(length) caps it. Validators.RegularExpression(pattern) requires a match. They are passed as an array on the validators parameter, as in Validators.Required() with Validators.MinLength(8) on a password prompt, and they compose, so a prompt can require a value and a minimum length at once.
Styling is global rather than per-prompt. The symbols are set on Prompt.Symbols, and each is a Symbol with an emoji and an ASCII fallback, so Prompt.Symbols.Prompt is set with a thinking face and a question mark, Done with sunglasses and a V, and Error with a scream and an arrow. The ASCII fallback is the detail that makes it usable in a terminal without emoji support, which is the same reason the library mentions multi-byte character support.
Colours work the same way, with Prompt.ColorSchema.Answer set to a ConsoleColor and Prompt.ColorSchema.Select set to another. Because the schema is global, you set it once at startup rather than per call.
Cancellation is handled two ways. Prompt.ThrowExceptionOnCancel set to true makes a Ctrl-C raise PromptCanceledException, which you catch as the example shows. And the code-driven route takes a CancellationToken, where using a CancellationTokenSource with a thirty second timeout and passing the token to a Confirm call with an options lambda throws OperationCanceledException.
The difference between the two is worth noting. The exception route is for the interactive case where the user pressed Ctrl-C, and it gives you a chance to print something before exiting. The token route is for the programmatic case, where a timeout means the prompt should stop waiting. Leaving ThrowExceptionOnCancel off gives you a null or default result instead, which is the right choice when a cancelled prompt should be treated as an ordinary empty answer.
Limits: an interactive library in a non-interactive world
The limits are the obvious ones for this category of library, and they are worth stating because they affect how you can use it.
The first is that every prompt blocks on the terminal. There is no timeout by default, no asynchronous variant and no headless mode, so a Sharprompt-based application cannot run unattended without the caller supplying a CancellationToken and the program deciding what an aborted prompt means.
The second is terminal-dependent rendering. The library draws the prompts, the choices and the colouring, which means its output assumes a terminal with cursor control. That is fine for an interactive tool and a problem for a program whose output is piped, redirected to a file or captured by a test. There is no documented non-interactive rendering path, so a test that exercises a prompt has to run in a pseudo-terminal.
The third is the Unicode dependency, and it is a real one. The README says to prefer UTF-8 as the output encoding with Console.OutputEncoding set to Encoding.UTF8, which means the library relies on the host terminal rendering multi-byte characters and emoji correctly. On a Windows console that has not been switched to UTF-8, or in a terminal with a limited font, the symbols and any user input in a non-Latin script will not render properly. The emoji-plus-ASCII fallback in the Symbol type mitigates this for the library's own decorations but not for the text the user types.
The fourth is the scope. There is no prompt for file paths, dates, masked numeric entry, tree selection or searchable lists, so a tool that needs those will still be writing that code itself.
The fifth is the version floor and the API surface. The repository uses a solution file with a newer format, Directory.Packages.props for central package version management and a global.json pinning the SDK, which together mean you need a recent .NET SDK. The prompts themselves are static members on a shared Prompt class with global Symbols and ColorSchema, which means the styling is process-wide rather than scoped, and two parts of the same program cannot use different looks.
Sharprompt against manual Console.ReadLine and against Spectre.Console
Two comparisons make the choice clearer.
The first is against writing the input handling yourself, which is what most C# console tools do. The difference in approach is that Sharprompt handles the parts that are tedious and easy to get subtly wrong: reprompting on validation failure without losing what was typed, type conversion with a sensible error message, masking a password so it is not echoed or captured in the scrollback, a select list with cursor navigation and paging, and cancellation that does not leave the terminal in a broken state. That last one is not trivial, because a prompt that reads a password and then throws leaves the console in no-echo mode, and recovering from that is the sort of bug that costs an afternoon.
The second comparison is against Spectre.Console, which is the closest thing in the .NET ecosystem and considerably more capable. The difference in approach is scope and style. Spectre is a general console formatting and interaction library: tables, panels, progress bars, live displays, status indicators, prompt widgets. Sharprompt is a set of prompts with validation and model binding, and nothing else. If your tool needs to render a table or a live progress display, Spectre gives you that and Sharprompt does not.
So the choice is between a focused prompt library and a general console toolkit. A tool that only asks questions should probably use Sharprompt, because its model binding and validators are exactly the problem. A tool that also draws a dashboard needs a toolkit like Spectre, and may then use its prompt widgets instead.
There is also a middle option that costs nothing to consider: writing the three or four prompts you actually need yourself, with a small helper for validation. If the tool has one prompt, that is under an hour of work, and you keep full control over the rendering.
Editorial conclusion
Adopt Sharprompt if you are building a C# console tool that needs to ask the user things and want the prompts to look and behave like a proper application rather than a series of Console.ReadLine calls. Do not expect it to work in a non-interactive context, since every prompt blocks on the terminal. Verify first that the target framework matches what your project uses, that the console encoding handles the characters you need, given the Unicode support depends on the host terminal, and that you turn off ThrowExceptionOnCancel if you would rather handle a cancelled prompt as a null result.
Frequently asked questions
How do I install Sharprompt and show a simple prompt?
Install it with dotnet add package Sharprompt, or Install-Package Sharprompt from the PowerShell package manager. A simple text prompt is Prompt.Input<string>("What's your name?"), which takes a generic type parameter and performs the type conversion for you.
What validators does Sharprompt provide?
Four built-in validators passed through the validators parameter: Required() ensures the input is not empty, MinLength(length) ensures at least that many characters, MaxLength(length) caps the length, and RegularExpression(pattern) requires a match. They compose, so a password prompt can require both a value and a minimum length of eight.
How do I handle Ctrl-C or a timeout on a Sharprompt prompt?
Set Prompt.ThrowExceptionOnCancel to true to raise a PromptCanceledException when the user presses Ctrl-C, and catch it. Alternatively pass a CancellationToken to a prompt, which throws OperationCanceledException; the README shows using a CancellationTokenSource with a thirty second timeout. Leaving the flag off makes a cancelled prompt return an empty or default result instead.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/shibayan-sharprompt)Was this useful?