Upgrade to Pro — share decks privately, control downloads, hide ads and more …

祝!!System.CommandLine GA!!

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for KM5075 KM5075
April 24, 2026
270

祝!!System.CommandLine GA!!

Avatar for KM5075

KM5075

April 24, 2026

Transcript

  1. Microsoft 公式の.NET 向け CLI パーサーライブラリ NuGet パッケージ: System.CommandLine リポジトリ: dotnet/command-line-api

    (GitHub ) .NET アプリにコマンドライン引数の解析機能を提供 オプション・引数・サブコマンドを宣言的に定義できる ヘルプ表示・バリデーション・タブ補完をサポート(dotnet-suggest ) dotnet コマンド自体も System.CommandLine 製 System.CommandLine とは? System.CommandLine とは? 5
  2. args[] を手動でパースすると… // 従来の方法 ← つらい if (args.Length > 0

    && args[0] == "--name") { var name = args[1]; // インデックスミス多発 } 純粋に1つのタスクだけを実行するならCLI ライブラリは不要。 ユーザーが入力したデータを受け取って、実行する処理を変えるようなケースでは arg のパースがしんどくなるためCLI ライブラリの使用が推奨。 なぜ CLI ライブラリを使用するか? なぜ CLI ライブラリを使用するか? 6
  3. CLI ツールの需要は高まっている? 自動化・CI/CD スクリプトとの連携 DevOps ツール・バッチ処理・開発補助ツール AI 連携をさせる場合、GUI ツールよりも安定 AI

    を使用して作成した業務効率化exe をまとめて管理することも可能 MCP との棲み分け なぜ CLI か?(続き) なぜ CLI か?(続き) 7
  4. 長い " ベータの旅" 時期 出来事 2020 年1 月 NuGet に

    版パッケージ初公開 0.3.0-alpha.20054.1 2020 〜2022 年 2.0.0-beta1 〜 beta3 リリース 2022 年〜2025 年 2.0.0-beta4.xxxx を最後に3 年間更新なし。 。 。 System.CommandLine の歴史 System.CommandLine の歴史 9
  5. 「Is this project dead? 」 ※2023 年 https://github.com/dotnet/command-line-api/issues/2285 「Roadmap for

    release? 」 ※2024 年 https://github.com/dotnet/command-line-api/issues/2500 Bata 版が長引いているときのコミュニティの反応 Bata 版が長引いているときのコミュニティの反応 10
  6. 「Announcing System.CommandLine 2.0.0-beta5 and our path to a stable release

    」 ※2025 年6 月 https://github.com/dotnet/command-line-api/issues/2576 そしてついに。 。 。 そしてついに。 。 。 11
  7. - 2.0.0-bata5 について API やメンバーのリネーム カスタム解析の改善 - 安定リリースについて - 一部実験プロジェクトの廃止について

    安定化リリースへの明確な道筋がなかったプロジェクトは非推奨に。 サードパーティーライブラリで代替 System.CommandLine としてはコア機能に集中 アナウンスの内容(抜粋) アナウンスの内容(抜粋) 12
  8. System.CommandLine.DragonFruit Main メソッドのみでCLI アプリケーションを完結させる static void Main(int intOption = 42,

    bool boolOption = false, FileInfo fileOption = null) { Console.WriteLine($"The value of intOption is: {intOption}"); Console.WriteLine($"The value of boolOption is: {boolOption}"); Console.WriteLine($"The value of fileOption is: {fileOption?.FullName ?? "null"}"); } Stable Release で削除された機能たち2 Stable Release で削除された機能たち2 14
  9. 実行例 $ myapp --name Alice Hello, Alice! $ myapp --help

    # ← ヘルプ自動生成! 基本的な使い方: Option の実行例 基本的な使い方: Option の実行例 17
  10. Option<T> でオプションを定義する var nameOption = new Option<string>("--name") { Description =

    "あいさつする相手の名前", DefaultValueFactory = _ => "World" // デフォルト値を設定する場合 }; var rootCommand = new RootCommand("あいさつアプリ"); rootCommand.Options.Add(nameOption); // 実行する処理 rootCommand.SetAction(parseResult => { var name = parseResult.GetValue(nameOption); Console.WriteLine($"Hello, {name}!"); }); 基本的な使い方: Option の追加 基本的な使い方: Option の追加 18
  11. Argument の定義 var fileArgument = Argument<string>("path"){ Description = "The path

    of file" }; rootCommand.Arguments.Add(nameArgument); rootCommand.SetAction( parseResult => { var path = parseResult.GetValue(nameArgument); Console.WriteLine($"Path is {path}!"); }); 基本的な使い方: Argument の定義 基本的な使い方: Argument の定義 20
  12. Option vs Argument の違い Option Argument 記法 --name Alice Alice

    (位置引数) 必須 任意(デフォルト値可) 通常は必須 例 --output ./out git add <pathspec> 基本的な使い方: Argument 基本的な使い方: Argument 21
  13. サブコマンドを実行する $ myapp add --item "タスクA" $ myapp list 基本的な使い方:

    サブコマンドの実行例 基本的な使い方: サブコマンドの実行例 22
  14. // 2. サブコマンド 'add' の定義とアクション設定 var addCommand = new Command("add",

    "新しいアイテムを追加します"); addCommand.SetAction(_ => { Console.WriteLine("「add」コマンドが実行されました。アイテムを追加します..."); }); // 3. サブコマンド 'list' の定義とアクション設定 var listCommand = new Command("list", "アイテムの一覧を表示します"); listCommand.SetAction(_ => { Console.WriteLine("「list」コマンドが実行されました。一覧を取得します..."); }); // 4. サブコマンドをルートに追加 rootCommand.Subcommands.Add(addCommand); rootCommand.Subcommands.Add(listCommand); 基本的な使い方: サブコマンドの使い方 基本的な使い方: サブコマンドの使い方 23
  15. 型バリデーションは自動 // int 型なので文字列を渡すとエラー var countOption = new Option<int>("--count", "繰り返し回数");

    // 必須オプションの設定 var nameOption = new Option<string>("--name", "名前") { IsRequired = true }; バリデーション バリデーション 24
  16. カスタムバリデーション Option<int> count = new Option<int>("--count") { Description = "The

    number of times to greet.", Required = true, }; // バリデーションロジック追加 count.Validators.Add(result => { if (result.GetValueOrDefault<int>() <= 0) { result.AddError("The count must be a positive integer."); } }); // ArgumentやCommandにもバリデーションロジックは追加可能 バリデーション バリデーション 25
  17. --help は自動生成 $ myapp --help Description: あいさつアプリ Options: --name <name>

    あいさつする相手の名前 [required] --version Show version information -?, -h, --help Show help and usage information ヘルプの自動生成 ヘルプの自動生成 26
  18. dotnet-suggest を用いることでサブコマンドやオプションの補完が可能。 ※この際に対象のExe のパスをdotnet-suggest register --command-path で登録 更にCompletionSources を実装することで動的に補完を構成することも可能 var

    idArg = new Argument<int>("id") { Description = "完了にするTodoのID" }; idArg.CompletionSources.Add((ctx) => { var todos = repo.GetAll(); return todos.Where(t => !t.IsCompleted).Select(t => t.Id.ToString()); }); タブ補完 タブ補完 27
  19. 機能 方法 オプション定義 new Option<T>("--name") 位置引数 new Argument<T>("file") サブコマンド new

    Command("add") ヘルプ自動生成 --help で自動表示 バリデーション AddValidator() タブ補完 dotnet-suggest 連携 System.CommandLine でできること System.CommandLine でできること 30