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,
clidevhandles 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.
```python
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-pluginsas separate installable packages- Richer dashboard layout options and live-updating widgets
License
MIT
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 clidevkit-1.0.1.tar.gz.
File metadata
- Download URL: clidevkit-1.0.1.tar.gz
- Upload date:
- Size: 41.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ded9fa43617db60e4fbb180b312a5b870b4c51d3e7b234f5d0916b7a7992f3c5
|
|
| MD5 |
5f32abc4fb8854df8aedd24f876c7809
|
|
| BLAKE2b-256 |
660b72b61e553f342a6a911f32c2880575540d8b4cf8b324f61a9c67dc888cad
|
File details
Details for the file clidevkit-1.0.1-py3-none-any.whl.
File metadata
- Download URL: clidevkit-1.0.1-py3-none-any.whl
- Upload date:
- Size: 40.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f1902237e011ab86767dbd3c7ebe005e34150b81a497544b986b64f09403310
|
|
| MD5 |
903dac97a1427b6956252c7c6254e3e5
|
|
| BLAKE2b-256 |
61edf50b085ccd6aeb107f6466f91f95bd7f93bf1ebf93b02fe893a4772d746e
|