Version

Click Extra provides its own version option which, compared to Click’s built-in:

Defaults

Here is how the defaults looks like:

import click
import click_extra

@click.command
@click_extra.version_option(version="1.2.3")
def cli():
    pass
$ cli --help
Usage: cli [OPTIONS]

Options:
  --version  Show the version and exit.
  --help     Show this message and exit.

The default version message is the same as Click’s default, but colored:

$ cli --version
cli, version 1.2.3

Hint

In the examples of this page the version is hard-coded to 1.2.3 for the sake of demonstration.

In most cases, you do not need to force it, as the version will be automatically fetched from the package metadata of the CLI or the __version__ attribute of the command.

Variables

The message template is a format string, which defaults to:

f"{prog_name}, version {version}"

Caution

This is different from Click, which uses the %(prog)s, version %(version)s template.

Click is based on old-school printf-style formatting, which relies on variables of the %(variable)s form.

Click Extra uses modern format string syntax, with variables of the {variable} form, to provide a more flexible and powerful templating.

You can customize the message template with the following variables:

Variable

Description

{module}

The module object in which the command is implemented.

{module_name}

The __name__ of the module in which the command is implemented.

{module_file}

The full path of the file in which the command is implemented.

{module_version}

The string found in the local __version__ variable of the module.

{package_name}

The name of the package in which the CLI is distributed.

{package_version}

The version from the package metadata in which the CLI is distributed.

{exec_name}

User-friendly name of the executed CLI. Returns {module_name}, {package_name} or script’s filename, in this order.

{version}

Version of the CLI. Returns {module_version}, {package_version} or None, in this order. For .dev versions, automatically appends the Git commit hash.

{git_repo_path}

The full path to the Git repository root directory, or None if not in a Git repository.

{git_branch}

The current Git branch name, or None if not in a Git repository or Git is not available.

{git_long_hash}

The full Git commit hash of the current HEAD, or None if not in a Git repository or Git is not available.

{git_short_hash}

The short Git commit hash of the current HEAD, or None if not in a Git repository or Git is not available.

{git_date}

The commit date of the current HEAD in ISO format (YYYY-MM-DD HH:MM:SS +ZZZZ), or None if not in a Git repository or Git is not available.

{git_tag}

The Git tag pointing at HEAD, or None if HEAD is not at a tagged commit.

{git_tag_sha}

The full commit SHA that the current tag points at, or None if HEAD is not at a tagged commit.

{prog_name}

The display name of the program. Defaults to Click’s info_name, but can be overridden via prog_name on the command decorator.

{env_info}

The environment information in JSON.

Note

The git_* variables are evaluated at runtime by calling git. They return None in environments where Git is not available (e.g., standalone Nuitka binaries, Docker containers without Git).

All git_* fields can be pre-baked at build time by defining __<field>__ dunder variables in the CLI module. Pre-baked values take priority over subprocess calls.

Hint

The {version} variable is resolved in this order:

  1. A __version__ variable defined alongside your CLI (see standalone scripts).

  2. A __version__ variable in the parent package’s __init__.py (for __main__ entry points, e.g. Nuitka-compiled binaries).

  3. The version from package metadata via importlib.metadata — this is the most common source for installed packages.

  4. None if none of the above succeeds (e.g. unpackaged scripts without __version__).

Error

Some Click’s built-in variables are not recognized:

  • %(package)s should be replaced by {package_name}

  • %(prog)s should be replaced by {prog_name}

  • All other %(variable)s should be replaced by their {variable} counterpart

You can compose your own version string by passing the message argument:

import click
import click_extra

@click.command
@click_extra.version_option(
    message="✨ {prog_name} v{version} - {package_name}",
    version="1.2.3",
)
def my_own_cli():
    pass
$ my-own-cli --version
✨ my-own-cli v1.2.3 - click_extra.sphinx

Caution

This results reports the package name as click_extra.sphinx because we are running the example from the click-extra documentation build environment. This is just a quirk of the documentation setup and will not affect your own CLI.

Overriding variables from the command

The version_fields parameter on @command and @group lets you override any template field without touching the default params list.

Fields can also be forced directly on the ExtraVersionOption instance via the params= argument:

import click
from click_extra import ExtraVersionOption

