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 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
- # Fall back to old commands directory for migration support
161
+ # Check if old commands directory exists (for migration support)
162
162
  commands_dir = local_mcli / "commands"
163
- return commands_dir
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.0
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=MQqIsvpJG9ev43nyD_q_QsViVXYhC40I-eTBpgCtTeU,68296
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=PWDMj2aGVZO-cVc-TSV9eK_B3si5rGwl-LkJjGmV2eE,6264
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.0.dist-info/licenses/LICENSE,sha256=sahwAMfrJv2-V66HNPTp7A9UmMjxtyejwTZZoWQvEcI,1075
272
- mcli_framework-7.11.0.dist-info/METADATA,sha256=I-WJjz8wDaJNvTojEHuQcp1kpJUH0h5I0jQIphxL14I,18190
273
- mcli_framework-7.11.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
274
- mcli_framework-7.11.0.dist-info/entry_points.txt,sha256=dYrZbDIm-KUPsl1wfv600Kx_8sMy89phMkCihbDRgP8,261
275
- mcli_framework-7.11.0.dist-info/top_level.txt,sha256=_bnO8J2EUkliWivey_1le0UrnocFKmyVMQjbQ8iVXjc,5
276
- mcli_framework-7.11.0.dist-info/RECORD,,
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,,