Skip to main content

A framework for building production-ready CLI apps and Terminal UIs with minimal code.

Project description

clidev

clidev is a Python framework for building production-ready Command Line Applications (CLI) and Terminal User Interfaces (TUI) with minimal code.

Unlike traditional CLI libraries that only parse arguments, clidev gives you a complete framework for interactive terminal apps — menus, forms, workflows, dashboards, state management, command execution, navigation, and event-driven logic — so you don't have to hand-write input loops, menu rendering, or terminal state machines.

Think of it as the Flutter/React of terminal applications: you describe what your app looks like and does, clidev handles the rendering loop.

Built on top of rich for terminal rendering and questionary for interactive prompts.


Installation

pip install -e .

(This installs clidev from this repo in editable mode, along with its dependencies: rich, questionary, pydantic, click, PyYAML, toml.)

Quick start

from clidev import App

app = App("My App")

home = app.menu("Home")
home.option("Say Hello", lambda: app.success("Hello!"))
home.option("Exit", app.exit)

app.run()

Or scaffold a brand-new project with the bundled CLI:

clidev new myproject
cd myproject
python app.py

Module guide

App (clidev/app.py)

The core object. Wires together state, storage, routing, events, plugins, theming, and every UI widget factory.

from clidev import App

app = App("Developer Toolkit", theme="dark", storage_backend="json")

State (clidev/state.py)

Global, dict-like state, accessible anywhere in your app.

app.state["username"] = "Vrushabh"
print(app.state["username"])

app.state.on_change(lambda key, old, new: print(f"{key}: {old} -> {new}"))

Storage (clidev/storage.py)

Every form (or any code) can persist data through a pluggable backend: memory, json, sqlite, yaml, or toml.

app.storage.save("user", {"name": "Bob"})
user = app.storage.load("user")
app = App("My App", storage_backend="sqlite")

Forms (clidev/forms.py, inputs.py, validators.py)

Chainable form builder with automatic validation.

form = app.form("User")
form.text("Name")
form.email("Email")
form.password("Password")
form.number("Age")

data = form.run()
# {"Name": "Vrushabh", "Email": "abc@gmail.com", "Password": "******", "Age": 17}

Supported field types: text, email, password, number, url, file, folder, date, time, checkbox, toggle, radio, select/dropdown, multiselect, searchable.

Custom validators can be attached per-field via extra_validators=[...] using anything from clidev.validators (min_length, max_length, min_value, max_value, is_date, etc.).

Menus (clidev/menus.py)

menu = app.menu("Main Menu")
menu.option("Create Project", create_project)
menu.option("Deploy", deploy)
menu.option("Exit", app.exit)

Nested menus:

main = app.menu("Main")
settings = app.menu("Settings")
main.link("Settings", settings)

Page routing (clidev/router.py, pages.py)

@app.page("home")
def home():
    ...

app.goto("settings")
app.back()

Conditional navigation (clidev/actions.py)

@app.when(lambda data: data["Role"] == "Admin")
def admin():
    app.goto("admin_menu")

or:

app.if_value("Role", equals="Admin").goto("admin_menu")
app.if_value("Age", greater_than=18).goto("adult_menu")

Supported comparisons: equals, not_equals, greater_than, less_than, greater_equal, less_equal, contains, in_list.

Workflow engine (clidev/workflow.py)

workflow = app.workflow()
workflow.step(login)
workflow.step(select_project)
workflow.step(build)
workflow.step(deploy)
result = workflow.start()

Each step can accept a shared context dict; whatever a step returns (as a dict) is merged into that context for subsequent steps.

Events (clidev/events.py)

@app.on_start
def startup():
    ...

@app.on_exit
def shutdown():
    ...

@app.on_submit(some_form)
def save(data):
    ...

@app.on_error
def on_error(e):
    ...

Images & Video (clidev/image.py)

Render static images and play video clips directly inside the terminal, using colored half-block characters (real truecolor, not ASCII-art approximation) for near photo-quality output in supporting terminals.

app.image("photo.png").show()
app.video("clip.mp4").play()

Requires optional dependencies:

pip install clidev[media]

or individually:

pip install Pillow            # for images
pip install opencv-python     # for video

If these aren't installed, calling .image() or .video() raises a clear ClidevError telling you what to install — the rest of clidev works fine without them.

Images

app.image("photo.png").show()
app.image("photo.png", width=60).show()   # control render width in columns
Argument Default Description
path Path to the image file
width terminal width (max 120) Render width in terminal columns

Video

app.video("clip.mp4").play()
app.video("clip.mp4", width=60, fps=10).play(max_frames=200)
Argument Default Description
path Path to the video file
width terminal width (max 100) Render width in terminal columns
fps source video's FPS Override playback frame rate

.play() options:

  • max_frames — stop after N rendered frames (default: play whole video)
  • skip — render every Nth source frame, useful to keep pace on longer or higher-fps clips where terminal redraw can't keep up

Terminal compatibility: works best in terminals with truecolor support (Windows Terminal, iTerm2, most modern Linux terminals). Classic cmd.exe may render duller or incorrect colors.

Command execution (clidev/shell.py)

app.cmd("git init")

result = app.cmd("git status", capture=True)
print(result.stdout, result.ok)

app.cmd("pip install -r requirements.txt", background=True)

