Intro
.NET is constantly evolving to make the development experience simpler and more efficient. Recently, the .NET CLI (command-line tool) introduced an exciting new feature: the ability to run C# source files directly without needing a project file. This feature is called File-based Programs, and .NET 10 will add support for dotnet run file. Currently available in .NET 10 Preview 4, you can download the latest .NET 10 SDK to try it out. Some of the functionality from my own dotnet-exec project can now be handled by the native SDK support.
What
Traditional .NET application development always requires a project file (.csproj), even just to run a simple piece of code. File-based programs remove this barrier, allowing you to run any C# file directly from the command line:
echo 'Console.WriteLine("Hello C#!");' > hello.cs
dotnet run hello.cs
No project file, no complex configuration—write C# like a script!

How it works
- When you execute
dotnet run file.cs, the CLI automatically generates an "implicit project" (a virtual project file) in memory for that file. This behaves exactly as if you had created a project based on thedotnet new consoletemplate. This ensures that when you use a single-file script, the behavior is consistent with developing with a standard project. Its implementation is very similar to the project compiler in dotnet-exec, but better—it creates a virtual project file without actually creating any files on disk. - All
.csfiles (including those in subdirectories) under the target file's directory will be compiled (e.g., common utility classes, resources). - Relevant build files (such as
Directory.Build.props) are automatically applied. - If the file you run has no entry point method, an error will be shown to prevent accidental execution, as illustrated below:

More Usage
To support the expansion of file-based programs, a new
#:directive has been introduced. These directives are automatically ignored when compiling a project file, but for file-based programs they are parsed and converted into the SDK, references, and project property settings in the project file.Using special directives at the top of the file (e.g.,
#:sdk Microsoft.NET.Sdk.Web,#:package,#:property), you can declare NuGet dependencies or project properties. For example:#:sdk Microsoft.NET.Sdk.Web #:package System.CommandLine@2.0.0-* #:property TargetFramework net10.0You can specify
#:sdk Microsoft.NET.Sdk.Webto create a single-file WebApplication:#:sdk Microsoft.NET.Sdk.Web var app = WebApplication.Create(args); app.MapGet("/", () => "Hello World!"); await app.RunAsync();Run our single-file webapi with
dotnet run webapi.cs:
Access our API:

We can also reference NuGet packages and configure properties, as shown below:
#:sdk Microsoft.NET.Sdk.Web #:package WeihanLi.Web.Extensions@2.1.0 #:property ManagePackageVersionsCentrally false using WeihanLi.Web.Extensions; var app = WebApplication.Create(args); app.MapGet("/", () => "Hello World!"); app.MapRuntimeInfo(); await app.RunAsync();Similarly, run with
dotnet run webapi.cs:
When your script becomes more complex and you want more customization without using file-based programs, you can convert it to a standard project with a single command. The CLI will automatically generate a
.csprojfile and migrate the relevant configuration, with no change in code behavior:dotnet project convert webapi.csThe converted project will look like this, and you can also run it directly with
dotnet run:
Supports shebang (
#!) on Linux/Unix, allowing C# scripts to be run directly like Bash/Python. You can execute./hello.cs:#!/usr/bin/dotnet run Console.WriteLine("Hello, .NET!");
Future Features
The proposal to run C# files directly with dotnet run file.cs brings flexible and powerful scripting to .NET. The design document also looks ahead to many possible future enhancements that will make file-based programs even more practical in the .NET ecosystem. Some future features include:
1. Expanded Target Path Support
- Folder as target: Allow folders to be used as targets for
dotnet run(e.g.,dotnet run ./my-app/), running the main entry point in that folder. - Standard input and inline code: Support
dotnet run --cs-from-stdinto read C# code from standard input, ordotnet run --cs-code 'Console.WriteLine("Hi")'for raw code scripting.
2. Unified Command-Line Arguments
- Directory and file options: Introduce
--directory,--file, or a unified--pathoption to make the command experience consistent for both file-based and project-based programs. - Multiple entry point support: Add parameters like
--entryto easily choose a specific entry point in multi-program directories.
3. Enhanced Integration and Consistency
- Seamless experience before and after growth: Ensure commands like
dotnet runwork smoothly whether in file-based form or after upgrading to a project. - Common options: In the future, a unified parameter that works for both project and file formats could make switching between formats smoother.
4. Performance and Usability Improvements
- Selective file inclusion: Use parameters or directives to control which files are included, reducing the trouble and performance overhead of accidentally including many files.
- Nested file error hints: If a subdirectory contains too many
.csfiles or.csprojfiles, consider showing errors or warnings to avoid accidentally compiling a large amount of content.
5. Optimization for Multi-Entry Point Scenarios
- Project structure generation: Optimize the structure generated when a multi-entry point directory "grows" into a project, with clear subdirectory division and cleaner shared code handling.
- Advanced access control: Explore features like
InternalsVisibleTofor better code sharing, and consider future enhancements to the C# language.
6. Shebang and Shell Support
- Dedicated executable: Might release a
dotnet-runordotnet-run-fileexecutable to improve shebang (#!) compatibility across different shell environments, enabling scripts to run directly cross-platform. - Support for
/usr/bin/env: Investigate how to work around the parameter-passing limitations of shebang in shells, improving CLI script usability.
7. More File-Based Program Command Support
- Build and restore: Extend commands like
dotnet restore file.csanddotnet build file.csto enable IDE and CI integration for file-based programs. - Package management:
dotnet package addcould directly add#:packagedirectives to the top of C# files, simplifying script dependency management.
8. Explicit File Imports
- Import directive: Future support for directives like
#import ./another-file.csto explicitly specify which C# files to include, giving developers more control.
More
Currently we still need to use dotnet run hello.cs, but in the future it may be simplified to dotnet hello.cs and even support executing raw code. Looking forward to even more useful features later~~
For more information, refer to the official documentation: https://github.com/dotnet/sdk/blob/main/documentation/general/dotnet-run-file.md
One slight imperfection is that this introduces yet another syntax for referencing NuGet packages, which is different from the nuget: package@version syntax in dotnet-script and not fully compatible with dotnet-script.
Custom entry points are not yet supported; if we could customize the entry method in the future, that would be even better. Looking forward to it~~
Finally, at Build there was an introduction video about dotnet run file – if you're interested, you can check it out.
[Click the original WeChat post to watch the video]
References
- • Document: https://github.com/dotnet/sdk/blob/main/documentation/general/dotnet-run-file.md
- • File-Based Programs IDE Spec: https://github.com/dotnet/roslyn/blob/main/docs/features/file-based-programs-vscode.md
- • Shebang in Unix: https://en.wikipedia.org/wiki/Shebang_(Unix)
- • https://github.com/dotnet/sdk/pull/46915/files
- • https://github.com/dotnet/sdk/pull/48782/files
- • https://github.com/dotnet/sdk/pulls?q=is%3Apr+label%3AArea-run-file+is%3Aclosed