mcli-framework 7.9.7__tar.gz → 7.10.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.

Potentially problematic release.


This version of mcli-framework might be problematic. Click here for more details.

Files changed (341) hide show
  1. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/PKG-INFO +1 -1
  2. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/pyproject.toml +1 -1
  3. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/app/commands_cmd.py +161 -15
  4. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/custom_commands.py +126 -6
  5. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli_framework.egg-info/PKG-INFO +1 -1
  6. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/.github/dependabot.yml +0 -0
  7. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/.github/workflows/build.yml +0 -0
  8. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/.github/workflows/ci.yml +0 -0
  9. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/.github/workflows/ml-pipeline.yml +0 -0
  10. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/.github/workflows/publish-self-hosted.yml +0 -0
  11. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/.github/workflows/publish.yml +0 -0
  12. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/.github/workflows/release.yml +0 -0
  13. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/.github/workflows/security.yml +0 -0
  14. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/.github/workflows/test.yml +0 -0
  15. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/LICENSE +0 -0
  16. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/MANIFEST.in +0 -0
  17. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/README.md +0 -0
  18. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/mcli_rust/Cargo.toml +0 -0
  19. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/mcli_rust/src/command_parser.rs +0 -0
  20. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/mcli_rust/src/file_watcher.rs +0 -0
  21. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/mcli_rust/src/lib.rs +0 -0
  22. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/mcli_rust/src/process_manager.rs +0 -0
  23. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/mcli_rust/src/tfidf.rs +0 -0
  24. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/setup.cfg +0 -0
  25. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/app/completion_helpers.py +0 -0
  26. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/app/main.py +0 -0
  27. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/app/model/model.py +0 -0
  28. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/app/model_cmd.py +0 -0
  29. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/app/video/video.py +0 -0
  30. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/chat/chat.py +0 -0
  31. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/chat/command_rag.py +0 -0
  32. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/chat/enhanced_chat.py +0 -0
  33. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/chat/system_controller.py +0 -0
  34. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/chat/system_integration.py +0 -0
  35. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/cli.py +0 -0
  36. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/config.toml +0 -0
  37. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/api/api.py +0 -0
  38. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/api/daemon_client.py +0 -0
  39. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/api/daemon_client_local.py +0 -0
  40. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/api/daemon_decorator.py +0 -0
  41. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/api/mcli_decorators.py +0 -0
  42. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/auth/auth.py +0 -0
  43. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/auth/aws_manager.py +0 -0
  44. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/auth/azure_manager.py +0 -0
  45. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/auth/credential_manager.py +0 -0
  46. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/auth/gcp_manager.py +0 -0
  47. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/auth/key_manager.py +0 -0
  48. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/auth/mcli_manager.py +0 -0
  49. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/auth/token_manager.py +0 -0
  50. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/auth/token_util.py +0 -0
  51. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/config/config.py +0 -0
  52. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/discovery/__init__.py +0 -0
  53. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/discovery/command_discovery.py +0 -0
  54. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/erd/erd.py +0 -0
  55. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/erd/generate_graph.py +0 -0
  56. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/files/files.py +0 -0
  57. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/fs/fs.py +0 -0
  58. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/lib.py +0 -0
  59. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/logger/logger.py +0 -0
  60. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/paths.py +0 -0
  61. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/performance/optimizer.py +0 -0
  62. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/performance/rust_bridge.py +0 -0
  63. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/performance/uvloop_config.py +0 -0
  64. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/pickles/pickles.py +0 -0
  65. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/search/cached_vectorizer.py +0 -0
  66. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/secrets/commands.py +0 -0
  67. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/secrets/manager.py +0 -0
  68. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/secrets/repl.py +0 -0
  69. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/secrets/store.py +0 -0
  70. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/services/data_pipeline.py +0 -0
  71. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/services/lsh_client.py +0 -0
  72. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/services/redis_service.py +0 -0
  73. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/shell/shell.py +0 -0
  74. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/toml/toml.py +0 -0
  75. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/ui/styling.py +0 -0
  76. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/ui/visual_effects.py +0 -0
  77. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/lib/watcher/watcher.py +0 -0
  78. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/app.py +0 -0
  79. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/middleware.py +0 -0
  80. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/routers/admin_router.py +0 -0
  81. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/routers/auth_router.py +0 -0
  82. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/routers/backtest_router.py +0 -0
  83. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/routers/data_router.py +0 -0
  84. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/routers/model_router.py +0 -0
  85. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/routers/monitoring_router.py +0 -0
  86. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/routers/portfolio_router.py +0 -0
  87. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/routers/prediction_router.py +0 -0
  88. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/routers/trade_router.py +0 -0
  89. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/routers/websocket_router.py +0 -0
  90. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/api/schemas.py +0 -0
  91. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/auth/auth_manager.py +0 -0
  92. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/auth/models.py +0 -0
  93. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/auth/permissions.py +0 -0
  94. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/backtesting/backtest_engine.py +0 -0
  95. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/backtesting/performance_metrics.py +0 -0
  96. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/backtesting/run.py +0 -0
  97. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/cache.py +0 -0
  98. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/cli/main.py +0 -0
  99. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/config/settings.py +0 -0
  100. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/configs/dvc_config.py +0 -0
  101. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/configs/mlflow_config.py +0 -0
  102. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/configs/mlops_manager.py +0 -0
  103. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/app.py +0 -0
  104. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/app_integrated.py +0 -0
  105. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/app_supabase.py +0 -0
  106. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/app_training.py +0 -0
  107. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/cli.py +0 -0
  108. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/common.py +0 -0
  109. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/components/charts.py +0 -0
  110. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/components/metrics.py +0 -0
  111. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/components/tables.py +0 -0
  112. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/overview.py +0 -0
  113. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/pages/cicd.py +0 -0
  114. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/pages/debug_dependencies.py +0 -0
  115. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/pages/gravity_viz.py +0 -0
  116. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/pages/monte_carlo_predictions.py +0 -0
  117. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/pages/predictions_enhanced.py +0 -0
  118. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/pages/scrapers_and_logs.py +0 -0
  119. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/pages/test_portfolio.py +0 -0
  120. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/pages/trading.py +0 -0
  121. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/pages/workflows.py +0 -0
  122. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/streamlit_extras_utils.py +0 -0
  123. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/styles.py +0 -0
  124. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/utils.py +0 -0
  125. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/dashboard/warning_suppression.py +0 -0
  126. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/data_ingestion/api_connectors.py +0 -0
  127. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/data_ingestion/data_pipeline.py +0 -0
  128. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/data_ingestion/stream_processor.py +0 -0
  129. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/database/migrations/env.py +0 -0
  130. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/database/models.py +0 -0
  131. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/database/session.py +0 -0
  132. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/experimentation/ab_testing.py +0 -0
  133. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/features/ensemble_features.py +0 -0
  134. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/features/political_features.py +0 -0
  135. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/features/recommendation_engine.py +0 -0
  136. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/features/stock_features.py +0 -0
  137. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/features/test_feature_engineering.py +0 -0
  138. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/logging.py +0 -0
  139. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/mlops/data_versioning.py +0 -0
  140. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/mlops/experiment_tracker.py +0 -0
  141. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/mlops/model_serving.py +0 -0
  142. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/mlops/pipeline_orchestrator.py +0 -0
  143. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/models/base_models.py +0 -0
  144. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/models/ensemble_models.py +0 -0
  145. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/models/recommendation_models.py +0 -0
  146. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/models/test_models.py +0 -0
  147. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/monitoring/drift_detection.py +0 -0
  148. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/monitoring/metrics.py +0 -0
  149. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/optimization/optimize.py +0 -0
  150. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/optimization/portfolio_optimizer.py +0 -0
  151. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/predictions/monte_carlo.py +0 -0
  152. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/predictions/prediction_engine.py +0 -0
  153. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/preprocessing/data_cleaners.py +0 -0
  154. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/preprocessing/feature_extractors.py +0 -0
  155. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/preprocessing/ml_pipeline.py +0 -0
  156. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/preprocessing/politician_trading_preprocessor.py +0 -0
  157. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/preprocessing/test_preprocessing.py +0 -0
  158. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/scripts/populate_sample_data.py +0 -0
  159. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/serving/serve.py +0 -0
  160. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/tasks.py +0 -0
  161. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/tests/test_integration.py +0 -0
  162. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/tests/test_training_dashboard.py +0 -0
  163. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/trading/alpaca_client.py +0 -0
  164. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/trading/migrations.py +0 -0
  165. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/trading/models.py +0 -0
  166. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/trading/paper_trading.py +0 -0
  167. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/trading/risk_management.py +0 -0
  168. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/trading/trading_service.py +0 -0
  169. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/training/train.py +0 -0
  170. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/ml/training/train_model.py +0 -0
  171. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/mygroup/test_cmd.py +0 -0
  172. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/public/oi/oi.py +0 -0
  173. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/public/public.py +0 -0
  174. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/self/completion_cmd.py +0 -0
  175. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/self/logs_cmd.py +0 -0
  176. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/self/redis_cmd.py +0 -0
  177. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/self/self_cmd.py +0 -0
  178. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/self/store_cmd.py +0 -0
  179. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/self/test_cmd.py +0 -0
  180. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/self/visual_cmd.py +0 -0
  181. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/self/zsh_cmd.py +0 -0
  182. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/daemon/async_command_database.py +0 -0
  183. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/daemon/async_process_manager.py +0 -0
  184. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/daemon/client.py +0 -0
  185. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/daemon/daemon.py +0 -0
  186. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/daemon/daemon_api.py +0 -0
  187. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/daemon/enhanced_daemon.py +0 -0
  188. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/daemon/process_cli.py +0 -0
  189. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/daemon/process_manager.py +0 -0
  190. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/daemon/test_daemon.py +0 -0
  191. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/dashboard/dashboard_cmd.py +0 -0
  192. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/doc_convert.py +0 -0
  193. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/docker/docker.py +0 -0
  194. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/gcloud/config.toml +0 -0
  195. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/gcloud/gcloud.py +0 -0
  196. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/git_commit/ai_service.py +0 -0
  197. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/lsh_integration.py +0 -0
  198. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/client.py +0 -0
  199. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/download_and_run_efficient_models.py +0 -0
  200. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/lightweight_embedder.py +0 -0
  201. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/lightweight_model_server.py +0 -0
  202. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/lightweight_test.py +0 -0
  203. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/model_service.py +0 -0
  204. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/ollama_efficient_runner.py +0 -0
  205. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/openai_adapter.py +0 -0
  206. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/pdf_processor.py +0 -0
  207. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/test_efficient_runner.py +0 -0
  208. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/test_example.py +0 -0
  209. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/test_integration.py +0 -0
  210. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/model_service/test_new_features.py +0 -0
  211. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/openai/openai.py +0 -0
  212. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/config.py +0 -0
  213. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/connectivity.py +0 -0
  214. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/data_sources.py +0 -0
  215. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/database.py +0 -0
  216. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/demo.py +0 -0
  217. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/models.py +0 -0
  218. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/monitoring.py +0 -0
  219. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/scrapers.py +0 -0
  220. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/scrapers_california.py +0 -0
  221. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/scrapers_corporate_registry.py +0 -0
  222. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/scrapers_eu.py +0 -0
  223. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/scrapers_free_sources.py +0 -0
  224. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/scrapers_third_party.py +0 -0
  225. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/scrapers_uk.py +0 -0
  226. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/scrapers_us_states.py +0 -0
  227. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/seed_database.py +0 -0
  228. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/supabase_functions.py +0 -0
  229. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/politician_trading/workflow.py +0 -0
  230. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/registry/registry.py +0 -0
  231. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/repo/repo.py +0 -0
  232. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/scheduler/cron_parser.py +0 -0
  233. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/scheduler/job.py +0 -0
  234. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/scheduler/monitor.py +0 -0
  235. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/scheduler/persistence.py +0 -0
  236. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/scheduler/scheduler.py +0 -0
  237. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/sync/test_cmd.py +0 -0
  238. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/wakatime/wakatime.py +0 -0
  239. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli/workflow/workflow.py +0 -0
  240. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli_framework.egg-info/SOURCES.txt +0 -0
  241. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli_framework.egg-info/dependency_links.txt +0 -0
  242. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli_framework.egg-info/entry_points.txt +0 -0
  243. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli_framework.egg-info/requires.txt +0 -0
  244. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/src/mcli_framework.egg-info/top_level.txt +0 -0
  245. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_all_commands.py +0 -0
  246. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_app_logs_cmd.py +0 -0
  247. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_app_redis_cmd.py +0 -0
  248. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_logs_cmd.py +0 -0
  249. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_main_app.py +0 -0
  250. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_model_cmd.py +0 -0
  251. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_self_cmd.py +0 -0
  252. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_self_cmd_commands.py +0 -0
  253. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_self_cmd_plugins.py +0 -0
  254. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_self_cmd_utilities.py +0 -0
  255. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_workflow_file.py +0 -0
  256. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_workflow_gcloud.py +0 -0
  257. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/cli/test_workflow_registry.py +0 -0
  258. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/conftest.py +0 -0
  259. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/demo_generate_graph.py +0 -0
  260. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/demo_hierarchical_transform.py +0 -0
  261. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/e2e/test_complete_workflows.py +0 -0
  262. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/e2e/test_model_workflow.py +0 -0
  263. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/e2e/test_new_user_workflow.py +0 -0
  264. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/e2e/test_update_workflow.py +0 -0
  265. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/fixtures/chat_fixtures.py +0 -0
  266. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/fixtures/cli_fixtures.py +0 -0
  267. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/fixtures/data_fixtures.py +0 -0
  268. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/fixtures/db_fixtures.py +0 -0
  269. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/fixtures/model_fixtures.py +0 -0
  270. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_agent.py +0 -0
  271. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_california_scraper.py +0 -0
  272. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_chat_client.py +0 -0
  273. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_chat_system.py +0 -0
  274. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_congress_scraper.py +0 -0
  275. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_daemon_client.py +0 -0
  276. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_daemon_server.py +0 -0
  277. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_e2e_dashboard_lsh_supabase.py +0 -0
  278. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_flask_webapp.py +0 -0
  279. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_gcloud_services.py +0 -0
  280. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_lsh_client.py +0 -0
  281. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_lsh_service.py +0 -0
  282. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_ml_auth.py +0 -0
  283. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_ml_data_pipeline.py +0 -0
  284. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_ml_models.py +0 -0
  285. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_ml_pipeline.py +0 -0
  286. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_module_imports.py +0 -0
  287. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_oi_service.py +0 -0
  288. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_politician_trading.py +0 -0
  289. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_repo_operations.py +0 -0
  290. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_scheduler_integration.py +0 -0
  291. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_service_registry.py +0 -0
  292. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_supabase_live_connection.py +0 -0
  293. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_uk_scraper.py +0 -0
  294. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_us_states_scraper.py +0 -0
  295. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_video_processing.py +0 -0
  296. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_wakatime_api.py +0 -0
  297. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_webapp_full.py +0 -0
  298. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_workflow.py +0 -0
  299. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/integration/test_workflow_commands.py +0 -0
  300. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/run_tests.py +0 -0
  301. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/test_harness.py +0 -0
  302. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/test_openai_adapter.py +0 -0
  303. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_api_utils.py +0 -0
  304. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_async_process_manager.py +0 -0
  305. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_auth_modules.py +0 -0
  306. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_bug_fixes.py +0 -0
  307. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_config.py +0 -0
  308. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_custom_commands.py +0 -0
  309. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_daemon_api.py +0 -0
  310. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_dashboard_components.py +0 -0
  311. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_dashboard_functions.py +0 -0
  312. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_dashboard_pages.py +0 -0
  313. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_dependencies.py +0 -0
  314. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_doc_convert_workflow.py +0 -0
  315. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_emulator_workflow.py +0 -0
  316. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_erd_generation.py +0 -0
  317. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_erd_generic.py +0 -0
  318. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_erd_imports.py +0 -0
  319. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_git_commit_workflow.py +0 -0
  320. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_lib_auth.py +0 -0
  321. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_lib_files.py +0 -0
  322. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_lib_utils.py +0 -0
  323. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_logger.py +0 -0
  324. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_ml_preprocessing.py +0 -0
  325. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_paths.py +0 -0
  326. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_pdf_compress.py +0 -0
  327. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_prediction_engine.py +0 -0
  328. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_regression.py +0 -0
  329. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_scheduler.py +0 -0
  330. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_scheduler_cron_parser.py +0 -0
  331. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_scheduler_job.py +0 -0
  332. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_scheduler_monitor.py +0 -0
  333. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_scheduler_persistence.py +0 -0
  334. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_self_update.py +0 -0
  335. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_store_cmd.py +0 -0
  336. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_supabase_connection.py +0 -0
  337. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_supabase_pagination.py +0 -0
  338. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_toml_utils.py +0 -0
  339. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_trading_imports.py +0 -0
  340. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_ui_rich.py +0 -0
  341. {mcli_framework-7.9.7 → mcli_framework-7.10.0}/tests/unit/test_uv_compat.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcli-framework