@click.command(params=[
    ExtraVersionOption(
        prog_name="Acme CLI",
        version="42.0",
        message="{prog_name} {version} (branch: {git_branch})",
        git_branch="release/42",
    ),
])
def acme():
    pass
$ acme --version
Acme CLI 42.0 (branch: release/42)

Standalone script

The --version option works with standalone scripts.

Let’s put this code in a file named greet.py:

greet.py
 1#!/usr/bin/env -S uv run --script
 2# /// script
 3# dependencies = ["click-extra"]
 4# ///
 5
 6import click_extra
 7
 8
 9@click_extra.command
10def greet():
11    print("Hello world")
12
13
14if __name__ == "__main__":
15    greet()

Here is the result of the --version option:

$ greet --version
greet, version None

Because the script is not packaged, the {version} variable is None.

But Click Extra recognize the __version__ variable, to force it in your script:

greet.py
 1#!/usr/bin/env -S uv run --script
 2# /// script
 3# dependencies = ["click-extra"]
 4# ///
 5
 6import click_extra
 7
 8
 9__version__ = "0.9.3-alpha"
10
11
12@click_extra.command
13def greet():
14    print("Hello world")
15
16
17if __name__ == "__main__":
18    greet()
$ greet --version
greet, version 0.9.3-alpha

Caution

The __version__ variable is not an enforced Python standard and more like a tradition.

It is supported by Click Extra as a convenience for script developers.

Development versions

When the version string contains .dev (as in PEP 440 development releases), Click Extra automatically appends the Git short commit hash as a PEP 440 local version identifier.

This lets you identify exactly which commit a development build was produced from:

import click
import click_extra

__version__ = "1.2.3.dev0"

@click.command
@click_extra.version_option()
def dev_cli():
    pass
$ dev-cli --version
dev-cli, version 1.2.3.dev0+8d89f53

For example, a version like 1.2.3.dev0 becomes 1.2.3.dev0+6e59c8c1 during development. Release versions (without .dev) are never modified.

If Git is not available or the CLI is not running from a Git repository, the plain .dev version is returned as-is.

Pre-baked versions

If the version string already contains a + (a PEP 440 local version identifier), Click Extra assumes the hash was pre-baked at build time and returns the version as-is, without appending a second hash.

This is useful for CI pipelines or Nuitka binaries where git is not available at runtime but the build step can inject the commit hash into __version__ before compilation:

import click
import click_extra

__version__ = "1.2.3.dev0+abc1234"

@click.command
@click_extra.version_option()
def prebaked_cli():
    pass
$ prebaked-cli --version
prebaked-cli, version 1.2.3.dev0+abc1234

Hint

Click Extra ships prebake_version(), a utility to automate this injection. It parses a Python source file with ast, locates the __version__ assignment, and appends a +<local_version> suffix in place. Call it in your build step before Nuitka/PyInstaller compilation.

Version lifecycle

The version resolution adapts to the runtime environment:

Scenario

__version__ in source

Git available?

{version} output

Local dev (from source)

1.0.0.dev0

Yes

1.0.0.dev0+abc1234

Nuitka binary (pre-baked)

1.0.0.dev0+abc1234

No

1.0.0.dev0+abc1234

Nuitka binary (not pre-baked)

1.0.0.dev0

No

1.0.0.dev0

Release

1.0.0

1.0.0

For Nuitka binaries, the recommended workflow is to inject the commit hash into __version__ before compilation. Repomatic automates this via its prebake-version command.

Pre-baking git metadata

All git_* template fields support pre-baking. If the CLI module defines a __<field>__ dunder variable with a non-empty string value, that value is used instead of calling git at runtime. This is the recommended approach for compiled binaries (Nuitka, PyInstaller) where git is unavailable.

The supported dunders are:

Dunder variable

Template field

Subprocess fallback

__git_branch__

{git_branch}

git rev-parse --abbrev-ref HEAD

__git_long_hash__

{git_long_hash}

git rev-parse HEAD

__git_short_hash__

{git_short_hash}

git rev-parse --short HEAD

__git_date__

{git_date}

git show -s --format=%ci HEAD

__git_tag__

{git_tag}

git describe --tags --exact-match HEAD

__git_tag_sha__

{git_tag_sha}

