claude-mpm 4.13.2__py3-none-any.whl → 4.18.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.
Files changed (250) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_ENGINEER.md +286 -0
  3. claude_mpm/agents/BASE_PM.md +48 -17
  4. claude_mpm/agents/OUTPUT_STYLE.md +329 -11
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +227 -8
  6. claude_mpm/agents/agent_loader.py +17 -5
  7. claude_mpm/agents/frontmatter_validator.py +284 -253
  8. claude_mpm/agents/templates/agentic-coder-optimizer.json +9 -2
  9. claude_mpm/agents/templates/api_qa.json +7 -1
  10. claude_mpm/agents/templates/clerk-ops.json +8 -1
  11. claude_mpm/agents/templates/code_analyzer.json +4 -1
  12. claude_mpm/agents/templates/dart_engineer.json +11 -1
  13. claude_mpm/agents/templates/data_engineer.json +11 -1
  14. claude_mpm/agents/templates/documentation.json +6 -1
  15. claude_mpm/agents/templates/engineer.json +18 -1
  16. claude_mpm/agents/templates/gcp_ops_agent.json +8 -1
  17. claude_mpm/agents/templates/golang_engineer.json +11 -1
  18. claude_mpm/agents/templates/java_engineer.json +12 -2
  19. claude_mpm/agents/templates/local_ops_agent.json +1217 -6
  20. claude_mpm/agents/templates/nextjs_engineer.json +11 -1
  21. claude_mpm/agents/templates/ops.json +8 -1
  22. claude_mpm/agents/templates/php-engineer.json +11 -1
  23. claude_mpm/agents/templates/project_organizer.json +10 -3
  24. claude_mpm/agents/templates/prompt-engineer.json +5 -1
  25. claude_mpm/agents/templates/python_engineer.json +11 -1
  26. claude_mpm/agents/templates/qa.json +7 -1
  27. claude_mpm/agents/templates/react_engineer.json +11 -1
  28. claude_mpm/agents/templates/refactoring_engineer.json +8 -1
  29. claude_mpm/agents/templates/research.json +4 -1
  30. claude_mpm/agents/templates/ruby-engineer.json +11 -1
  31. claude_mpm/agents/templates/rust_engineer.json +11 -1
  32. claude_mpm/agents/templates/security.json +6 -1
  33. claude_mpm/agents/templates/svelte-engineer.json +225 -0
  34. claude_mpm/agents/templates/ticketing.json +6 -1
  35. claude_mpm/agents/templates/typescript_engineer.json +11 -1
  36. claude_mpm/agents/templates/vercel_ops_agent.json +8 -1
  37. claude_mpm/agents/templates/version_control.json +8 -1
  38. claude_mpm/agents/templates/web_qa.json +7 -1
  39. claude_mpm/agents/templates/web_ui.json +11 -1
  40. claude_mpm/cli/__init__.py +34 -706
  41. claude_mpm/cli/commands/agent_manager.py +25 -12
  42. claude_mpm/cli/commands/agent_state_manager.py +186 -0
  43. claude_mpm/cli/commands/agents.py +204 -148
  44. claude_mpm/cli/commands/aggregate.py +7 -3
  45. claude_mpm/cli/commands/analyze.py +9 -4
  46. claude_mpm/cli/commands/analyze_code.py +7 -2
  47. claude_mpm/cli/commands/auto_configure.py +7 -9
  48. claude_mpm/cli/commands/config.py +47 -13
  49. claude_mpm/cli/commands/configure.py +294 -1788
  50. claude_mpm/cli/commands/configure_agent_display.py +261 -0
  51. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  52. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  53. claude_mpm/cli/commands/configure_models.py +18 -0
  54. claude_mpm/cli/commands/configure_navigation.py +167 -0
  55. claude_mpm/cli/commands/configure_paths.py +104 -0
  56. claude_mpm/cli/commands/configure_persistence.py +254 -0
  57. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  58. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  59. claude_mpm/cli/commands/configure_validators.py +73 -0
  60. claude_mpm/cli/commands/local_deploy.py +537 -0
  61. claude_mpm/cli/commands/memory.py +54 -20
  62. claude_mpm/cli/commands/mpm_init.py +39 -25
  63. claude_mpm/cli/commands/mpm_init_handler.py +8 -3
  64. claude_mpm/cli/executor.py +202 -0
  65. claude_mpm/cli/helpers.py +105 -0
  66. claude_mpm/cli/interactive/__init__.py +3 -0
  67. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  68. claude_mpm/cli/parsers/__init__.py +7 -1
  69. claude_mpm/cli/parsers/base_parser.py +98 -3
  70. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  71. claude_mpm/cli/shared/output_formatters.py +28 -19
  72. claude_mpm/cli/startup.py +481 -0
  73. claude_mpm/cli/utils.py +52 -1
  74. claude_mpm/commands/mpm-help.md +3 -0
  75. claude_mpm/commands/mpm-version.md +113 -0
  76. claude_mpm/commands/mpm.md +1 -0
  77. claude_mpm/config/agent_config.py +2 -2
  78. claude_mpm/config/model_config.py +428 -0
  79. claude_mpm/core/base_service.py +13 -12
  80. claude_mpm/core/enums.py +452 -0
  81. claude_mpm/core/factories.py +1 -1
  82. claude_mpm/core/instruction_reinforcement_hook.py +2 -1
  83. claude_mpm/core/interactive_session.py +9 -3
  84. claude_mpm/core/logging_config.py +6 -2
  85. claude_mpm/core/oneshot_session.py +8 -4
  86. claude_mpm/core/optimized_agent_loader.py +3 -3
  87. claude_mpm/core/output_style_manager.py +12 -192
  88. claude_mpm/core/service_registry.py +5 -1
  89. claude_mpm/core/types.py +2 -9
  90. claude_mpm/core/typing_utils.py +7 -6
  91. claude_mpm/dashboard/static/js/dashboard.js +0 -14
  92. claude_mpm/dashboard/templates/index.html +3 -41
  93. claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
  94. claude_mpm/hooks/instruction_reinforcement.py +7 -2
  95. claude_mpm/models/resume_log.py +340 -0
  96. claude_mpm/services/agents/auto_config_manager.py +10 -11
  97. claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
  98. claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
  99. claude_mpm/services/agents/deployment/agent_validator.py +17 -1
  100. claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
  101. claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
  102. claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
  103. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
  104. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
  105. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
  106. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
  107. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
  108. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
  109. claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
  110. claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
  111. claude_mpm/services/agents/local_template_manager.py +1 -1
  112. claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
  113. claude_mpm/services/agents/registry/modification_tracker.py +5 -2
  114. claude_mpm/services/command_handler_service.py +11 -5
  115. claude_mpm/services/core/interfaces/__init__.py +74 -2
  116. claude_mpm/services/core/interfaces/health.py +172 -0
  117. claude_mpm/services/core/interfaces/model.py +281 -0
  118. claude_mpm/services/core/interfaces/process.py +372 -0
  119. claude_mpm/services/core/interfaces/restart.py +307 -0
  120. claude_mpm/services/core/interfaces/stability.py +260 -0
  121. claude_mpm/services/core/models/__init__.py +33 -0
  122. claude_mpm/services/core/models/agent_config.py +12 -28
  123. claude_mpm/services/core/models/health.py +162 -0
  124. claude_mpm/services/core/models/process.py +235 -0
  125. claude_mpm/services/core/models/restart.py +302 -0
  126. claude_mpm/services/core/models/stability.py +264 -0
  127. claude_mpm/services/core/path_resolver.py +23 -7
  128. claude_mpm/services/diagnostics/__init__.py +2 -2
  129. claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
  130. claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
  131. claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
  132. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
  133. claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
  134. claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
  135. claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
  136. claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
  137. claude_mpm/services/diagnostics/checks/mcp_services_check.py +36 -31
  138. claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
  139. claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
  140. claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
  141. claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
  142. claude_mpm/services/diagnostics/models.py +19 -24
  143. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
  144. claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
  145. claude_mpm/services/infrastructure/monitoring/base.py +5 -13
  146. claude_mpm/services/infrastructure/monitoring/network.py +7 -6
  147. claude_mpm/services/infrastructure/monitoring/process.py +13 -12
  148. claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
  149. claude_mpm/services/infrastructure/monitoring/service.py +16 -15
  150. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  151. claude_mpm/services/local_ops/__init__.py +163 -0
  152. claude_mpm/services/local_ops/crash_detector.py +257 -0
  153. claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
  154. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  155. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  156. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  157. claude_mpm/services/local_ops/health_manager.py +430 -0
  158. claude_mpm/services/local_ops/log_monitor.py +396 -0
  159. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  160. claude_mpm/services/local_ops/process_manager.py +595 -0
  161. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  162. claude_mpm/services/local_ops/restart_manager.py +401 -0
  163. claude_mpm/services/local_ops/restart_policy.py +387 -0
  164. claude_mpm/services/local_ops/state_manager.py +372 -0
  165. claude_mpm/services/local_ops/unified_manager.py +600 -0
  166. claude_mpm/services/mcp_config_manager.py +9 -4
  167. claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
  168. claude_mpm/services/mcp_gateway/core/base.py +18 -31
  169. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +71 -24
  170. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
  171. claude_mpm/services/memory_hook_service.py +4 -1
  172. claude_mpm/services/model/__init__.py +147 -0
  173. claude_mpm/services/model/base_provider.py +365 -0
  174. claude_mpm/services/model/claude_provider.py +412 -0
  175. claude_mpm/services/model/model_router.py +453 -0
  176. claude_mpm/services/model/ollama_provider.py +415 -0
  177. claude_mpm/services/monitor/daemon_manager.py +3 -2
  178. claude_mpm/services/monitor/handlers/dashboard.py +2 -1
  179. claude_mpm/services/monitor/handlers/hooks.py +2 -1
  180. claude_mpm/services/monitor/management/lifecycle.py +3 -2
  181. claude_mpm/services/monitor/server.py +2 -1
  182. claude_mpm/services/session_management_service.py +3 -2
  183. claude_mpm/services/session_manager.py +205 -1
  184. claude_mpm/services/shared/async_service_base.py +16 -27
  185. claude_mpm/services/shared/lifecycle_service_base.py +1 -14
  186. claude_mpm/services/socketio/handlers/__init__.py +5 -2
  187. claude_mpm/services/socketio/handlers/hook.py +13 -2
  188. claude_mpm/services/socketio/handlers/registry.py +4 -2
  189. claude_mpm/services/socketio/server/main.py +10 -8
  190. claude_mpm/services/subprocess_launcher_service.py +14 -5
  191. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
  192. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
  193. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
  194. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
  195. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
  196. claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
  197. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
  198. claude_mpm/services/unified/deployment_strategies/local.py +6 -5
  199. claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
  200. claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
  201. claude_mpm/services/unified/interfaces.py +3 -1
  202. claude_mpm/services/unified/unified_analyzer.py +14 -10
  203. claude_mpm/services/unified/unified_config.py +2 -1
  204. claude_mpm/services/unified/unified_deployment.py +9 -4
  205. claude_mpm/services/version_service.py +104 -1
  206. claude_mpm/skills/__init__.py +21 -0
  207. claude_mpm/skills/bundled/__init__.py +6 -0
  208. claude_mpm/skills/bundled/api-documentation.md +393 -0
  209. claude_mpm/skills/bundled/async-testing.md +571 -0
  210. claude_mpm/skills/bundled/code-review.md +143 -0
  211. claude_mpm/skills/bundled/database-migration.md +199 -0
  212. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  213. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  214. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  215. claude_mpm/skills/bundled/git-workflow.md +414 -0
  216. claude_mpm/skills/bundled/imagemagick.md +204 -0
  217. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  218. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  219. claude_mpm/skills/bundled/pdf.md +141 -0
  220. claude_mpm/skills/bundled/performance-profiling.md +567 -0
  221. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  222. claude_mpm/skills/bundled/security-scanning.md +327 -0
  223. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  224. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  225. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  226. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  227. claude_mpm/skills/bundled/xlsx.md +157 -0
  228. claude_mpm/skills/registry.py +286 -0
  229. claude_mpm/skills/skill_manager.py +310 -0
  230. claude_mpm/tools/code_tree_analyzer.py +177 -141
  231. claude_mpm/tools/code_tree_events.py +4 -2
  232. claude_mpm/utils/agent_dependency_loader.py +2 -2
  233. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +117 -8
  234. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +238 -174
  235. claude_mpm/dashboard/static/css/code-tree.css +0 -1639
  236. claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
  237. claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
  238. claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
  239. claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
  240. claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
  241. claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
  242. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
  243. claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
  244. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
  245. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
  246. claude_mpm/services/project/analyzer_refactored.py +0 -450
  247. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
  248. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
  249. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
  250. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
