CLI Patterns¶
Advanced patterns and techniques for building CLIs with params-proto.
Grouped Options with Prefixes¶
Use @proto.prefix to organize related parameters into logical groups:
@proto.prefix
class Model:
"""Model architecture."""
name: str = "resnet50"
hidden_size: int = 256
@proto.prefix
class Training:
"""Training hyperparameters."""
lr: float = 0.001
batch_size: int = 32
@proto.cli
def main(seed: int = 42):
"""Train model."""
pass
Generated help:
usage: main.py [-h] [--seed INT] [OPTIONS]
Train model.
options:
-h, --help show this help message and exit
--seed INT Random seed (default: 42)
Model options:
Model architecture.
--Model.name STR Model name (default: resnet50)
--Model.hidden-size INT Hidden size (default: 256)
Training options:
Training hyperparameters.
--Training.lr FLOAT Learning rate (default: 0.001)
--Training.batch-size INT Batch size (default: 32)
This groups options visually and makes help text more readable for complex CLIs with many parameters.
Benefits¶
Organization - Related parameters grouped together
Readability - Help text clearly shows which parameters belong together
Discoverability - Users can find related options easily
Scalability - Works well with many parameters
See Advanced Patterns for more on prefixes and singleton behavior.
Custom Program Name¶
Override the program name displayed in help text:
@proto.cli(prog="train_model")
def train(lr: float = 0.001):
"""Train a model."""
pass
Generated help:
usage: train_model [-h] [--lr FLOAT]
Without prog, uses the script filename from sys.argv[0].
Use Cases¶
Wrapped scripts - When your script is called via a wrapper or alias
Clarity - Set a clearer name than the actual filename
Documentation - Use a name that matches your documentation
Testing Help Generation¶
Access generated help text programmatically for testing and documentation:
@proto.cli
def train(lr: float = 0.001):
"""Train a model."""
pass
# Plain text (for testing, logs, pipes)
print(train.__help_str__)
# Colorized (for terminal display)
print(train.__ansi_str__)
Use Cases¶
Unit tests - Verify help text is generated correctly
Documentation generation - Extract help text for docs
Debugging - Inspect what users will see
CI/CD - Validate help output in pipelines
Example Test¶
def test_help_text():
@proto.cli
def train(lr: float = 0.001):
"""Train a model."""
pass
help_text = train.__help_str__
assert "--lr" in help_text
assert "FLOAT" in help_text
assert "default: 0.001" in help_text
Edge Cases¶
Long Parameter Names¶
Long parameter names are automatically wrapped in help text:
@proto.cli
def train(
this_is_a_very_long_parameter_name: int = 1000,
):
"""Train with long names."""
pass
Generated help (wraps nicely):
--this-is-a-very-long-parameter-name INT
This is a very long parameter name (default: 1000)
Numbers in Names¶
Numbers are preserved in parameter names and converted properly:
@proto.cli
def train(
model_2d: bool = False, # → --model-2d
resnet50_pretrained: bool = True, # → --resnet50-pretrained
):
pass
Numbers remain in both the parameter name and the CLI argument, making it easy to reference models by version or variant.
Quick Pattern Reference¶
Pattern |
When to Use |
Example |
|---|---|---|
Basic CLI |
Simple scripts with few parameters |
|
Grouped Options |
Many related parameters |
Use |
Custom Program Name |
Wrapped scripts or clarity |
|
Testing |
Verify help output |
Access |