git rev-list -1 <tag> (if {git_tag} resolves)

To pre-bake a value, declare the dunder with an empty string placeholder in your __init__.py:

mypackage/__init__.py
__version__ = "1.0.0.dev0"
__git_branch__ = ""
__git_short_hash__ = ""

Then inject values at build time using prebake_dunder():

from pathlib import Path
from click_extra.version import prebake_dunder

prebake_dunder(Path("mypackage/__init__.py"), "__git_branch__", "main")
prebake_dunder(Path("mypackage/__init__.py"), "__git_short_hash__", "abc1234")

prebake_dunder() only replaces empty strings, so running it twice is safe (idempotent). It preserves the quoting style and surrounding file content.

discover_package_init_files() can auto-discover __init__.py paths from [project.scripts] in pyproject.toml, so you don’t need to hardcode paths in your build scripts.

CLI usage

The click-extra prebake command exposes these utilities from the command line, without writing Python:

$ # Bake __version__ and all git fields in one pass
$ click-extra prebake all

$ # Only inject Git hash into __version__
$ click-extra prebake version
$ click-extra prebake version --hash abc1234

$ # Set a specific field (double underscores added automatically)
$ click-extra prebake field git_tag_sha abc123def456...
$ click-extra prebake field git_branch main --module mypackage/__init__.py

All subcommands auto-discover target files from [project.scripts] in pyproject.toml. Use --module to target a specific file instead.

Colors

Each variable listed in the section above can be rendered in its own style. They all have dedicated parameters you can pass to the version_option decorator:

Parameter

Description

Default Style

message_style

Style of the whole message.

None

module_style

Style for {module} variable.

None

module_name_style

Style for {module_name} variable.

default_theme.invoked_command

module_file_style

Style for {module_file} variable.

None

module_version_style

Style for {module_version} variable.

Style(fg="green")

package_name_style

Style for {package_name} variable.

default_theme.invoked_command

package_version_style

Style for {package_version} variable.

Style(fg="green")

exec_name_style

Style for {exec_name} variable.

default_theme.invoked_command

version_style

Style for {version} variable.

Style(fg="green")

git_repo_path_style

Style for {git_repo_path} variable.

Style(fg="bright_black")

git_branch_style

Style for {git_branch} variable.

Style(fg="cyan")

git_long_hash_style

Style for {git_long_hash} variable.

Style(fg="yellow")

git_short_hash_style

Style for {git_short_hash} variable.

Style(fg="yellow")

git_date_style

Style for {git_date} variable.

Style(fg="bright_black")

git_tag_style

Style for {git_tag} variable.

Style(fg="cyan")

git_tag_sha_style

Style for {git_tag_sha} variable.

Style(fg="yellow")

prog_name_style

Style for {prog_name} variable.

default_theme.invoked_command

env_info_style

Style for {env_info} variable.

Style(fg="bright_black")

Here is an example:

import click
from click_extra import version_option, Style

@click.command
@version_option(
    message="{prog_name} v{version} 🔥 {package_name} ( ͡❛ ͜ʖ ͡❛)",
    message_style=Style(fg="cyan"),
    prog_name_style=Style(fg="green", bold=True),
    version_style=Style(fg="bright_yellow", bg="red"),
    package_name_style=Style(fg="bright_blue", italic=True),
    version="1.2.3",
)
def cli():
    pass
$ cli --version
cli v1.2.3 🔥 click_extra.sphinx ( ͡❛ ͜ʖ ͡❛)

You can pass None to any of the style parameters to disable styling for the corresponding variable:

import click
from click_extra import version_option

@click.command
@version_option(
    message_style=None,
    version_style=None,
    prog_name_style=None,
    version="1.2.3",
)
def cli():
    pass
$ cli --version
cli, version 1.2.3

Environment information

The {env_info} variable compiles all sorts of environment information.

Here is how it looks like:

import click
from click_extra import version_option

@click.command
@version_option(message="{env_info}")
def env_info_cli():
    pass
