mcli-framework 7.11.0__py3-none-any.whl → 7.11.2__py3-none-any.whl
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.
Potentially problematic release.
This version of mcli-framework might be problematic. Click here for more details.
- mcli/app/commands_cmd.py +261 -0
- mcli/lib/paths.py +6 -2
- {mcli_framework-7.11.0.dist-info → mcli_framework-7.11.2.dist-info}/METADATA +19 -1
- {mcli_framework-7.11.0.dist-info → mcli_framework-7.11.2.dist-info}/RECORD +8 -8
- {mcli_framework-7.11.0.dist-info → mcli_framework-7.11.2.dist-info}/WHEEL +0 -0
- {mcli_framework-7.11.0.dist-info → mcli_framework-7.11.2.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.11.0.dist-info → mcli_framework-7.11.2.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.11.0.dist-info → mcli_framework-7.11.2.dist-info}/top_level.txt +0 -0
mcli/app/commands_cmd.py
CHANGED
|
@@ -182,6 +182,267 @@ def workflow():
|
|
|
182
182
|
commands = workflow
|
|
183
183
|
|
|
184
184
|
|
|
185
|
+
@workflow.command("init")
|
|
186
|
+
@click.option(
|
|
187
|
+
"--global", "-g", "is_global", is_flag=True, help="Initialize global workflows directory instead of local"
|
|
188
|
+
)
|
|
189
|
+
@click.option(
|
|
190
|
+
"--git", is_flag=True, help="Initialize git repository in workflows directory"
|
|
191
|
+
)
|
|
192
|
+
@click.option(
|
|
193
|
+
"--force", "-f", is_flag=True, help="Force initialization even if directory exists"
|
|
194
|
+
)
|
|
195
|
+
def init_workflows(is_global, git, force):
|
|
196
|
+
"""
|
|
197
|
+
Initialize workflows directory structure.
|
|
198
|
+
|
|
199
|
+
Creates the necessary directories and configuration files for managing
|
|
200
|
+
custom workflows. By default, creates a local .mcli/workflows/ directory
|
|
201
|
+
if in a git repository, otherwise uses ~/.mcli/workflows/.
|
|
202
|
+
|
|
203
|
+
Examples:
|
|
204
|
+
mcli workflow init # Initialize local workflows (if in git repo)
|
|
205
|
+
mcli workflow init --global # Initialize global workflows
|
|
206
|
+
mcli workflow init --git # Also initialize git repository
|
|
207
|
+
"""
|
|
208
|
+
from mcli.lib.paths import (
|
|
209
|
+
get_mcli_home,
|
|
210
|
+
get_local_mcli_dir,
|
|
211
|
+
get_git_root,
|
|
212
|
+
is_git_repository,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Determine if we're in a git repository
|
|
216
|
+
in_git_repo = is_git_repository() and not is_global
|
|
217
|
+
git_root = get_git_root() if in_git_repo else None
|
|
218
|
+
|
|
219
|
+
# Explicitly create workflows directory (not commands)
|
|
220
|
+
# This bypasses the migration logic that would check for old commands/ directory
|
|
221
|
+
if not is_global and in_git_repo:
|
|
222
|
+
local_mcli = get_local_mcli_dir()
|
|
223
|
+
workflows_dir = local_mcli / "workflows"
|
|
224
|
+
else:
|
|
225
|
+
workflows_dir = get_mcli_home() / "workflows"
|
|
226
|
+
|
|
227
|
+
lockfile_path = workflows_dir / "commands.lock.json"
|
|
228
|
+
|
|
229
|
+
# Check if already initialized
|
|
230
|
+
if workflows_dir.exists() and not force:
|
|
231
|
+
if lockfile_path.exists():
|
|
232
|
+
console.print(f"[yellow]Workflows directory already initialized at:[/yellow] {workflows_dir}")
|
|
233
|
+
console.print(f"[dim]Use --force to reinitialize[/dim]")
|
|
234
|
+
|
|
235
|
+
should_continue = Prompt.ask(
|
|
236
|
+
"Continue anyway?", choices=["y", "n"], default="n"
|
|
237
|
+
)
|
|
238
|
+
if should_continue.lower() != "y":
|
|
239
|
+
return 0
|
|
240
|
+
|
|
241
|
+
# Create workflows directory
|
|
242
|
+
workflows_dir.mkdir(parents=True, exist_ok=True)
|
|
243
|
+
console.print(f"[green]✓[/green] Created workflows directory: {workflows_dir}")
|
|
244
|
+
|
|
245
|
+
# Create README.md
|
|
246
|
+
readme_path = workflows_dir / "README.md"
|
|
247
|
+
if not readme_path.exists() or force:
|
|
248
|
+
scope = "local" if in_git_repo else "global"
|
|
249
|
+
scope_desc = f"for repository: {git_root.name}" if in_git_repo else "globally"
|
|
250
|
+
|
|
251
|
+
readme_content = f"""# MCLI Custom Workflows
|
|
252
|
+
|
|
253
|
+
This directory contains custom workflow commands {scope_desc}.
|
|
254
|
+
|
|
255
|
+
## Quick Start
|
|
256
|
+
|
|
257
|
+
### Create a New Workflow
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
# Python workflow
|
|
261
|
+
mcli workflow add my-workflow
|
|
262
|
+
|
|
263
|
+
# Shell workflow
|
|
264
|
+
mcli workflow add my-script --language shell
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### List Workflows
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
mcli workflow list --custom-only
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Execute a Workflow
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
mcli workflows my-workflow
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Edit a Workflow
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
mcli workflow edit my-workflow
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Export/Import Workflows
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
# Export all workflows
|
|
289
|
+
mcli workflow export workflows-backup.json
|
|
290
|
+
|
|
291
|
+
# Import workflows
|
|
292
|
+
mcli workflow import workflows-backup.json
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Directory Structure
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
{workflows_dir.name}/
|
|
299
|
+
├── README.md # This file
|
|
300
|
+
├── commands.lock.json # Lockfile for workflow state
|
|
301
|
+
└── *.json # Individual workflow definitions
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Workflow Format
|
|
305
|
+
|
|
306
|
+
Workflows are stored as JSON files with the following structure:
|
|
307
|
+
|
|
308
|
+
```json
|
|
309
|
+
{{
|
|
310
|
+
"name": "workflow-name",
|
|
311
|
+
"description": "Workflow description",
|
|
312
|
+
"code": "Python or shell code",
|
|
313
|
+
"language": "python",
|
|
314
|
+
"group": "workflow",
|
|
315
|
+
"version": "1.0",
|
|
316
|
+
"created_at": "2025-10-30T...",
|
|
317
|
+
"updated_at": "2025-10-30T..."
|
|
318
|
+
}}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## Scope
|
|
322
|
+
|
|
323
|
+
- **Scope**: {'Local (repository-specific)' if in_git_repo else 'Global (user-wide)'}
|
|
324
|
+
- **Location**: `{workflows_dir}`
|
|
325
|
+
{f"- **Git Repository**: `{git_root}`" if git_root else ""}
|
|
326
|
+
|
|
327
|
+
## Documentation
|
|
328
|
+
|
|
329
|
+
- [MCLI Documentation](https://github.com/gwicho38/mcli)
|
|
330
|
+
- [Workflow Guide](https://github.com/gwicho38/mcli/blob/main/docs/features/LOCAL_VS_GLOBAL_COMMANDS.md)
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
*Initialized: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*
|
|
335
|
+
"""
|
|
336
|
+
|
|
337
|
+
readme_path.write_text(readme_content)
|
|
338
|
+
console.print(f"[green]✓[/green] Created README: {readme_path.name}")
|
|
339
|
+
|
|
340
|
+
# Initialize lockfile
|
|
341
|
+
if not lockfile_path.exists() or force:
|
|
342
|
+
lockfile_data = {
|
|
343
|
+
"version": "1.0",
|
|
344
|
+
"initialized_at": datetime.now().isoformat(),
|
|
345
|
+
"scope": "local" if in_git_repo else "global",
|
|
346
|
+
"commands": {}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
with open(lockfile_path, "w") as f:
|
|
350
|
+
json.dump(lockfile_data, f, indent=2)
|
|
351
|
+
|
|
352
|
+
console.print(f"[green]✓[/green] Initialized lockfile: {lockfile_path.name}")
|
|
353
|
+
|
|
354
|
+
# Create .gitignore if in workflows directory
|
|
355
|
+
gitignore_path = workflows_dir / ".gitignore"
|
|
356
|
+
if not gitignore_path.exists() or force:
|
|
357
|
+
gitignore_content = """# Backup files
|
|
358
|
+
*.backup
|
|
359
|
+
*.bak
|
|
360
|
+
|
|
361
|
+
# Temporary files
|
|
362
|
+
*.tmp
|
|
363
|
+
*.temp
|
|
364
|
+
|
|
365
|
+
# OS files
|
|
366
|
+
.DS_Store
|
|
367
|
+
Thumbs.db
|
|
368
|
+
|
|
369
|
+
# Editor files
|
|
370
|
+
*.swp
|
|
371
|
+
*.swo
|
|
372
|
+
*~
|
|
373
|
+
.vscode/
|
|
374
|
+
.idea/
|
|
375
|
+
"""
|
|
376
|
+
gitignore_path.write_text(gitignore_content)
|
|
377
|
+
console.print(f"[green]✓[/green] Created .gitignore")
|
|
378
|
+
|
|
379
|
+
# Initialize git if requested
|
|
380
|
+
if git and not (workflows_dir / ".git").exists():
|
|
381
|
+
try:
|
|
382
|
+
subprocess.run(
|
|
383
|
+
["git", "init"],
|
|
384
|
+
cwd=workflows_dir,
|
|
385
|
+
check=True,
|
|
386
|
+
capture_output=True
|
|
387
|
+
)
|
|
388
|
+
console.print(f"[green]✓[/green] Initialized git repository in workflows directory")
|
|
389
|
+
|
|
390
|
+
# Create initial commit
|
|
391
|
+
subprocess.run(
|
|
392
|
+
["git", "add", "."],
|
|
393
|
+
cwd=workflows_dir,
|
|
394
|
+
check=True,
|
|
395
|
+
capture_output=True
|
|
396
|
+
)
|
|
397
|
+
subprocess.run(
|
|
398
|
+
["git", "commit", "-m", "Initial commit: Initialize workflows directory"],
|
|
399
|
+
cwd=workflows_dir,
|
|
400
|
+
check=True,
|
|
401
|
+
capture_output=True
|
|
402
|
+
)
|
|
403
|
+
console.print(f"[green]✓[/green] Created initial commit")
|
|
404
|
+
|
|
405
|
+
except subprocess.CalledProcessError as e:
|
|
406
|
+
console.print(f"[yellow]⚠[/yellow] Git initialization failed: {e}")
|
|
407
|
+
except FileNotFoundError:
|
|
408
|
+
console.print(f"[yellow]⚠[/yellow] Git not found. Skipping git initialization.")
|
|
409
|
+
|
|
410
|
+
# Summary
|
|
411
|
+
console.print()
|
|
412
|
+
console.print("[bold green]Workflows directory initialized successfully![/bold green]")
|
|
413
|
+
console.print()
|
|
414
|
+
|
|
415
|
+
# Display summary table
|
|
416
|
+
table = Table(title="Initialization Summary", show_header=False)
|
|
417
|
+
table.add_column("Property", style="cyan")
|
|
418
|
+
table.add_column("Value", style="green")
|
|
419
|
+
|
|
420
|
+
table.add_row("Scope", "Local (repository-specific)" if in_git_repo else "Global (user-wide)")
|
|
421
|
+
table.add_row("Location", str(workflows_dir))
|
|
422
|
+
if git_root:
|
|
423
|
+
table.add_row("Git Repository", str(git_root))
|
|
424
|
+
table.add_row("Lockfile", str(lockfile_path))
|
|
425
|
+
table.add_row("Git Initialized", "Yes" if git and (workflows_dir / ".git").exists() else "No")
|
|
426
|
+
|
|
427
|
+
console.print(table)
|
|
428
|
+
console.print()
|
|
429
|
+
|
|
430
|
+
# Next steps
|
|
431
|
+
console.print("[bold]Next Steps:[/bold]")
|
|
432
|
+
console.print(" 1. Create a workflow: [cyan]mcli workflow add my-workflow[/cyan]")
|
|
433
|
+
console.print(" 2. List workflows: [cyan]mcli workflow list --custom-only[/cyan]")
|
|
434
|
+
console.print(" 3. Execute workflow: [cyan]mcli workflows my-workflow[/cyan]")
|
|
435
|
+
console.print(" 4. View README: [cyan]cat {}/README.md[/cyan]".format(workflows_dir))
|
|
436
|
+
console.print()
|
|
437
|
+
|
|
438
|
+
if in_git_repo:
|
|
439
|
+
console.print(f"[dim]Tip: Workflows are local to this repository. Use --global for user-wide workflows.[/dim]")
|
|
440
|
+
else:
|
|
441
|
+
console.print(f"[dim]Tip: Use workflows in any git repository, or create local ones with 'mcli workflow init' inside repos.[/dim]")
|
|
442
|
+
|
|
443
|
+
return 0
|
|
444
|
+
|
|
445
|
+
|
|
185
446
|
@workflow.command("list")
|
|
186
447
|
@click.option("--include-groups", is_flag=True, help="Include command groups in listing")
|
|
187
448
|
@click.option("--daemon-only", is_flag=True, help="Show only daemon database commands")
|
mcli/lib/paths.py
CHANGED
|
@@ -158,9 +158,13 @@ def get_local_commands_dir() -> Optional[Path]:
|
|
|
158
158
|
if workflows_dir.exists():
|
|
159
159
|
return workflows_dir
|
|
160
160
|
|
|
161
|
-
#
|
|
161
|
+
# Check if old commands directory exists (for migration support)
|
|
162
162
|
commands_dir = local_mcli / "commands"
|
|
163
|
-
|
|
163
|
+
if commands_dir.exists():
|
|
164
|
+
return commands_dir
|
|
165
|
+
|
|
166
|
+
# If neither exists, return workflows path (for new installations)
|
|
167
|
+
return workflows_dir
|
|
164
168
|
return None
|
|
165
169
|
|
|
166
170
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcli-framework
|
|
3
|
-
Version: 7.11.
|
|
3
|
+
Version: 7.11.2
|
|
4
4
|
Summary: Portable workflow framework - transform any script into a versioned, schedulable command. Store in ~/.mcli/commands/, version with lockfile, run as daemon or cron job.
|
|
5
5
|
Author-email: Luis Fernandez de la Vara <luis@lefv.io>
|
|
6
6
|
Maintainer-email: Luis Fernandez de la Vara <luis@lefv.io>
|
|
@@ -216,6 +216,24 @@ pip install mcli-framework
|
|
|
216
216
|
uv pip install mcli-framework
|
|
217
217
|
```
|
|
218
218
|
|
|
219
|
+
### Initialize Workflows Directory
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# Initialize workflows in current git repository
|
|
223
|
+
mcli workflow init
|
|
224
|
+
|
|
225
|
+
# Or initialize global workflows
|
|
226
|
+
mcli workflow init --global
|
|
227
|
+
|
|
228
|
+
# Initialize with git repository for workflows
|
|
229
|
+
mcli workflow init --git
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
This creates a `.mcli/workflows/` directory (local to your repo) or `~/.mcli/workflows/` (global) with:
|
|
233
|
+
- README.md with usage instructions
|
|
234
|
+
- commands.lock.json for version tracking
|
|
235
|
+
- .gitignore for backup files
|
|
236
|
+
|
|
219
237
|
### Create Your First Workflow
|
|
220
238
|
|
|
221
239
|
#### Method 1: From a Python Script
|
|
@@ -3,7 +3,7 @@ mcli/__main__.py,sha256=nKdf3WqtXi5PhWhZGjpXKAT3a2yGUYkYCBgSLxk4hSQ,295
|
|
|
3
3
|
mcli/cli.py,sha256=6KTyXn-pmVkAbCDu59PbiNKBwNra5su31ujFFZ6CBOM,389
|
|
4
4
|
mcli/config.toml,sha256=263yEVvP_W9F2zOLssUBgy7amKaRAFQuBrfxcMhKxaQ,1706
|
|
5
5
|
mcli/app/__init__.py,sha256=D4RiKk2gOEXwanbe_jXyNSb5zdgNi47kahtskMnEwjY,489
|
|
6
|
-
mcli/app/commands_cmd.py,sha256=
|
|
6
|
+
mcli/app/commands_cmd.py,sha256=gyvjkX8HyImUKaO37Du6XwklN6FJwvQX-VD3tNU0TGQ,76191
|
|
7
7
|
mcli/app/completion_helpers.py,sha256=e62C6w2N-XoD66GYYHgtvKKoD3kYMuIeBBGzVKbuL04,7497
|
|
8
8
|
mcli/app/main.py,sha256=CzF1iudFhVdAtC5d_KzRVAc6XT5Lkq6WZ1NnNKpdWnE,19165
|
|
9
9
|
mcli/app/model_cmd.py,sha256=LQQD8FaebFoaJGK3u_kt19wZ3HJyo_ecwSMYyC2xIp8,2497
|
|
@@ -21,7 +21,7 @@ mcli/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
21
21
|
mcli/lib/custom_commands.py,sha256=oDgNuPHonjZ7ckwX4-38XsqZOcaR05ESpuSbSFMB-s4,21739
|
|
22
22
|
mcli/lib/lib.py,sha256=-CFUfmcubYBxt3LDBY0uj9DF232pz8MPDu-Qg0Ocy8M,850
|
|
23
23
|
mcli/lib/optional_deps.py,sha256=z6jPjU9mjK2ipMf8gzdc_izYSyqefQRzUZWgj_CumtM,7568
|
|
24
|
-
mcli/lib/paths.py,sha256=
|
|
24
|
+
mcli/lib/paths.py,sha256=3-yseYbqQ-711GUSO8qlI3Tnlwx4BFO48IeiUETIY-A,6412
|
|
25
25
|
mcli/lib/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
26
|
mcli/lib/api/api.py,sha256=sPgAIYC8Z7AWV2TCBssNSKotbRggBqNLsbfzbjkhmUY,18558
|
|
27
27
|
mcli/lib/api/daemon_client.py,sha256=Nq8sVvNKyIGvWp9G_O3NEFo9JDqA1TEx5FOB7iqslB4,7415
|
|
@@ -268,9 +268,9 @@ mcli/workflow/sync/test_cmd.py,sha256=neVgs9zEnKSxlvzDpFkuCGucqnzjrShm2OvJtHibsl
|
|
|
268
268
|
mcli/workflow/videos/__init__.py,sha256=aV3DEoO7qdKJY4odWKoQbOKDQq4ludTeCLnZcupOFIM,25
|
|
269
269
|
mcli/workflow/wakatime/__init__.py,sha256=wKG8cVIHVtMPhNRFGFtX43bRnocHqOMMkFMkmW-M6pU,2626
|
|
270
270
|
mcli/workflow/wakatime/wakatime.py,sha256=sEjsUKa3-XyE8Ni6sAb_D3GAY5jDcA30KknW9YTbLTA,142
|
|
271
|
-
mcli_framework-7.11.
|
|
272
|
-
mcli_framework-7.11.
|
|
273
|
-
mcli_framework-7.11.
|
|
274
|
-
mcli_framework-7.11.
|
|
275
|
-
mcli_framework-7.11.
|
|
276
|
-
mcli_framework-7.11.
|
|
271
|
+
mcli_framework-7.11.2.dist-info/licenses/LICENSE,sha256=sahwAMfrJv2-V66HNPTp7A9UmMjxtyejwTZZoWQvEcI,1075
|
|
272
|
+
mcli_framework-7.11.2.dist-info/METADATA,sha256=b7Gcj2KCC86Lu2OTxVRCi_NmfDb40mADWTigjuFcATg,18655
|
|
273
|
+
mcli_framework-7.11.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
274
|
+
mcli_framework-7.11.2.dist-info/entry_points.txt,sha256=dYrZbDIm-KUPsl1wfv600Kx_8sMy89phMkCihbDRgP8,261
|
|
275
|
+
mcli_framework-7.11.2.dist-info/top_level.txt,sha256=_bnO8J2EUkliWivey_1le0UrnocFKmyVMQjbQ8iVXjc,5
|
|
276
|
+
mcli_framework-7.11.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|