dotnet-file-based-apps について
`.csproj` を作成せず、単一の `.cs` ファイルから C# アプリをビルド、実行、公開する .NET 10 SDK の使い方を解説するスキルです。スクリプトや小規模アプリ向けに、ディレクティブ、CLI 操作、プロジェクト形式への移行を扱います。
主な機能
- 01`#:` ディレクティブによるアプリ設定
- 02NuGet パッケージと SDK 設定の管理
- 03CLI での実行、ビルド、公開
- 04標準入力と Unix shebang からの実行
- 05ファイルベースアプリのプロジェクト変換
活用シーン
- 01プロジェクトの雛形なしで小規模な C# ツールを作成
- 02シェル入力から C# コード片を実行
- 03単一ファイルアプリを .NET Tool としてパッケージ化
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ wshaddix/ dotnet-skills --skill dotnet-file-based-appsインストール後、Claude Code で/dotnet-file-based-appsを入力して読み込まれたか確認します。
詳細
dotnet-file-based-apps
.NET 10 SDK のファイルベースアプリでは、.csproj プロジェクトファイルを作成せず、単一の .cs ファイルから C# アプリケーションをビルド、実行、発行できます。SDK は、ソースファイルに埋め込まれた #: ディレクティブからプロジェクト構成を自動生成します。この機能は、従来のプロジェクトのひな形が不要なスクリプト、ユーティリティ、小規模なアプリケーションを対象としています。
これはファイル I/O ではありません。 FileStream、RandomAccess、FileSystemWatcher、パス処理については、[skill:dotnet-file-io] を参照してください。
前提条件: .NET 10 SDK 以降が必要です。SDK のバージョンを確認するには、[skill:dotnet-version-detection] を実行してください。
相互参照:SDK バージョンの判定については [skill:dotnet-version-detection]、プロジェクトベースの分析については [skill:dotnet-project-analysis](ファイルベースアプリには .csproj がありません)、csproj ベースのプロジェクトのひな形作成については [skill:dotnet-scaffold-project] を参照してください。
ディレクティブの概要
ファイルベースアプリでは、ビルドの構成に #: ディレクティブを使用します。ディレクティブはSDK レベルの命令であり、C# の構文ではありません。.cs ファイルの先頭に、C# コードより前に記述する必要があります。
次の 4 種類のディレクティブがサポートされています。
| ディレクティブ | 用途 | 例 |
|---|---|---|
#:package | NuGet パッケージ参照を追加する | #:package [email protected] |
#:sdk | SDK を設定する(既定値:Microsoft.NET.Sdk) | #:sdk Microsoft.NET.Sdk.Web |
#:property | MSBuild プロパティを設定する | #:property PublishAot=false |
#:project | 別のプロジェクトファイルを参照する | #:project ../Lib/Lib.csproj |
#:package ディレクティブ
NuGet パッケージ参照を追加します。パッケージ名を指定し、必要に応じて @version を続けます。
#:package Newtonsoft.Json
#:package [email protected]
#:package Spectre.Console@*
バージョンの動作:
@version-- 特定のバージョンに固定します@*-- 最新の安定版を使用します(NuGet の浮動バージョン)- バージョン指定なし -- Central Package Management(CPM)を
Directory.Packages.propsファイルで構成している場合にのみ機能します。そうでない場合は、バージョンを明示的に指定するか、@*を使用してください
#:sdk ディレクティブ
使用する SDK を指定します。省略した場合、既定値は Microsoft.NET.Sdk です。
#:sdk Microsoft.NET.Sdk.Web
#:sdk [email protected]
このディレクティブを使用して、SDK 固有の機能を利用できます。たとえば、Microsoft.NET.Sdk.Web を指定すると ASP.NET Core の機能が有効になり、ビルド時に *.json 構成ファイルが自動的に含まれます。
#:property ディレクティブ
MSBuild プロパティの値を設定します。ビルドの動作をカスタマイズするには、これを使用します。
#:property TargetFramework=net10.0
#:property PublishAot=false
条件付きプロパティ値
プロパティディレクティブは、条件付き構成に MSBuild のプロパティ関数と式をサポートしています。
既定値を指定した環境変数:
#:property LogLevel=$([MSBuild]::ValueOrDefault('$(LOG_LEVEL)', 'Information'))
条件式:
#:property EnableLogging=$([System.Convert]::ToBoolean($([MSBuild]::ValueOrDefault('$(ENABLE_LOGGING)', 'true'))))
#:project ディレクティブ
別のプロジェクトファイル、またはプロジェクトファイルを含むディレクトリを参照します。ファイルベースアプリと従来のプロジェクトでコードを共有するには、これを使用します。
#:project ../SharedLibrary/SharedLibrary.csproj
参照先のプロジェクトはビルドされ、.csproj の <ProjectReference> と同様にプロジェクト参照としてリンクされます。
CLI コマンド
.NET CLI は、使い慣れたコマンドでファイルベースアプリをサポートしています。
実行
# Preferred: pass file directly
dotnet run app.cs
# Explicit --file option
dotnet run --file app.cs
# Shorthand (no 'run' subcommand)
dotnet app.cs
# Pass arguments after --
dotnet run app.cs -- arg1 arg2
現在のディレクトリに .csproj がある場合、dotnet run app.cs(--file なし)はプロジェクトを実行し、後方互換性を保つために app.cs を引数として渡します。ファイルベースでの実行を強制するには、dotnet run --file app.cs を使用してください。
stdin からパイプ入力
echo 'Console.WriteLine("hello");' | dotnet run -
- 引数は、標準入力から C# コードを読み込みます。簡単なテストやシェルスクリプトとの連携に便利です。
ビルド
dotnet build app.cs
ビルド出力は、既定でシステムの一時ディレクトリ内のキャッシュされた場所に保存されます。--output または #:property OutputPath=./output で変更できます。
クリーン
# Clean build artifacts for a specific file
dotnet clean app.cs
# Clean all file-based app caches in the current directory
dotnet clean file-based-apps
# Clean caches unused for N days (default: 30)
dotnet clean file-based-apps --days 7
発行
dotnet publish app.cs
ファイルベースアプリでは、ネイティブ AOT が既定で有効になります。出力は .cs ファイルと同じ場所にある artifacts ディレクトリに保存されます。AOT を無効にするには、#:property PublishAot=false を指定してください。
.NET ツールとしてパック
dotnet pack app.cs
ファイルベースアプリでは、既定で PackAsTool=true が設定されます。無効にするには、#:property PackAsTool=false を指定してください。
復元
dotnet restore app.cs
復元はビルド/実行時に暗黙的に行われます。スキップするには、dotnet build または dotnet run に --no-restore を渡します。
シェルでの実行(Unix)
シバン行を使用すると、Unix 系システムで直接実行できます。
#!/usr/bin/env dotnet
#:package Spectre.Console
using Spectre.Console;
AnsiConsole.MarkupLine("[green]Hello, World![/]");
chmod +x app.cs
./app.cs
ファイルには LF の行末を使用する必要があります(CRLF は不可)。また、BOM を含めることはできません。
起動プロファイル
ファイルベースのアプリでは、ソースファイルと同じディレクトリにあるフラットな [AppName].run.json ファイルを使用して起動プロファイルを設定できます。app.cs の場合は、app.run.json を作成します。
{
"profiles": {
"https": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
--launch-profile を指定してプロファイルを選択します。
dotnet run app.cs --launch-profile https
app.run.json と Properties/launchSettings.json の両方が存在する場合は、従来の場所が優先されます。
ユーザーシークレット
ファイルベースのアプリでは、ファイルのフルパスから安定したユーザーシークレット ID が生成されます。
dotnet user-secrets set "ApiKey" "your-secret-value" --file app.cs
dotnet user-secrets list --file app.cs
暗黙的なビルドファイル
ファイルベースのアプリでは、同じディレクトリまたは親ディレクトリにある MSBuild および NuGet の構成ファイルが適用されます。
Directory.Build.props-- 継承される MSBuild プロパティDirectory.Build.targets-- 継承される MSBuild ターゲットDirectory.Packages.props-- 一元管理されたパッケージのバージョンnuget.config-- NuGet パッケージソースの構成global.json-- SDK バージョンの固定
従来のプロジェクトも含まれるリポジトリにファイルベースのアプリを配置する場合は、これらのファイルに注意してください。継承されたプロパティによって、予期しないビルド動作が発生する場合があります。
ビルドキャッシュ
SDK は、ソースの内容、ディレクティブ、SDK バージョン、暗黙的なビルドファイルに基づいてビルド出力をキャッシュします。キャッシュにより、dotnet run を繰り返し実行する際のパフォーマンスが向上します。
既知のキャッシュに関する注意点:
- 暗黙的なビルドファイル(
Directory.Build.propsなど)を変更しても、再ビルドが実行されない場合があります - ファイルを別のディレクトリに移動しても、キャッシュは無効になりません
- 同じファイルベースのアプリを同時に実行すると、ビルドの競合エラーが発生することがあります。まず
dotnet build app.csでビルドし、その後dotnet run app.cs --no-buildで複数のインスタンスを実行してください
dotnet clean app.cs または dotnet clean file-based-apps を実行すると、キャッシュをクリアできます。
フォルダーレイアウト
ファイルベースのアプリを、.csproj プロジェクトのディレクトリツリー内に配置しないでください。プロジェクトの暗黙的なビルド構成が干渉します。
# Recommended layout
repo/
src/
MyProject/
MyProject.csproj
Program.cs
scripts/ # Separate directory for file-based apps
utility.cs
tool.cs
移行:ファイルベースからプロジェクトベースへ
ファイルベースのアプリが単一ファイルでは収まらなくなった場合は、従来のプロジェクトに変換します。
自動変換
dotnet project convert app.cs
これにより、アプリ名の新しいディレクトリが作成され、次の内容が含まれます。
#:ディレクティブから導出された、同等の SDK、プロパティ、パッケージ参照を含む.csproj#:ディレクティブを削除した.csファイルのコピー
元の .cs ファイルは変更されません。
変換するタイミング
次の場合は、プロジェクトベースのアプリに変換してください。
- 複数のソースファイルが必要な場合
#:propertyでサポートされる範囲を超える、複雑な MSBuild のカスタマイズが必要な場合- テストフレームワークを使った
dotnet testが必要な場合 .csprojを想定した CI/CD ワークフローとの統合が必要な場合- チームメンバーが IDE のプロジェクトサポート(ソリューションエクスプローラーなど)を必要とする場合
既定の動作
ファイルベースのアプリでは、プロジェクトベースのアプリとは既定の設定が一部異なります。
| 設定 | ファイルベースの既定値 | プロジェクトベースの既定値 |
|---|---|---|
ネイティブ AOT(PublishAot) | true | false |
ツールとしてパッケージ化(PackAsTool) | true | false |
| ビルド出力先 | システムの一時ディレクトリ | プロジェクトディレクトリ内の bin/ |
| 発行出力先 | .cs ファイルの隣にある artifacts/ | bin/<config>/<tfm>/publish/ |
エージェントでの注意点
- ファイルベースアプリとファイル I/O を混同しないでください --
dotnet-file-based-appsは、プロジェクトファイルなしで C# を実行する方法を扱います(.NET 10 SDK feature)。FileStream、RandomAccess、パスの処理には、[skill:dotnet-file-io] を使用してください。 - C# コードの後に
#:ディレクティブを置かないでください -- すべてのディレクティブは、C# のステートメント、usingディレクティブ、名前空間宣言より前の、ファイルの先頭に置く必要があります。SDK はファイルの後半に置かれたディレクティブを無視します。 - CPM なしでパッケージのバージョンを省略しないでください --
#:package SomePackageでバージョンを省略できるのは、Directory.Packages.propsを使って Central Package Management を構成している場合のみです。CPM がない場合は、#:package [email protected]または#:package SomePackage@*を使用してください。 dotnet buildとdotnet testが同じように動作すると思い込まないでください --dotnet build app.csは仮想プロジェクトを通じてコンパイルしますが、dotnet testはファイルベースアプリには適用されません。テストフレームワークをサポートするには、プロジェクトに変換してください。- ファイルベースアプリを
.csprojプロジェクトのディレクトリ内に置かないでください -- プロジェクトの暗黙的なビルドファイル(Directory.Build.propsなど)がファイルベースアプリに影響し、予期しない動作を引き起こします。別のディレクトリを使用してください。 - 事前ビルドせずに複数のインスタンスを同時実行しないでください -- 同じファイルベースアプリを並列実行すると、ビルド出力が競合します。最初に
dotnet build app.csでビルドしてから、dotnet run app.cs --no-buildでインスタンスを実行してください。 - 後方互換性を忘れないでください -- 現在のディレクトリに
.csprojがある場合、dotnet run app.csはファイルベースアプリとして実行せず、app.csをプロジェクトへの引数として渡します。ファイルベースアプリとして実行するには、dotnet run --file app.csを使用してください。 - シバンを使う場合、
CRLFの改行コードを使用しないでください -- Unix のシバン実行には、LFの改行コードと BOM がないことが必要です。CRLFのファイルは/usr/bin/env: 'dotnet\r': No such file or directoryというエラーで失敗します。