$ env-info-cli --version
{'username': '-', 'guid': '32cbbb0a0996e49b5d7d77ac6ef932c', 'hostname': '-', 'hostfqdn': '-', 'uname': {'system': 'Linux', 'node': '-', 'release': '6.1.146.1-microsoft-standard', 'version': '#1 SMP Mon Jul 21 20:38:16 UTC 2025', 'machine': 'x86_64', 'processor': 'x86_64'}, 'linux_dist_name': '', 'linux_dist_version': '', 'cpu_count': 1, 'fs_encoding': 'utf-8', 'ulimit_soft': 1048576, 'ulimit_hard': 1048576, 'cwd': '-', 'umask': '0o2', 'python': {'argv': '-', 'bin': '-', 'version': '3.14.4 (main, Apr 14 2026, 14:26:14) [Clang 22.1.3 ]', 'compiler': 'Clang 22.1.3 ', 'build_date': 'Apr 14 2026 14:26:14', 'version_info': [3, 14, 4, 'final', 0], 'features': {'openssl': 'OpenSSL 3.5.6 7 Apr 2026', 'expat': 'expat_2.6.3', 'sqlite': '3.50.4', 'tkinter': '9.0', 'zlib': '1.3.1', 'unicode_wide': True, 'readline': True, '64bit': True, 'ipv6': True, 'threading': True, 'urandom': True}}, 'time_utc': '2026-04-16 16:13:46.456264+00:00', 'time_utc_offset': 0.0, '_eco_version': '1.1.0'}

It’s verbose but it’s helpful for debugging and reporting of issues from end users.

Important

The JSON output is scrubbed out of identifiable information by default: current working directory, hostname, Python executable path, command-line arguments and username are replaced with -.

Another trick consist in picking into the content of {env_info} to produce highly customized version strings. This can be done because {env_info} is kept as a dict:

import click
from click_extra import version_option

@click.command
@version_option(
    message="{prog_name} {version}, from {module_file} (Python {env_info[python][version]})",
    version="1.2.3",
)
def custom_env_info():
    pass
$ custom-env-info --version
custom-env-info 1.2.3, from /home/runner/work/click-extra/click-extra/click_extra/sphinx/click.py (Python 3.14.4 (main, Apr 14 2026, 14:26:14) [Clang 22.1.3 ])

Debug logs

When the DEBUG level is enabled, all available variables will be printed in the log:

import click
from click_extra import version_option, verbosity_option, echo

@click.command
@version_option(version="1.2.3")
@verbosity_option
def version_in_logs():
    echo("Standard operation")

Which is great to see how each variable is populated and styled:

$ version-in-logs --verbosity DEBUG
debug: Set <Logger click_extra (DEBUG)> to DEBUG.
debug: Set <RootLogger root (DEBUG)> to DEBUG.
debug: Cannot get version: 'click_extra.sphinx' package not found or not installed.
debug: Version string template variables:
debug: {module}         : <module 'click_extra.sphinx.click' from '/home/runner/work/click-extra/click-extra/click_extra/sphinx/click.py'>
debug: {module_name}    : click_extra.sphinx.click
debug: {module_file}    : /home/runner/work/click-extra/click-extra/click_extra/sphinx/click.py
debug: {module_version} : 1.2.3.dev0+abc1234
debug: {package_name}   : click_extra.sphinx
debug: {package_version}: None
debug: {exec_name}      : click_extra.sphinx.click
debug: {version}        : 1.2.3
debug: {git_repo_path}  : /home/runner/work/click-extra/click-extra
debug: {git_branch}     : main
debug: {git_long_hash}  : 8d89f53f3cad3e1978dbf88d1f67dd95fad0c646
debug: {git_short_hash} : 8d89f53
debug: {git_date}       : 2026-04-16 18:08:06 +0200
debug: {git_tag}        : None
debug: {git_tag_sha}    : None
debug: {prog_name}      : version-in-logs
debug: {env_info}       : {'username': '-', 'guid': '32cbbb0a0996e49b5d7d77ac6ef932c', 'hostname': '-', 'hostfqdn': '-', 'uname': {'system': 'Linux', 'node': '-', 'release': '6.1.146.1-microsoft-standard', 'version': '#1 SMP Mon Jul 21 20:38:16 UTC 2025', 'machine': 'x86_64', 'processor': 'x86_64'}, 'linux_dist_name': '', 'linux_dist_version': '', 'cpu_count': 1, 'fs_encoding': 'utf-8', 'ulimit_soft': 1048576, 'ulimit_hard': 1048576, 'cwd': '-', 'umask': '0o2', 'python': {'argv': '-', 'bin': '-', 'version': '3.14.4 (main, Apr 14 2026, 14:26:14) [Clang 22.1.3 ]', 'compiler': 'Clang 22.1.3 ', 'build_date': 'Apr 14 2026 14:26:14', 'version_info': [3, 14, 4, 'final', 0], 'features': {'openssl': 'OpenSSL 3.5.6 7 Apr 2026', 'expat': 'expat_2.6.3', 'sqlite': '3.50.4', 'tkinter': '9.0', 'zlib': '1.3.1', 'unicode_wide': True, 'readline': True, '64bit': True, 'ipv6': True, 'threading': True, 'urandom': True}}, 'time_utc': '2026-04-16 16:13:46.456264+00:00', 'time_utc_offset': 0.0, '_eco_version': '1.1.0'}
Standard operation
debug: Reset <RootLogger root (DEBUG)> to WARNING.
debug: Reset <Logger click_extra (DEBUG)> to WARNING.

