/commands/csharp/run-cs-file-without-project
dotnet run app.cs: run a C# file without a project (.NET 10 file-based apps)
- tool
- C#
- versions
- .NET 10 SDK+, #:include: SDK 10.0.300+
- os
- linux, macos, windows
With the .NET 10 SDK, dotnet run app.cs builds and runs a single C# file directly: no .csproj, no Program.cs template. The file uses top-level statements, and directives at the top such as #:package and #:property replace the project file. Arguments for your program go after --, and dotnet app.cs is an even shorter form.
Run a file
cat > app.cs <<'EOF'
var name = args.Length > 0 ? args[0] : "world";
Console.WriteLine($"Hello, {name}! Running on .NET {Environment.Version.Major}");
Console.WriteLine($"args: [{string.Join(", ", args)}]");
EOF
dotnet run app.cs
dotnet run app.cs -- file-based --verboseOutput
Hello, world! Running on .NET 10 args: [] Hello, file-based! Running on .NET 10 args: [file-based, --verbose]
Everything after -- reaches args; without the separator, options such as --verbose would be read by dotnet run itself. The first run takes a few seconds because the SDK builds a virtual project; later runs of an unchanged file reuse the cached build.
Directives
| Directive | Example | Effect |
|---|---|---|
| #:package | #:package Serilog@3.1.1 | Add a NuGet package reference |
| #:property | #:property TargetFramework=net10.0 | Set any MSBuild property |
| #:sdk | #:sdk Microsoft.NET.Sdk.Web | Use another SDK, for example for a minimal web API |
| #:project | #:project ../Shared/Shared.csproj | Reference a project |
| #:include | #:include helpers.cs | Compile another file into the app (SDK 10.0.300+) |
| #! | #!/usr/bin/env -S dotnet -- | Shebang: run ./app.cs directly on Linux and macOS after chmod +x |
Related commands
| Command | What it does |
|---|---|
| dotnet app.cs | Shorthand for dotnet run app.cs |
| echo 'Console.WriteLine(1);' | dotnet run - | Read the program from standard input |
| dotnet build app.cs | Build only |
| dotnet publish app.cs | Publish a native AOT executable (on by default; #:property PublishAot=false disables it) |
| dotnet project convert app.cs | Create a regular project from the file |
| dotnet clean file-based-apps | Delete cached builds unused for 30 days (--days to change) |
Pitfalls
- A project in the same folder wins. When the current directory contains a
.csproj,dotnet run app.csruns that project and passesapp.csto it as an argument. Usedotnet run --file app.csor move the file. - SDK too old. Before .NET 10,
dotnet run app.cswithout a project fails with Couldn't find a project to run. Checkdotnet --version(10.0.100 or later). - Shebang files need LF line endings and no byte order mark, according to the documentation; files saved with CRLF fail to start from the shell.
- Build files in parent folders.
Directory.Build.props,Directory.Packages.propsandNuGet.configabove the file still apply to it. - Compile errors look like any C# build error, for example CS0103 for a misspelled name.
Confirm it worked
The program's output appears and the exit status is the value your code returns (0 by default). dotnet build app.cs shows where the compiled files went.
FAQ
Where does dotnet run app.cs put the build output?
In a per-user cache under the system temporary directory (dotnet/runfile/APPNAME-HASH), not next to the file. dotnet clean file-based-apps removes old entries; --output on dotnet build chooses another folder.
Can a file-based app use NuGet packages?
Yes. Add a #:package Name@Version line at the top of the file; the SDK restores it on the first run. Without central package management the version (or @* for the latest) is required.
How do I turn the file into a normal project later?
dotnet project convert app.cs creates a folder with a .csproj and a copy of the file, translating the #: directives into project settings. The original file is left untouched.