3
- Version: 7.9.7
3
+ Version: 7.10.0
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>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mcli-framework"
3
- version = "7.9.7"
3
+ version = "7.10.0"
4
4
  description = "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
  readme = "README.md"
6
6
  requires-python = ">=3.9"
@@ -496,6 +496,37 @@ def {name}_command(name: str = "World"):
496
496
  return template
497
497
 
498
498
 
499
+ def get_shell_command_template(name: str, shell: str = "bash", description: str = "") -> str:
500
+ """Generate template shell script for a new command."""
501
+ template = f"""#!/usr/bin/env {shell}
502
+ # {name} - {description or "Shell workflow command"}
503
+ #
504
+ # This is a shell-based MCLI workflow command.
505
+ # Arguments are passed as positional parameters: $1, $2, $3, etc.
506
+ # The command name is available in: $MCLI_COMMAND
507
+
508
+ set -euo pipefail # Exit on error, undefined variables, and pipe failures
509
+
510
+ # Command logic
511
+ echo "Hello from {name} shell command!"
512
+ echo "Command: $MCLI_COMMAND"
513
+
514
+ # Example: Access arguments
515
+ if [ $# -gt 0 ]; then
516
+ echo "Arguments: $@"
517
+ for arg in "$@"; do
518
+ echo " - $arg"
519
+ done
520
+ else
521
+ echo "No arguments provided"
522
+ fi
523
+
524
+ # Exit successfully
525
+ exit 0
526
+ """
527
+ return template
528
+
529
+
499
530
  def open_editor_for_command(
500
531
  command_name: str, command_group: str, description: str
501
532
  ) -> Optional[str]:
@@ -655,20 +686,39 @@ logger = get_logger()
655
686
  is_flag=True,
656
687
  help="Use template mode (skip editor and use predefined template)",
657
688
  )
658
- def add_command(command_name, group, description, template):
689
+ @click.option(
690
+ "--language",
691
+ "-l",
692
+ type=click.Choice(["python", "shell"], case_sensitive=False),
693
+ default="python",
694
+ help="Command language (python or shell)",
695
+ )
696
+ @click.option(
697
+ "--shell",
698
+ "-s",
699
+ type=click.Choice(["bash", "zsh", "fish", "sh"], case_sensitive=False),
700
+ help="Shell type for shell commands (defaults to $SHELL)",
701
+ )
702
+ def add_command(command_name, group, description, template, language, shell):
659
703
  """
660
704
  Generate a new portable custom command saved to ~/.mcli/commands/.
661
705
 
662
- This command will open your default editor to allow you to write the Python logic
663
- for your command. The editor will be opened with a template that you can modify.
706
+ This command will open your default editor to allow you to write Python or shell
707
+ logic for your command. The editor will be opened with a template that you can modify.
664
708
 
665
709
  Commands are automatically nested under the 'workflow' group by default,
666
710
  making them portable and persistent across updates.
667
711
 
668
- Example:
712
+ Examples:
713
+ # Python command (default)
669
714
  mcli commands add my_command
670
715
  mcli commands add analytics --group data
671
- mcli commands add quick_cmd --template # Use template without editor
716
+ mcli commands add quick_cmd --template
717
+
718
+ # Shell command
719
+ mcli commands add backup-db --language shell
720
+ mcli commands add deploy --language shell --shell bash
721
+ mcli commands add quick-sh -l shell -t # Template mode
672
722
  """