Get metadata values

You can get the uncolored, Python values used in the composition of the version message from the context:

import click
from click_extra import echo, pass_context, version_option

@click.command
@version_option(version="1.2.3")
@pass_context
def version_metadata(ctx):
    version = ctx.meta["click_extra.version"]
    package_name = ctx.meta["click_extra.package_name"]
    prog_name = ctx.meta["click_extra.prog_name"]
    env_info = ctx.meta["click_extra.env_info"]

    echo(f"version = {version}")
    echo(f"package_name = {package_name}")
    echo(f"prog_name = {prog_name}")
    echo(f"env_info = {env_info}")
$ version-metadata --version
version-metadata, version 1.2.3
$ version-metadata
version = 1.2.3
package_name = click_extra.sphinx
prog_name = version-metadata
env_info = {'username': '-', 'guid': '32cbbb0a0996e49b5d7d77ac6ef932c', 'hostname': '-', 'hostfqdn': '-', 'uname': {'system': 'Linux', 'node': '-', 'release': '6.1.146.1-microsoft-standard', 'version': '#1 SMP Mon Jul 21 20:38:16 UTC 2025', 'machine': 'x86_64', 'processor': 'x86_64'}, 'linux_dist_name': '', 'linux_dist_version': '', 'cpu_count': 1, 'fs_encoding': 'utf-8', 'ulimit_soft': 1048576, 'ulimit_hard': 1048576, 'cwd': '-', 'umask': '0o2', 'python': {'argv': '-', 'bin': '-', 'version': '3.14.4 (main, Apr 14 2026, 14:26:14) [Clang 22.1.3 ]', 'compiler': 'Clang 22.1.3 ', 'build_date': 'Apr 14 2026 14:26:14', 'version_info': [3, 14, 4, 'final', 0], 'features': {'openssl': 'OpenSSL 3.5.6 7 Apr 2026', 'expat': 'expat_2.6.3', 'sqlite': '3.50.4', 'tkinter': '9.0', 'zlib': '1.3.1', 'unicode_wide': True, 'readline': True, '64bit': True, 'ipv6': True, 'threading': True, 'urandom': True}}, 'time_utc': '2026-04-16 16:13:46.456264+00:00', 'time_utc_offset': 0.0, '_eco_version': '1.1.0'}

Hint

These variables are presented in their original Python type. If most of these variables are strings, others like env_info retains their original dict type.

Note

Metadata values in ctx.meta are lazily evaluated: a field like env_info or git_long_hash is only computed the first time you access it. If your command only reads ctx.meta["click_extra.version"], the expensive Git subprocess calls and environment profiling are never executed.

Template rendering

You can render the version string manually by calling the option’s internal methods:

import click
from click_extra import echo, pass_context, version_option, ExtraVersionOption, search_params

@click.command
@version_option(version="1.2.3")
@pass_context
def template_rendering(ctx):
    # Search for a ``--version`` parameter.
    version_opt = search_params(ctx.command.params, ExtraVersionOption)
    version_string = version_opt.render_message()
    echo(f"Version string ~> {version_string}")

Hint

To fetch the --version parameter defined on the command, we rely on the click_extra.search_params.

