Skip to content

kaptive.serotyping.cli

Command line interface commands and exporter for serotyping.

This module provides CLI command implementations for performing in silico serotyping on genome assemblies and converting serialized serotyping results to various tabular, JSON, or graphical output formats.

Classes:

  • [`ResultExporter`][kaptive.serotyping.cli.ResultExporter] –

    Evaluates output options and dispatches serialization tasks.

  • [`Type`][kaptive.serotyping.cli.Type] –

    Subcommand for in silico serotyping of genome assemblies.

  • [`Convert`][kaptive.serotyping.cli.Convert] –

    Subcommand for converting serialized JSON-lines results.

Convert

Convert()

              flowchart TD
              kaptive.serotyping.cli.Convert[Convert]
              kaptive.cli.Command[Command]

                              kaptive.cli.Command --> kaptive.serotyping.cli.Convert
                


              click kaptive.serotyping.cli.Convert href "" "kaptive.serotyping.cli.Convert"
              click kaptive.cli.Command href "" "kaptive.cli.Command"
            

🔄 Convert serialized Kaptive results into different formats.

Reads serialized JSON-lines serotyping output records and converts them into tabular TSV, PHA4GE TSV, or sequence FASTA files without re-running the serotyping pipeline.

Methods:

  • __call__ –

    Execute result format conversion from serialized JSON-lines input.

  • add_output_arguments –

    Add standard report and FASTA file output options to argument group.

  • build –

    Wire command parser and subcommands into parent argparse hierarchy.

  • get_shared_parser –

    Return shared parent parser containing options passed to subcommands.

  • register_subcommands –

    Register child subcommand instances into subcommands list.

  • setup_arguments –

    Configure argument parser options for the convert subcommand.

Source code in src/kaptive/cli.py
def __init__(self) -> None:
    r"""Initialize command instance and populate metadata attributes."""
    self.parser: argparse.ArgumentParser | None = None
    self.subcommands: list[Command] = []
    self.cli: Cli | None = None

    # Auto-populate name from the class name
    if not self.name:
        self.name = type(self).__name__.lower()

    # Auto-populate description from class docstring
    if not self.description:
        if type(self).__doc__ and type(self).__doc__ != Command.__doc__:
            self.description = type(self).__doc__  # type: ignore

    # Auto-populate short help text from the first line of the description
    if not self.help_text and self.description:
        self.help_text = self.description.strip().split("\n")[0]

    self.register_subcommands()

__call__

__call__(args: Namespace) -> None

Execute result format conversion from serialized JSON-lines input.

Deserializes line-delimited JSON records into SerotypingResult objects and dispatches them to registered output writers.

Parameters:

  • args

    (Namespace) –

    Parsed command-line arguments.

Raises:

  • SystemExit –

    If orjson is not installed in the current Python environment.

Source code in src/kaptive/serotyping/cli.py
def __call__(self, args: argparse.Namespace) -> None:
    r"""Execute result format conversion from serialized JSON-lines input.

    Deserializes line-delimited JSON records into [`SerotypingResult`][kaptive.serotyping.models.SerotypingResult]
    objects and dispatches them to registered output writers.

    Args:
        args (argparse.Namespace): Parsed command-line arguments.

    Raises:
        SystemExit: If `orjson` is not installed in the current Python environment.
    """
    try:
        from orjson import loads
    except ImportError:
        self.cli.exit("orjson not installed. Please run: pip install kaptive[json]")  # type: ignore

    from kaptive.serotyping import SerotypingResult

    exporter = ResultExporter(self.cli, args)  # type: ignore

    handle = self.cli.open_file(args.jsonl, mode="rb")  # type: ignore
    for line in self.cli.progress(handle, "💱 Converting results..."):  # type: ignore
        line = line.strip()
        if not line:
            continue

        result = SerotypingResult.from_dict(loads(line))  # type: ignore
        exporter(result)

    self.cli.msg("✅ Conversion complete.")  # type: ignore