673
723
  command_name = command_name.lower().replace("-", "_")
674
724
 
@@ -713,18 +763,61 @@ def add_command(command_name, group, description, template):
713
763
  click.echo("Command creation aborted.")
714
764
  return 1
715
765
 
766
+ # Normalize language
767
+ language = language.lower()
768
+
769
+ # Determine shell type for shell commands
770
+ if language == "shell":
771
+ if not shell:
772
+ # Default to $SHELL environment variable or bash
773
+ shell_env = os.environ.get("SHELL", "/bin/bash")
774
+ shell = shell_env.split("/")[-1]
775
+ click.echo(f"Using shell: {shell} (from $SHELL environment variable)")
776
+
716
777
  # Generate command code
717
778
  if template:
718
779
  # Use template mode - generate and save directly
719
- code = get_command_template(command_name, command_group)
720
- click.echo(f"Using template for command: {command_name}")
780
+ if language == "shell":
781
+ code = get_shell_command_template(command_name, shell, description)
782
+ click.echo(f"Using shell template for command: {command_name}")
783
+ else:
784
+ code = get_command_template(command_name, command_group)
785
+ click.echo(f"Using Python template for command: {command_name}")
721
786
  else:
722
787
  # Editor mode - open editor for user to write code
723
788
  click.echo(f"Opening editor for command: {command_name}")