$ template-rendering --version
template-rendering, version 1.2.3
$ template-rendering
Version string ~> template-rendering, version 1.2.3

That way you can collect the rendered version_string, as if it was printed to the terminal by a call to --version, and use it in your own way.

Other internal methods to build-up and render the version string are available in the API below.

click_extra.version API

        classDiagram
  ExtraOption <|-- ExtraVersionOption
    

Gather CLI metadata and print them.

Pre-baking is inspired by shadow-rs, which injects build-time constants (BRANCH, SHORT_COMMIT, COMMIT_HASH, COMMIT_DATE, TAG, …) into Rust binaries at compile time.

Todo

shadow-rs also provides constants not yet covered here: BUILD_TIME, BUILD_TIME_2822, BUILD_TIME_3339, BUILD_OS, BUILD_TARGET, BUILD_TARGET_ARCH. Some overlap with data already in {env_info} (Python version, OS, architecture). Others like BUILD_TIME could be added as new template fields.

click_extra.version.GIT_FIELDS: dict[str, tuple[str, ...]] = {'git_branch': ('rev-parse', '--abbrev-ref', 'HEAD'), 'git_date': ('show', '-s', '--format=%ci', 'HEAD'), 'git_long_hash': ('rev-parse', 'HEAD'), 'git_short_hash': ('rev-parse', '--short', 'HEAD'), 'git_tag': ('describe', '--tags', '--exact-match', 'HEAD')}

Git fields that can be pre-baked, mapped to their git subcommand args.

git_tag_sha is excluded because its resolution depends on git_tag (it runs git rev-list -1 <tag>), so it cannot be expressed as a static argument tuple.

click_extra.version.run_git(*args, cwd=None)[source]

Run a git command and return its stripped output, or None.

cwd defaults to the current working directory when not provided.

Return type:

str | None

click_extra.version.prebake_version(file_path, local_version)[source]

Pre-bake a __version__ string with a PEP 440 local version identifier.

Reads file_path, finds the __version__ assignment via ast, and — if the version contains .dev and does not already contain + — appends +<local_version>.

This is the compile-time complement to the runtime ExtraVersionOption.version property: Nuitka/PyInstaller binaries cannot run git at runtime, so the hash must be baked into __version__ in the source file before compilation.

Returns the new version string on success, or None if no change was made (release version, already pre-baked, or no __version__ found).

Return type:

str | None

click_extra.version.prebake_dunder(file_path, name, value)[source]

Replace an empty dunder variable’s value in a Python source file.

Reads file_path, finds a top-level name = "" assignment via ast, and — if the current value is an empty string — replaces it with value.

Placeholders must use empty strings (__field__ = "", not None). The AST matcher only recognizes string literals, and the empty string serves as a falsy sentinel that stays type-consistent with baked values (always str).

This is the generic counterpart to prebake_version(): where prebake_version appends a PEP 440 local identifier to __version__, this function does a full replacement of any dunder variable that starts empty. Typical use case: injecting a release commit SHA into __git_tag_sha__ = "" at build time.

Returns the new value on success, or None if no change was made (variable not found, or already has a non-empty value).

Return type:

str | None

click_extra.version.discover_package_init_files()[source]

Discover __init__.py files from [project.scripts].

Reads the pyproject.toml in the current working directory, extracts [project.scripts] entry points, and returns the unique __init__.py paths for each top-level package.

Only returns paths that exist on disk. Returns an empty list if pyproject.toml is missing or has no [project.scripts].

Return type:

list[Path]

class click_extra.version.ExtraVersionOption(param_decls=None, message=None, module=None, module_name=None, module_file=None, module_version=None, package_name=None, package_version=None, exec_name=None, version=None, git_repo_path=None, git_branch=None, git_long_hash=None, git_short_hash=None, git_date=None, git_tag=None, git_tag_sha=None, prog_name=None, env_info=None, message_style=None, module_style=None, module_name_style=Style(fg='bright_white', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'bright_white', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), module_file_style=None, module_version_style=Style(fg='green', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'green', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), package_name_style=Style(fg='bright_white', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'bright_white', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), package_version_style=Style(fg='green', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'green', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), exec_name_style=Style(fg='bright_white', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'bright_white', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), version_style=Style(fg='green', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'green', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), git_repo_path_style=Style(fg='bright_black', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'bright_black', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), git_branch_style=Style(fg='cyan', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'cyan', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), git_long_hash_style=Style(fg='yellow', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'yellow', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), git_short_hash_style=Style(fg='yellow', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'yellow', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), git_date_style=Style(fg='bright_black', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'bright_black', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), git_tag_style=Style(fg='cyan', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'cyan', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), git_tag_sha_style=Style(fg='yellow', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'yellow', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), prog_name_style=Style(fg='bright_white', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'bright_white', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), env_info_style=Style(fg='bright_black', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'bright_black', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), is_flag=True, expose_value=False, is_eager=True, help='Show the version and exit.', **kwargs)[source]