add_output_arguments

add_output_arguments(opts: _ArgumentGroup, tsv_flags: tuple[str, str] = ('-o', '--out'), include_json: bool = True) -> None

Add standard report and FASTA file output options to argument group.

Parameters:

  • opts

    (_ArgumentGroup) –

    Target argument group to populate.

  • tsv_flags

    (tuple[str, str], default: ('-o', '--out') ) –

    Short and long flag options for TSV report output. Defaults to ("-o", "--out").

  • include_json

    (bool, default: True ) –

    Flag indicating whether to include --json argument option. Defaults to True.

Source code in src/kaptive/cli.py
def add_output_arguments(
    self,
    opts: argparse._ArgumentGroup,
    tsv_flags: tuple[str, str] = ("-o", "--out"),
    include_json: bool = True,
) -> None:
    r"""Add standard report and FASTA file output options to argument group.

    Args:
        opts (argparse._ArgumentGroup): Target argument group to populate.
        tsv_flags (tuple[str, str]): Short and long flag options for TSV report output.
            Defaults to `("-o", "--out")`.
        include_json (bool): Flag indicating whether to include `--json` argument option.
            Defaults to `True`.
    """
    help_msg = (
        "Write serotyping results as a TSV report to a file (default: %(default)s)"
        if tsv_flags[0] == "-o"
        else "Write serotyping results as a TSV report to a file (default: %(const)s)"
    )
    opts.add_argument(
        tsv_flags[0],
        tsv_flags[1],
        metavar="FILE",
        nargs="?" if tsv_flags[0] == "-t" else None,
        default="stdout" if tsv_flags[0] == "-o" else None,
        const="stdout" if tsv_flags[0] == "-t" else None,
        help=help_msg,
    )
    opts.add_argument(
        "-l",
        "--loci",
        metavar="DIR",
        nargs="?",
        const="./",
        type=Path,
        help="Write locus nucleotide fasta files to a directory (default: %(const)s)",
    )
    opts.add_argument(
        "-g",
        "--genes",
        metavar="DIR",
        nargs="?",
        const="./",
        type=Path,
        help="Write gene nucleotide fasta files to a directory (default: %(const)s)",
    )
    opts.add_argument(
        "-p",
        "--proteins",
        metavar="DIR",
        nargs="?",
        const="./",
        type=Path,
        help="Write translation amino-acid fasta files to a directory (default: %(const)s)",
    )
    if include_json:
        opts.add_argument(
            "-j",
            "--json",
            metavar="FILE",
            nargs="?",
            const="kaptive_results.jsonl",
            help="Write serialised results to a newline-delimited JSON (default: %(const)s)",
        )
    opts.add_argument(
        "--pha4ge",
        metavar="FILE",
        nargs="?",
        const="kaptive_results.pha4ge",
        type=Path,
        help="Write PHA4GE-compliant serotyping report to a TSV file (default: %(const)s)",
    )
    opts.add_argument(
        "--plots",
        metavar="DIR",
        nargs="?",
        const="./",
        type=Path,
        help="Generate interactive locus plots to a directory (default: %(const)s)",
    )

build

build(subparsers: _SubParsersAction, parent_parsers: list[ArgumentParser] | None = None) -> None

Wire command parser and subcommands into parent argparse hierarchy.

Parameters:

  • subparsers

    (_SubParsersAction) –

    Target subparser action registry.

  • parent_parsers

    (list[ArgumentParser] | None, default: None ) –

    Parent shared parsers to inherit.

