Back to Skills

building-python-clis

verified

Builds command-line interfaces for Python libraries using Click or Typer. Includes command groups, argument handling, progress bars, shell completion, and CLI testing with CliRunner. Use when adding CLI functionality to a library or building standalone command-line tools.

View on GitHub

Marketplace

python-library-dev

wdm0006/python-skills

Plugin

python-library-quality

Repository

wdm0006/python-skills

skills/cli-development/SKILL.md

Last Verified

January 20, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/wdm0006/python-skills/blob/main/skills/cli-development/SKILL.md -a claude-code --skill building-python-clis

Installation paths:

Claude
.claude/skills/building-python-clis/
Powered by add-skill CLI

Instructions

# Python CLI Development

## Framework Selection

**Click** (Recommended): Mature, extensive features
**Typer**: Modern, type-hint focused
**argparse**: Zero dependencies, standard library

## Click Quick Start

```python
import click

@click.group()
@click.version_option(version='1.0.0')
def cli():
    """My CLI tool."""
    pass

@cli.command()
@click.argument('input_file', type=click.Path(exists=True))
@click.option('--output', '-o', default='-', help='Output file')
@click.option('--verbose', '-v', is_flag=True)
def process(input_file, output, verbose):
    """Process an input file."""
    if verbose:
        click.echo(f"Processing {input_file}")
    # ...

if __name__ == '__main__':
    cli()
```

## Entry Point (pyproject.toml)

```toml
[project.scripts]
mycli = "my_package.cli:cli"

[project.optional-dependencies]
cli = ["click>=8.0"]
```

## Common Patterns

```python
# File I/O with stdin/stdout support
@click.argument('input', type=click.File('r'), default='-')
@click.argument('output', type=click.File('w'), default='-')

# Progress bar
with click.progressbar(items, label='Processing') as bar:
    for item in bar:
        process(item)

# Colored output
click.secho("Success!", fg='green', bold=True)
click.secho("Error!", fg='red', err=True)

# Error handling
if not valid:
    raise click.BadParameter(f'Invalid value: {value}')
```

## Testing with CliRunner

```python
from click.testing import CliRunner
from mypackage.cli import cli

def test_process():
    runner = CliRunner()
    result = runner.invoke(cli, ['process', 'input.txt'])
    assert result.exit_code == 0
    assert 'expected output' in result.output

def test_stdin():
    runner = CliRunner()
    result = runner.invoke(cli, ['process', '-'], input='test data\n')
    assert result.exit_code == 0
```

## Shell Completion

```bash
# Generate completion scripts
_MYCLI_COMPLETE=bash_source mycli > ~/.mycli-complete.bash
_MYCLI_COMPLETE=zsh_source mycli > ~/.mycli-complete.zsh
```

For detailed patt

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
2388 chars

Issues Found:

  • name_directory_mismatch