Bases: ExtraOption

Gather CLI metadata and prints a colored version string.

Note

This started as a copy of the standard @click.version_option() decorator, but is no longer a drop-in replacement. Hence the Extra prefix.

This address the following Click issues:

  • click#2324, to allow its use with the declarative params= argument.

  • click#2331, by distinguishing the module from the package.

  • click#1756, by allowing path and Python version.

Preconfigured as a --version option flag.

Parameters:
  • message (str | None) – the message template to print, in format string syntax. Defaults to {prog_name}, version {version}.

  • module (str | None) – forces the value of {module}.

  • module_name (str | None) – forces the value of {module_name}.

  • module_file (str | None) – forces the value of {module_file}.

  • module_version (str | None) – forces the value of {module_version}.

  • package_name (str | None) – forces the value of {package_name}.

  • package_version (str | None) – forces the value of {package_version}.

  • exec_name (str | None) – forces the value of {exec_name}.

  • version (str | None) – forces the value of {version}.

  • git_repo_path (str | None) – forces the value of {git_repo_path}.

  • git_branch (str | None) – forces the value of {git_branch}.

  • git_long_hash (str | None) – forces the value of {git_long_hash}.

  • git_short_hash (str | None) – forces the value of {git_short_hash}.

  • git_date (str | None) – forces the value of {git_date}.

  • git_tag (str | None) – forces the value of {git_tag}.

  • git_tag_sha (str | None) – forces the value of {git_tag_sha}.

  • prog_name (str | None) – forces the value of {prog_name}.

  • env_info (dict[str, str] | None) – forces the value of {env_info}.

  • message_style (Callable[[str], str] | None) – default style of the message.

  • module_style (Callable[[str], str] | None) – style of {module}.

  • module_name_style (Callable[[str], str] | None) – style of {module_name}.

  • module_file_style (Callable[[str], str] | None) – style of {module_file}.

  • module_version_style (Callable[[str], str] | None) – style of {module_version}.

  • package_name_style (Callable[[str], str] | None) – style of {package_name}.

  • package_version_style (Callable[[str], str] | None) – style of {package_version}.

  • exec_name_style (Callable[[str], str] | None) – style of {exec_name}.

  • version_style (Callable[[str], str] | None) – style of {version}.

  • git_repo_path_style (Callable[[str], str] | None) – style of {git_repo_path}.

  • git_branch_style (Callable[[str], str] | None) – style of {git_branch}.

  • git_long_hash_style (Callable[[str], str] | None) – style of {git_long_hash}.

  • git_short_hash_style (Callable[[str], str] | None) – style of {git_short_hash}.

  • git_date_style (Callable[[str], str] | None) – style of {git_date}.

  • git_tag_style (Callable[[str], str] | None) – style of {git_tag}.

  • git_tag_sha_style (Callable[[str], str] | None) – style of {git_tag_sha}.

  • prog_name_style (Callable[[str], str] | None) – style of {prog_name}.

  • env_info_style (Callable[[str], str] | None) – style of {env_info}.

template_fields: tuple[str, ...] = ('module', 'module_name', 'module_file', 'module_version', 'package_name', 'package_version', 'exec_name', 'version', 'git_repo_path', 'git_branch', 'git_long_hash', 'git_short_hash', 'git_date', 'git_tag', 'git_tag_sha', 'prog_name', 'env_info')

List of field IDs recognized by the message template.

message: str = '{prog_name}, version {version}'

Default message template used to render the version string.

static cli_frame()[source]

Returns the frame in which the CLI is implemented.