Source code in src/kaptive/cli.py
def build(
    self,
    subparsers: argparse._SubParsersAction,  # type: ignore
    parent_parsers: list[argparse.ArgumentParser] | None = None,
) -> None:
    r"""Wire command parser and subcommands into parent argparse hierarchy.

    Args:
        subparsers (argparse._SubParsersAction): Target subparser action registry.
        parent_parsers (list[argparse.ArgumentParser] | None): Parent shared parsers to inherit.
    """
    parents = parent_parsers or []

    self.parser = subparsers.add_parser(
        name=self.name,
        aliases=self.aliases,
        description=Colors.wrap(self.description, Colors.BOLD),
        help=self.help_text or self.description,
        parents=parents,
        formatter_class=KaptiveHelpFormatter,
    )

    # 1. Add specific arguments for this command
    self.setup_arguments()

    # Rename the default options group and move it to the bottom of the help menu
    if hasattr(self.parser, "_optionals"):
        self.parser._optionals.title = Colors.wrap("🌎 Global options", Colors.BOLD)
        # Pop the group out of the internal list and append it to the end
        groups = self.parser._action_groups
        if self.parser._optionals in groups:
            groups.append(groups.pop(groups.index(self.parser._optionals)))

    # 2. Bind the execution function (only if __call__ was actually overridden)
    if type(self).__call__ != Command.__call__:
        self.parser.set_defaults(func=self.__call__)

    # 3. Process subcommands (if any)
    if self.subcommands:
        # If this command doesn't do anything itself, it MUST require a subcommand
        is_required = type(self).__call__ == Command.__call__
        sub_action = self.parser.add_subparsers(
            title=Colors.wrap(f"'{self.name}' subcommands", Colors.BOLD),
            dest=f"{self.name}_subcommand",
            required=is_required,
        )

        # Collect shared arguments to pass down
        child_parents = parents.copy()
        if shared := self.get_shared_parser():
            child_parents.append(shared)

        for cmd in self.subcommands:
            cmd.cli = self.cli
            cmd.build(sub_action, parent_parsers=child_parents)

get_shared_parser

get_shared_parser() -> ArgumentParser | None

Return shared parent parser containing options passed to subcommands.

Returns:

  • ArgumentParser | None –

    argparse.ArgumentParser | None: Shared non-help argument parser or None.

Source code in src/kaptive/cli.py
def get_shared_parser(self) -> argparse.ArgumentParser | None:
    r"""Return shared parent parser containing options passed to subcommands.

    Returns:
        argparse.ArgumentParser | None: Shared non-help argument parser or `None`.
    """
    return None

register_subcommands

register_subcommands() -> None

Register child subcommand instances into subcommands list.

Source code in src/kaptive/cli.py
def register_subcommands(self) -> None:
    r"""Register child subcommand instances into `subcommands` list."""
    pass

setup_arguments

setup_arguments() -> None

Configure argument parser options for the convert subcommand.

Defines the input JSON-lines source parameter and output target flags via add_output_arguments.

Source code in src/kaptive/serotyping/cli.py
def setup_arguments(self) -> None:
    r"""Configure argument parser options for the convert subcommand.

    Defines the input JSON-lines source parameter and output target flags via
    `add_output_arguments`.
    """
    opts = self.parser.add_argument_group(Colors.wrap("📥 Inputs", Colors.BOLD))  # type: ignore
    opts.add_argument(
        "jsonl",
        default="stdin",
        help="Serialised results in JSON-lines format (default: stdin)",
    )

    opts = self.parser.add_argument_group(Colors.wrap("📤 Outputs", Colors.BOLD))  # type: ignore
    self.add_output_arguments(opts, tsv_flags=("-t", "--tsv"), include_json=False)

ResultExporter

ResultExporter(cli: Cli, args: Namespace)

Evaluates CLI arguments once and sets up a pipeline of output writers.

This eliminates conditional branching inside the processing loop and allows reusability between the Type and Convert commands.

Attributes:

  • file_suffix (str) –

    Default filename suffix used when writing output files (default: 'kaptive_results').

  • writers (list[Callable[[SerotypingResult], None]]) –

    List of registered writer callback functions.

Inspects output flags in args and registers appropriate serialization callbacks for TSV, PHA4GE TSV, JSON, locus nucleotide FASTA, gene nucleotide FASTA, translated protein FASTA, and interactive HTML plots.

