typer-shell icon indicating copy to clipboard operation
typer-shell copied to clipboard

Simple wrapper around the Typer library for making beautiful shells/REPLs for fast command-line prototyping with Python.

Typer Shell!

Beautiful command-line shell with Typer!

This is just an update to click-shell for typer.

I also added some features like:

  • better help by default
  • support for typer default functions (just name one of your commands 'default' and it will be triggered when nothing else is recognized)
  • easily drop into an ipython terminal with the local context loaded with 'shell'
  • rich sample commands for file operations, tables, progress bars, and more

See it in action!

And checkout the demo script:

To run the demos, you can execute them with uv run:

uv run python demo/demo.py
uv run python demo/simple_demo.py

Or use the convenient just commands:

just demo
just simple-demo

There are also sample helper functions in typer_shell/samples.py that you can use in your own applications. These include:

Sample Commands

  • File Operations: ls, cat, pwd - basic file system navigation
  • Rich UI: table, progress, panel - demonstrate rich formatting capabilities
  • Interactive: ask - prompt for user input with rich styling
  • System: env, date - show environment variables and current time
  • Development: shell - drop into IPython with current context

Add them to your shell with:

from typer_shell.samples import add_sample_commands
add_sample_commands(app)

Using Callbacks

Because typer-shell uses Typer's callback mechanism to launch the interactive shell, you cannot use the standard @app.callback() decorator, as it will conflict and prevent the shell from loading.

If you need to run code before the shell launches (for example, to set up state), you can pass a function to the user_callback parameter in make_typer_shell.

Your function will be called with the Typer.Context object before the shell starts.

import typer
from typer_shell import make_typer_shell

def my_setup_logic(ctx: typer.Context):
    print("This runs before the shell starts!")
    # You can access and modify the context object here
    ctx.obj.my_value = 42

app = make_typer_shell(user_callback=my_setup_logic)

@app.command()
def my_command(ctx: typer.Context):
    print(f"my_value is: {ctx.obj.my_value}")

if __name__ == "__main__":
    app()

Development

This project uses uv for dependency management and ruff for linting/formatting.

# Setup development environment
uv sync

# Run demos
just demo
just simple-demo

# Code quality
just format  # Format code
just lint    # Check for issues
just fix     # Auto-fix issues

# Build and publish
just build
just publish