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.
Nested Dataclass Configuration¶
Override fields in nested dataclasses using dot notation:
from dataclasses import dataclass, field
@dataclass
class ModelConfig:
hidden_size: int = 256
num_layers: int = 4
@dataclass
class TrainConfig:
epochs: int = 100
model: ModelConfig = field(default_factory=ModelConfig)
@proto.cli
def main(config: TrainConfig):
"""Train with nested config."""
print(f"epochs={config.epochs}")
print(f"model.hidden_size={config.model.hidden_size}")
CLI usage:
# Override top-level and nested fields
python train.py train-config --epochs 200 --model.hidden-size 512 --model.num-layers 8
Output:
epochs=200
model.hidden_size=512
model.num_layers=8
Benefits¶
Deep nesting - Works with arbitrary nesting depth (
--model.encoder.layers)Type conversion - Nested fields are converted to their annotated types
Kebab-case - Use
--model.hidden-size(kebab) forhidden_size(snake)
Quick Pattern Reference¶
Pattern |
When to Use |
Example |
|---|---|---|
Basic CLI |
Simple scripts with few parameters |
|
Grouped Options |
Many related parameters |
Use |
Nested Configs |
Hierarchical configuration |
Use nested dataclasses with dot notation |
Custom Program Name |
Wrapped scripts or clarity |
|
Testing |
Verify help output |
Access |