CLI tool
jonsequitur/dotnet-repl avatar
jonsequitur/dotnet-repl

dotnet-repl: a polyglot REPL for C#, F# and PowerShell on the command line

A polyglot REPL built on .NET Interactive

840 stars41 forksC#MIT

At a glance

What is it?
dotnet-repl is a command line REPL built on .NET Interactive and Spectre.Console that evaluates C# and F# in one session, adds NuGet packages on the fly and runs notebooks or script files with a non-zero exit code when a cell fails. The README calls it a personal project and an experiment, and that framing is accurate.
Who is it for?
dotnet-repl suits a .NET developer who wants to try an API, mix C# and F# in one scratch session, or turn a notebook into a CI-checked script without leaving 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 115 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 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A terminal front end for .NET Interactive

dotnet-repl is described as a polyglot REPL built on .NET Interactive, and the README is candid about what that means in practice: it is an experiment using .NET Interactive, also known as Polyglot Notebooks, together with Spectre.Console to create a polyglot .NET REPL for use on the command line. The README also states plainly that this is a personal project.

Those two sentences set the expectations correctly. The heavy lifting is done by .NET Interactive, which is the Microsoft project that provides the kernels, the magic commands and the multi-language notebook format. What dotnet-repl adds is a terminal experience over that engine, with Spectre.Console supplying the rendering, and a set of command line options that a person or a script can drive.

The result is a REPL where the default language is C#, but F# is available, and the two can be switched within a single session. That last point is the reason the project exists in its current form. The dotnet-interactive and Spectre.Console projects are the upstream dependencies, and the topic tags of the repository are just dotnet, dotnet-interactive and repl.

The licence is MIT, and the project is published on NuGet as dotnet-repl. The repository has no GitHub releases, so the NuGet version is the version to track.

Installing the tool and starting a session

Installation is a single .NET tool command.

bash
> dotnet tool install -g dotnet-repl

That installs it globally as a dotnet tool, so the command is available in the terminal path once the install finishes.

The REPL is started with `dotnet repl`, and the default kernel is C#.

bash
> dotnet repl --default-kernel csharp
> dotnet repl

The README notes that these two are equivalent, which is a nice touch of consistency: the default kernel argument is spelled out so a script can be explicit about what it is asking for.

F# is the other mode, and it can be selected either with the same argument or through an environment variable, which is the useful one for a shell profile.

bash
# DOTNET_REPL_DEFAULT_KERNEL=fsharp
> dotnet repl

Once the REPL is up, code is typed at the prompt and run by pressing Enter. The README points out that the C# dialect is the C# scripting dialect, the same one used in the Visual Studio C# Interactive Window and in .NET Interactive Notebooks, so what you learn here transfers.

The trailing expression and multi-line entries

Two details make the C# mode feel different from a plain console.

The first is the trailing expression. The README describes it as a notable feature of C# scripting, the ability to specify a return value for a code submission using a trailing expression. In effect the last expression in what you type is the value the REPL shows you, which removes the need to wrap everything in a call to a print helper.

The second is multi-line input. Pressing Shift-Enter adds a line without running anything, and Enter submits. The README points out that this removes the need to follow the F# Interactive convention of terminating a line with `;;` to indicate that the accumulated submission should be run. That is a real difference in feel between the two languages, and here the C# style wins: you type a class or a multi-line construct, press Shift-Enter as you go, and press Enter when it is done.

The README also shows a way to switch languages within the same session, without leaving it. For a developer evaluating a library from F# and then checking its behaviour from C#, that is the feature that makes a polyglot session worth the setup.

NuGet packages, notebooks and exit codes

Packages can be added from inside the session with the `#r nuget` magic command, which installs a package for the duration of the current session. That is a small thing with a large effect on how useful a scratch session is, since the alternative is a project file and a restore.

A file can also be used to initialise the session.

bash
> dotnet repl --run /path/to/notebook.ipynb