724
- code = open_editor_for_command(command_name, command_group, description)
725
- if code is None:
726
- click.echo("Command creation cancelled.")
727
- return 1
789
+
790
+ if language == "shell":
791
+ # For shell commands, open editor with shell template
792
+ shell_template = get_shell_command_template(command_name, shell, description)
793
+
794
+ # Create temp file with shell template
795
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".sh", delete=False) as tmp:
796
+ tmp.write(shell_template)
797
+ tmp_path = tmp.name
798
+
799
+ try:
800
+ editor = os.environ.get("EDITOR", "vim")
801
+ result = subprocess.run([editor, tmp_path])
802
+
803
+ if result.returncode != 0:
804
+ click.echo("Editor exited with error. Command creation cancelled.")
805
+ return 1
806
+
807
+ with open(tmp_path, "r") as f:
808
+ code = f.read()
809
+
810
+ if not code.strip():
811
+ click.echo("No code provided. Command creation cancelled.")
812
+ return 1
813
+ finally:
814
+ Path(tmp_path).unlink(missing_ok=True)
815
+ else:
816
+ # Python command - use existing editor function
817
+ code = open_editor_for_command(command_name, command_group, description)
818
+ if code is None:
819
+ click.echo("Command creation cancelled.")
820
+ return 1
728
821
 
