Repository: dotnet/command-line-api (2026-03-10T20:14:05Z)

Issue:
--help output lacks "[default: true]" if Option<bool> has `DefaultValueFactory` returning `true`
System.CommandLine version 2.0.0-rc.2.25502.107

Define an `Option` with a `DefaultValueFactory` for some non-default value and `--help` outputs the option, description and default value UNLESS the type is `bool` then the default is omitted even though `DefaultValueFactory` returns `true`

```
...
new Option<int>("--bool")
{
    Description = "Bool value"
},
new Option<int>("--bool-default")
{
    Description = "Bool value with default",
    DefaultValueFactory = result => { return true; }
},
new Option<int>("--int")
{
    Description = "Int value"
},
new Option<int>("--int-default")
{
    Description = "Int value with default",
    DefaultValueFactory = result => { return 123; }
},
new Option<string>("--string")
{
    Description = "String value"
},
new Option<string>("--string-default")
{
    Description = "String value with default",
    DefaultValueFactory = result => { return "my.default.value"; }
},
...
```

Run `foo.exe --help` and the output's

```
...
  --bool                                                        Bool value
  --bool-default                                                Bool value with default
  --int <int>                                                   Int value
  --int-default <int-default>                                   Int value with default [default: 123]
  --string <string>                                             String value
  --string-default <string-default>                             String value with default [default: my.default.value]
...
```

The 2nd line is wrong it should end with "[default: true]" e.g.

```
--bool-default                                                Bool value with default [default: true]
```


Discussion:
ping
ping



Patch:
diff --git a/src/System.CommandLine/Help/HelpBuilder.Default.cs b/src/System.CommandLine/Help/HelpBuilder.Default.cs
index 6dd03f433c..00364784dd 100644
--- a/src/System.CommandLine/Help/HelpBuilder.Default.cs
+++ b/src/System.CommandLine/Help/HelpBuilder.Default.cs
@@ -24,16 +24,18 @@ public static string GetArgumentDefaultValue(Symbol symbol)
             return symbol switch
             {
                 Argument argument => ShouldShowDefaultValue(argument) 
-                                         ? ToString(argument.GetDefaultValue()) 
+                                         ? ToString(argument.GetDefaultValue(), argument.ValueType) 
                                          : "",
                 Option option => ShouldShowDefaultValue(option) 
-                                     ? ToString(option.GetDefaultValue()) 
+                                     ? ToString(option.GetDefaultValue(), option.ValueType) 
                                      : "",
                 _ => throw new InvalidOperationException("Symbol must be an Argument or Option.")
             };
 
-            static string ToString(object? value) => value switch
+            static string ToString(object? value, Type valueType) => value switch
             {
+                _ when (valueType == typeof(bool) || valueType == typeof(bool?)) && value is not true => string.Empty,
+                bool boolValue => boolValue ? "true" : "false",
                 null => string.Empty,
                 string str => str,
                 IEnumerable enumerable => string.Join("|", enumerable.Cast<object>()),
@@ -50,12 +52,10 @@ public static bool ShouldShowDefaultValue(Symbol symbol) =>
             };
 
         public static bool ShouldShowDefaultValue(Option option) =>
-            option.HasDefaultValue && 
-            !(option.ValueType == typeof(bool) || option.ValueType == typeof(bool?));
+            option.HasDefaultValue;
 
         public static bool ShouldShowDefaultValue(Argument argument) =>
-            argument.HasDefaultValue && 
-            !(argument.ValueType == typeof(bool) || argument.ValueType == typeof(bool?));
+            argument.HasDefaultValue;
 
         /// <summary>
         /// Gets the description for an argument (typically used in the second column text in the arguments section).
@@ -289,4 +289,4 @@ public static Func<HelpContext, bool> OptionsSection() =>
         public static Func<HelpContext, bool> AdditionalArgumentsSection() =>
             ctx => ctx.HelpBuilder.WriteAdditionalArguments(ctx);
     }
-}
\ No newline at end of file
+}
diff --git a/src/System.CommandLine/Help/HelpBuilder.cs b/src/System.CommandLine/Help/HelpBuilder.cs
index af6046d898..eccbd7a668 100644
--- a/src/System.CommandLine/Help/HelpBuilder.cs
+++ b/src/System.CommandLine/Help/HelpBuilder.cs
@@ -475,10 +475,9 @@ string GetOptionOrCommandDefaultValue()
                 }
 
                 var isSingleArgument = defaultArguments.Length == 1;
-                var argumentDefaultValues = string.Join(
-                    ", ",
-                    defaultArguments
-                        .Select(argument => GetArgumentDefaultValue(symbol, argument, isSingleArgument, context)));
+                var argumentDefaultValues = string.Join(", ", defaultArguments
+                    .Select(argument => GetArgumentDefaultValue(symbol, argument, isSingleArgument, context))
+                    .Where(defaultValue => !string.IsNullOrEmpty(defaultValue)));
 
                 return string.IsNullOrEmpty(argumentDefaultValues)
                            ? ""


Test patch:
diff --git a/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs b/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs
index 342907d5db..1126365073 100644
--- a/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs
+++ b/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs
@@ -1350,6 +1350,27 @@ public void Help_describes_default_value_for_option_with_argument_having_default
             help.Should().Contain($"[default: the-arg-value]");
         }
 
+        [Fact]
+        public void Help_describes_default_value_for_boolean_option_when_default_value_is_true()
+        {
+            var command = new Command("the-command", "command help")
+            {
+                new Option<bool>("--bool-default")
+                {
+                    Description = "Bool value with default",
+                    DefaultValueFactory = _ => true
+                }
+            };
+
+            HelpBuilder helpBuilder = GetHelpBuilder(SmallMaxWidth);
+
+            helpBuilder.Write(command, _console);
+
+            var help = _console.ToString();
+
+            help.Should().Contain("--bool-default").And.Contain("[default: true]");
+        }
+
         [Fact]
         public void Option_arguments_with_default_values_that_are_enumerable_display_pipe_delimited_list()
         {