Inspects the execution stack frames to find the package in which the user’s CLI is implemented.

Returns the frame itself.

Return type:

FrameType

property module: ModuleType[source]

Returns the module in which the CLI resides.

property module_name: str[source]

Returns the full module name or ``__main__`.

property module_file: str | None[source]

Returns the module’s file full path.

property module_version: str | None[source]

Returns the string found in the local __version__ variable.

Hint

__version__ is an old pattern from early Python packaging. It is not a standard variable and is not defined in the packaging PEPs.

You should prefer using the package_version property below instead, which uses the standard library importlib.metadata API.

We’re still supporting it for backward compatibility with existing codebases, as Click removed it in version 8.2.0.

property package_name: str | None[source]

Returns the package name.

property package_version: str | None[source]

Returns the package version if installed.

property exec_name: str[source]

User-friendly name of the executed CLI.

Returns the module name. But if the later is __main__, returns the package name.

If not packaged, the CLI is assumed to be a simple standalone script, and the returned name is the script’s file name (including its extension).

property version: str | None[source]

Return the version of the CLI.

Returns the module version if a __version__ variable is set alongside the CLI in its module.

Else returns the package version if the CLI is implemented in a package, using importlib.metadata.version().

For development versions (containing .dev), automatically appends the Git short hash as a PEP 440 local version identifier, producing versions like 1.2.3.dev0+abc1234. This helps identify the exact commit a dev build was produced from. If Git is unavailable, the plain dev version is returned.

Versions that already contain a + (i.e., a pre-baked local version identifier, typically set at build time by CI pipelines) are returned as-is to avoid producing invalid double-suffixed versions like 1.2.3.dev0+abc1234+xyz5678.

property git_repo_path: Path | None[source]

Find the Git repository root directory.

property git_branch: str | None[source]

Returns the current Git branch name.

Checks for a pre-baked __git_branch__ dunder first, then falls back to git rev-parse --abbrev-ref HEAD.

property git_long_hash: str | None[source]

Returns the full Git commit hash.

Checks for a pre-baked __git_long_hash__ dunder first, then falls back to git rev-parse HEAD.

property git_short_hash: str | None[source]

Returns the short Git commit hash.

Checks for a pre-baked __git_short_hash__ dunder first, then falls back to git rev-parse --short HEAD.

Hint

The short hash is usually the first 7 characters of the full hash, but this is not guaranteed to be the case.

But it is at least guaranteed to be unique within the repository, and a minimum of 4 characters.

property git_date: str | None[source]

Returns the commit date in ISO format: YYYY-MM-DD HH:MM:SS +ZZZZ.

Checks for a pre-baked __git_date__ dunder first, then falls back to git show -s --format=%ci HEAD.

property git_tag: str | None[source]

Returns the Git tag pointing at HEAD, if any.

Checks for a pre-baked __git_tag__ dunder first, then falls back to git describe --tags --exact-match HEAD.

Returns None if HEAD is not at a tagged commit.

property git_tag_sha: str | None[source]

Returns the commit SHA that the current tag points at.

Checks for a pre-baked __git_tag_sha__ dunder first, then falls back to git rev-list -1 on the tag returned by git_tag. Returns None if HEAD is not at a tag.

property prog_name: str | None[source]

Return the name of the CLI, from Click’s point of view.

Get the info_name of the root command.

property env_info: dict[str, Any][source]

Various environment info.

Returns the data produced by boltons.ecoutils.get_profile().

colored_template(template=None)[source]

Insert ANSI styles to a message template.

Accepts a custom template as parameter, otherwise uses the default message defined on the Option instance.

This step is necessary because we need to linearize the template to apply the ANSI codes on the string segments. This is a consequence of the nature of ANSI, directives which cannot be encapsulated within another (unlike markup tags like HTML).

Return type:

str

render_message(template=None)[source]

Render the version string from the provided template.

Accepts a custom template as parameter, otherwise uses the default self.colored_template() produced by the instance.

Return type:

str

print_debug_message()[source]

Render in debug logs all template fields in color.

Todo

Pretty print JSON output (easier to read in bug reports)?

Return type:

None

print_and_exit(ctx, param, value)[source]

Print the version string and exits.

Also stores all version string elements in the Context’s meta dict.

Return type:

None