@@ -11,11 +11,96 @@ and reduce duplication across command parsers.
11
11
  """
12
12
 
13
13
  import argparse
14
+ import sys
14
15
  from typing import List, Optional
15
16
 
16
17
  from ...constants import CLICommands, CLIPrefix, LogLevel
17
18
 
18
19
 
20
+ class SuggestingArgumentParser(argparse.ArgumentParser):
21
+ """
22
+ Custom ArgumentParser that suggests similar commands on error.
23
+
24
+ WHY: Provides better user experience by suggesting corrections for typos
25
+ and invalid commands instead of just showing an error message.
26
+
27
+ DESIGN DECISION: Extends ArgumentParser.error() to add suggestions before
28
+ exiting. This catches all parser errors including invalid subcommands and
29
+ invalid options.
30
+ """
31
+
32
+ def error(self, message: str) -> None:
33
+ """
34
+ Override error method to add command suggestions.
35
+
36
+ Args:
37
+ message: Error message from argparse
38
+ """
39
+ from ..utils import suggest_similar_commands
40
+
41
+ # Try to extract the invalid command/option from the error message
42
+ invalid_value = None
43
+ valid_choices = []
44
+
45
+ # Handle invalid subcommand errors
46
+ # Format: "argument COMMAND: invalid choice: 'tickts' (choose from ...)"
47
+ if "invalid choice:" in message:
48
+ try:
49
+ # Extract the invalid choice
50
+ parts = message.split("invalid choice: '")
51
+ if len(parts) > 1:
52
+ invalid_value = parts[1].split("'")[0]
53
+
54
+ # Extract valid choices
55
+ if "(choose from" in message:
56
+ choices_part = message.split("(choose from")[1]
57
+ # Remove trailing parenthesis and split
58
+ choices_str = choices_part.rstrip(")")
59
+ # Parse choices - they may be quoted or unquoted
60
+ valid_choices = [
61
+ c.strip().strip("'\"")
62
+ for c in choices_str.split(",")
63
+ if c.strip()
64
+ ]
65
+ except (IndexError, ValueError):
66
+ pass
67
+
68
+ # Handle unrecognized arguments (invalid options)
69
+ # Format: "unrecognized arguments: --verbos"
70
+ elif "unrecognized arguments:" in message:
71
+ try:
72
+ parts = message.split("unrecognized arguments:")
73
+ if len(parts) > 1:
74
+ invalid_value = parts[1].strip().split()[0]
75
+
76
+ # Get common options from parser
77
+ valid_choices = []
78
+ for action in self._actions:
79
+ for option in action.option_strings:
80
+ valid_choices.append(option)
81
+ except (IndexError, ValueError):
82
+ pass
83
+
84
+ # Build error message with suggestions
85
+ from rich.console import Console
86
+
87
+ console = Console(stderr=True)
88
+
89
+ console.print(f"\n[red]Error:[/red] {message}\n", style="bold")
90
+
91
+ # Add suggestions if we found valid choices
92
+ if invalid_value and valid_choices:
93
+ suggestion = suggest_similar_commands(invalid_value, valid_choices)
94
+ if suggestion:
95
+ console.print(f"[yellow]{suggestion}[/yellow]\n")
96
+
97
+ # Show help hint
98
+ console.print(f"[dim]Run '{self.prog} --help' for usage information.[/dim]\n")
99
+
100
+ # Exit with error code
101
+ sys.exit(2)
102
+
103
+
19
104
  def _get_enhanced_version(base_version: str) -> str:
20
105
  """
