Command aliases for Typer CLI applications
Project description
typer-extensions
Command aliases for Typer CLI applications with grouped help text display
Overview
Typer is great, but it could be even better!
typer-extensions extends Typer to provide simple drop-in support for command aliases. Instead of duplicating commands, hiding commands, or maintaining wrapper functions, define aliases directly and have them displayed cleanly in help text.
100% backwards compatible with Typer & existing Typer apps!
The Problem
Standard Typer requires duplicating or hiding commands to create aliases:
from typer import Typer
app = Typer()
@app.command()
def list_items():
"""List all items."""
print("Listing...")
# Registered as separate command, hidden in help
@app.command("ls", hidden=True)
def ls_items():
list_items()
@app.command("l")("list") # Duplicate!
Help output:
Commands:
list List all items.
l List all items.
Issues:
- Code duplication
- Help text shows commands & aliases separately
- Hidden 'aliases' not shown in help text
- Maintenance burden
The Solution
With typer-extensions:
from typer_extensions import ExtendedTyper
app = ExtendedTyper()
@app.command_with_aliases("list", aliases=["ls", "l"])
def list_items():
"""List all items."""
print("Listing...")
Help output:
Commands:
list (ls, l) List all items.
All work identically:
app list
app ls
app l
Features
✨ Decorator-based alias registration - Clean, intuitive syntax
🔧 Programmatic API - Dynamic alias management at runtime
📋 Grouped help display - Aliases shown with their primary command
⚙️ Highly configurable - Customise format, separators, truncation
🎯 Type-safe - Full type hints and editor support
🔄 Fully backwards compatible - Works with all Typer/Click features and existing Typer apps
✅ Shell completion ready - Alias support doesn't interfere with existing shell completion
🧪 Well-tested - Tested on Python 3.9-3.14 with 100% test coverage
Installation
pip install typer-extensions
[!NOTE] Requirements:
- Python 3.9+
- typer >= 0.9.0 (recommend installing the latest version)
- click >= 8.0.0
Quick Start
Basic Usage
from typer_extensions import ExtendedTyper
app = ExtendedTyper()
@app.command_with_aliases("list", aliases=["ls", "l"])
def list_items():
"""List all items."""
print("Listing items...")
@app.command_with_aliases("delete", aliases=["rm", "remove"])
def delete_item(name: str):
"""Delete an item."""
print(f"Deleting {name}")
if __name__ == "__main__":
app()
Run it:
$ python app.py --help
Commands:
list (ls, l) List all items.
delete (rm, remove) Delete an item.
$ python app.py ls
Listing items...
$ python app.py rm test.txt
Deleting test.txt
[!TIP] Want to learn more? Check the API Reference for detailed configuration options, or see the User Guide for patterns and best practices.
Drop-in Compatibility
Have an existing Typer project? Add alias support without changing your code:
# Before (regular Typer)
from typer import Typer
app = Typer()
# After (with typer-extensions)
from typer_extensions import ExtendedTyper
app = ExtendedTyper()
# That's it! Everything else stays the same.
# Existing commands, shell completion and help text configuration still work exactly as before.
Once migrated, you can add aliases to new commands using @app.command_with_aliases(), or to existing commands using the programmatic API.
[!TIP] See Migration Guide for detailed migration strategies and patterns.
Advanced Features
Programmatic alias management:
# Add aliases dynamically
app.add_alias("list", "dir")
# Remove aliases
app.remove_alias("dir")
# Query aliases
aliases = app.get_aliases("list") # ["ls", "l"]
Custom help formatting:
app = ExtendedTyper(
alias_display_format="[{aliases}]", # Use brackets
alias_separator=" | ", # Pipe separator
max_aliases_inline=2, # Show max 2, then "+N more"
)
Configuration-based aliases:
# Load aliases from config
config = {"list": ["ls", "l", "dir"]}
for cmd, aliases in config.items():
for alias in aliases:
app.add_alias(cmd, alias)
Documentation
📚 User Guide - Tutorials and common patterns
📖 API Reference - Complete API documentation
🔄 Migration Guide - Migrating from standard Typer
Examples
All examples are in the examples/ directory:
- basic_usage.py - Simple CLI with aliases
- advanced_usage.py - Git-like CLI with options
- programmatic_usage.py - Dynamic alias management
- help_formatting.py - Customising help display
- argument_option_usage.py - Using Typer's Argument & Option
Run any example:
python examples/basic_usage.py --help
python examples/basic_usage.py ls
Real-World Use Cases
Git-like CLI
@app.command_with_aliases("checkout", aliases=["co"])
def checkout(branch: str):
"""Switch branches."""
...
@app.command_with_aliases("status", aliases=["st"])
def status():
"""Show status."""
...
Package Manager
@app.command_with_aliases("install", aliases=["i", "add"])
def install(package: str):
"""Install a package."""
...
@app.command_with_aliases("remove", aliases=["rm", "uninstall"])
def remove(package: str):
"""Remove a package."""
...
Cross-Platform Commands
@app.command("list")
def list_files():
"""List files."""
...
# Add platform-specific aliases
if platform.system() == "Windows":
app.add_alias("list", "dir")
else:
app.add_alias("list", "ls")
API Overview
Decorator Registration
@app.command_with_aliases(name, aliases=[...])
Programmatic Registration
app.add_aliased_command(func, name, aliases=[...])
Alias Management
app.add_alias(command, alias) # Add alias
app.remove_alias(alias) → bool # Remove alias
app.get_aliases(command) → list # Query aliases
app.list_commands_with_aliases() → dict # All mappings
Configuration
ExtendedTyper(
alias_case_sensitive=None, # Case-sensitive (default True, matching Typer)
show_aliases_in_help=True, # Display aliases in help
alias_display_format="({aliases})", # Display format
alias_separator=", ", # Between aliases
max_num_aliases=3, # Before truncation
)
Development
Setup
Standard setup with pip:
git clone https://github.com/rdawebb/typer-extensions.git
cd typer-extensions
python -m venv venv
source venv/bin/activate # or venv\Scripts\activate on Windows
pip install -e ".[dev]"
Or with uv (recommended):
git clone https://github.com/rdawebb/typer-extensions.git
cd typer-extensions
uv sync --all-extras
source .venv/bin/activate
Quick commands with justfile:
If you have just installed (included in [dev]), common tasks are available:
just test # Run tests
just lint # Run linter
just format # Format code
just type # Check type safety
just test-cov # Full test suite with coverage
just help # List all available commands
[!NOTE] If you prefer to use
justwithout the dev setup, you can install it globally viapip install rust-justor your system package manager.
[!TIP] See
Justfilefor all available commands.
Testing
With justfile (recommended):
just check # Run linting, formatting, and type checks
just test # Run tests
just test-cov # Run tests with coverage report
just pre # Full pre-commit check (all checks + tests)
Or with direct commands:
pytest # Run all tests
pytest --cov # With coverage
pytest -v # Verbose output
ruff check . # Lint
ruff format . # Format
ty check src/ # Type check
Contributing
Contributions are welcome! Please open an issue, ask a question, or submit a pull request.
Project Status
Current Version: 0.2.1 (Beta)
✅ Core Features Complete:
- Alias registration (decorator + programmatic)
- Help text formatting
- Dynamic alias management
- Full test coverage
🚧 In Development:
- Dynamic config file loading with import/export
- Shell completion enhancement and typo suggestions
- Documentation site
- Performance optimisations
📋 Planned Features:
- Shared & chained subcommand aliases
- Per-alias help text
- Dataclass, Pydantic & Attrs support
- Custom themes and help text formatting
- Argument & Option customisation
[!NOTE] See CHANGELOG.md for version history.
Why typer-extensions?
For Users:
- ⚡ Faster workflows with short aliases
- 🎯 Familiar commands (git-like shortcuts)
- 📖 Clear help text showing all options
For Developers:
- 🧹 DRY - no code duplication
- 🔧 Flexible - static or dynamic aliases
- 🎨 Customisable - match your style
- ✅ Tested - reliable, stable, and type-safe
Compared to Alternatives:
- Plain Typer: Requires command duplication or hiding
- click-aliases: Click-specific, no Typer integration
- Custom solutions: Reinventing the wheel
Related Projects
- Typer - The CLI framework this extends
- Click - The underlying library
- Rich - Beautiful terminal formatting (used by Typer)
License
MIT License - see LICENSE file for details.
Acknowledgments
Built on the excellent Typer framework by Sebastián Ramírez.
Inspired by Git's command aliasing and various CLI tools that make shortcuts feel natural.
Support
- 🐛 Issues: GitHub Issues
- 💬 Discussions: GitHub Discussions
- 📧 Contact: Create an issue for questions
Links
- GitHub: https://github.com/rdawebb/typer-extensions
- PyPI: https://pypi.org/project/typer-extensions/
- Changelog: CHANGELOG.md
Making CLI aliases natural and maintainable
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file typer_extensions-0.2.2.tar.gz.
File metadata
- Download URL: typer_extensions-0.2.2.tar.gz
- Upload date:
- Size: 34.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1c2f17fc4e26cd4013ef6a30ecf0403ef331990a5a910fd124671ae4496afe7a
|
|
| MD5 |
ba563bafe98949cd5c5f4dbb24aeed6f
|
|
| BLAKE2b-256 |
3bc70d37b0b2a077722a36ad8aba044d43fa244bc70460137450a1427521a895
|
File details
Details for the file typer_extensions-0.2.2-py3-none-any.whl.
File metadata
- Download URL: typer_extensions-0.2.2-py3-none-any.whl
- Upload date:
- Size: 12.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6510b90fa87b25088bc24cd693b9294d1eb96460991a6b0451e18d17ac68b335
|
|
| MD5 |
0e0d3bc680ac1c4a0211e17c8aff2f42
|
|
| BLAKE2b-256 |
deeb4945c731a0102cfa386341e064a50b69292ddb1dd660f14496021ba573e5
|