Automatically generate desktop GUIs for Typer CLI applications using Flet
Project description
Typer2UI
Automatically generate desktop GUIs for existing Typer CLI applications using Flet.
Overview
Typer2UI is a Python library that bridges the gap between command-line interfaces and graphical user interfaces. If you have a Typer-based CLI application, you can instantly create a desktop GUI for it with just a few lines of code.
Key Features
- Zero or minimal code changes to your existing Typer app
- Automatic GUI generation from Typer commands and parameters
- Simple, elegant API -
ui(component)for all output - Auto-update components - modify components and see changes instantly
- Progressive rendering - update UI in real-time with context managers
- Rich UI components - Tables, Markdown, Buttons, Rows, Columns, and more
- Type-aware controls - text fields, dropdowns, checkboxes based on parameter types
- Real-time output streaming - see output as it's produced for long-running commands
- Clean, modern interface powered by Flet
Installation
Using pip
pip install typer2ui
This will automatically install typer and flet as dependencies if they're not already present.
For development
# Clone the repository
git clone https://github.com/rados4y/typer2ui.git
cd typer2ui
# Create a virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install in development mode
pip install -e .
Quick Start
Here's a minimal example to get you started:
# my_app.py
import typer
import typer2ui as tu
# Create the Typer app
app = typer.Typer()
# Create the UI wrapper
ui = tu.Ui(
app,
title="My App",
description="A graphical interface for my CLI app"
)
@app.command()
def greet(name: str, excited: bool = False):
"""Greet someone with a friendly message."""
punctuation = "!" if excited else "."
# Use ui() to output components
ui(tu.Md(f"# Hello {name}{punctuation}"))
ui(tu.Text("Thanks for using Typer2UI!"))
@app.command()
def add(a: int, b: int):
"""Add two numbers together."""
result = a + b
# You can also use print()
print(f"{a} + {b} = {result}")
if __name__ == "__main__":
# Launch the GUI
ui.app()
Run it:
# Launch GUI
python my_app.py
# Or run CLI directly with --cli flag
python my_app.py --cli greet "World" --excited
python my_app.py --cli add 5 10
That's it! Your CLI app now has a fully functional GUI.
The Simple API
Universal Output: ui(component)
Instead of multiple output methods, Typer2UI has one simple pattern:
# Output any component
ui(tu.Text("Hello"))
ui(tu.Md("# Header"))
ui(tu.Table(cols=["Name"], data=[["Alice"]]))
# Or return a component (auto-displayed)
@app.command()
def get_data():
return tu.Table(cols=["Name"], data=[["Bob"]])
Available Components
Text & Markdown
ui(tu.Text("Plain text"))
ui(tu.Md("**Bold** and *italic* with markdown"))
ui(tu.Md("""
# Report
- Item 1
- Item 2
"""))
Tables
ui(tu.Table(
cols=["Name", "Age", "City"],
data=[
["Alice", 30, "NYC"],
["Bob", 25, "LA"],
],
title="Users"
))
Layout Components
# Horizontal layout
ui(tu.Row([
tu.Button("Save", on_click=save_data),
tu.Button("Cancel", on_click=cancel),
]))
# Vertical layout
ui(tu.Column([
tu.Md("# Dashboard"),
tu.Table(cols=["Metric", "Value"], data=get_metrics()),
]))
Interactive Components
# Buttons (GUI only)
ui(tu.Button("Click me", on_click=lambda: print("Clicked!")))
# Links (GUI only)
ui(tu.Link("Learn more", on_click=open_docs))
# Text input (GUI only)
ui(tu.TextInput(
label="Name",
value="",
on_change=lambda text: print(f"Changed to: {text}")
))
Auto-Update Components
One of Typer2UI's most powerful features: components automatically update when modified!
@app.command()
def process_items():
# Create and present a table
table = tu.Table(cols=["Item", "Status"], data=[])
ui(table) # Present it
# Add rows - table auto-updates in real-time!
for i in range(10):
table.add_row([f"Item {i}", "Processing..."])
time.sleep(0.5)
ui(tu.Md("✓ Complete!"))
Progressive Rendering with Context Managers
For even cleaner code, use context managers:
@app.command()
@ui.command(is_long=True)
def analyze_data():
# Present and update in one flow
with ui(tu.Table(cols=["Step", "Progress"], data=[])) as table:
table.add_row(["Loading", "0%"])
time.sleep(1)
table.add_row(["Processing", "50%"])
time.sleep(1)
table.add_row(["Complete", "100%"])
GUI Customization
Use the @ui.command() decorator to customize command behavior:
@app.command()
@ui.command(is_button=True, is_long=True)
def process():
"""Long-running process with button styling."""
with ui(tu.Table(cols=["Step", "Status"], data=[])) as t:
for i in range(10):
t.add_row([f"Step {i+1}", "Running..."])
time.sleep(1)
Available options:
is_button(bool): Display command as a highlighted buttonis_long(bool): Enable real-time output streamingis_auto_exec(bool): Execute automatically when selected
Comprehensive Example
import typer
import typer2ui as tu
import time
app = typer.Typer()
ui = tu.Ui(app, title="Data Processor", description="Process and analyze data")
@app.command()
def show_report():
"""Display a formatted report."""
ui(tu.Md("""
# System Report
## Summary
All systems operational.
"""))
ui(tu.Table(
cols=["Component", "Status", "Usage"],
data=[
["CPU", "✓", "45%"],
["Memory", "✓", "60%"],
["Disk", "✓", "70%"],
],
title="System Metrics"
))
@app.command()
@ui.command(is_button=True, is_long=True)
def process_files(count: int = 5):
"""Process multiple files with progress updates."""
ui(tu.Md(f"# Processing {count} files"))
with ui(tu.Table(cols=["File", "Status"], data=[])) as table:
for i in range(count):
table.add_row([f"file_{i}.txt", "Processing..."])
time.sleep(0.5)
ui(tu.Md("✓ **All files processed!**"))
@app.command()
def dashboard():
"""Show interactive dashboard."""
ui(tu.Column([
tu.Md("# Dashboard"),
tu.Row([
tu.Button("Refresh", on_click=lambda: print("Refreshing...")),
tu.Button("Export", on_click=lambda: print("Exporting...")),
]),
tu.Table(
cols=["Metric", "Value"],
data=[
["Users", "1,234"],
["Revenue", "$56,789"],
["Growth", "+12%"],
]
),
]))
@app.command()
def analyze():
"""Return data for automatic display."""
return tu.Table(
cols=["Analysis", "Result"],
data=[
["Mean", "42.5"],
["Median", "40.0"],
["Std Dev", "5.2"],
]
)
if __name__ == "__main__":
ui.app()
Supported Parameter Types
Typer2UI automatically maps Python types to appropriate GUI controls:
| Python Type | GUI Control | Notes |
|---|---|---|
str |
Text field | For string input |
int |
Text field | Numeric keyboard, validates integers |
float |
Text field | Numeric keyboard, validates floats |
bool |
Checkbox | For boolean flags |
Enum |
Dropdown | Shows all enum values as options |
Example with Enums
from enum import Enum
class LogLevel(str, Enum):
DEBUG = "debug"
INFO = "info"
WARNING = "warning"
ERROR = "error"
@app.command()
def configure(level: LogLevel = LogLevel.INFO):
"""Configure logging level."""
print(f"Log level set to: {level.value}")
In the GUI, the level parameter will appear as a dropdown with all enum values.
API Reference
Ui Class
The main entry point for Typer2UI.
Constructor:
Ui(app, *, title=None, description=None)
Parameters:
app(typer.Typer): The Typer application instancetitle(str, optional): Window title for the GUIdescription(str, optional): Description text shown at the top
Methods:
ui(component) - Universal Output
Output any UI component. Returns the component for chaining/context managers.
# Simple output
ui(tu.Text("Hello"))
# Store reference for updates
table = tu.Table(cols=["Name"], data=[])
ui(table)
table.add_row(["Alice"]) # Auto-updates!
# Context manager
with ui(tu.Table(cols=["Name"], data=[])) as t:
t.add_row(["Bob"])
ui.command(*, is_button=False, is_long=False, is_auto_exec=False)
Decorator to customize command appearance and behavior.
@app.command()
@ui.command(is_button=True, is_long=True)
def process():
print("Processing...")
ui.app()
Launch the GUI or run in CLI mode with --cli flag.
python my_app.py # Launch GUI
python my_app.py --cli hello # Run CLI
UI Components
All components are in the typer2ui module:
import typer2ui as tu
# Simple components
tu.Text("content") # Plain text
tu.Md("# markdown") # Markdown
# Data display
tu.Table(
cols=["A", "B"], # Column headers
data=[["1", "2"]], # Row data
title="Table Title" # Optional title
)
# Layout
tu.Row([comp1, comp2]) # Horizontal
tu.Column([comp1, comp2]) # Vertical
# Interactive (GUI only)
tu.Button("text", on_click=callback)
tu.Link("text", on_click=callback)
tu.TextInput("label", value="", on_change=callback)
Examples
Check out the examples/ directory for working examples:
01_basic_typer_to_gui.py- Minimal example showing basic usage02_arguments_and_output.py- Parameters and UI components03_ui_blocks.py- Tables, layout, and composition04_customizations.py- Buttons, streaming, and advanced features
Run examples:
# GUI mode
python examples/01_basic_typer_to_gui.py
# CLI mode
python examples/01_basic_typer_to_gui.py --cli add 5 3
Features
Current Features
- ✅ Simple, unified API with
ui(component) - ✅ Auto-update components when modified
- ✅ Progressive rendering with context managers
- ✅ Rich UI components (Text, Markdown, Table, Row, Column, Button, Link)
- ✅ Automatic GUI generation from Typer commands
- ✅ Type-aware form controls
- ✅ Real-time output streaming (
is_long=True) - ✅ Command customization (
is_button,is_auto_exec) - ✅ Both GUI and CLI modes from single entry point
- ✅ Cross-platform (Windows, macOS, Linux)
Planned Features
- Path/file selection widgets
- Progress bars and spinners
- Date/time pickers
- Custom themes
- Nested/grouped commands
- Command history
- Tabs and panels
How It Works
- Reflection: Analyzes your Typer app using Python's introspection
- GUI Generation: Creates Flet-based UI with appropriate controls
- Direct Execution: Calls your command functions directly (not via subprocess)
- Component System: Simple
show_cli()andshow_gui()methods for each component - Auto-Update: Components track when they're presented and update automatically
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
License
MIT License - see LICENSE file for details.
Credits
Built with:
Made with ❤️ for the Python CLI community
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 typer2ui-0.14.0.tar.gz.
File metadata
- Download URL: typer2ui-0.14.0.tar.gz
- Upload date:
- Size: 59.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f62c9ae4075d9bad683e643ee54dbac803ca35293153553fdde1826a72f742f6
|
|
| MD5 |
d467801d879660984c9419a04b478f8d
|
|
| BLAKE2b-256 |
6f24b1773a91fa5e1c1754601e227a7ff40438f77dd7ef0a9d49092650823868
|
File details
Details for the file typer2ui-0.14.0-py3-none-any.whl.
File metadata
- Download URL: typer2ui-0.14.0-py3-none-any.whl
- Upload date:
- Size: 63.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a33211439cb656e0c1f29c9defc51b8bdaa3e12bc7f5006c01d272b80de2311f
|
|
| MD5 |
7ac690655cf2b12bbc4742a584642817
|
|
| BLAKE2b-256 |
3c11a446bb1d1681de12001d8fb98ff151ca4dae7db3441c87b7ce641ad259b6
|