21
106
  Get enhanced version string with build number if available.
@@ -111,15 +196,18 @@ def create_main_parser(
111
196
  WHY: This creates the foundation parser that other modules will extend
112
197
  with their specific subcommands and arguments.
113
198
 
199
+ DESIGN DECISION: Uses SuggestingArgumentParser to provide helpful suggestions
200
+ for typos and invalid commands, improving user experience.
201
+
114
202
  Args:
115
203
  prog_name: The program name to use
116
204
  version: The version string to display
117
205
 
118
206
  Returns:
119
- Configured ArgumentParser instance ready for subparser addition
207
+ Configured SuggestingArgumentParser instance ready for subparser addition
120
208
  """
121
- # Main parser
122
- parser = argparse.ArgumentParser(
209
+ # Main parser with suggestion support
210
+ parser = SuggestingArgumentParser(
123
211
  prog=prog_name,
124
212
  description=f"Claude Multi-Agent Project Manager v{version} - Orchestrate Claude with agent delegation and ticket tracking",
125
213
  epilog="By default, runs an orchestrated Claude session. Use 'claude-mpm' for interactive mode or 'claude-mpm -i \"prompt\"' for non-interactive mode.\n\nTo pass arguments to Claude CLI, use -- separator: claude-mpm run -- --model sonnet --temperature 0.1",
@@ -336,6 +424,13 @@ def create_parser(
336
424
  except ImportError:
337
425
  pass
338
426
 
427
+ try:
428
+ from .local_deploy_parser import add_local_deploy_arguments
429
+
430
+ add_local_deploy_arguments(subparsers)
431
+ except ImportError:
432
+ pass
433
+
339
434
  try:
340
435
  from .mcp_parser import add_mcp_subparser
341
436
 
@@ -0,0 +1,227 @@
1
+ """
2
+ Local Deploy parser module for claude-mpm CLI.
3
+
4
+ WHY: Provides argument parsing for local deployment management commands.
5
+ Extracted from the monolithic parser.py for better organization.
6
+
7
+ DESIGN DECISION: Supports multiple subcommands (start, stop, restart, status, etc.)
8
+ with command-specific arguments for comprehensive process management.
9
+ """
10
+
11
+ from pathlib import Path
12
+
13
+
14
+ def add_local_deploy_arguments(subparsers) -> None:
15
+ """
16
+ Add local-deploy command and its subcommands to the parser.
17
+
18
+ WHY: Provides a comprehensive CLI for managing local development deployments
19
+ with process monitoring, health checks, and auto-restart capabilities.
20
+
21
+ Args:
22
+ subparsers: The subparsers object to add commands to
23
+ """
24
+ # Main local-deploy command
25
+ local_deploy_parser = subparsers.add_parser(
26
+ "local-deploy",
27
+ help="Manage local development deployments with process monitoring",
28
+ description=(
29
+ "Manage local development deployments with comprehensive process management, "
30
+ "health monitoring, and auto-restart capabilities."
31
+ ),
32
+ )
33
+
34
+ # Create subparsers for local-deploy subcommands
35
+ local_deploy_subparsers = local_deploy_parser.add_subparsers(
36
+ dest="local_deploy_command",
37
+ help="Local deployment commands",
38
+ )
39
+
40
+ # ===== START command =====
41
+ start_parser = local_deploy_subparsers.add_parser(
42
+ "start",
43
+ help="Start a new local deployment",
44
+ description="Start a new local deployment with process monitoring and optional auto-restart",
45
+ )
46
+ start_parser.add_argument(
47
+ "--command",
48
+ "-c",
49
+ required=True,
50
+ help="Command to execute (e.g., 'npm run dev' or 'python manage.py runserver')",
51
+ )
52
+ start_parser.add_argument(
53
+ "--working-directory",
54
+ "-d",
55
+ type=Path,
56
+ help="Working directory for the process (default: current directory)",
57
+ )
58
+ start_parser.add_argument(
59
+ "--port",
60
+ "-p",
61
+ type=int,
62
+ help="Port number for the deployment",
63
+ )
64
+ start_parser.add_argument(
65
+ "--auto-find-port",
66
+ action="store_true",
67
+ default=True,
68
+ help="Automatically find alternative port if specified port is unavailable (default: enabled)",
69
+ )
70
+ start_parser.add_argument(
71
+ "--no-auto-find-port",
72
+ action="store_false",
73
+ dest="auto_find_port",
74
+ help="Disable automatic port finding",
75
+ )
76
+ start_parser.add_argument(
77
+ "--auto-restart",
78
+ action="store_true",
79
+ help="Enable automatic restart on crashes",
80
+ )
81
+ start_parser.add_argument(
82
+ "--log-file",
83
+ type=Path,
84
+ help="Path to log file for monitoring error patterns",
85
+ )
86
+ start_parser.add_argument(
87
+ "--env",
88
+ "-e",
89
+ action="append",
90
+ help="Environment variables in KEY=VALUE format (can be specified multiple times)",
91
+ )
92
+
93
+ # ===== STOP command =====
94
+ stop_parser = local_deploy_subparsers.add_parser(
95
+ "stop",
96
+ help="Stop a running deployment",
97
+ description="Stop a running deployment with graceful shutdown",
98
+ )
99
+ stop_parser.add_argument(
100
+ "deployment_id",
101
+ help="Deployment ID to stop",
102
+ )
103
+ stop_parser.add_argument(
104
+ "--timeout",
105
+ "-t",
106
+ type=int,
107
+ default=10,
108
+ help="Timeout in seconds for graceful shutdown (default: 10)",
109
+ )
110
+ stop_parser.add_argument(
111
+ "--force",
112
+ "-f",
113
+ action="store_true",
114
+ help="Force kill immediately without graceful shutdown",
115
+ )
116
+
117
+ # ===== RESTART command =====
118
+ restart_parser = local_deploy_subparsers.add_parser(
119
+ "restart",
120
+ help="Restart a deployment",
121
+ description="Restart a deployment with the same configuration",
122
+ )
123
+ restart_parser.add_argument(
124
+ "deployment_id",
125
+ help="Deployment ID to restart",
126
+ )
127
+ restart_parser.add_argument(
128
+ "--timeout",
129
+ "-t",
130
+ type=int,
131
+ default=10,
132
+ help="Timeout in seconds for graceful shutdown (default: 10)",
133
+ )
134
+
135
+ # ===== STATUS command =====
136
+ status_parser = local_deploy_subparsers.add_parser(
137
+ "status",
138
+ help="Show comprehensive deployment status",
139
+ description="Show comprehensive status including process info, health, and restart history",
140
+ )
141
+ status_parser.add_argument(
142
+ "deployment_id",
143
+ help="Deployment ID to check",
144
+ )
145
+ status_parser.add_argument(
146
+ "--json",
147
+ action="store_true",
148
+ help="Output status in JSON format",
149
+ )
150
+
151
+ # ===== HEALTH command =====
152
+ health_parser = local_deploy_subparsers.add_parser(
153
+ "health",
154
+ help="Show health status",
155
+ description="Show health check status including HTTP, process, and resource checks",
156
+ )
157
+ health_parser.add_argument(
158
+ "deployment_id",
159
+ help="Deployment ID to check",
160
+ )
161
+
162
+ # ===== LIST command =====
163
+ list_parser = local_deploy_subparsers.add_parser(
164
+ "list",
165
+ help="List all deployments",
166
+ description="List all local deployments with their status",
167
+ )
168
+ list_parser.add_argument(
169
+ "--status",
170
+ "-s",
171
+ choices=["running", "stopped", "crashed", "stopping"],
172
+ help="Filter deployments by status",
173
+ )
174
+
175
+ # ===== MONITOR command =====
176
+ monitor_parser = local_deploy_subparsers.add_parser(
177
+ "monitor",
178
+ help="Live monitoring dashboard",
179
+ description="Display live monitoring dashboard for a deployment",
180
+ )
181
+ monitor_parser.add_argument(
182
+ "deployment_id",
183
+ help="Deployment ID to monitor",
184
+ )
185
+ monitor_parser.add_argument(
186
+ "--refresh",
187
+ "-r",
188
+ type=int,
189
+ default=2,
190
+ help="Refresh interval in seconds (default: 2)",
191
+ )
192
+
193
+ # ===== HISTORY command =====
194
+ history_parser = local_deploy_subparsers.add_parser(
195
+ "history",
196
+ help="Show restart history",
197
+ description="Show restart history and statistics for a deployment",
198
+ )
199
+ history_parser.add_argument(
200
+ "deployment_id",
201
+ help="Deployment ID to check",
202
+ )
203
+
204
+ # ===== ENABLE-AUTO-RESTART command =====
205
+ enable_auto_restart_parser = local_deploy_subparsers.add_parser(
206
+ "enable-auto-restart",
207
+ help="Enable auto-restart for a deployment",
208
+ description="Enable automatic restart on crashes for a deployment",
209
+ )
210
+ enable_auto_restart_parser.add_argument(
211
+ "deployment_id",
212
+ help="Deployment ID to enable auto-restart for",
213
+ )
214
+
215
+ # ===== DISABLE-AUTO-RESTART command =====
216
+ disable_auto_restart_parser = local_deploy_subparsers.add_parser(
217
+ "disable-auto-restart",
218
+ help="Disable auto-restart for a deployment",
219
+ description="Disable automatic restart on crashes for a deployment",
220
+ )
221
+ disable_auto_restart_parser.add_argument(
222
+ "deployment_id",
223
+ help="Deployment ID to disable auto-restart for",
224
+ )
225
+
226
+
227
+ __all__ = ["add_local_deploy_arguments"]
@@ -7,6 +7,8 @@ from typing import Any, Dict, List, Optional, Union
7
7
 
8
8
  import yaml
9
9
 
10
+ from claude_mpm.core.enums import OutputFormat
11
+
10
12
 
11
13
  class OutputFormatter:
12
14
  """Handles formatting output in different formats."""
@@ -104,13 +106,13 @@ class OutputFormatter:
104
106
  return str(data)
105
107
 
106
108
 
107
- def format_output(data: Any, format_type: str = "text", **kwargs) -> str:
109
+ def format_output(data: Any, format_type: str = OutputFormat.TEXT, **kwargs) -> str:
108
110
  """
109
111
  Format data according to the specified format.
110
112
 
111
113
  Args:
112
114
  data: Data to format
113
- format_type: Output format ('json', 'yaml', 'table', 'text')
115
+ format_type: Output format (use OutputFormat enum or string)
114
116
  **kwargs: Additional formatting options
115
117
 
116
118
  Returns:
@@ -118,20 +120,23 @@ def format_output(data: Any, format_type: str = "text", **kwargs) -> str:
118
120
  """
119
121
  formatter = OutputFormatter()
120
122
 
121
- if format_type == "json":
123
+ # Convert to string for comparison (handles both enum and string inputs)
124
+ fmt = str(format_type).lower()
125
+
126
+ if fmt == OutputFormat.JSON:
122
127
  return formatter.format_json(data, **kwargs)
123
- if format_type == "yaml":
128
+ if fmt == OutputFormat.YAML:
124
129
  return formatter.format_yaml(data)
125
- if format_type == "table":
130
+ if fmt == OutputFormat.TABLE:
126
131
  return formatter.format_table(data, **kwargs)
127
- if format_type == "text":
132
+ if fmt == OutputFormat.TEXT:
128
133
  return formatter.format_text(data)
129
134
  # Fallback to text format
130
135
  return formatter.format_text(data)
131
136
 
132
137
 
133
138
  def format_success_message(
134
- message: str, data: Any = None, format_type: str = "text"
139
+ message: str, data: Any = None, format_type: str = OutputFormat.TEXT
135
140
  ) -> str:
136
141
  """
137
142
  Format a success message with optional data.
@@ -139,12 +144,13 @@ def format_success_message(
139
144
  Args:
140
145
  message: Success message
141
146
  data: Optional data to include
142
- format_type: Output format
147
+ format_type: Output format (use OutputFormat enum or string)
143
148
 
144
149
  Returns:
145
150
  Formatted success message
146
151
  """
147
- if format_type in ("json", "yaml"):
152
+ fmt = str(format_type).lower()
153
+ if fmt in (OutputFormat.JSON, OutputFormat.YAML):
148
154
  result = {"success": True, "message": message}
149
155
  if data is not None:
150
156
  result["data"] = data
@@ -158,7 +164,7 @@ def format_success_message(
158
164
 
159
165
 
160
166
  def format_error_message(
161
- message: str, details: Any = None, format_type: str = "text"
167
+ message: str, details: Any = None, format_type: str = OutputFormat.TEXT
162
168
  ) -> str:
163
169
  """
164
170
  Format an error message with optional details.
@@ -166,12 +172,13 @@ def format_error_message(
166
172
  Args:
167
173
  message: Error message
168
174
  details: Optional error details
169
- format_type: Output format
175
+ format_type: Output format (use OutputFormat enum or string)
170
176
 
171
177
  Returns:
172
178
  Formatted error message
173
179
  """
174
- if format_type in ("json", "yaml"):
180
+ fmt = str(format_type).lower()
181
+ if fmt in (OutputFormat.JSON, OutputFormat.YAML):
175
182
  result = {"success": False, "error": message}
176
183
  if details is not None:
177
184
  result["details"] = details
@@ -187,7 +194,7 @@ def format_error_message(
187
194
  def format_list_output(
188
195
  items: List[Any],
189
196
  title: Optional[str] = None,
190
- format_type: str = "text",
197
+ format_type: str = OutputFormat.TEXT,
191
198
  headers: Optional[List[str]] = None,
192
199
  ) -> str:
193
200
  """
@@ -196,29 +203,31 @@ def format_list_output(
196
203
  Args:
197
204
  items: List of items to format
198
205
  title: Optional title for the list
199
- format_type: Output format
206
+ format_type: Output format (use OutputFormat enum or string)
200
207
  headers: Optional headers for table format
201
208
 
202
209
  Returns:
203
210
  Formatted list output
204
211
  """
212
+ fmt = str(format_type).lower()
213
+
205
214
  if not items:
206
215
  empty_msg = f"No {title.lower() if title else 'items'} found"
207
- if format_type in ("json", "yaml"):
216
+ if fmt in (OutputFormat.JSON, OutputFormat.YAML):
208
217
  return format_output({"items": [], "message": empty_msg}, format_type)
209
218
  return empty_msg
210
219
 
211
- if format_type in ("json", "yaml"):
220
+ if fmt in (OutputFormat.JSON, OutputFormat.YAML):
212
221
  result = {"items": items}
213
222
  if title:
214
223
  result["title"] = title
215
224
  return format_output(result, format_type)
216
225
 
217
- if format_type == "table":
226
+ if fmt == OutputFormat.TABLE:
218
227
  output = ""
219
228
  if title:
220
229
  output += f"{title}\n{'=' * len(title)}\n\n"
221
- output += format_output(items, "table", headers=headers)
230
+ output += format_output(items, OutputFormat.TABLE, headers=headers)
222
231
  return output
223
232
 
224
233
  # Text format
@@ -228,5 +237,5 @@ def format_list_output(
228
237
  lines.append("=" * len(title))
229
238
  lines.append("")
230
239
 
231
- lines.append(format_output(items, "text"))
240
+ lines.append(format_output(items, OutputFormat.TEXT))
232
241
  return "\n".join(lines)