The same flag with `--exit-after-run` turns the whole thing into a non-interactive script, and the README says that as long as the file extension indicates a language understood by .NET Interactive it will try to run it.

bash
> dotnet repl --run /path/to/notebook.ipynb --exit-after-run

The supported formats are listed in the README: `.ipynb` for a Jupyter notebook that can contain code cells in several languages, `.dib` for a .NET Interactive script file, `.cs` for a C# source file, `.csx` for a C# script, `.fs` and `.fsx` for F#, `.ps1` for PowerShell, and `.html` and `.js`, which render in an external browser window. The `.cs` entry carries its own caveat, that some constructs such as namespaces are not supported, so it is described as extra experimental.

The exit code behaviour is the part with real engineering value. If all of the notebook's cells execute successfully a 0 exit code is returned, otherwise 2, and the README says this can be used as a way to test notebooks. That is what turns a notebook into something a CI pipeline can gate on.

Capturing output and passing parameters

Output can be captured from a run with the `--output-path` and `--output-format` options. The path is the file name to write, and the format is either `ipynb` or `trx`, with `ipynb` as the default.

The `ipynb` result is a Jupyter notebook with the outputs captured from the run, and the README notes it can be opened with the .NET Interactive Notebooks extension in Visual Studio Code or any number of other Jupyter readers, and it can be displayed in GitHub. The `trx` format is a .NET test result file, useful in CI pipelines such as Azure DevOps, and it can also be opened with Visual Studio or read with the `t-rex` tool.

That dual format is a sensible design. The notebook output is for reading, the test result is for a pipeline that wants to publish results into an existing reporting system.

Parameters work the other way round. A notebook containing magic commands with `@input` tokens creates a prompt for user input when run in a notebook editor, and those values can be supplied on the command line with the `--input` option. The README's example is a `#!connect mssql --kernel-name mydatabase @input:connectionString` command, where the connection string would otherwise have to be typed at the prompt. Supplying it as an argument is what allows the same notebook to run unattended against a database.

An already running session can also pull in a file with the `#!import` magic command, and every format that `--run` accepts is supported there too.

Where dotnet-repl is the wrong tool

The first limitation is the one the README states itself. This is an experiment and a personal project, with no GitHub releases to track, no stated support commitment and no compatibility matrix for .NET SDK versions. If your build depends on the exact behaviour of a tool, that is a risk you are taking knowingly.

The second is that the value is mostly in the shell, not the engine. .NET Interactive already provides the notebooks, the kernels and the magic commands, and the .NET Interactive Notebooks extension puts them inside Visual Studio Code with debugging and a proper cell editor. If you work in Visual Studio Code most of the time, the terminal REPL saves you a window switch but adds little.

The third is the file format list. Several of the supported formats are explicitly experimental, and the HTML and JavaScript ones render in an external browser window, which is a different tool from the one you are in. The C# source file support has known gaps, with namespaces unsupported.

The fourth is that the exit code contract covers the notebook as a whole. A 2 tells you something failed and nothing about which cell, and the details are in the output file. For a pipeline that wants a per-test result rather than a per-notebook verdict, the `trx` format exists but the flow is not documented in detail here.

The fifth is the quiet dependency on Spectre.Console for the rendering. A terminal with an unusual configuration, a very old console host, or a CI environment that does not support interactive rendering can behave differently, and the README does not discuss that.

How it compares with dotnet script, csi and the Visual Studio Code extension

dotnet script was the standard answer for years, and it is the most obvious comparison. It is a .NET tool that runs a single C# script file, and it is the natural choice when you have one `.csx` file to execute. The difference in approach is that dotnet script is a file runner, while dotnet-repl is an interactive session that can also run files. The session is where dotnet-repl earns its keep, because state persists between submissions and the language can change mid-session.

csi, the C# interactive compiler shipped with Visual Studio, is the older answer and is still present on many developer machines. It gives you a C# prompt with top-level statements and trailing expressions, and it is fast, but it is C# only, it has no NuGet magic, and it does not run notebooks.

