[Feature] Enable --flag / --no-flag syntax for DisallowNone[bool | None]
When using DisallowNone[bool | None] for boolean fields with None defaults, tyro currently generates choice-based syntax ({True,False}) instead of the standard boolean flag syntax (--flag / --no-flag). This creates a UX inconsistency where plain bool fields get natural flag syntax, but nullable booleans with DisallowNone require explicit values.
Current Behavior
from dataclasses import dataclass
from typing import Annotated
import tyro
@dataclass
class Config:
# Plain bool: gets --flag / --no-flag syntax
plain: bool = False
# DisallowNone bool: requires explicit True/False
configurable: Annotated[
tyro.conf.DisallowNone[bool | None],
tyro.conf.arg(aliases=('--cfg',)),
] = None
tyro.cli(Config)
Help output:
--flag, --no-flag, --plain, --no-plain
Description (default: False)
--cfg {True,False}, --configurable {True,False}
Description (default: None)
Required usage:
./script.py --configurable True # verbose, non-standard
Desired Behavior
Since DisallowNone prevents users from explicitly passing None via the CLI, the type effectively becomes a two-state boolean from the CLI's perspective (even though None remains valid as a default value). It would be more intuitive if tyro treated this as equivalent to a plain bool for CLI syntax purposes:
Desired help output:
--cfg, --no-cfg, --configurable, --no-configurable
Description (default: None)
Desired usage:
./script.py --configurable # sets to True
./script.py --no-configurable # sets to False
./script.py # uses None default
Use Case
This pattern is particularly valuable for CLIs with configurable config file locations (e.g., --configfile). You need three-state logic:
-
None= "consult the config file" (default) -
True/False= "override the config file value"
But you can't load config defaults before parsing CLI args (chicken-and-egg problem with --configfile). DisallowNone[bool | None] currently solves the semantic problem but creates a UX friction point.
Related Issues
This relates to #254 (detecting provided vs default values), but represents a simpler, more targeted enhancement that could be implemented independently. While #254 would provide a more general solution, this feature would address the specific UX pain point for boolean flags in the meantime.
Co-Authored-By: Claude [email protected]
Just made a PR with a fix, thanks @emcd!
Awesome! Thank you, @brentyi . Yet another iteration towards convergence on CLI generator perfection.