claude-mpm 4.14.6__py3-none-any.whl → 4.21.0__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 claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +272 -23
- claude_mpm/agents/OUTPUT_STYLE.md +48 -3
- claude_mpm/agents/PM_INSTRUCTIONS.md +49 -0
- claude_mpm/agents/agent_loader.py +17 -5
- claude_mpm/agents/frontmatter_validator.py +284 -253
- claude_mpm/agents/templates/agentic-coder-optimizer.json +9 -2
- claude_mpm/agents/templates/api_qa.json +7 -1
- claude_mpm/agents/templates/clerk-ops.json +8 -1
- claude_mpm/agents/templates/code_analyzer.json +4 -1
- claude_mpm/agents/templates/dart_engineer.json +11 -1
- claude_mpm/agents/templates/data_engineer.json +11 -1
- claude_mpm/agents/templates/documentation.json +6 -1
- claude_mpm/agents/templates/engineer.json +18 -1
- claude_mpm/agents/templates/gcp_ops_agent.json +8 -1
- claude_mpm/agents/templates/golang_engineer.json +11 -1
- claude_mpm/agents/templates/java_engineer.json +12 -2
- claude_mpm/agents/templates/local_ops_agent.json +216 -37
- claude_mpm/agents/templates/nextjs_engineer.json +11 -1
- claude_mpm/agents/templates/ops.json +8 -1
- claude_mpm/agents/templates/php-engineer.json +20 -4
- claude_mpm/agents/templates/project_organizer.json +10 -3
- claude_mpm/agents/templates/prompt-engineer.json +5 -1
- claude_mpm/agents/templates/python_engineer.json +19 -4
- claude_mpm/agents/templates/qa.json +7 -1
- claude_mpm/agents/templates/react_engineer.json +11 -1
- claude_mpm/agents/templates/refactoring_engineer.json +8 -1
- claude_mpm/agents/templates/research.json +4 -1
- claude_mpm/agents/templates/ruby-engineer.json +11 -1
- claude_mpm/agents/templates/rust_engineer.json +23 -8
- claude_mpm/agents/templates/security.json +6 -1
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/ticketing.json +6 -1
- claude_mpm/agents/templates/typescript_engineer.json +11 -1
- claude_mpm/agents/templates/vercel_ops_agent.json +8 -1
- claude_mpm/agents/templates/version_control.json +8 -1
- claude_mpm/agents/templates/web_qa.json +7 -1
- claude_mpm/agents/templates/web_ui.json +11 -1
- claude_mpm/cli/__init__.py +34 -740
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_manager.py +25 -12
- claude_mpm/cli/commands/agent_state_manager.py +186 -0
- claude_mpm/cli/commands/agents.py +204 -148
- claude_mpm/cli/commands/aggregate.py +7 -3
- claude_mpm/cli/commands/analyze.py +9 -4
- claude_mpm/cli/commands/analyze_code.py +7 -2
- claude_mpm/cli/commands/auto_configure.py +7 -9
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +294 -1788
- claude_mpm/cli/commands/configure_agent_display.py +261 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +167 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/local_deploy.py +3 -2
- claude_mpm/cli/commands/memory.py +54 -20
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +525 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +75 -4
- claude_mpm/cli/commands/skills.py +488 -0
- claude_mpm/cli/executor.py +204 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +3 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parsers/base_parser.py +7 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
- claude_mpm/cli/parsers/skills_parser.py +137 -0
- claude_mpm/cli/shared/output_formatters.py +28 -19
- claude_mpm/cli/startup.py +538 -0
- claude_mpm/commands/mpm-auto-configure.md +52 -0
- claude_mpm/commands/mpm-help.md +3 -0
- claude_mpm/commands/mpm-init.md +112 -6
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +1 -0
- claude_mpm/config/agent_config.py +2 -2
- claude_mpm/constants.py +12 -0
- claude_mpm/core/base_service.py +13 -12
- claude_mpm/core/config.py +42 -0
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/instruction_reinforcement_hook.py +2 -1
- claude_mpm/core/interactive_session.py +6 -3
- claude_mpm/core/interfaces.py +56 -1
- claude_mpm/core/logging_config.py +6 -2
- claude_mpm/core/oneshot_session.py +8 -4
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/core/output_style_manager.py +12 -192
- claude_mpm/core/service_registry.py +5 -1
- claude_mpm/core/types.py +2 -9
- claude_mpm/core/typing_utils.py +7 -6
- claude_mpm/dashboard/static/js/dashboard.js +0 -14
- claude_mpm/dashboard/templates/index.html +3 -41
- claude_mpm/hooks/__init__.py +8 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/instruction_reinforcement.py +7 -2
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/auto_config_manager.py +10 -11
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
- claude_mpm/services/agents/deployment/agent_validator.py +17 -1
- claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
- claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
- claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
- claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
- claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
- claude_mpm/services/agents/local_template_manager.py +1 -1
- claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
- claude_mpm/services/agents/recommender.py +47 -0
- claude_mpm/services/agents/registry/modification_tracker.py +5 -2
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +87 -0
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +372 -0
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/interfaces/process.py +6 -6
- claude_mpm/services/core/interfaces.py +56 -1
- claude_mpm/services/core/models/__init__.py +0 -2
- claude_mpm/services/core/models/agent_config.py +15 -28
- claude_mpm/services/core/models/health.py +1 -28
- claude_mpm/services/core/models/process.py +22 -41
- claude_mpm/services/core/path_resolver.py +1 -1
- claude_mpm/services/diagnostics/__init__.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
- claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
- claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
- claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
- claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
- claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
- claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +36 -31
- claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
- claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
- claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
- claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
- claude_mpm/services/diagnostics/models.py +37 -21
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
- claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
- claude_mpm/services/infrastructure/monitoring/base.py +5 -13
- claude_mpm/services/infrastructure/monitoring/network.py +7 -6
- claude_mpm/services/infrastructure/monitoring/process.py +13 -12
- claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
- claude_mpm/services/infrastructure/monitoring/service.py +16 -15
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/local_ops/__init__.py +5 -3
- claude_mpm/services/local_ops/crash_detector.py +1 -1
- claude_mpm/services/local_ops/health_checks/http_check.py +2 -1
- claude_mpm/services/local_ops/health_checks/process_check.py +2 -1
- claude_mpm/services/local_ops/health_checks/resource_check.py +2 -1
- claude_mpm/services/local_ops/health_manager.py +1 -1
- claude_mpm/services/local_ops/process_manager.py +12 -12
- claude_mpm/services/local_ops/restart_manager.py +1 -1
- claude_mpm/services/local_ops/state_manager.py +6 -5
- claude_mpm/services/local_ops/unified_manager.py +2 -2
- claude_mpm/services/mcp_config_manager.py +7 -126
- claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
- claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
- claude_mpm/services/mcp_gateway/core/base.py +18 -31
- claude_mpm/services/mcp_gateway/core/process_pool.py +19 -10
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +97 -45
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
- claude_mpm/services/memory_hook_service.py +4 -1
- claude_mpm/services/monitor/daemon_manager.py +3 -2
- claude_mpm/services/monitor/handlers/dashboard.py +2 -1
- claude_mpm/services/monitor/handlers/hooks.py +2 -1
- claude_mpm/services/monitor/management/lifecycle.py +3 -2
- claude_mpm/services/monitor/server.py +2 -1
- claude_mpm/services/session_management_service.py +3 -2
- claude_mpm/services/session_manager.py +205 -1
- claude_mpm/services/shared/async_service_base.py +16 -27
- claude_mpm/services/shared/lifecycle_service_base.py +1 -14
- claude_mpm/services/socketio/handlers/__init__.py +5 -2
- claude_mpm/services/socketio/handlers/hook.py +13 -2
- claude_mpm/services/socketio/handlers/registry.py +4 -2
- claude_mpm/services/socketio/server/main.py +10 -8
- claude_mpm/services/subprocess_launcher_service.py +14 -5
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
- claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
- claude_mpm/services/unified/deployment_strategies/local.py +6 -5
- claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
- claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
- claude_mpm/services/unified/interfaces.py +3 -1
- claude_mpm/services/unified/unified_analyzer.py +14 -10
- claude_mpm/services/unified/unified_config.py +2 -1
- claude_mpm/services/unified/unified_deployment.py +9 -4
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +42 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +567 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +310 -0
- claude_mpm/skills/skills_registry.py +348 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/tools/code_tree_analyzer.py +177 -141
- claude_mpm/tools/code_tree_events.py +4 -2
- claude_mpm/utils/agent_dependency_loader.py +2 -2
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.21.0.dist-info}/METADATA +211 -33
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.21.0.dist-info}/RECORD +339 -199
- claude_mpm/agents/INSTRUCTIONS_OLD_DEPRECATED.md +0 -602
- claude_mpm/cli/commands/mpm_init.py +0 -1994
- claude_mpm/dashboard/static/css/code-tree.css +0 -1639
- claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
- claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
- claude_mpm/services/project/analyzer_refactored.py +0 -450
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.21.0.dist-info}/WHEEL +0 -0
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.21.0.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.21.0.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.21.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Skills command implementation for claude-mpm.
|
|
3
|
+
|
|
4
|
+
WHY: This module provides CLI commands for managing Claude Code skills,
|
|
5
|
+
exposing SkillsService functionality for skill discovery, deployment, validation,
|
|
6
|
+
updates, and configuration.
|
|
7
|
+
|
|
8
|
+
DESIGN DECISIONS:
|
|
9
|
+
- Use BaseCommand pattern for consistency with other CLI commands
|
|
10
|
+
- Rich output formatting for user-friendly display
|
|
11
|
+
- Graceful error handling with informative messages
|
|
12
|
+
- Support for verbose output and structured formats
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
import subprocess
|
|
17
|
+
from typing import Optional
|
|
18
|
+
|
|
19
|
+
from rich.console import Console
|
|
20
|
+
from rich.markdown import Markdown
|
|
21
|
+
from rich.panel import Panel
|
|
22
|
+
|
|
23
|
+
from ...constants import SkillsCommands
|
|
24
|
+
from ...skills.skills_service import SkillsService
|
|
25
|
+
from ..shared import BaseCommand, CommandResult
|
|
26
|
+
|
|
27
|
+
console = Console()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class SkillsManagementCommand(BaseCommand):
|
|
31
|
+
"""Skills management command for Claude Code skills."""
|
|
32
|
+
|
|
33
|
+
def __init__(self):
|
|
34
|
+
super().__init__("skills")
|
|
35
|
+
self._skills_service = None
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def skills_service(self) -> SkillsService:
|
|
39
|
+
"""Get skills service instance (lazy loaded)."""
|
|
40
|
+
if self._skills_service is None:
|
|
41
|
+
self._skills_service = SkillsService()
|
|
42
|
+
return self._skills_service
|
|
43
|
+
|
|
44
|
+
def validate_args(self, args) -> Optional[str]:
|
|
45
|
+
"""Validate command arguments."""
|
|
46
|
+
# Most skills commands are optional, basic validation
|
|
47
|
+
if hasattr(args, "skills_command") and args.skills_command:
|
|
48
|
+
if args.skills_command == SkillsCommands.VALIDATE.value:
|
|
49
|
+
if not hasattr(args, "skill_name") or not args.skill_name:
|
|
50
|
+
return "Validate command requires a skill name"
|
|
51
|
+
elif args.skills_command == SkillsCommands.INFO.value:
|
|
52
|
+
if not hasattr(args, "skill_name") or not args.skill_name:
|
|
53
|
+
return "Info command requires a skill name"
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
def run(self, args) -> CommandResult:
|
|
57
|
+
"""Execute the skills command."""
|
|
58
|
+
try:
|
|
59
|
+
# Handle default case (no subcommand) - show list
|
|
60
|
+
if not hasattr(args, "skills_command") or not args.skills_command:
|
|
61
|
+
return self._list_skills(args)
|
|
62
|
+
|
|
63
|
+
# Route to appropriate subcommand
|
|
64
|
+
command_map = {
|
|
65
|
+
SkillsCommands.LIST.value: self._list_skills,
|
|
66
|
+
SkillsCommands.DEPLOY.value: self._deploy_skills,
|
|
67
|
+
SkillsCommands.VALIDATE.value: self._validate_skill,
|
|
68
|
+
SkillsCommands.UPDATE.value: self._update_skills,
|
|
69
|
+
SkillsCommands.INFO.value: self._show_skill_info,
|
|
70
|
+
SkillsCommands.CONFIG.value: self._manage_config,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
handler = command_map.get(args.skills_command)
|
|
74
|
+
if handler:
|
|
75
|
+
return handler(args)
|
|
76
|
+
return CommandResult(
|
|
77
|
+
success=False,
|
|
78
|
+
message=f"Unknown skills command: {args.skills_command}",
|
|
79
|
+
exit_code=1,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
self.logger.error(f"Skills command failed: {e}")
|
|
84
|
+
if hasattr(args, "debug") and args.debug:
|
|
85
|
+
import traceback
|
|
86
|
+
|
|
87
|
+
traceback.print_exc()
|
|
88
|
+
return CommandResult(
|
|
89
|
+
success=False, message=f"Skills command failed: {e}", exit_code=1
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def _list_skills(self, args) -> CommandResult:
|
|
93
|
+
"""List available skills."""
|
|
94
|
+
try:
|
|
95
|
+
# Get skills based on filter
|
|
96
|
+
if hasattr(args, "agent") and args.agent:
|
|
97
|
+
skills = self.skills_service.get_skills_for_agent(args.agent)
|
|
98
|
+
console.print(
|
|
99
|
+
f"\n[bold cyan]Skills for agent '{args.agent}':[/bold cyan]\n"
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
if not skills:
|
|
103
|
+
console.print(
|
|
104
|
+
f"[yellow]No skills found for agent '{args.agent}'[/yellow]"
|
|
105
|
+
)
|
|
106
|
+
return CommandResult(success=True, exit_code=0)
|
|
107
|
+
|
|
108
|
+
for skill_name in skills:
|
|
109
|
+
# Get skill metadata
|
|
110
|
+
skill_info = self._get_skill_metadata(skill_name)
|
|
111
|
+
if skill_info:
|
|
112
|
+
console.print(f" [green]•[/green] {skill_name}")
|
|
113
|
+
if (
|
|
114
|
+
hasattr(args, "verbose")
|
|
115
|
+
and args.verbose
|
|
116
|
+
and skill_info.get("description")
|
|
117
|
+
):
|
|
118
|
+
console.print(f" {skill_info['description']}")
|
|
119
|
+
else:
|
|
120
|
+
console.print(f" [green]•[/green] {skill_name}")
|
|
121
|
+
|
|
122
|
+
else:
|
|
123
|
+
# Discover all bundled skills
|
|
124
|
+
skills = self.skills_service.discover_bundled_skills()
|
|
125
|
+
|
|
126
|
+
# Filter by category if specified
|
|
127
|
+
if hasattr(args, "category") and args.category:
|
|
128
|
+
skills = [s for s in skills if s.get("category") == args.category]
|
|
129
|
+
console.print(
|
|
130
|
+
f"\n[bold cyan]Skills in category '{args.category}':[/bold cyan]\n"
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
console.print("\n[bold cyan]Available Skills:[/bold cyan]\n")
|
|
134
|
+
|
|
135
|
+
if not skills:
|
|
136
|
+
console.print("[yellow]No skills found[/yellow]")
|
|
137
|
+
return CommandResult(success=True, exit_code=0)
|
|
138
|
+
|
|
139
|
+
# Group by category
|
|
140
|
+
by_category = {}
|
|
141
|
+
for skill in skills:
|
|
142
|
+
category = skill.get("category", "uncategorized")
|
|
143
|
+
if category not in by_category:
|
|
144
|
+
by_category[category] = []
|
|
145
|
+
by_category[category].append(skill)
|
|
146
|
+
|
|
147
|
+
# Display by category
|
|
148
|
+
for category, category_skills in sorted(by_category.items()):
|
|
149
|
+
console.print(f"[bold yellow]{category}[/bold yellow]")
|
|
150
|
+
for skill in sorted(
|
|
151
|
+
category_skills, key=lambda s: s.get("name", "")
|
|
152
|
+
):
|
|
153
|
+
name = skill.get("name", "unknown")
|
|
154
|
+
console.print(f" [green]•[/green] {name}")
|
|
155
|
+
|
|
156
|
+
if hasattr(args, "verbose") and args.verbose:
|
|
157
|
+
metadata = skill.get("metadata", {})
|
|
158
|
+
if desc := metadata.get("description"):
|
|
159
|
+
console.print(f" {desc}")
|
|
160
|
+
if version := metadata.get("version"):
|
|
161
|
+
console.print(f" [dim]Version: {version}[/dim]")
|
|
162
|
+
console.print()
|
|
163
|
+
|
|
164
|
+
return CommandResult(success=True, exit_code=0)
|
|
165
|
+
|
|
166
|
+
except Exception as e:
|
|
167
|
+
console.print(f"[red]Error listing skills: {e}[/red]")
|
|
168
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
169
|
+
|
|
170
|
+
def _deploy_skills(self, args) -> CommandResult:
|
|
171
|
+
"""Deploy bundled skills to project."""
|
|
172
|
+
try:
|
|
173
|
+
force = getattr(args, "force", False)
|
|
174
|
+
specific_skills = getattr(args, "skills", None)
|
|
175
|
+
|
|
176
|
+
console.print("\n[bold cyan]Deploying skills...[/bold cyan]\n")
|
|
177
|
+
|
|
178
|
+
result = self.skills_service.deploy_bundled_skills(
|
|
179
|
+
force=force, skill_names=specific_skills
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Display results
|
|
183
|
+
if result["deployed"]:
|
|
184
|
+
console.print(
|
|
185
|
+
f"[green]✓ Deployed {len(result['deployed'])} skill(s):[/green]"
|
|
186
|
+
)
|
|
187
|
+
for skill in result["deployed"]:
|
|
188
|
+
console.print(f" • {skill}")
|
|
189
|
+
console.print()
|
|
190
|
+
|
|
191
|
+
if result["skipped"]:
|
|
192
|
+
console.print(
|
|
193
|
+
f"[yellow]⊘ Skipped {len(result['skipped'])} skill(s) (already deployed):[/yellow]"
|
|
194
|
+
)
|
|
195
|
+
for skill in result["skipped"]:
|
|
196
|
+
console.print(f" • {skill}")
|
|
197
|
+
console.print("[dim]Use --force to redeploy[/dim]\n")
|
|
198
|
+
|
|
199
|
+
if result["errors"]:
|
|
200
|
+
console.print(
|
|
201
|
+
f"[red]✗ Failed to deploy {len(result['errors'])} skill(s):[/red]"
|
|
202
|
+
)
|
|
203
|
+
for skill, error in result["errors"].items():
|
|
204
|
+
console.print(f" • {skill}: {error}")
|
|
205
|
+
console.print()
|
|
206
|
+
|
|
207
|
+
# Summary
|
|
208
|
+
total = (
|
|
209
|
+
len(result["deployed"]) + len(result["skipped"]) + len(result["errors"])
|
|
210
|
+
)
|
|
211
|
+
console.print(
|
|
212
|
+
f"[bold]Summary:[/bold] {len(result['deployed'])} deployed, "
|
|
213
|
+
f"{len(result['skipped'])} skipped, {len(result['errors'])} errors "
|
|
214
|
+
f"(Total: {total})\n"
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
# Exit with error if any deployments failed
|
|
218
|
+
exit_code = 1 if result["errors"] else 0
|
|
219
|
+
return CommandResult(success=not result["errors"], exit_code=exit_code)
|
|
220
|
+
|
|
221
|
+
except Exception as e:
|
|
222
|
+
console.print(f"[red]Error deploying skills: {e}[/red]")
|
|
223
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
224
|
+
|
|
225
|
+
def _validate_skill(self, args) -> CommandResult:
|
|
226
|
+
"""Validate skill structure and metadata."""
|
|
227
|
+
try:
|
|
228
|
+
skill_name = args.skill_name
|
|
229
|
+
strict = getattr(args, "strict", False)
|
|
230
|
+
|
|
231
|
+
console.print(
|
|
232
|
+
f"\n[bold cyan]Validating skill '{skill_name}'...[/bold cyan]\n"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
result = self.skills_service.validate_skill(skill_name)
|
|
236
|
+
|
|
237
|
+
if result["valid"]:
|
|
238
|
+
console.print(f"[green]✓ {skill_name} is valid[/green]\n")
|
|
239
|
+
|
|
240
|
+
if result.get("warnings"):
|
|
241
|
+
console.print(
|
|
242
|
+
f"[yellow]Warnings ({len(result['warnings'])}):[/yellow]"
|
|
243
|
+
)
|
|
244
|
+
for warning in result["warnings"]:
|
|
245
|
+
console.print(f" • {warning}")
|
|
246
|
+
console.print()
|
|
247
|
+
|
|
248
|
+
# Treat warnings as errors in strict mode
|
|
249
|
+
if strict:
|
|
250
|
+
console.print(
|
|
251
|
+
"[red]Strict mode: treating warnings as errors[/red]"
|
|
252
|
+
)
|
|
253
|
+
return CommandResult(success=False, exit_code=1)
|
|
254
|
+
|
|
255
|
+
return CommandResult(success=True, exit_code=0)
|
|
256
|
+
console.print(f"[red]✗ {skill_name} has validation errors:[/red]")
|
|
257
|
+
for error in result.get("errors", []):
|
|
258
|
+
console.print(f" • {error}")
|
|
259
|
+
console.print()
|
|
260
|
+
|
|
261
|
+
if result.get("warnings"):
|
|
262
|
+
console.print("[yellow]Warnings:[/yellow]")
|
|
263
|
+
for warning in result["warnings"]:
|
|
264
|
+
console.print(f" • {warning}")
|
|
265
|
+
console.print()
|
|
266
|
+
|
|
267
|
+
return CommandResult(success=False, exit_code=1)
|
|
268
|
+
|
|
269
|
+
except Exception as e:
|
|
270
|
+
console.print(f"[red]Error validating skill: {e}[/red]")
|
|
271
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
272
|
+
|
|
273
|
+
def _update_skills(self, args) -> CommandResult:
|
|
274
|
+
"""Check for and install skill updates."""
|
|
275
|
+
try:
|
|
276
|
+
skill_names = getattr(args, "skill_names", [])
|
|
277
|
+
check_only = getattr(args, "check_only", False)
|
|
278
|
+
force = getattr(args, "force", False)
|
|
279
|
+
|
|
280
|
+
action = "Checking" if check_only else "Updating"
|
|
281
|
+
console.print(f"\n[bold cyan]{action} skills...[/bold cyan]\n")
|
|
282
|
+
|
|
283
|
+
result = self.skills_service.check_for_updates(skill_names)
|
|
284
|
+
|
|
285
|
+
if not result.get("updates_available"):
|
|
286
|
+
console.print("[green]All skills are up to date[/green]\n")
|
|
287
|
+
return CommandResult(success=True, exit_code=0)
|
|
288
|
+
|
|
289
|
+
# Display available updates
|
|
290
|
+
console.print(
|
|
291
|
+
f"[yellow]Updates available for {len(result['updates_available'])} skill(s):[/yellow]"
|
|
292
|
+
)
|
|
293
|
+
for update_info in result["updates_available"]:
|
|
294
|
+
skill_name = update_info["skill"]
|
|
295
|
+
current = update_info["current_version"]
|
|
296
|
+
latest = update_info["latest_version"]
|
|
297
|
+
console.print(f" • {skill_name}: {current} → {latest}")
|
|
298
|
+
console.print()
|
|
299
|
+
|
|
300
|
+
if check_only:
|
|
301
|
+
console.print(
|
|
302
|
+
"[dim]Run without --check-only to install updates[/dim]\n"
|
|
303
|
+
)
|
|
304
|
+
return CommandResult(success=True, exit_code=0)
|
|
305
|
+
|
|
306
|
+
# Install updates
|
|
307
|
+
console.print("[bold cyan]Installing updates...[/bold cyan]\n")
|
|
308
|
+
install_result = self.skills_service.install_updates(
|
|
309
|
+
result["updates_available"], force=force
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
if install_result["updated"]:
|
|
313
|
+
console.print(
|
|
314
|
+
f"[green]✓ Updated {len(install_result['updated'])} skill(s)[/green]\n"
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
if install_result.get("errors"):
|
|
318
|
+
console.print(
|
|
319
|
+
f"[red]✗ Failed to update {len(install_result['errors'])} skill(s)[/red]"
|
|
320
|
+
)
|
|
321
|
+
for skill, error in install_result["errors"].items():
|
|
322
|
+
console.print(f" • {skill}: {error}")
|
|
323
|
+
console.print()
|
|
324
|
+
|
|
325
|
+
exit_code = 1 if install_result.get("errors") else 0
|
|
326
|
+
return CommandResult(
|
|
327
|
+
success=not install_result.get("errors"), exit_code=exit_code
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
except Exception as e:
|
|
331
|
+
console.print(f"[red]Error updating skills: {e}[/red]")
|
|
332
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
333
|
+
|
|
334
|
+
def _show_skill_info(self, args) -> CommandResult:
|
|
335
|
+
"""Show detailed skill information."""
|
|
336
|
+
try:
|
|
337
|
+
skill_name = args.skill_name
|
|
338
|
+
show_content = getattr(args, "show_content", False)
|
|
339
|
+
|
|
340
|
+
skill_info = self._get_skill_metadata(skill_name)
|
|
341
|
+
|
|
342
|
+
if not skill_info:
|
|
343
|
+
console.print(f"[red]Skill '{skill_name}' not found[/red]")
|
|
344
|
+
return CommandResult(success=False, exit_code=1)
|
|
345
|
+
|
|
346
|
+
# Display skill info in a panel
|
|
347
|
+
info_text = f"[bold cyan]{skill_name}[/bold cyan]\n\n"
|
|
348
|
+
|
|
349
|
+
if desc := skill_info.get("description"):
|
|
350
|
+
info_text += f"{desc}\n\n"
|
|
351
|
+
|
|
352
|
+
if category := skill_info.get("category"):
|
|
353
|
+
info_text += f"[bold]Category:[/bold] {category}\n"
|
|
354
|
+
|
|
355
|
+
if version := skill_info.get("version"):
|
|
356
|
+
info_text += f"[bold]Version:[/bold] {version}\n"
|
|
357
|
+
|
|
358
|
+
if source := skill_info.get("source"):
|
|
359
|
+
info_text += f"[bold]Source:[/bold] {source}\n"
|
|
360
|
+
|
|
361
|
+
# Show agents using this skill
|
|
362
|
+
agents_using = self.skills_service.get_agents_for_skill(skill_name)
|
|
363
|
+
if agents_using:
|
|
364
|
+
info_text += (
|
|
365
|
+
f"\n[bold]Used by agents:[/bold] {', '.join(agents_using)}\n"
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
console.print(
|
|
369
|
+
Panel(info_text, title="Skill Information", border_style="cyan")
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
# Show content if requested
|
|
373
|
+
if show_content:
|
|
374
|
+
skill_path = self.skills_service.get_skill_path(skill_name)
|
|
375
|
+
skill_md = skill_path / "SKILL.md"
|
|
376
|
+
|
|
377
|
+
if skill_md.exists():
|
|
378
|
+
console.print("\n[bold cyan]Skill Content:[/bold cyan]\n")
|
|
379
|
+
content = skill_md.read_text()
|
|
380
|
+
console.print(Markdown(content))
|
|
381
|
+
else:
|
|
382
|
+
console.print(
|
|
383
|
+
f"\n[yellow]SKILL.md not found at {skill_md}[/yellow]"
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
return CommandResult(success=True, exit_code=0)
|
|
387
|
+
|
|
388
|
+
except Exception as e:
|
|
389
|
+
console.print(f"[red]Error showing skill info: {e}[/red]")
|
|
390
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
391
|
+
|
|
392
|
+
def _manage_config(self, args) -> CommandResult:
|
|
393
|
+
"""View or edit skills configuration."""
|
|
394
|
+
try:
|
|
395
|
+
scope = getattr(args, "scope", "project")
|
|
396
|
+
edit = getattr(args, "edit", False)
|
|
397
|
+
show_path = getattr(args, "path", False)
|
|
398
|
+
|
|
399
|
+
config_path = self.skills_service.get_config_path(scope)
|
|
400
|
+
|
|
401
|
+
if show_path:
|
|
402
|
+
console.print(
|
|
403
|
+
f"\n[cyan]Configuration path ({scope}):[/cyan] {config_path}\n"
|
|
404
|
+
)
|
|
405
|
+
return CommandResult(success=True, exit_code=0)
|
|
406
|
+
|
|
407
|
+
if not config_path.exists():
|
|
408
|
+
console.print(
|
|
409
|
+
f"\n[yellow]Configuration file does not exist: {config_path}[/yellow]"
|
|
410
|
+
)
|
|
411
|
+
console.print("[dim]Would you like to create it? (y/n):[/dim] ", end="")
|
|
412
|
+
|
|
413
|
+
if input().lower() == "y":
|
|
414
|
+
self.skills_service.create_default_config(scope)
|
|
415
|
+
console.print(
|
|
416
|
+
f"[green]Created default configuration at {config_path}[/green]\n"
|
|
417
|
+
)
|
|
418
|
+
else:
|
|
419
|
+
return CommandResult(success=False, exit_code=1)
|
|
420
|
+
|
|
421
|
+
if edit:
|
|
422
|
+
# Open in editor
|
|
423
|
+
editor = os.environ.get("EDITOR", "nano")
|
|
424
|
+
try:
|
|
425
|
+
subprocess.run([editor, str(config_path)], check=True)
|
|
426
|
+
console.print(
|
|
427
|
+
f"\n[green]Configuration saved to {config_path}[/green]\n"
|
|
428
|
+
)
|
|
429
|
+
return CommandResult(success=True, exit_code=0)
|
|
430
|
+
except subprocess.CalledProcessError as e:
|
|
431
|
+
console.print(f"[red]Error opening editor: {e}[/red]")
|
|
432
|
+
return CommandResult(success=False, exit_code=1)
|
|
433
|
+
else:
|
|
434
|
+
# Display config
|
|
435
|
+
console.print(
|
|
436
|
+
f"\n[bold cyan]Skills Configuration ({scope}):[/bold cyan]\n"
|
|
437
|
+
)
|
|
438
|
+
console.print(f"[dim]Path: {config_path}[/dim]\n")
|
|
439
|
+
|
|
440
|
+
import yaml
|
|
441
|
+
|
|
442
|
+
config = yaml.safe_load(config_path.read_text())
|
|
443
|
+
console.print(yaml.dump(config, default_flow_style=False))
|
|
444
|
+
|
|
445
|
+
return CommandResult(success=True, exit_code=0)
|
|
446
|
+
|
|
447
|
+
except Exception as e:
|
|
448
|
+
console.print(f"[red]Error managing configuration: {e}[/red]")
|
|
449
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
450
|
+
|
|
451
|
+
def _get_skill_metadata(self, skill_name: str) -> Optional[dict]:
|
|
452
|
+
"""Get skill metadata from SKILL.md file."""
|
|
453
|
+
try:
|
|
454
|
+
skill_path = self.skills_service.get_skill_path(skill_name)
|
|
455
|
+
skill_md = skill_path / "SKILL.md"
|
|
456
|
+
|
|
457
|
+
if not skill_md.exists():
|
|
458
|
+
return None
|
|
459
|
+
|
|
460
|
+
# Parse SKILL.md metadata
|
|
461
|
+
content = skill_md.read_text()
|
|
462
|
+
return self.skills_service.parse_skill_metadata(content)
|
|
463
|
+
|
|
464
|
+
except Exception:
|
|
465
|
+
return None
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def manage_skills(args) -> int:
|
|
469
|
+
"""
|
|
470
|
+
Main entry point for skills command.
|
|
471
|
+
|
|
472
|
+
Args:
|
|
473
|
+
args: Parsed command-line arguments
|
|
474
|
+
|
|
475
|
+
Returns:
|
|
476
|
+
Exit code (0 for success, non-zero for failure)
|
|
477
|
+
"""
|
|
478
|
+
command = SkillsManagementCommand()
|
|
479
|
+
|
|
480
|
+
# Validate arguments
|
|
481
|
+
error = command.validate_args(args)
|
|
482
|
+
if error:
|
|
483
|
+
console.print(f"[red]Error: {error}[/red]")
|
|
484
|
+
return 1
|
|
485
|
+
|
|
486
|
+
# Run command
|
|
487
|
+
result = command.run(args)
|
|
488
|
+
return result.exit_code
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI Command Executor
|
|
3
|
+
====================
|
|
4
|
+
|
|
5
|
+
This module handles command execution routing and argument preparation.
|
|
6
|
+
|
|
7
|
+
Part of cli/__init__.py refactoring to reduce file size and improve modularity.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from ..constants import CLICommands
|
|
11
|
+
from .commands import (
|
|
12
|
+
aggregate_command,
|
|
13
|
+
cleanup_memory,
|
|
14
|
+
manage_agent_manager,
|
|
15
|
+
manage_agents,
|
|
16
|
+
manage_config,
|
|
17
|
+
manage_configure,
|
|
18
|
+
manage_debug,
|
|
19
|
+
manage_mcp,
|
|
20
|
+
manage_memory,
|
|
21
|
+
manage_monitor,
|
|
22
|
+
manage_tickets,
|
|
23
|
+
run_doctor,
|
|
24
|
+
run_session,
|
|
25
|
+
show_info,
|
|
26
|
+
)
|
|
27
|
+
from .commands.analyze_code import manage_analyze_code
|
|
28
|
+
from .commands.dashboard import manage_dashboard
|
|
29
|
+
from .commands.skills import manage_skills
|
|
30
|
+
from .commands.upgrade import upgrade
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def ensure_run_attributes(args):
|
|
34
|
+
"""
|
|
35
|
+
Ensure run command attributes exist when defaulting to run.
|
|
36
|
+
|
|
37
|
+
WHY: When no command is specified, we default to 'run' but the args object
|
|
38
|
+
won't have run-specific attributes from the subparser. This function ensures
|
|
39
|
+
they exist with sensible defaults.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
args: Parsed arguments object to update
|
|
43
|
+
"""
|
|
44
|
+
# Set defaults for run command attributes
|
|
45
|
+
args.no_tickets = getattr(args, "no_tickets", False)
|
|
46
|
+
args.no_hooks = getattr(args, "no_hooks", False)
|
|
47
|
+
args.intercept_commands = getattr(args, "intercept_commands", False)
|
|
48
|
+
args.input = getattr(args, "input", None)
|
|
49
|
+
args.non_interactive = getattr(args, "non_interactive", False)
|
|
50
|
+
args.no_native_agents = getattr(args, "no_native_agents", False)
|
|
51
|
+
|
|
52
|
+
# Handle claude_args - if --resume flag is set, add it to claude_args
|
|
53
|
+
claude_args = getattr(args, "claude_args", [])
|
|
54
|
+
if getattr(args, "resume", False):
|
|
55
|
+
# Add --resume to claude_args if not already present
|
|
56
|
+
if "--resume" not in claude_args:
|
|
57
|
+
claude_args = ["--resume", *claude_args]
|
|
58
|
+
args.claude_args = claude_args
|
|
59
|
+
|
|
60
|
+
args.launch_method = getattr(args, "launch_method", "exec")
|
|
61
|
+
args.websocket = getattr(args, "websocket", False)
|
|
62
|
+
args.websocket_port = getattr(args, "websocket_port", 8765)
|
|
63
|
+
# CRITICAL: Include mpm_resume attribute for session resumption
|
|
64
|
+
args.mpm_resume = getattr(args, "mpm_resume", None)
|
|
65
|
+
# Also include monitor and force attributes
|
|
66
|
+
args.monitor = getattr(args, "monitor", False)
|
|
67
|
+
args.force = getattr(args, "force", False)
|
|
68
|
+
args.reload_agents = getattr(args, "reload_agents", False)
|
|
69
|
+
# Include dependency checking attributes
|
|
70
|
+
args.check_dependencies = getattr(args, "check_dependencies", True)
|
|
71
|
+
args.force_check_dependencies = getattr(args, "force_check_dependencies", False)
|
|
72
|
+
args.no_prompt = getattr(args, "no_prompt", False)
|
|
73
|
+
args.force_prompt = getattr(args, "force_prompt", False)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def execute_command(command: str, args) -> int:
|
|
77
|
+
"""
|
|
78
|
+
Execute the specified command.
|
|
79
|
+
|
|
80
|
+
WHY: This function maps command names to their implementations, providing
|
|
81
|
+
a single place to manage command routing. Experimental commands are imported
|
|
82
|
+
lazily to avoid loading unnecessary code.
|
|
83
|
+
|
|
84
|
+
DESIGN DECISION: run_guarded is imported only when needed to maintain
|
|
85
|
+
separation between stable and experimental features. Command suggestions
|
|
86
|
+
are provided for unknown commands to improve user experience.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
command: The command name to execute
|
|
90
|
+
args: Parsed command line arguments
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Exit code from the command
|
|
94
|
+
"""
|
|
95
|
+
# Handle experimental run-guarded command separately with lazy import
|
|
96
|
+
if command == "run-guarded":
|
|
97
|
+
# Lazy import to avoid loading experimental code unless needed
|
|
98
|
+
from .commands.run_guarded import execute_run_guarded
|
|
99
|
+
|
|
100
|
+
result = execute_run_guarded(args)
|
|
101
|
+
return result if result is not None else 0
|
|
102
|
+
|
|
103
|
+
# Handle mpm-init command with lazy import
|
|
104
|
+
if command == "mpm-init":
|
|
105
|
+
# Lazy import to avoid loading unless needed
|
|
106
|
+
from .commands.mpm_init_handler import manage_mpm_init
|
|
107
|
+
|
|
108
|
+
result = manage_mpm_init(args)
|
|
109
|
+
return result if result is not None else 0
|
|
110
|
+
|
|
111
|
+
# Handle uninstall command with lazy import
|
|
112
|
+
if command == "uninstall":
|
|
113
|
+
# Lazy import to avoid loading unless needed
|
|
114
|
+
from .commands.uninstall import UninstallCommand
|
|
115
|
+
|
|
116
|
+
cmd = UninstallCommand()
|
|
117
|
+
result = cmd.execute(args)
|
|
118
|
+
# Convert CommandResult to exit code
|
|
119
|
+
return result.exit_code if result else 0
|
|
120
|
+
|
|
121
|
+
# Handle verify command with lazy import
|
|
122
|
+
if command == "verify":
|
|
123
|
+
# Lazy import to avoid loading unless needed
|
|
124
|
+
from .commands.verify import handle_verify
|
|
125
|
+
|
|
126
|
+
result = handle_verify(args)
|
|
127
|
+
return result if result is not None else 0
|
|
128
|
+
|
|
129
|
+
# Handle auto-configure command with lazy import
|
|
130
|
+
if command == "auto-configure":
|
|
131
|
+
# Lazy import to avoid loading unless needed
|
|
132
|
+
from .commands.auto_configure import AutoConfigureCommand
|
|
133
|
+
|
|
134
|
+
cmd = AutoConfigureCommand()
|
|
135
|
+
result = cmd.run(args)
|
|
136
|
+
# Convert CommandResult to exit code
|
|
137
|
+
return result.exit_code if result else 0
|
|
138
|
+
|
|
139
|
+
# Handle local-deploy command with lazy import
|
|
140
|
+
if command == "local-deploy":
|
|
141
|
+
# Lazy import to avoid loading unless needed
|
|
142
|
+
from .commands.local_deploy import LocalDeployCommand
|
|
143
|
+
|
|
144
|
+
cmd = LocalDeployCommand()
|
|
145
|
+
result = cmd.run(args)
|
|
146
|
+
# Convert CommandResult to exit code
|
|
147
|
+
return result.exit_code if result else 0
|
|
148
|
+
|
|
149
|
+
# Map stable commands to their implementations
|
|
150
|
+
command_map = {
|
|
151
|
+
CLICommands.RUN.value: run_session,
|
|
152
|
+
# CLICommands.RUN_GUARDED.value is handled above
|
|
153
|
+
CLICommands.TICKETS.value: manage_tickets,
|
|
154
|
+
CLICommands.INFO.value: show_info,
|
|
155
|
+
CLICommands.AGENTS.value: manage_agents,
|
|
156
|
+
CLICommands.AGENT_MANAGER.value: manage_agent_manager,
|
|
157
|
+
CLICommands.MEMORY.value: manage_memory,
|
|
158
|
+
CLICommands.MONITOR.value: manage_monitor,
|
|
159
|
+
CLICommands.DASHBOARD.value: manage_dashboard,
|
|
160
|
+
CLICommands.CONFIG.value: manage_config,
|
|
161
|
+
CLICommands.CONFIGURE.value: manage_configure,
|
|
162
|
+
CLICommands.AGGREGATE.value: aggregate_command,
|
|
163
|
+
CLICommands.ANALYZE_CODE.value: manage_analyze_code,
|
|
164
|
+
CLICommands.CLEANUP.value: cleanup_memory,
|
|
165
|
+
CLICommands.MCP.value: manage_mcp,
|
|
166
|
+
CLICommands.DOCTOR.value: run_doctor,
|
|
167
|
+
CLICommands.UPGRADE.value: upgrade,
|
|
168
|
+
CLICommands.SKILLS.value: manage_skills,
|
|
169
|
+
"debug": manage_debug, # Add debug command
|
|
170
|
+
"mpm-init": None, # Will be handled separately with lazy import
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
# Execute command if found
|
|
174
|
+
if command in command_map:
|
|
175
|
+
result = command_map[command](args)
|
|
176
|
+
# Commands may return None (success) or an exit code
|
|
177
|
+
return result if result is not None else 0
|
|
178
|
+
|
|
179
|
+
# Unknown command - provide suggestions
|
|
180
|
+
from rich.console import Console
|
|
181
|
+
|
|
182
|
+
from .utils import suggest_similar_commands
|
|
183
|
+
|
|
184
|
+
console = Console(stderr=True)
|
|
185
|
+
|
|
186
|
+
console.print(f"\n[red]Error:[/red] Unknown command: {command}\n", style="bold")
|
|
187
|
+
|
|
188
|
+
# Get all valid commands for suggestions
|
|
189
|
+
all_commands = [
|
|
190
|
+
*command_map.keys(),
|
|
191
|
+
"run-guarded",
|
|
192
|
+
"uninstall",
|
|
193
|
+
"verify",
|
|
194
|
+
"auto-configure",
|
|
195
|
+
"local-deploy",
|
|
196
|
+
]
|
|
197
|
+
|
|
198
|
+
suggestion = suggest_similar_commands(command, all_commands)
|
|
199
|
+
if suggestion:
|
|
200
|
+
console.print(f"[yellow]{suggestion}[/yellow]\n")
|
|
201
|
+
|
|
202
|
+
console.print("[dim]Run 'claude-mpm --help' for usage information.[/dim]\n")
|
|
203
|
+
|
|
204
|
+
return 1
|