729
822
  # Save the command
730
823
  saved_path = manager.save_command(
@@ -732,11 +825,18 @@ def add_command(command_name, group, description, template):
732
825
  code=code,
733
826
  description=description,
734
827
  group=command_group,
828
+ language=language,
829
+ shell=shell if language == "shell" else None,
735
830
  )
736
831
 
737
- logger.info(f"Created portable custom command: {command_name}")
738
- console.print(f"[green]Created portable custom command: {command_name}[/green]")
832
+ lang_display = f"{language}" if language == "python" else f"{language} ({shell})"
833
+ logger.info(f"Created portable custom command: {command_name} ({lang_display})")
834
+ console.print(
835
+ f"[green]Created portable custom command: {command_name}[/green] [dim]({lang_display})[/dim]"
836
+ )
739
837
  console.print(f"[dim]Saved to: {saved_path}[/dim]")
838
+ console.print(f"[dim]Group: {command_group}[/dim]")
839
+ console.print(f"[dim]Execute with: mcli {command_group} {command_name}[/dim]")
740
840
  console.print("[dim]Command will be automatically loaded on next mcli startup[/dim]")
741
841
  console.print(
742
842
  f"[dim]You can share this command by copying {saved_path} to another machine's ~/.mcli/commands/ directory[/dim]"
@@ -903,7 +1003,7 @@ def import_commands(source, script, overwrite, name, group, description, interac
903
1003
  source_path = Path(source)
904
1004
 
905
1005
  if script:
906
- # Import Python script as command
1006
+ # Import script as command (Python or Shell)
907
1007
  if not source_path.exists():
908
1008
  console.print(f"[red]Script not found: {source_path}[/red]")
909
1009
  return 1
@@ -916,6 +1016,43 @@ def import_commands(source, script, overwrite, name, group, description, interac
916
1016
  console.print(f"[red]Failed to read script: {e}[/red]")
917
1017
  return 1
918
1018
 
1019
+ # Auto-detect language from shebang or file extension
1020
+ detected_language = "python"
1021
+ detected_shell = None
1022
+
1023
+ if code.strip().startswith("#!"):
1024
+ # Parse shebang
1025
+ shebang = code.strip().split("\n")[0]
1026
+ if "bash" in shebang:
1027
+ detected_language = "shell"
1028
+ detected_shell = "bash"
1029
+ elif "zsh" in shebang:
1030
+ detected_language = "shell"
1031
+ detected_shell = "zsh"
1032
+ elif "fish" in shebang:
1033
+ detected_language = "shell"
1034
+ detected_shell = "fish"
1035
+ elif "/bin/sh" in shebang or "/sh" in shebang:
1036
+ detected_language = "shell"
1037
+ detected_shell = "sh"
1038
+ elif "python" in shebang:
1039
+ detected_language = "python"
1040
+
1041
+ # Also check file extension
1042
+ if source_path.suffix in [".sh", ".bash", ".zsh"]:
1043
+ detected_language = "shell"
1044
+ if not detected_shell:
1045
+ if source_path.suffix == ".bash":
1046
+ detected_shell = "bash"
1047
+ elif source_path.suffix == ".zsh":
1048
+ detected_shell = "zsh"
1049
+ else:
1050
+ detected_shell = "bash" # Default for .sh
1051
+
1052
+ console.print(f"[dim]Detected language: {detected_language}[/dim]")
1053
+ if detected_language == "shell":
1054
+ console.print(f"[dim]Detected shell: {detected_shell}[/dim]")
1055
+
919
1056
  # Determine command name
920
1057
  if not name:
921
1058
  name = source_path.stem.lower().replace("-", "_")
@@ -961,6 +1098,8 @@ def import_commands(source, script, overwrite, name, group, description, interac
961
1098
  code=code,
962
1099
  description=description,
963
1100
  group=group,
1101
+ language=detected_language,
1102
+ shell=detected_shell if detected_language == "shell" else None,
964
1103
  metadata={
965
1104
  "source": "import-script",
966
1105
  "original_file": str(source_path),
@@ -968,7 +1107,14 @@ def import_commands(source, script, overwrite, name, group, description, interac
968
1107
  },
969
1108
  )
970
1109
 
971
- console.print(f"[green]Imported script as command: {name}[/green]")
1110
+ lang_display = (
1111
+ f"{detected_language}"
1112
+ if detected_language == "python"
1113
+ else f"{detected_language} ({detected_shell})"
1114
+ )
1115
+ console.print(
1116
+ f"[green]Imported script as command: {name}[/green] [dim]({lang_display})[/dim]"
1117
+ )
972
1118
  console.print(f"[dim]Saved to: {saved_path}[/dim]")
973
1119
  console.print(f"[dim]Use with: mcli {group} {name}[/dim]")
974
1120
  console.print("[dim]Command will be available after restart or reload[/dim]")
@@ -7,6 +7,9 @@ format in ~/.mcli/commands/ and automatically load them at startup.
7
7
 
8
8
  import importlib.util
9
9
  import json
10
+ import os
11
+ import stat
12
+ import subprocess
10
13
  import sys
11
14
  import tempfile
12
15
  from datetime import datetime
@@ -15,7 +18,7 @@ from typing import Any, Dict, List, Optional
15
18
 
16
19
  import click
17
20
 
18
- from mcli.lib.logger.logger import get_logger
21
+ from mcli.lib.logger.logger import get_logger, register_subprocess
19
22
  from mcli.lib.paths import get_custom_commands_dir
20
23
 
21
24
  logger = get_logger()
@@ -36,16 +39,20 @@ class CustomCommandManager:
36
39
  description: str = "",
37
40
  group: Optional[str] = None,
38
41
  metadata: Optional[Dict[str, Any]] = None,
42
+ language: str = "python",
43
+ shell: Optional[str] = None,
39
44
  ) -> Path:
40
45
  """
41
46
  Save a custom command to the commands directory.
42
47
 
43
48
  Args:
44
49
  name: Command name
45
- code: Python code for the command
50
+ code: Python code or shell script for the command
46
51
  description: Command description
47
52
  group: Optional command group
48
53
  metadata: Additional metadata
54
+ language: Command language ("python" or "shell")
55
+ shell: Shell type for shell commands (bash, zsh, fish, sh)
49
56
 
50
57
  Returns:
51
58
  Path to the saved command file
@@ -55,12 +62,17 @@ class CustomCommandManager:
55
62
  "code": code,
56
63
  "description": description,
57
64
  "group": group,
65
+ "language": language,
58
66
  "created_at": datetime.utcnow().isoformat() + "Z",
59
67
  "updated_at": datetime.utcnow().isoformat() + "Z",
60
68
  "version": "1.0",
61
69
  "metadata": metadata or {},
62
70
  }
63
71
 
72
+ # Add shell type for shell commands
73
+ if language == "shell":
74
+ command_data["shell"] = shell or os.environ.get("SHELL", "bash").split("/")[-1]
75
+
64
76
  # Save as JSON file
65
77
  command_file = self.commands_dir / f"{name}.json"
66
78
  with open(command_file, "w") as f:
@@ -307,6 +319,103 @@ class CustomCommandManager:
307
319
  logger.error(f"Failed to register custom command {name}: {e}")
308
320
  return False
309
321
 
322
+ def register_shell_command_with_click(
323
+ self, command_data: Dict[str, Any], target_group: click.Group
324
+ ) -> bool:
325
+ """
326
+ Dynamically register a shell command with a Click group.
327
+
328
+ Args:
329
+ command_data: Command data dictionary
330
+ target_group: Click group to register the command with
331
+
332
+ Returns:
333
+ True if successful, False otherwise
334
+ """
335
+ try:
336
+ name = command_data["name"]
337
+ code = command_data["code"]
338
+ shell_type = command_data.get("shell", "bash")
339
+ description = command_data.get("description", "Shell command")
340
+
341
+ # Create a Click command wrapper for the shell script
342
+ def create_shell_command(script_code: str, shell: str, cmd_name: str):
343
+ """Factory function to create shell command wrapper."""
344
+
345
+ @click.command(name=cmd_name, help=description)
346
+ @click.argument("args", nargs=-1)
347
+ @click.pass_context
348
+ def shell_command(ctx, args):
349
+ """Execute shell script command."""
350
+ # Create temporary script file
351
+ with tempfile.NamedTemporaryFile(
352
+ mode="w", suffix=".sh", delete=False, prefix=f"mcli_{cmd_name}_"
353
+ ) as temp_file:
354
+ # Add shebang if not present
355
+ if not script_code.strip().startswith("#!"):
356
+ temp_file.write(f"#!/usr/bin/env {shell}\n")
357
+ temp_file.write(script_code)
358
+ temp_file_path = temp_file.name
359
+
360
+ try:
361
+ # Make script executable
362
+ os.chmod(temp_file_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
363
+
364
+ # Execute the shell script
365
+ logger.info(f"Executing shell command: {cmd_name}")
366
+ process = subprocess.Popen(
367
+ [temp_file_path] + list(args),
368
+ stdout=subprocess.PIPE,
369
+ stderr=subprocess.PIPE,
370
+ text=True,
371
+ env={**os.environ, "MCLI_COMMAND": cmd_name},
372
+ )
373
+
374
+ # Register for monitoring
375
+ register_subprocess(process)
376
+
377
+ # Wait and capture output
378
+ stdout, stderr = process.communicate()
379
+
380
+ # Print output
381
+ if stdout:
382
+ click.echo(stdout, nl=False)
383
+ if stderr:
384
+ click.echo(stderr, nl=False, err=True)
385
+
386
+ # Exit with same code as script
387
+ if process.returncode != 0:
388
+ logger.warning(
389
+ f"Shell command {cmd_name} exited with code {process.returncode}"
390
+ )
391
+ ctx.exit(process.returncode)
392
+
393
+ except Exception as e:
394
+ logger.error(f"Failed to execute shell command {cmd_name}: {e}")
395
+ click.echo(f"Error executing shell command: {e}", err=True)
396
+ ctx.exit(1)
397
+ finally:
398
+ # Clean up temporary file
399
+ try:
400
+ Path(temp_file_path).unlink(missing_ok=True)
401
+ except Exception:
402
+ pass
403
+
404
+ return shell_command
405
+
406
+ # Create the command
407
+ command_obj = create_shell_command(code, shell_type, name)
408
+
409
+ # Register with the target group
410
+ target_group.add_command(command_obj, name=name)
411
+ self.loaded_commands[name] = command_obj
412
+ logger.info(f"Registered shell command: {name} (shell: {shell_type})")
413
+ return True
414
+
415
+ except Exception as e:
416
+ logger.error(f"Failed to register shell command {name}: {e}")
417
+ return False
418
+
310
419
  def export_commands(self, export_path: Path) -> bool:
311
420
  """
312
421
  Export all custom commands to a single JSON file.
@@ -396,6 +505,7 @@ def load_custom_commands(target_group: click.Group) -> int:
396
505
  for command_data in commands:
397
506
  # Check if command should be nested under a group
398
507
  group_name = command_data.get("group")
508
+ language = command_data.get("language", "python")
399
509
 
400
510
  if group_name:
401
511
  # Find or create the group
@@ -414,13 +524,23 @@ def load_custom_commands(target_group: click.Group) -> int:
414
524
  target_group.add_command(group_cmd)
415
525
  logger.info(f"Created command group: {group_name}")
416
526
 
417
- # Register the command under the group
527
+ # Register the command under the group based on language
418
528
  if isinstance(group_cmd, click.Group):
419
- if manager.register_command_with_click(command_data, group_cmd):
529
+ if language == "shell":
530
+ success = manager.register_shell_command_with_click(command_data, group_cmd)
531
+ else:
532
+ success = manager.register_command_with_click(command_data, group_cmd)
533
+
534
+ if success:
420
535
  loaded_count += 1
421
536
  else:
422
- # Register at top level
423
- if manager.register_command_with_click(command_data, target_group):
537
+ # Register at top level based on language
538
+ if language == "shell":
539
+ success = manager.register_shell_command_with_click(command_data, target_group)
540
+ else:
541
+ success = manager.register_command_with_click(command_data, target_group)
542
+
543
+ if success:
424
544
  loaded_count += 1
425
545
 
426
546
  if loaded_count > 0:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcli-framework
3
- Version: 7.9.7
3
+ Version: 7.10.0
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>
File without changes