Skip to main content

A modern CLI framework based on Click, Rich and Textual.

Project description

yotta

Build complete CLIs and TUIs in Python, the fast way. (Django-inspired)

yotta is designed to simplify the creation of Command Line Interfaces (CLI) and Terminal User Interfaces (TUI).

It combines the robustness of Click, the beauty of Rich, and the interactivity of Textual within a modular architecture inspired by Django.

Why yotta?

Most CLI applications follow the same foundational patterns. yotta packages those patterns into a framework so you can ship faster without giving up structure, readability, or user experience.

Building a CLI app with yotta is making sure to get:

  • Modular Architecture: Split your code into reusable "Apps" (startproject, startapp).
  • UI-First Spirit: A native UX engine. Display tables, spinners, and alerts without manually importing Rich.
  • Hybrid TUI Mode: Transform a command into a full interactive dashboard (mouse/keyboard) via native Textual integration.
  • Smart Arguments: Automatic validation (Email, Files, Ranges) before your code even runs.

Installation

Install the CLI from PyPI

Use a global tool install if you want the yotta command available everywhere:

uv tool install yotta-framework
yotta --version

Add yotta to a project

If you want to use yotta inside an existing project managed by uv:

uv add yotta-framework

Development setup

If you want to work on yotta itself:

git clone https://github.com/dim-gggl/yotta.git
cd yotta
uv sync --all-extras
uv pip install -e .

Quick Start

  1. Create a new project

yotta scaffolds the entire folder structure for you.

yotta startproject my_cli
cd my_cli
uv sync
# A pyproject.toml and .env.example (with YOTTA_SETTINGS_MODULE) are created for you
  1. Create an app (module)
uv run ./manage.py startapp inventory

Note: Don't forget to add 'my_cli.inventory' (replace with your project name) to INSTALLED_APPS in your settings.py file.

  1. Scaffold a command interactively (optional)
uv run ./manage.py startcommand

Follow the prompts to pick the target app, command name, arguments, and options. yotta will append a ready-to-edit function to the selected app's commands.py. 4. Write your first command In my_cli/inventory/commands.py:

import time

from yotta.cli.decorators import command, argument
from yotta.core.context import YottaContext
from yotta.core.types import EMAIL


@command(name="add_user", help="Adds a user to the inventory")
@argument("email", type=EMAIL)
def add_user(yotta: YottaContext, email: str) -> None:
    # Using the native UI engine
    yotta.ui.header("New User")
    # Access project configuration without extra imports
    # (settings are loaded lazily on first attribute access)
    _ = yotta.settings

    with yotta.ui.spinner("Checking database..."):
        # Simulate work
        time.sleep(1)

    yotta.ui.success(f"User [bold]{email}[/] added successfully!")

    # Automatic formatted table
    yotta.ui.table(
        columns=["ID", "Email", "Status"],
        rows=[["1", email, "Active"]],
        title="Summary",
    )
  1. Run the command
uv run ./manage.py add_user contact@example.com

Settings and environment

  • YOTTA_SETTINGS_MODULE is loaded from .env or .env.local (the latter overrides).
  • You can also set YOTTA_ENV=prod to auto-load settings_prod.py.
  • YOTTA_DEBUG=1 will surface full tracebacks during settings import and loader errors.
  • THEME controls the console palette. Supported values: "default", "dark" (unknown values fall back to "default").

To override the theme, set it in your project's settings.py:

# settings.py
THEME = "dark"

Debugging imports and discovery

  • Loader warnings surface when an app has no commands.py; use --verbose for extra details or --quiet to silence.
  • Use --strict to fail fast on missing/broken command modules (useful in CI).

TUI Mode (Textual Integration)

Need a real-time interactive dashboard? yotta integrates Textual natively.

Define a view in my_cli/inventory/ui.py:

from textual.app import ComposeResult
from textual.widgets import Placeholder
from yotta.ui.tui import YottaApp


class MonitorDashboard(YottaApp):
    def compose(self) -> ComposeResult:
        yield Placeholder("Performance charts here")

Launch it from a standard command:

from yotta.cli.decorators import command
from yotta.core.context import YottaContext


@command(name="monitor")
def launch_monitor(yotta: YottaContext) -> None:
    app = MonitorDashboard(title="Super Monitor")
    app.run()

