rich-argparse
rich-argparse is a set of Rich-powered help formatters for Python's standard argparse, plus integrations for Django management commands and experimental optparse support. Replace an ArgumentParser's formatter class and it colors usage, option names, metavariables, group titles, defaults, descriptions, and epilogs while leaving argparse responsible for parsing and validation. It can preserve raw text or paragraphs, render Markdown and other Rich objects, customize regex highlights, and export help previews to SVG, HTML, or text.
rich-argparse is the right small upgrade for an argparse CLI whose help deserves better hierarchy and documentation output. Do not install it expecting a new command framework, and account for markup escaping, per-subparser setup, Rich's dependency cost, and terminal-dependent snapshots.
Use it if
- You already have an argparse CLI and want more readable help without moving every command and option to another framework
- You need the same parsing semantics as argparse while adding themeable colors, markup, highlights, or Rich renderables
- You want generated SVG, HTML, or text help previews for documentation
- You need to apply Rich help formatting across Django management commands or an old optparse CLI
- You want command decorators, type-driven option creation, prompts, shell completion, configuration files, or command execution helpers: this package formats help and does not replace argparse's programming model
- Your CLI already uses Click or Typer: rich-click is designed for that command tree, while rich-argparse only integrates with argparse, Django's argparse layer, and experimental optparse
- You need zero third-party runtime dependencies for a tiny utility: the only behavioral change is help presentation, but it brings Rich and its dependency footprint
- Your help text contains user-controlled or literal square-bracket syntax: descriptions, epilogs, and argument help are interpreted as Rich markup by default unless escaped or markup is disabled
- You rely on one parent formatter setting flowing into every command: argparse subparsers do not inherit formatter_class, so each subparser must receive it explicitly
Setup reality
pip install rich-argparse installs Rich 11 or newer and version 1.8.0 requires Python 3.9+. It does not change an existing parser until formatter_class is passed to ArgumentParser, and it does not alter parsing, errors, defaults, or actions. Subparsers are the first surprise: argparse creates a new parser for each command and does not inherit the parent's formatter, so pass formatter_class=parser.formatter_class to every add_parser call or commands fall back to plain help. The five core formatters mirror argparse's standard wrapping choices. RichHelpFormatter collapses ordinary line breaks like HelpFormatter; use RawDescriptionRichHelpFormatter, RawTextRichHelpFormatter, ParagraphRichHelpFormatter, or ExtendedParagraphRichHelpFormatter only when their whitespace rules are intentional. Text and help markup are enabled by default. Literal examples such as array[index], regular expressions, or template syntax can be consumed as Rich tags or raise markup errors; escape brackets or set text_markup and help_markup false on a dedicated subclass. Do not mutate RichHelpFormatter.styles or highlights globally inside a reusable library, because those class-level dictionaries and lists affect every parser in the process. Create a subclass with copied containers for one CLI. Generated usage is styled automatically, but custom usage is plain unless usage_markup is enabled, at which point its brackets need Rich escaping too. Rich decides color from the output environment, while terminal width and COLUMNS affect wrapping. Snapshot tests should use a controlled Console with fixed width, color policy, and output capture rather than recording whatever the developer terminal emits. Arbitrary Rich renderables work as description and epilog, but they do not receive string highlighting, argparse.text styling, or %(prog)s substitution. HelpPreviewAction writes to disk when its hidden option is invoked, so choose a path the process may write and do not accidentally overwrite checked-in documentation. Django integration must run before execute_from_command_line. Optparse support is explicitly experimental, so do not treat it as equal in stability to the argparse formatter classes. Legacy Windows 7 needs colorama for color support.
Patterns
Add Rich formatting to an argparse parserformat-basic-help
import argparse
from rich_argparse import RichHelpFormatter
parser = argparse.ArgumentParser(
prog='acme',
description='Manage the Acme service.',
formatter_class=RichHelpFormatter,
)
parser.add_argument('--region', metavar='NAME', help='Target region')
args = parser.parse_args()Only help rendering changes. Argument parsing, validation, actions, and the returned Namespace still come from argparse.
Include defaults in styled helpshow-default-values
from rich_argparse import ArgumentDefaultsRichHelpFormatter
parser = argparse.ArgumentParser(
formatter_class=ArgumentDefaultsRichHelpFormatter,
)
parser.add_argument('--timeout', type=float, default=10.0, help='Request timeout')Defaults may expose local paths, hosts, or other environment-specific values. Do not put secrets in argument defaults.
Preserve deliberate description line breakspreserve-description-layout
from rich_argparse import RawDescriptionRichHelpFormatter
parser = argparse.ArgumentParser(
description='First step:\n acme init\n\nSecond step:\n acme run',
formatter_class=RawDescriptionRichHelpFormatter,
)RawDescription preserves the description and epilog layout, but ordinary argument help still follows argparse wrapping rules.
Preserve paragraphs while wrapping their linespreserve-paragraphs
from rich_argparse.contrib import ParagraphRichHelpFormatter
parser = argparse.ArgumentParser(
description='First paragraph wraps normally.\n\nSecond paragraph stays separate.',
formatter_class=ParagraphRichHelpFormatter,
)Paragraph breaks require two newlines. Version 1.8 also offers ExtendedParagraphRichHelpFormatter for separate spacing control.
Pass the formatter to each subcommandstyle-subparsers
parser = argparse.ArgumentParser(formatter_class=RichHelpFormatter)
commands = parser.add_subparsers(dest='command', required=True)
build = commands.add_parser('build', formatter_class=parser.formatter_class)
build.add_argument('--release', action='store_true')
deploy = commands.add_parser('deploy', formatter_class=parser.formatter_class)
deploy.add_argument('environment')argparse subparsers do not inherit formatter_class from the parent. Omitting it gives that command plain help.
Customize styles without global mutationcustomize-theme
class AcmeHelpFormatter(RichHelpFormatter):
styles = {
**RichHelpFormatter.styles,
'argparse.args': 'bold cyan',
'argparse.groups': 'bold magenta',
'argparse.metavar': 'yellow',
}
parser = argparse.ArgumentParser(formatter_class=AcmeHelpFormatter)Copy the styles dictionary on a subclass. Mutating RichHelpFormatter.styles changes every parser using the base class in this process.
Treat brackets as literal help textdisable-markup
class LiteralHelpFormatter(RichHelpFormatter):
text_markup = False
help_markup = False
parser = argparse.ArgumentParser(
description='Accepts values like array[index].',
formatter_class=LiteralHelpFormatter,
)Markup is enabled by default in descriptions, epilogs, and argument help. Disable it when text is generated or bracket-heavy.
Highlight a project-specific filenameadd-custom-highlight
class ProjectHelpFormatter(RichHelpFormatter):
styles = {**RichHelpFormatter.styles, 'argparse.config': 'bold green'}
highlights = [
*RichHelpFormatter.highlights,
r'\b(?P<config>pyproject\.toml)\b',
]
parser = argparse.ArgumentParser(formatter_class=ProjectHelpFormatter)The named regex group must match a style suffix, here config maps to argparse.config.
Use Markdown as the parser descriptionrender-markdown-description
from rich.markdown import Markdown
description = Markdown('''
# Acme deploy
* Validates the release
* Uploads artifacts
''', style='argparse.text')
parser = argparse.ArgumentParser(
description=description,
formatter_class=RichHelpFormatter,
)Arbitrary renderables do not receive string highlights, automatic argparse.text styling, or %(prog)s replacement.
Style the argparse version actionstyle-version-output
parser.add_argument(
'--version',
action='version',
version='[argparse.prog]%(prog)s[/] version [bold]1.8.0[/]',
)Version strings accept Rich markup. Keep the program's real version in one source instead of duplicating the literal shown here.
Export help as an SVG documentation assetgenerate-help-preview
from rich_argparse import HelpPreviewAction
parser.add_argument(
'--generate-help-preview',
action=HelpPreviewAction,
path='docs/help.svg',
)The action is hidden from help and writes when invoked. The directory must exist and be writable; COLUMNS controls the preview width.
Use a fixed console for deterministic help testsstabilize-snapshot-output
from rich.console import Console
console = Console(width=100, color_system=None, force_terminal=False)
def formatter(prog):
return RichHelpFormatter(prog, console=console)
parser = argparse.ArgumentParser(formatter_class=formatter)
help_text = parser.format_help()The console argument is keyword-only. Fix width and color policy so snapshots do not depend on the developer terminal.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| rich-click | PyPI | Your CLI uses Click and you want Rich help applied to Click commands and groups |
| typer | PyPI | You want to design a new CLI from type annotations with commands, validation, completion, and Rich output included |
| click | PyPI | You want a mature full command framework and are comfortable with conventional help or adding a separate styling layer |