The .NET Interactive Notebooks extension in Visual Studio Code is the strongest alternative and the closest in capability. It shares the engine, so the kernels, the magic commands and the file formats are the same, and it adds a cell editor, a variable explorer, output rendering and debugging. The trade is exactly the shell against the IDE: the extension is better for anything longer than a couple of lines, and the REPL is better when you want to stay in the terminal and pipe things.

A fourth option worth naming is a plain C# file and `dotnet run`, which needs no extra tooling at all. For a script that lives in version control next to a project, that remains the least surprising choice, and dotnet-repl is a better fit for the throwaway exploration it is actually good at.

Licence, maintenance and what to check before adopting it

The licence is MIT, with the LICENSE file at the root of the repository, so the source can be read, forked and modified. The project also has a CODE_OF_CONDUCT.md and a Developer-guide.ipynb, the latter being a notebook in the repository's own format, which is a nice detail to find in a project about notebooks.

The repository is not archived and the last push was on 2026-06-30, so the code is being worked on, but there are no GitHub releases, so there is no published version history to inspect and no changelog to read before an upgrade. The NuGet package version is the only version marker, and the build is driven by the dotnet-repl.sln with an appveyor.yml configuration and a global.json pinning the SDK.

There are three things to verify before adopting it in a workflow. Run a notebook that contains a failing cell and confirm the process returns 2, because that contract is the basis of any CI use. Check the `--output-format trx` path in your own pipeline, since a test result file only helps if your reporting system reads that format. And confirm the .NET SDK version pinned in global.json matches what is installed on the machines that will run it, since a global.json mismatch is the most common reason a dotnet tool behaves differently on a build agent than on a laptop.

The last point about the project itself is that it is a personal experiment that has been kept alive long enough to be useful. That is a fair summary of the risk: useful software with no support commitment behind it.

Editorial conclusion

dotnet-repl suits a .NET developer who wants to try an API, mix C# and F# in one scratch session, or turn a notebook into a CI-checked script without leaving the terminal. It is a poor fit for a team that already has its own notebook pipeline, since the .NET Interactive Notebooks extension covers the same ground inside Visual Studio Code, and a poor fit for anyone who needs a stable supported tool, because the README describes the project as an experiment and the repository has no GitHub releases. Before depending on the exit code behaviour in a pipeline, run one notebook that fails on purpose and confirm it returns 2, and read the --output-format trx path if you want test results rather than a notebook.

Frequently asked questions

How do I install dotnet-repl?

Run `dotnet tool install -g dotnet-repl` in your terminal. The package is published on NuGet as dotnet-repl, and the project is built on .NET Interactive and Spectre.Console.

Which languages can dotnet-repl run?

C# by default and F# through --default-kernel or the DOTNET_REPL_DEFAULT_KERNEL environment variable, and the README also shows switching languages within a running session. The supported file formats add PowerShell, and .NET Interactive script, C# and F# source and script files.

How do I add a NuGet package in a dotnet-repl session?

Use the #r nuget magic command, which installs the package for the duration of the current session.

What exit code does dotnet-repl return when a notebook fails?

If all of the notebook's cells execute successfully a 0 exit code is returned, otherwise 2. The README says this can be used as a way to test notebooks.

How do I capture the output of a notebook run in dotnet-repl?

Pass the --output-path and --output-format options. The format is either ipynb, which writes a Jupyter notebook with the captured outputs, or trx, a .NET test result file that CI pipelines such as Azure DevOps can consume.

How do I submit multiple lines of code in dotnet-repl?

Press Shift-Enter to add a line without running it and press Enter to submit. The README notes this removes the need for the F# Interactive convention of ending a line with ;; to trigger the accumulated submission.

Official sources

  1. Issues
  2. jonsequitur/dotnet-repl on GitHub
  3. License: MIT
  4. README
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jonsequitur-dotnet-repl.svg)](https://hysenlabs.com/projects/jonsequitur-dotnet-repl)

Was this useful?