You can build your own decorator that encapsulates the common options:

def common_options(function):
    function = click.option('--unique-flag-1', is_flag=True)(function)
    function = click.option('--bar', is_flag=True)(function)
    function = click.option('--foo', is_flag=True)(function)
    return function

@click.command()
@common_options
def command():
    pass
Answer from Will Vousden on Stack Overflow
Top answer
1 of 1
18

The way you currently defined it it will work, but the --verbose option belongs to the main command group, so you'd need to call it as python script.py --verbose list (and my_find_command and my_list_command won't receive it as an argument, only cli).

To use the same option across multiple commands without repeating yourself too much, you can just assign it to a variable and then use it twice:

verbose_option = click.option(
    "-v",
    "--verbose",
    count=True,
    default=0,
    help="-v for DEBUG",
)

...

@click.command()
@verbose_option
def foo(verbose):
    ...

@click.command()
@verbose_option
def bar(verbose):
    ...

Unrelated, but while we're at it: There's a simpler way of grouping commands, without having to do cli.add_command(my_find_command): Just use @cli.command() instead of @click.command():

import click

option_verbose = click.option(
    "-v",
    "--verbose",
    count=True,
    default=0,
    help="-v for DEBUG",
)

@click.group()
def cli():
    pass


@cli.command("list")
@option_verbose
@click.option(
    "--list-option",
    help="Special option for list command.",
)
def my_list_command(verbose, list_option):
    print(verbose, list_option)

@cli.command("find")
@option_verbose
@click.option(
    "--find-option",
    help="Special option for find command.",
)
def my_find_command(verbose, list_option):
    print(verbose, list_option)

if __name__ == '__main__':
    cli()

If there's several options you want to apply, you can define your own decorator that calls all those options on the argument:

def common_options(fn):
    return click.option(
        "-v",
        "--verbose",
    )(
        click.option(
            "-n",
            "--dry-run",
        )(fn)
    )
Discussions