Progress & tasks (clidev/progress.py, spinner.py, tasks.py, scheduler.py)

with app.progress("Installing"):
    app.cmd("pip install numpy")
    app.cmd("pip install pandas")

@app.task
def build():
    ...

app.run_task("build")

Plugins (clidev/plugins.py)

from clidev.plugins import Plugin

class GitPlugin(Plugin):
    name = "git"

    def on_install(self, app):
        ...

    def on_start(self, app):
        ...

app.use(GitPlugin())

Themes (clidev/themes.py, colors.py)

app = App("My App", theme="dark")

theme = Theme()
theme.primary("blue")
theme.success("green")

Banner (clidev/banner.py)

Render text as large ASCII-art block letters — great for app splash screens, section headers, or command output.

app.banner("HI").show()

Customize the symbol used to draw the letters:

app.banner("DEPLOYED", symbol="@").show()

Or use it standalone (outside an App instance):

from clidev.banner import Banner

Banner("HELLO", symbol="*").show()

Supported characters: A-Z (case-insensitive), 0-9, and basic punctuation (. , ! ? - :). Unsupported characters render as blank space rather than raising an error.

Constructor options:

Argument Default Description
text Text to render (auto-uppercased)
symbol "#" Character used to draw filled pixels
spacing 1 Blank columns between letters
theme None If set (e.g. via app.banner(...)), colors the banner using the theme's primary color

.render() returns the raw multi-line string (useful if you want to embed it inside a Card, log it, or write it to a file) — .show() prints it directly to the console with theme styling applied.

from clidev import App

app = App("My App") app.banner("MY APP").show() ...

Logging (clidev/logger.py)

app.logger.info("Started")
app.logger.warning("Warning")
app.logger.error("Failed")

UI widgets

  • app.table(title, columns=[...]) — data tables (clidev/table.py)
  • app.tree(label) — tree views (clidev/tree.py)
  • app.card(title, content) — bordered content cards (clidev/cards.py)
  • app.dashboard(title) — multi-panel grid overview (clidev/dashboard.py)
  • app.dialog.confirm(...), app.dialog.prompt(...), app.dialog.alert(...) (clidev/dialogs.py)
  • app.notify.success/error/warning/info(...) (clidev/notifications.py)
  • app.statusbar.set(...).render() (clidev/statusbar.py)

Project generator (clidev/generators/, cli.py)

clidev new myproject

Creates:

myproject/
│
├── app.py
├── routes.py
├── menus.py
├── forms.py
├── workflows.py
├── commands.py
├── storage.py
├── settings.py
└── assets/

Full example

See examples/basic_app.py for the complete "Developer Toolkit" example (menus, page routing, forms, storage, conditional navigation, and shell commands), and examples/workflow_app.py for a workflow + plugin + dashboard example.

from clidev import App

app = App("Developer Toolkit")

home = app.menu("Home")
home.option("Create Project", "project_form")
home.option("Settings", "settings")
home.option("Exit", app.exit)


@app.page("project_form")
def project_form_page():
    project = app.form("Project")
    project.text("Project Name")
    project.select("Language", ["Python", "Rust", "Go"])
    data = project.run()

    if not data:
        return

    app.storage.save("project", data)
    app._last_form_data = data

    if data["Language"] == "Python":
        app.goto("python_setup")
    else:
        app.success(f"Project '{data['Project Name']}' created ({data['Language']}).")


@app.page("python_setup")
def python_setup():
    with app.progress("Setting up Python project"):
        app.cmd("python -m venv .venv_demo")
        app.cmd("git init")
    app.success("Project Created")


if __name__ == "__main__":
    app.run()

Running the tests

pip install -e ".[dev]"
pytest tests/ -v

The test suite (in tests/) covers global state, all storage backends, form field validation, the shell command wrapper, routing/history, the workflow engine, conditional navigation, the event dispatcher, theming, the project generator, and full App integration — 85 tests in total.

Roadmap

  • Additional storage backends: PostgreSQL, MongoDB, Redis
  • clidev-auth, clidev-cloud, clidev-testing, clidev-plugins as separate installable packages
  • Richer dashboard layout options and live-updating widgets

License

MIT

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

clidevkit-1.0.0.tar.gz (39.2 kB view details)

Uploaded Source

Built Distribution

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

clidevkit-1.0.0-py3-none-any.whl (39.5 kB view details)

Uploaded Python 3

File details

Details for the file clidevkit-1.0.0.tar.gz.

File metadata

  • Download URL: clidevkit-1.0.0.tar.gz
  • Upload date:
  • Size: 39.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for clidevkit-1.0.0.tar.gz
Algorithm Hash digest
SHA256 0f6c6953abfbe8ff760d367ad68ea766ce0e02500bf9a71085a4bf8f49bf3134
MD5 61594f1636b7850f7d6fe7fd60dc0a90
BLAKE2b-256 8461a66d4af0a985fb84fd341d05c6ae0c5eb80aec13453c5b2adc5920ac9e3f

See more details on using hashes here.

File details

Details for the file clidevkit-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: clidevkit-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 39.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for clidevkit-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d70ba5fb67fe728f61472276d73fb13c10c10652731db07ff0bd86414446b485
MD5 230c7492d21d81639834738072eb5e89
BLAKE2b-256 093ebeaf5511be2cfc1318fdb9c5e8846278fa8376640fc907a1521ea192d97c

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