The PHA4GE TSV output adheres to the Public Health Alliance for Genomic Epidemiology genotyping specification (https://github.com/pha4ge/genotyping-specification).

Parameters:

  • cli

    (Cli) –

    Parent Cli execution context.

  • args

    (Namespace) –

    Parsed command-line arguments containing output flags.

Raises:

  • SystemExit –

    If --json is set but orjson is not installed, or --plots is set but plotly is not installed.

Methods:

  • __call__ –

    Pass the serotyping result to all registered output writers.

Source code in src/kaptive/serotyping/cli.py
def __init__(self, cli: Cli, args: argparse.Namespace) -> None:
    r"""Initialize output writers based on parsed command-line arguments.

    Inspects output flags in `args` and registers appropriate serialization callbacks
    for TSV, PHA4GE TSV, JSON, locus nucleotide FASTA, gene nucleotide FASTA,
    translated protein FASTA, and interactive HTML plots.

    The PHA4GE TSV output adheres to the Public Health Alliance for Genomic Epidemiology
    genotyping specification (https://github.com/pha4ge/genotyping-specification).

    Args:
        cli (Cli): Parent `Cli` execution context.
        args (argparse.Namespace): Parsed command-line arguments containing output flags.

    Raises:
        SystemExit: If `--json` is set but `orjson` is not installed, or `--plots`
            is set but `plotly` is not installed.
    """
    self.writers = []

    if tsv_file := getattr(args, "out", getattr(args, "tsv", None)):
        from kaptive.serotyping import KaptiveRow

        tsv_handle = cli.open_file(tsv_file, mode="wb")
        tsv_handle.write(KaptiveRow.header())
        self.writers.append(lambda r: tsv_handle.write(bytes(KaptiveRow.from_result(r))))

    if pha4ge_file := getattr(args, "pha4ge", None):
        from kaptive.serotyping import Pha4geRow

        pha4ge_handle = cli.open_file(pha4ge_file, mode="wb")
        pha4ge_handle.write(Pha4geRow.header())
        self.writers.append(lambda r: pha4ge_handle.write(bytes(Pha4geRow.from_result(r))))

    if json_file := getattr(args, "json", None):
        try:
            from orjson import OPT_APPEND_NEWLINE, OPT_SERIALIZE_NUMPY, dumps
        except ImportError:
            cli.exit("orjson not installed. Please run: pip install kaptive[json]")
        json_handle = cli.open_file(json_file, mode="wb")
        self.writers.append(
            lambda r: json_handle.write(dumps(r.to_dict(), option=OPT_SERIALIZE_NUMPY | OPT_APPEND_NEWLINE))
        )

    if loci_dir := getattr(args, "loci", None):
        self.writers.append(
            lambda r: (loci_dir / f"{r.genome}_{self.file_suffix}.fna").write_bytes(r.locus_seqs.to_fasta())
        )

    if genes_dir := getattr(args, "genes", None):
        self.writers.append(
            lambda r: (genes_dir / f"{r.genome}_{self.file_suffix}.ffn").write_bytes(r.gene_seqs.to_fasta())
        )

    if proteins_dir := getattr(args, "proteins", None):
        self.writers.append(
            lambda r: (proteins_dir / f"{r.genome}_{self.file_suffix}.faa").write_bytes(r.translations.to_fasta())
        )

    if plot_dir := getattr(args, "plots", None):
        try:
            from kaptive.plotting import SerotypingResultPlotter
        except ImportError:
            cli.exit("plotly not installed. Please run: pip install kaptive[plot]")
        self.writers.append(
            lambda r: SerotypingResultPlotter()(r).write_html(
                plot_dir / f"{r.genome}_{self.file_suffix}.html",
                include_plotlyjs="cdn",
                full_html=True,
            )
        )

__call__

__call__(result: Any) -> None

Pass the serotyping result to all registered output writers.

Parameters:

Source code in src/kaptive/serotyping/cli.py
def __call__(self, result: Any) -> None:
    r"""Pass the serotyping result to all registered output writers.

    Args:
        result (SerotypingResult): The [`SerotypingResult`][kaptive.serotyping.models.SerotypingResult]
            instance to serialize and write out.
    """
    for write in self.writers:
        write(result)

Type

Type()

              flowchart TD
              kaptive.serotyping.cli.Type[Type]
              kaptive.cli.Command[Command]

                              kaptive.cli.Command --> kaptive.serotyping.cli.Type
                


              click kaptive.serotyping.cli.Type href "" "kaptive.serotyping.cli.Type"
              click kaptive.cli.Command href "" "kaptive.cli.Command"
            

💉 In silico serotyping of genome assemblies.

Aliases

assembly

Methods:

  • __call__ –

    Execute the serotyping workflow on input genome assemblies.

  • add_output_arguments –

    Add standard report and FASTA file output options to argument group.

  • build –

    Wire command parser and subcommands into parent argparse hierarchy.

  • get_shared_parser –

    Return shared parent parser containing options passed to subcommands.

  • register_subcommands –

    Register child subcommand instances into subcommands list.

  • setup_arguments –

    Configure argument parser options for the type subcommand.

Source code in src/kaptive/cli.py
def __init__(self) -> None:
    r"""Initialize command instance and populate metadata attributes."""
    self.parser: argparse.ArgumentParser | None = None
    self.subcommands: list[Command] = []
    self.cli: Cli | None = None

    # Auto-populate name from the class name
    if not self.name:
        self.name = type(self).__name__.lower()

    # Auto-populate description from class docstring
    if not self.description:
        if type(self).__doc__ and type(self).__doc__ != Command.__doc__:
            self.description = type(self).__doc__  # type: ignore

    # Auto-populate short help text from the first line of the description
    if not self.help_text and self.description:
        self.help_text = self.description.strip().split("\n")[0]

    self.register_subcommands()

__call__

__call__(args: Namespace) -> None

Execute the serotyping workflow on input genome assemblies.

Loads the requested locus database, initializes the serotyping engine, iterates through genome assemblies to call serotypes, and streams results to configured output targets.

Parameters:

  • args

    (Namespace) –

    Parsed command-line arguments.

Source code in src/kaptive/serotyping/cli.py
def __call__(self, args: argparse.Namespace) -> None:
    r"""Execute the serotyping workflow on input genome assemblies.

    Loads the requested locus database, initializes the serotyping engine, iterates
    through genome assemblies to call serotypes, and streams results to configured output targets.

    Args:
        args (argparse.Namespace): Parsed command-line arguments.
    """
    self.cli.msg(f"💽 Loading database {args.database}...")  # type: ignore
    from kaptive.db import DatabaseManager
    from kaptive.serotyping import Serotyper

    db = DatabaseManager.get(args.database)
    exporter = ResultExporter(self.cli, args)  # type: ignore

    serotyper = Serotyper(
        db=db,
        max_other_genes=args.max_other_genes,
        min_completeness=args.min_completeness,
        allow_below_threshold=args.below_threshold,
        partial_edge_tolerance=args.partial_edge_tolerance,
    )
    for genome in self.cli.progress(args.genomes, "💉 Serotyping genomes..."):  # type: ignore
        if result := serotyper(genome):
            exporter(result)

    self.cli.msg(f"✅ Serotyping complete. Results written to '{args.out}'.")  # type: ignore

add_output_arguments

add_output_arguments(opts: _ArgumentGroup, tsv_flags: tuple[str, str] = ('-o', '--out'), include_json: bool = True) -> None

Add standard report and FASTA file output options to argument group.

Parameters:

  • opts

    (_ArgumentGroup) –

    Target argument group to populate.

  • tsv_flags

    (tuple[str, str], default: ('-o', '--out') ) –

    Short and long flag options for TSV report output. Defaults to ("-o", "--out").

  • include_json

    (bool, default: True ) –

    Flag indicating whether to include --json argument option. Defaults to True.

Source code in src/kaptive/cli.py
def add_output_arguments(
    self,
    opts: argparse._ArgumentGroup,
    tsv_flags: tuple[str, str] = ("-o", "--out"),
    include_json: bool = True,
) -> None:
    r"""Add standard report and FASTA file output options to argument group.

    Args:
        opts (argparse._ArgumentGroup): Target argument group to populate.
        tsv_flags (tuple[str, str]): Short and long flag options for TSV report output.
            Defaults to `("-o", "--out")`.
        include_json (bool): Flag indicating whether to include `--json` argument option.
            Defaults to `True`.
    """
    help_msg = (
        "Write serotyping results as a TSV report to a file (default: %(default)s)"
        if tsv_flags[0] == "-o"
        else "Write serotyping results as a TSV report to a file (default: %(const)s)"
    )
    opts.add_argument(
        tsv_flags[0],
        tsv_flags[1],
        metavar="FILE",
        nargs="?" if tsv_flags[0] == "-t" else None,
        default="stdout" if tsv_flags[0] == "-o" else None,
        const="stdout" if tsv_flags[0] == "-t" else None,
        help=help_msg,
    )
    opts.add_argument(
        "-l",
        "--loci",
        metavar="DIR",
        nargs="?",
        const="./",
        type=Path,
        help="Write locus nucleotide fasta files to a directory (default: %(const)s)",
    )
    opts.add_argument(
        "-g",
        "--genes",
        metavar="DIR",
        nargs="?",
        const="./",
        type=Path,
        help="Write gene nucleotide fasta files to a directory (default: %(const)s)",
    )
    opts.add_argument(
        "-p",
        "--proteins",
        metavar="DIR",
        nargs="?",
        const="./",
        type=Path,
        help="Write translation amino-acid fasta files to a directory (default: %(const)s)",
    )
    if include_json:
        opts.add_argument(
            "-j",
            "--json",
            metavar="FILE",
            nargs="?",
            const="kaptive_results.jsonl",
            help="Write serialised results to a newline-delimited JSON (default: %(const)s)",
        )
    opts.add_argument(
        "--pha4ge",
        metavar="FILE",
        nargs="?",
        const="kaptive_results.pha4ge",
        type=Path,
        help="Write PHA4GE-compliant serotyping report to a TSV file (default: %(const)s)",
    )
    opts.add_argument(
        "--plots",
        metavar="DIR",
        nargs="?",
        const="./",
        type=Path,
        help="Generate interactive locus plots to a directory (default: %(const)s)",
    )

build

build(subparsers: _SubParsersAction, parent_parsers: list[ArgumentParser] | None = None) -> None

Wire command parser and subcommands into parent argparse hierarchy.

Parameters:

  • subparsers

    (_SubParsersAction) –

    Target subparser action registry.

  • parent_parsers

    (list[ArgumentParser] | None, default: None ) –

    Parent shared parsers to inherit.

Source code in src/kaptive/cli.py
def build(
    self,
    subparsers: argparse._SubParsersAction,  # type: ignore
    parent_parsers: list[argparse.ArgumentParser] | None = None,
) -> None:
    r"""Wire command parser and subcommands into parent argparse hierarchy.

    Args:
        subparsers (argparse._SubParsersAction): Target subparser action registry.
        parent_parsers (list[argparse.ArgumentParser] | None): Parent shared parsers to inherit.
    """
    parents = parent_parsers or []

    self.parser = subparsers.add_parser(
        name=self.name,
        aliases=self.aliases,
        description=Colors.wrap(self.description, Colors.BOLD),
        help=self.help_text or self.description,
        parents=parents,
        formatter_class=KaptiveHelpFormatter,
    )

    # 1. Add specific arguments for this command
    self.setup_arguments()

    # Rename the default options group and move it to the bottom of the help menu
    if hasattr(self.parser, "_optionals"):
        self.parser._optionals.title = Colors.wrap("🌎 Global options", Colors.BOLD)
        # Pop the group out of the internal list and append it to the end
        groups = self.parser._action_groups
        if self.parser._optionals in groups:
            groups.append(groups.pop(groups.index(self.parser._optionals)))

    # 2. Bind the execution function (only if __call__ was actually overridden)
    if type(self).__call__ != Command.__call__:
        self.parser.set_defaults(func=self.__call__)

    # 3. Process subcommands (if any)
    if self.subcommands:
        # If this command doesn't do anything itself, it MUST require a subcommand
        is_required = type(self).__call__ == Command.__call__
        sub_action = self.parser.add_subparsers(
            title=Colors.wrap(f"'{self.name}' subcommands", Colors.BOLD),
            dest=f"{self.name}_subcommand",
            required=is_required,
        )

        # Collect shared arguments to pass down
        child_parents = parents.copy()
        if shared := self.get_shared_parser():
            child_parents.append(shared)

        for cmd in self.subcommands:
            cmd.cli = self.cli
            cmd.build(sub_action, parent_parsers=child_parents)

get_shared_parser

get_shared_parser() -> ArgumentParser | None

Return shared parent parser containing options passed to subcommands.

Returns:

  • ArgumentParser | None –

    argparse.ArgumentParser | None: Shared non-help argument parser or None.

Source code in src/kaptive/cli.py
def get_shared_parser(self) -> argparse.ArgumentParser | None:
    r"""Return shared parent parser containing options passed to subcommands.

    Returns:
        argparse.ArgumentParser | None: Shared non-help argument parser or `None`.
    """
    return None

register_subcommands

register_subcommands() -> None

Register child subcommand instances into subcommands list.

Source code in src/kaptive/cli.py
def register_subcommands(self) -> None:
    r"""Register child subcommand instances into `subcommands` list."""
    pass

setup_arguments

setup_arguments() -> None

Configure argument parser options for the type subcommand.

Defines input database/genome arguments, output formatting flags via add_output_arguments, confidence options, and thread count parameters.

Source code in src/kaptive/serotyping/cli.py
def setup_arguments(self) -> None:
    r"""Configure argument parser options for the type subcommand.

    Defines input database/genome arguments, output formatting flags via
    `add_output_arguments`, confidence options,
    and thread count parameters.
    """
    opts = self.parser.add_argument_group(Colors.wrap("📥 Inputs", Colors.BOLD))  # type: ignore
    opts.add_argument("database", help="Database path or keyword (see: `kaptive db list`)")
    opts.add_argument(
        "genomes",
        nargs="+",
        help="Genome assemblies in fasta format; can be compressed",
    )

    opts = self.parser.add_argument_group(Colors.wrap("📤 Outputs", Colors.BOLD))  # type: ignore
    self.add_output_arguments(opts, tsv_flags=("-o", "--out"), include_json=True)

    opts = self.parser.add_argument_group(Colors.wrap("🔬 Confidence options", Colors.BOLD))  # type: ignore
    opts.add_argument(
        "--max-other-genes",
        type=int,
        metavar="",
        default=1,
        help="Typeable if <= other genes (default: %(default)s)",
    )
    opts.add_argument(
        "--min-completeness",
        type=float,
        metavar="",
        default=0.5,
        help="Typeable if >= completeness (default: %(default)s)",
    )
    opts.add_argument(
        "--below-threshold",
        action="store_true",
        help="Typeable if any genes in locus are below threshold (default: False)",
    )

    opts = self.parser.add_argument_group(Colors.wrap("🔧 Other options", Colors.BOLD))  # type: ignore
    opts.add_argument(
        "-t",
        "--threads",
        type=int,
        default=0,
        metavar="",
        help="Number threads or 0 for all available (default: 0)",
    )
    opts.add_argument(
        "--partial-edge-tolerance",
        type=int,
        default=5,
        metavar="",
        help="Tolerance in bases from contig edge to call a partial gene (default: %(default)s)",
    )