Option instance reuse with custom `cls` impossible
There was an error while loading. Please reload this page More on github.com
๐ŸŒ github.com
2
February 8, 2018
Reusing options at different commands
Long ago I used click and I got frustrated how I can't reuse code. I then contrived a method where I could define options at a central place and then reuse it but it felt like a hack. I wonder ... More on github.com
๐ŸŒ github.com
1
1
June 17, 2025
python - How to pass several list of arguments to @click.option - Stack Overflow
I want to call a python script through the command line with this kind of parameter (list could be any size, eg with 3): python test.py --option1 ["o11", "o12", "o13"] --option2 ["o21", "o22", "o2... More on stackoverflow.com
๐ŸŒ stackoverflow.com
python - Merge arguments and options of multiple Click commands under a single CLI command - Stack Overflow
Is there a way to group multiple commands, each with their own different parameters under a single function. At first glance, a MultiCommand or Group might seem like a natural way of doing what I'... More on stackoverflow.com
๐ŸŒ stackoverflow.com
๐ŸŒ
GitHub
github.com โ€บ pallets โ€บ click โ€บ issues โ€บ 926
Option instance reuse with custom `cls` impossible ยท Issue #926 ยท pallets/click
February 8, 2018 - Option instance reuse with custom cls impossible#926 ยท Copy link ยท Labels ยท bug ยท Milestone ยท 7.0 ยท simonpercivall ยท opened ยท on Feb 8, 2018 ยท Issue body actions ยท Let's say I pre-define an option meant for multiple commands: opt = click.option('opt', cls=CustomOption) @opt def cmd1(opt): pass @opt def cmd2(opt): pass ยท
Author: pallets
๐ŸŒ
Prodevsblog
prodevsblog.com โ€บ questions โ€บ 115737 โ€บ is-it-possible-to-reuse-python-click-option-decorators-for-multiple-commands
Q&A ProDevsBlog | Is it possible to reuse python @click.option decorators for multiple commands?
July 26, 2020 - def common_options(function): function = click.option('--unique-flag-1', is_flag=True)(function) function = click.option('--bar', is_flag=True)(function) function = click.option('--foo', is_flag=True)(function) return function @click.command() @common_options def command(): pass
๐ŸŒ
GitHub
github.com โ€บ pallets โ€บ click โ€บ discussions โ€บ 2978
Reusing options at different commands ยท pallets/click ยท Discussion #2978
June 17, 2025 - Assign the decorator produced by click.option to a name, then use that name as the decorator in multiple places. This is not specific to Click, you could do this with any function that produces a decorator in Python. name_option = ...
Author: pallets
๐ŸŒ
Click Documentation
click.palletsprojects.com โ€บ en โ€บ stable โ€บ advanced
Advanced Patterns โ€” Click Documentation (8.5.x)
Note: an actual implementation of a --version parameter that is reusable is available in Click as click.version_option().
Find elsewhere
Top answer
1 of 6
93

If you don't insist on passing something that looks like a list, but simply want to pass multiple variadic arguments, you can use the multiple option.

From the click documentation

@click.command()
@click.option('--message', '-m', multiple=True)
def commit(message):
    click.echo('\n'.join(message))
$ commit -m foo -m bar
foo
bar
2 of 6
41

You can coerce click into taking multiple list arguments, if the lists are formatted as a string literals of python lists by using a custom option class like:

Custom Class:

import click
import ast

class PythonLiteralOption(click.Option):

    def type_cast_value(self, ctx, value):
        try:
            return ast.literal_eval(value)
        except:
            raise click.BadParameter(value)

This class will use Python's Abstract Syntax Tree module to parse the parameter as a python literal.

Custom Class Usage:

To use the custom class, pass the cls parameter to @click.option() decorator like:

@click.option('--option1', cls=PythonLiteralOption, default=[])

How does this work?

This works because click is a well designed OO framework. The @click.option() decorator usually instantiates a click.Option object but allows this behavior to be over ridden with the cls parameter. So it is a relatively easy matter to inherit from click.Option in our own class and over ride the desired methods.

In this case we over ride click.Option.type_cast_value() and then call ast.literal_eval() to parse the list.

Test Code:

@click.command(context_settings=dict(help_option_names=['-h', '--help']))
@click.option('--option1', cls=PythonLiteralOption, default=[])
@click.option('--option2', cls=PythonLiteralOption, default=[])
def cli(option1, option2):
    click.echo("Option 1, type: {}  value: {}".format(
        type(option1), option1))
    click.echo("Option 2, type: {}  value: {}".format(
        type(option2), option2))

# do stuff
if __name__ == '__main__':
    import shlex
    cli(shlex.split(
        '''--option1 '["o11", "o12", "o13"]' 
        --option2 '["o21", "o22", "o23"]' '''))

Test Results:

Option 1, type: <type 'list'>  value: ['o11', 'o12', 'o13']
Option 2, type: <type 'list'>  value: ['o21', 'o22', 'o23']
๐ŸŒ
Digitalk
digitalk.tech โ€บ blog โ€บ python-click-or-how-to-write-professional-cli-applications
Mndwrk Blog - Python click or how to write professional CLI applications
June 17, 2022 - In this case, we need a multiple option by using the multiple=True parameter: @click.command(help="Sum the given numbers") @click.option("-n", "--number", multiple=True, type=float, help="Numbers") def main(number): print(sum(number))
๐ŸŒ
pythontutorials
pythontutorials.net โ€บ blog โ€บ how-to-pass-several-list-of-arguments-to-click-option
How to Pass Multiple List Arguments to @click.option in Python Command Line Scripts โ€” pythontutorials.net
Reusable across multiple options (e.g., --fruits and --vegetables). Clean, declarative syntax in @click.option. Requires defining a custom class (slightly more setup). For large lists (e.g., hundreds of items), users may prefer passing a file ...
๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 60439663 โ€บ merge-arguments-and-options-of-multiple-click-commands-under-a-single-cli-comman
python - Merge arguments and options of multiple Click commands under a single CLI command - Stack Overflow
import click @click.command() @click.option('--db-file', type=click.File(mode='r')) def db_reader(db_file): click.echo(db_file) @click.command() @click.option('--xval', type=float) @click.option('--yval', type=float) def get_vals(xval, yval): return xval, yval @click.command() @click.option('--absolutize/--no-absolutize') def flagger(absolutize): click.echo(absolutize) @click.command() def cli_runner(): db = db_reader.main(standalone_mode=False) vals = flagger.main(standalone_mode=False) flag = flagger.main(standalone_mode=False) if __name__ == '__main__': cli_runner()
๐ŸŒ
Better Stack
betterstack.com โ€บ community โ€บ guides โ€บ scaling-python โ€บ click-explained
Creating composable CLIs with click in Python | Better Stack Community
Usage: cli.py create [OPTIONS] NAME Create a new entry with NAME. Options: --help Show this message and exit. You can further organize your CLI by nesting command groups. This is useful for complex applications with multiple related command sets:
Top answer
1 of 1
1

The custom class found here, can be adapted to your case.

Using the Custom Class:

To use the custom class, just use the cls parameter to the click.command() decorator like:

@cli.command(cls=AcceptAllCommand)
@click.pass_context
def command1(ctx, **kwargs):
    """Add command1."""
    ...

Test Code:

import click

class AcceptAllCommand(click.Command):

    def make_parser(self, ctx):
        """Hook 'make_parser' and allow the opt dict to find any option"""
        parser = super(AcceptAllCommand, self).make_parser(ctx)
        command = self

        class AcceptAllDict(dict):

            def __contains__(self, item):
                """If the parser does no know this option, add it"""

                if not super(AcceptAllDict, self).__contains__(item):
                    # create an option name
                    name = item.lstrip('-')

                    # add the option to our command
                    click.option(item)(command)

                    # get the option instance from the command
                    option = command.params[-1]

                    # add the option instance to the parser
                    parser.add_option(
                        [item], name.replace('-', '_'), obj=option)
                return True

        # set the parser options to our dict
        parser._short_opt = AcceptAllDict(parser._short_opt)
        parser._long_opt = AcceptAllDict(parser._long_opt)

        return parser


@click.group(chain=True)
@click.pass_context
def cli(ctx, **kwargs):
    """"""


@cli.command(cls=AcceptAllCommand)
@click.pass_context
def command1(ctx, **kwargs):
    """Add command1."""
    ctx.obj['command1_args'] = {}
    for k, v in kwargs.items():
        ctx.obj['command1_args'][k] = v


@cli.command()
@click.argument('command2-argument1', type=str)
@click.pass_context
def command2(ctx, **kwargs):
    """Add command2."""
    print(ctx.obj)
    print(kwargs)


if __name__ == "__main__":
    commands = (
        "command1 --cmd1-opt1 foo --cmd1-opt2 bar command2 hello",
        '--help',
    )

    import sys, time

    time.sleep(1)
    print('Click Version: {}'.format(click.__version__))
    print('Python Version: {}'.format(sys.version))
    for cmd in commands:
        try:
            time.sleep(0.1)
            print('-----------')
            print('> ' + cmd)
            time.sleep(0.1)
            cli(cmd.split(), obj={})

        except BaseException as exc:
            if str(exc) != '0' and \
                    not isinstance(exc, (click.ClickException, SystemExit)):
                raise

Results:

Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> command1 --cmd1-opt1 foo --cmd1-opt2 bar command2 hello
{'command1_args': {'cmd1_opt1': 'foo', 'cmd1_opt2': 'bar'}}
{'command2_argument1': 'hello'}
-----------
> --help
Usage: test.py [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...

Options:
  --help  Show this message and exit.

Commands:
  command1  Add command1.
  command2  Add command2.
๐ŸŒ
Readthedocs
pocoo-click.readthedocs.io โ€บ en โ€บ latest โ€บ options
Options - the Click Documentation
For instance, git commit -m foo -m bar would record two lines for the commit message: foo and bar. This can be accomplished with the multiple flag: ... @click.command() @click.option('--message', '-m', multiple=True) def commit(message): click.echo('\n'.join(message))
๐ŸŒ
ZetCode
zetcode.com โ€บ python โ€บ click
Python click - creating command line interfaces
January 29, 2024 - In the example, we can specify the --word/-w options multiple times. $ ./multiples.py -w sky --word forest --word rock -w cloud sky forest rock cloud ยท The click.File type declares a parameter to be a file for reading or writing. The file is automatically closed once the context tears down ...
๐ŸŒ
Readthedocs
pocoo-click.readthedocs.io โ€บ en โ€บ latest โ€บ advanced
Advanced Patterns - the Click Documentation
If an option or argument is split up on the command line into multiple places because it is repeated โ€“ for instance, --exclude foo --include baz --exclude bar โ€“ the callback will fire based on the position of the first option. In this case, the callback will fire for exclude and it will ...
๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 73594892 โ€บ how-to-reuse-options-from-groups-to-command-in-python-click
How to reuse options from groups to command in Python Click? - Stack Overflow
2 Using click.CommandCollection drops group options ยท 9 Get params sent to a subcommand of a click.group() ... 2 Python Click options - Avoid taking multiple times the same option if the parameter multiple is not passed
๐ŸŒ
DEV Community
dev.to โ€บ drcloudycoder โ€บ develop-python-cli-with-subcommands-using-click-4892
Develop python CLI with subcommands using Click - DEV Community
November 27, 2020 - ๐Ÿ“Œ If you have a working structure at this point, then you can easily follow similar process for adding new sub-commands into separate python files under commands/ dir or any other dir. For example, let's add a deploy subcommand functionality to our main CLI program. This subcommand should expose 2 options (--env and --cloud) and prompt the user to enter input while displaying allowed values and a default value. Define functionality and available options for deploy subcommand: import click @click.command() @click.option('--env', '-e', default="dev", type=click.Choice(['dev', 'stg', 'prd'], c
๐ŸŒ
Click Documentation
click.palletsprojects.com โ€บ en โ€บ stable โ€บ options
Options โ€” Click Documentation (8.5.x)
A simple click.Option takes one option name. By default, itโ€™s assumed that the decorated function argument is not required and the expected type is str. If the decorated function takes a positional argument but the option is not passed with the command, then None is passed.