clidevkit 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- clidevkit-0.1.0/PKG-INFO +449 -0
- clidevkit-0.1.0/README.md +419 -0
- clidevkit-0.1.0/clidev/__init__.py +67 -0
- clidevkit-0.1.0/clidev/actions.py +73 -0
- clidevkit-0.1.0/clidev/app.py +210 -0
- clidevkit-0.1.0/clidev/builtins/__init__.py +1 -0
- clidevkit-0.1.0/clidev/builtins/plugins.py +26 -0
- clidevkit-0.1.0/clidev/cards.py +19 -0
- clidevkit-0.1.0/clidev/cli.py +42 -0
- clidevkit-0.1.0/clidev/colors.py +27 -0
- clidevkit-0.1.0/clidev/config.py +36 -0
- clidevkit-0.1.0/clidev/dashboard.py +28 -0
- clidevkit-0.1.0/clidev/dialogs.py +24 -0
- clidevkit-0.1.0/clidev/events.py +39 -0
- clidevkit-0.1.0/clidev/exceptions.py +35 -0
- clidevkit-0.1.0/clidev/forms.py +97 -0
- clidevkit-0.1.0/clidev/generators/__init__.py +13 -0
- clidevkit-0.1.0/clidev/generators/form.py +11 -0
- clidevkit-0.1.0/clidev/generators/menu.py +11 -0
- clidevkit-0.1.0/clidev/generators/project.py +150 -0
- clidevkit-0.1.0/clidev/generators/workflow.py +17 -0
- clidevkit-0.1.0/clidev/icons.py +16 -0
- clidevkit-0.1.0/clidev/inputs.py +90 -0
- clidevkit-0.1.0/clidev/logger.py +50 -0
- clidevkit-0.1.0/clidev/menus.py +69 -0
- clidevkit-0.1.0/clidev/notifications.py +26 -0
- clidevkit-0.1.0/clidev/pages.py +42 -0
- clidevkit-0.1.0/clidev/plugins.py +51 -0
- clidevkit-0.1.0/clidev/progress.py +42 -0
- clidevkit-0.1.0/clidev/router.py +37 -0
- clidevkit-0.1.0/clidev/scheduler.py +59 -0
- clidevkit-0.1.0/clidev/shell.py +84 -0
- clidevkit-0.1.0/clidev/spinner.py +25 -0
- clidevkit-0.1.0/clidev/state.py +47 -0
- clidevkit-0.1.0/clidev/statusbar.py +20 -0
- clidevkit-0.1.0/clidev/storage.py +221 -0
- clidevkit-0.1.0/clidev/table.py +39 -0
- clidevkit-0.1.0/clidev/tasks.py +28 -0
- clidevkit-0.1.0/clidev/themes.py +96 -0
- clidevkit-0.1.0/clidev/tree.py +36 -0
- clidevkit-0.1.0/clidev/utils.py +20 -0
- clidevkit-0.1.0/clidev/validators.py +90 -0
- clidevkit-0.1.0/clidev/workflow.py +52 -0
- clidevkit-0.1.0/clidevkit.egg-info/PKG-INFO +449 -0
- clidevkit-0.1.0/clidevkit.egg-info/SOURCES.txt +61 -0
- clidevkit-0.1.0/clidevkit.egg-info/dependency_links.txt +1 -0
- clidevkit-0.1.0/clidevkit.egg-info/entry_points.txt +2 -0
- clidevkit-0.1.0/clidevkit.egg-info/requires.txt +9 -0
- clidevkit-0.1.0/clidevkit.egg-info/top_level.txt +1 -0
- clidevkit-0.1.0/pyproject.toml +46 -0
- clidevkit-0.1.0/setup.cfg +4 -0
- clidevkit-0.1.0/tests/test_actions.py +73 -0
- clidevkit-0.1.0/tests/test_app.py +101 -0
- clidevkit-0.1.0/tests/test_events.py +58 -0
- clidevkit-0.1.0/tests/test_forms.py +72 -0
- clidevkit-0.1.0/tests/test_generators.py +27 -0
- clidevkit-0.1.0/tests/test_router.py +49 -0
- clidevkit-0.1.0/tests/test_shell.py +42 -0
- clidevkit-0.1.0/tests/test_state.py +46 -0
- clidevkit-0.1.0/tests/test_storage.py +67 -0
- clidevkit-0.1.0/tests/test_themes.py +37 -0
- clidevkit-0.1.0/tests/test_validators.py +93 -0
- clidevkit-0.1.0/tests/test_workflow.py +51 -0
clidevkit-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: clidevkit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A framework for building production-ready CLI apps and Terminal UIs with minimal code.
|
|
5
|
+
Author-email: Vrushabh Sonawane <shivandmau25@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/yourname/clidev
|
|
8
|
+
Project-URL: Repository, https://github.com/yourname/clidev
|
|
9
|
+
Project-URL: Issues, https://github.com/yourname/clidev/issues
|
|
10
|
+
Keywords: cli,tui,terminal,framework,forms,menus
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
19
|
+
Classifier: Environment :: Console
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: rich>=13.7.0
|
|
23
|
+
Requires-Dist: questionary>=2.0.1
|
|
24
|
+
Requires-Dist: pydantic>=2.6.0
|
|
25
|
+
Requires-Dist: click>=8.1.7
|
|
26
|
+
Requires-Dist: PyYAML>=6.0.1
|
|
27
|
+
Requires-Dist: toml>=0.10.2
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
30
|
+
|
|
31
|
+
# clidev
|
|
32
|
+
|
|
33
|
+
**clidev** is a Python framework for building **production-ready Command Line
|
|
34
|
+
Applications (CLI)** and **Terminal User Interfaces (TUI)** with minimal code.
|
|
35
|
+
|
|
36
|
+
Unlike traditional CLI libraries that only parse arguments, `clidev` gives you
|
|
37
|
+
a complete framework for interactive terminal apps — menus, forms, workflows,
|
|
38
|
+
dashboards, state management, command execution, navigation, and
|
|
39
|
+
event-driven logic — so you don't have to hand-write input loops, menu
|
|
40
|
+
rendering, or terminal state machines.
|
|
41
|
+
|
|
42
|
+
> Think of it as the Flutter/React of terminal applications: you describe
|
|
43
|
+
> what your app looks like and does, `clidev` handles the rendering loop.
|
|
44
|
+
|
|
45
|
+
Built on top of [`rich`](https://github.com/Textualize/rich) for terminal
|
|
46
|
+
rendering and [`questionary`](https://github.com/tmbo/questionary) for
|
|
47
|
+
interactive prompts.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install -e .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
(This installs `clidev` from this repo in editable mode, along with its
|
|
58
|
+
dependencies: `rich`, `questionary`, `pydantic`, `click`, `PyYAML`, `toml`.)
|
|
59
|
+
|
|
60
|
+
## Quick start
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from clidev import App
|
|
64
|
+
|
|
65
|
+
app = App("My App")
|
|
66
|
+
|
|
67
|
+
home = app.menu("Home")
|
|
68
|
+
home.option("Say Hello", lambda: app.success("Hello!"))
|
|
69
|
+
home.option("Exit", app.exit)
|
|
70
|
+
|
|
71
|
+
app.run()
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or scaffold a brand-new project with the bundled CLI:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
clidev new myproject
|
|
78
|
+
cd myproject
|
|
79
|
+
python app.py
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Module guide
|
|
85
|
+
|
|
86
|
+
### `App` (`clidev/app.py`)
|
|
87
|
+
|
|
88
|
+
The core object. Wires together state, storage, routing, events, plugins,
|
|
89
|
+
theming, and every UI widget factory.
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from clidev import App
|
|
93
|
+
|
|
94
|
+
app = App("Developer Toolkit", theme="dark", storage_backend="json")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### State (`clidev/state.py`)
|
|
98
|
+
|
|
99
|
+
Global, dict-like state, accessible anywhere in your app.
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
app.state["username"] = "Vrushabh"
|
|
103
|
+
print(app.state["username"])
|
|
104
|
+
|
|
105
|
+
app.state.on_change(lambda key, old, new: print(f"{key}: {old} -> {new}"))
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Storage (`clidev/storage.py`)
|
|
109
|
+
|
|
110
|
+
Every form (or any code) can persist data through a pluggable backend:
|
|
111
|
+
`memory`, `json`, `sqlite`, `yaml`, or `toml`.
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
app.storage.save("user", {"name": "Bob"})
|
|
115
|
+
user = app.storage.load("user")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
app = App("My App", storage_backend="sqlite")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Forms (`clidev/forms.py`, `inputs.py`, `validators.py`)
|
|
123
|
+
|
|
124
|
+
Chainable form builder with automatic validation.
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
form = app.form("User")
|
|
128
|
+
form.text("Name")
|
|
129
|
+
form.email("Email")
|
|
130
|
+
form.password("Password")
|
|
131
|
+
form.number("Age")
|
|
132
|
+
|
|
133
|
+
data = form.run()
|
|
134
|
+
# {"Name": "Vrushabh", "Email": "abc@gmail.com", "Password": "******", "Age": 17}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Supported field types: `text`, `email`, `password`, `number`, `url`, `file`,
|
|
138
|
+
`folder`, `date`, `time`, `checkbox`, `toggle`, `radio`, `select`/`dropdown`,
|
|
139
|
+
`multiselect`, `searchable`.
|
|
140
|
+
|
|
141
|
+
Custom validators can be attached per-field via `extra_validators=[...]`
|
|
142
|
+
using anything from `clidev.validators` (`min_length`, `max_length`,
|
|
143
|
+
`min_value`, `max_value`, `is_date`, etc.).
|
|
144
|
+
|
|
145
|
+
### Menus (`clidev/menus.py`)
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
menu = app.menu("Main Menu")
|
|
149
|
+
menu.option("Create Project", create_project)
|
|
150
|
+
menu.option("Deploy", deploy)
|
|
151
|
+
menu.option("Exit", app.exit)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Nested menus:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
main = app.menu("Main")
|
|
158
|
+
settings = app.menu("Settings")
|
|
159
|
+
main.link("Settings", settings)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Page routing (`clidev/router.py`, `pages.py`)
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
@app.page("home")
|
|
166
|
+
def home():
|
|
167
|
+
...
|
|
168
|
+
|
|
169
|
+
app.goto("settings")
|
|
170
|
+
app.back()
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Conditional navigation (`clidev/actions.py`)
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
@app.when(lambda data: data["Role"] == "Admin")
|
|
177
|
+
def admin():
|
|
178
|
+
app.goto("admin_menu")
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
or:
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
app.if_value("Role", equals="Admin").goto("admin_menu")
|
|
185
|
+
app.if_value("Age", greater_than=18).goto("adult_menu")
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Supported comparisons: `equals`, `not_equals`, `greater_than`, `less_than`,
|
|
189
|
+
`greater_equal`, `less_equal`, `contains`, `in_list`.
|
|
190
|
+
|
|
191
|
+
### Workflow engine (`clidev/workflow.py`)
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
workflow = app.workflow()
|
|
195
|
+
workflow.step(login)
|
|
196
|
+
workflow.step(select_project)
|
|
197
|
+
workflow.step(build)
|
|
198
|
+
workflow.step(deploy)
|
|
199
|
+
result = workflow.start()
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Each step can accept a shared `context` dict; whatever a step returns (as a
|
|
203
|
+
dict) is merged into that context for subsequent steps.
|
|
204
|
+
|
|
205
|
+
### Events (`clidev/events.py`)
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
@app.on_start
|
|
209
|
+
def startup():
|
|
210
|
+
...
|
|
211
|
+
|
|
212
|
+
@app.on_exit
|
|
213
|
+
def shutdown():
|
|
214
|
+
...
|
|
215
|
+
|
|
216
|
+
@app.on_submit(some_form)
|
|
217
|
+
def save(data):
|
|
218
|
+
...
|
|
219
|
+
|
|
220
|
+
@app.on_error
|
|
221
|
+
def on_error(e):
|
|
222
|
+
...
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Command execution (`clidev/shell.py`)
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
app.cmd("git init")
|
|
229
|
+
|
|
230
|
+
result = app.cmd("git status", capture=True)
|
|
231
|
+
print(result.stdout, result.ok)
|
|
232
|
+
|
|
233
|
+
app.cmd("pip install -r requirements.txt", background=True)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Progress & tasks (`clidev/progress.py`, `spinner.py`, `tasks.py`, `scheduler.py`)
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
with app.progress("Installing"):
|
|
240
|
+
app.cmd("pip install numpy")
|
|
241
|
+
app.cmd("pip install pandas")
|
|
242
|
+
|
|
243
|
+
@app.task
|
|
244
|
+
def build():
|
|
245
|
+
...
|
|
246
|
+
|
|
247
|
+
app.run_task("build")
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Plugins (`clidev/plugins.py`)
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
from clidev.plugins import Plugin
|
|
254
|
+
|
|
255
|
+
class GitPlugin(Plugin):
|
|
256
|
+
name = "git"
|
|
257
|
+
|
|
258
|
+
def on_install(self, app):
|
|
259
|
+
...
|
|
260
|
+
|
|
261
|
+
def on_start(self, app):
|
|
262
|
+
...
|
|
263
|
+
|
|
264
|
+
app.use(GitPlugin())
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Themes (`clidev/themes.py`, `colors.py`)
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
app = App("My App", theme="dark")
|
|
271
|
+
|
|
272
|
+
theme = Theme()
|
|
273
|
+
theme.primary("blue")
|
|
274
|
+
theme.success("green")
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Logging (`clidev/logger.py`)
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
app.logger.info("Started")
|
|
281
|
+
app.logger.warning("Warning")
|
|
282
|
+
app.logger.error("Failed")
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### UI widgets
|
|
286
|
+
|
|
287
|
+
- `app.table(title, columns=[...])` — data tables (`clidev/table.py`)
|
|
288
|
+
- `app.tree(label)` — tree views (`clidev/tree.py`)
|
|
289
|
+
- `app.card(title, content)` — bordered content cards (`clidev/cards.py`)
|
|
290
|
+
- `app.dashboard(title)` — multi-panel grid overview (`clidev/dashboard.py`)
|
|
291
|
+
- `app.dialog.confirm(...)`, `app.dialog.prompt(...)`, `app.dialog.alert(...)`
|
|
292
|
+
(`clidev/dialogs.py`)
|
|
293
|
+
- `app.notify.success/error/warning/info(...)` (`clidev/notifications.py`)
|
|
294
|
+
- `app.statusbar.set(...).render()` (`clidev/statusbar.py`)
|
|
295
|
+
|
|
296
|
+
### Project generator (`clidev/generators/`, `cli.py`)
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
clidev new myproject
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Creates:
|
|
303
|
+
|
|
304
|
+
```text
|
|
305
|
+
myproject/
|
|
306
|
+
│
|
|
307
|
+
├── app.py
|
|
308
|
+
├── routes.py
|
|
309
|
+
├── menus.py
|
|
310
|
+
├── forms.py
|
|
311
|
+
├── workflows.py
|
|
312
|
+
├── commands.py
|
|
313
|
+
├── storage.py
|
|
314
|
+
├── settings.py
|
|
315
|
+
└── assets/
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Full example
|
|
321
|
+
|
|
322
|
+
See [`examples/basic_app.py`](examples/basic_app.py) for the complete
|
|
323
|
+
"Developer Toolkit" example (menus, page routing, forms, storage, conditional
|
|
324
|
+
navigation, and shell commands), and
|
|
325
|
+
[`examples/workflow_app.py`](examples/workflow_app.py) for a workflow +
|
|
326
|
+
plugin + dashboard example.
|
|
327
|
+
|
|
328
|
+
```python
|
|
329
|
+
from clidev import App
|
|
330
|
+
|
|
331
|
+
app = App("Developer Toolkit")
|
|
332
|
+
|
|
333
|
+
home = app.menu("Home")
|
|
334
|
+
home.option("Create Project", "project_form")
|
|
335
|
+
home.option("Settings", "settings")
|
|
336
|
+
home.option("Exit", app.exit)
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
@app.page("project_form")
|
|
340
|
+
def project_form_page():
|
|
341
|
+
project = app.form("Project")
|
|
342
|
+
project.text("Project Name")
|
|
343
|
+
project.select("Language", ["Python", "Rust", "Go"])
|
|
344
|
+
data = project.run()
|
|
345
|
+
|
|
346
|
+
if not data:
|
|
347
|
+
return
|
|
348
|
+
|
|
349
|
+
app.storage.save("project", data)
|
|
350
|
+
app._last_form_data = data
|
|
351
|
+
|
|
352
|
+
if data["Language"] == "Python":
|
|
353
|
+
app.goto("python_setup")
|
|
354
|
+
else:
|
|
355
|
+
app.success(f"Project '{data['Project Name']}' created ({data['Language']}).")
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
@app.page("python_setup")
|
|
359
|
+
def python_setup():
|
|
360
|
+
with app.progress("Setting up Python project"):
|
|
361
|
+
app.cmd("python -m venv .venv_demo")
|
|
362
|
+
app.cmd("git init")
|
|
363
|
+
app.success("Project Created")
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
if __name__ == "__main__":
|
|
367
|
+
app.run()
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## Running the tests
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
pip install -e ".[dev]"
|
|
376
|
+
pytest tests/ -v
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
The test suite (in `tests/`) covers global state, all storage backends, form
|
|
380
|
+
field validation, the shell command wrapper, routing/history, the workflow
|
|
381
|
+
engine, conditional navigation, the event dispatcher, theming, the project
|
|
382
|
+
generator, and full `App` integration — 85 tests in total.
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## Project layout
|
|
387
|
+
|
|
388
|
+
```text
|
|
389
|
+
clidev/
|
|
390
|
+
├── __init__.py
|
|
391
|
+
├── app.py # Main application
|
|
392
|
+
├── router.py # Navigation
|
|
393
|
+
├── pages.py # Pages
|
|
394
|
+
├── menus.py # Menu engine
|
|
395
|
+
├── forms.py # Forms
|
|
396
|
+
├── inputs.py # Input widgets
|
|
397
|
+
├── validators.py
|
|
398
|
+
│
|
|
399
|
+
├── state.py # Global state
|
|
400
|
+
├── storage.py # JSON/SQLite/YAML/TOML storage
|
|
401
|
+
├── workflow.py # Workflow engine
|
|
402
|
+
├── events.py # Event dispatcher
|
|
403
|
+
├── actions.py # Conditional navigation
|
|
404
|
+
│
|
|
405
|
+
├── shell.py # Execute commands
|
|
406
|
+
├── tasks.py # Background tasks
|
|
407
|
+
├── scheduler.py
|
|
408
|
+
│
|
|
409
|
+
├── progress.py
|
|
410
|
+
├── spinner.py
|
|
411
|
+
├── dashboard.py
|
|
412
|
+
├── table.py
|
|
413
|
+
├── tree.py
|
|
414
|
+
├── cards.py
|
|
415
|
+
├── dialogs.py
|
|
416
|
+
├── notifications.py
|
|
417
|
+
├── statusbar.py
|
|
418
|
+
│
|
|
419
|
+
├── themes.py
|
|
420
|
+
├── colors.py
|
|
421
|
+
├── icons.py
|
|
422
|
+
│
|
|
423
|
+
├── logger.py
|
|
424
|
+
├── config.py
|
|
425
|
+
├── plugins.py
|
|
426
|
+
├── utils.py
|
|
427
|
+
├── exceptions.py
|
|
428
|
+
│
|
|
429
|
+
├── generators/
|
|
430
|
+
│ ├── project.py
|
|
431
|
+
│ ├── menu.py
|
|
432
|
+
│ ├── form.py
|
|
433
|
+
│ └── workflow.py
|
|
434
|
+
│
|
|
435
|
+
├── templates/
|
|
436
|
+
├── builtins/ # Example plugins (GitPlugin, DatabasePlugin)
|
|
437
|
+
└── cli.py # "clidev" terminal command
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
## Roadmap
|
|
441
|
+
|
|
442
|
+
- Additional storage backends: PostgreSQL, MongoDB, Redis
|
|
443
|
+
- `clidev-auth`, `clidev-cloud`, `clidev-testing`, `clidev-plugins` as
|
|
444
|
+
separate installable packages
|
|
445
|
+
- Richer dashboard layout options and live-updating widgets
|
|
446
|
+
|
|
447
|
+
## License
|
|
448
|
+
|
|
449
|
+
MIT
|