Key Features

The UI Context (yotta.ui)

yotta injects a ui wrapper into all your commands. No need to instantiate Console everywhere.

Method Description
yotta.ui.header(title, subtitle) Displays a stylized panel header.
yotta.ui.success(msg) Displays a success message (green).
yotta.ui.error(msg) Displays an error message (red).
yotta.ui.table(cols, rows) Generates a formatted Rich table.
yotta.ui.spinner(msg) Context manager for an animated loader.
yotta.ui.confirm(question) Interactive Yes/No prompt.

RichUI - Unified Access to All Rich Components

Need direct access to Rich components? Use the rich singleton to instantiate any Rich component without manual imports.

from yotta.ui import rich

# Instead of: from rich.align import Align
align = rich.align("Centered text", align="center")

# Instead of: from rich.syntax import Syntax
syntax = rich.syntax(code, "python", theme="monokai")

# Instead of: from rich.table import Table
table = rich.table(title="My Data")

# Instead of: from rich.tree import Tree
tree = rich.tree("Root")

# Instead of: from rich.panel import Panel
panel = rich.panel("Content", title="Info")

Available components and utilities:

  • Core: console, group
  • Layout: align, columns, constrain, layout, padding
  • Containers: panel
  • Text & Styling: color, emoji, pretty, style, styled, syntax, text, theme, markdown
  • Tables & Trees: table, tree
  • Progress: progress, spinner, status, live (with bar_column, text_column, etc.)
  • Prompts: prompt, confirm, int_prompt, float_prompt
  • Rendering: rule, segment, traceback, json
  • Utilities: pprint, pretty_repr, install_traceback, escape_markup, render_markup

Box styles: Access via rich.ROUNDED, rich.HEAVY, rich.DOUBLE, rich.MINIMAL

This singleton approach provides seamless access to all Rich functionality through a single import, keeping your code clean and consistent.

Smart Types (yotta.core.types)

Validate user input without writing a single if/else.

EMAIL: Validates email format (Regex).

File(extension='.json'): Checks for file existence AND specific extension.

Range(min=18, max=99): Enforces numeric range.

Choice([...]): Restrict values to a predefined list (case-insensitive by default).

Path() / Directory(): Validate existing filesystem paths (files or directories).

UUID(): Validate UUID strings.

URL(): Validate http/https URLs.

JSON(): Accept JSON strings or paths to JSON files, returns parsed objects.

Port(min,max): Validate port numbers in the allowed range.

EnumChoice(MyEnum): Use Python Enums as a source of allowed values.

Project Structure

my_cli/
├── .env.example           # Environment bootstrap
├── manage.py              # Project entry point
├── pyproject.toml         # Project metadata and dependencies
├── settings.py            # Global configuration
└── my_cli/                # Your applications folder (as a package)
    ├── main/
    │   ├── __init__.py
    │   └── commands.py    # Example command created by startproject
    └── inventory/
        ├── __init__.py
        ├── commands.py    # Your CLI commands
        └── ui.py          # Your visual components

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yotta_framework-1.0.2.tar.gz (32.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yotta_framework-1.0.2-py3-none-any.whl (35.8 kB view details)

Uploaded Python 3

File details

Details for the file yotta_framework-1.0.2.tar.gz.

File metadata

  • Download URL: yotta_framework-1.0.2.tar.gz
  • Upload date:
  • Size: 32.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for yotta_framework-1.0.2.tar.gz
Algorithm Hash digest
SHA256 6cbb5656b8e212d2f57c0d32485bb0635954134c2cd5319de69d467d7729410f
MD5 5533141bcba6daafbc09c2f0f11c4bf4
BLAKE2b-256 553fbb1310a203c48032ff7bd6a2844ec57e55b513aea6e81146d0e1d2f6fd4b

See more details on using hashes here.

File details

Details for the file yotta_framework-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: yotta_framework-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 35.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for yotta_framework-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 138b08cbb3eb682224fae270689ac5597b2125bdc63a1e56bf319bfcc498f51f
MD5 d895a995366193b448fd84aa0d3af371
BLAKE2b-256 8756fb8cd429f1e565741dac706a8a5a2faed26923c305cbf33f5e6ce5e491a6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page