claude-mpm 4.20.3__py3-none-any.whl → 5.1.8__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_PM.md +35 -6
- claude_mpm/agents/OUTPUT_STYLE.md +3 -48
- claude_mpm/agents/PM_INSTRUCTIONS.md +1241 -667
- claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +1322 -0
- claude_mpm/agents/WORKFLOW.md +75 -2
- claude_mpm/agents/__init__.py +6 -0
- claude_mpm/agents/agent_loader.py +1 -4
- claude_mpm/agents/base_agent.json +6 -3
- claude_mpm/agents/base_agent_loader.py +10 -35
- claude_mpm/agents/frontmatter_validator.py +1 -1
- claude_mpm/agents/templates/circuit-breakers.md +1254 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +89 -19
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/cli/__init__.py +37 -2
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +188 -30
- claude_mpm/cli/commands/agents.py +959 -36
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +1 -1
- claude_mpm/cli/commands/analyze.py +3 -3
- claude_mpm/cli/commands/auto_configure.py +537 -239
- claude_mpm/cli/commands/cleanup.py +1 -1
- claude_mpm/cli/commands/config.py +7 -4
- claude_mpm/cli/commands/configure.py +924 -45
- claude_mpm/cli/commands/configure_agent_display.py +4 -4
- claude_mpm/cli/commands/configure_navigation.py +63 -46
- claude_mpm/cli/commands/debug.py +12 -12
- claude_mpm/cli/commands/doctor.py +10 -2
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/local_deploy.py +1 -4
- claude_mpm/cli/commands/mcp_install_commands.py +1 -1
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +573 -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 +67 -1
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/run.py +125 -167
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +835 -44
- claude_mpm/cli/executor.py +78 -3
- claude_mpm/cli/interactive/agent_wizard.py +1032 -47
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +256 -4
- claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
- claude_mpm/cli/parsers/base_parser.py +53 -0
- claude_mpm/cli/parsers/config_parser.py +96 -43
- claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +145 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/startup.py +564 -108
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/cli_module/commands.py +1 -1
- claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
- claude_mpm/commands/mpm-agents-detect.md +9 -0
- claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
- claude_mpm/commands/mpm-agents-recommend.md +9 -0
- claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
- claude_mpm/commands/mpm-doctor.md +9 -0
- claude_mpm/commands/mpm-help.md +17 -2
- claude_mpm/commands/mpm-init.md +28 -3
- claude_mpm/commands/mpm-monitor.md +9 -0
- claude_mpm/commands/mpm-postmortem.md +123 -0
- claude_mpm/commands/mpm-session-resume.md +381 -0
- claude_mpm/commands/mpm-status.md +9 -0
- claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
- claude_mpm/commands/mpm-ticket-view.md +552 -0
- claude_mpm/commands/mpm-version.md +9 -0
- claude_mpm/commands/mpm.md +11 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +325 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/constants.py +13 -0
- claude_mpm/core/api_validator.py +1 -1
- claude_mpm/core/claude_runner.py +19 -35
- claude_mpm/core/config.py +24 -0
- claude_mpm/core/constants.py +1 -1
- claude_mpm/core/framework/__init__.py +3 -16
- claude_mpm/core/framework/loaders/file_loader.py +54 -101
- claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
- claude_mpm/core/framework/processors/metadata_processor.py +1 -1
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +41 -2
- claude_mpm/core/interactive_session.py +131 -10
- claude_mpm/core/interfaces.py +56 -1
- claude_mpm/core/logger.py +3 -1
- claude_mpm/core/oneshot_session.py +110 -8
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/shared/singleton_manager.py +11 -4
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/unified_config.py +22 -0
- claude_mpm/dashboard/static/css/activity.css +69 -69
- claude_mpm/dashboard/static/css/connection-status.css +10 -10
- claude_mpm/dashboard/static/css/dashboard.css +15 -15
- claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
- claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
- claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
- claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
- claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
- claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
- claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
- claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
- claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
- claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
- claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
- claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
- claude_mpm/dashboard/static/js/connection-manager.js +76 -76
- claude_mpm/dashboard/static/js/dashboard.js +76 -58
- claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
- claude_mpm/dashboard/static/js/socket-client.js +138 -121
- claude_mpm/dashboard/templates/code_simple.html +23 -23
- claude_mpm/dashboard/templates/index.html +18 -18
- claude_mpm/experimental/cli_enhancements.py +1 -5
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
- claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
- claude_mpm/hooks/claude_hooks/installer.py +45 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
- claude_mpm/hooks/failure_learning/__init__.py +2 -8
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
- claude_mpm/hooks/kuzu_response_hook.py +1 -5
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/scripts/claude-hook-handler.sh +3 -3
- claude_mpm/scripts/start_activity_logging.py +3 -1
- claude_mpm/services/agents/agent_builder.py +45 -9
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
- claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
- claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
- claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
- claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
- claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
- claude_mpm/services/agents/git_source_manager.py +629 -0
- claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
- claude_mpm/services/agents/local_template_manager.py +50 -10
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
- claude_mpm/services/agents/startup_sync.py +239 -0
- claude_mpm/services/agents/toolchain_detector.py +474 -0
- claude_mpm/services/analysis/__init__.py +25 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +36 -16
- claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
- claude_mpm/services/command_deployment_service.py +200 -6
- claude_mpm/services/core/base.py +31 -11
- claude_mpm/services/core/interfaces/__init__.py +1 -3
- claude_mpm/services/core/interfaces/health.py +1 -4
- claude_mpm/services/core/interfaces.py +56 -1
- claude_mpm/services/core/models/__init__.py +2 -11
- claude_mpm/services/core/models/agent_config.py +3 -0
- claude_mpm/services/core/models/process.py +4 -0
- claude_mpm/services/diagnostics/checks/__init__.py +4 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
- claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
- claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
- claude_mpm/services/diagnostics/models.py +21 -0
- claude_mpm/services/event_bus/direct_relay.py +3 -3
- claude_mpm/services/event_bus/event_bus.py +36 -3
- claude_mpm/services/event_bus/relay.py +23 -7
- claude_mpm/services/events/consumers/logging.py +1 -2
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +494 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
- claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
- claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +5 -13
- claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
- claude_mpm/services/local_ops/health_manager.py +1 -4
- claude_mpm/services/local_ops/process_manager.py +1 -1
- claude_mpm/services/local_ops/resource_monitor.py +2 -2
- claude_mpm/services/mcp_config_manager.py +75 -145
- claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
- claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
- claude_mpm/services/mcp_gateway/core/process_pool.py +41 -26
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +26 -21
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
- claude_mpm/services/mcp_service_verifier.py +6 -3
- claude_mpm/services/memory/failure_tracker.py +19 -4
- claude_mpm/services/memory/optimizer.py +1 -1
- claude_mpm/services/model/model_router.py +8 -9
- claude_mpm/services/monitor/daemon.py +29 -9
- claude_mpm/services/monitor/daemon_manager.py +96 -19
- claude_mpm/services/monitor/server.py +2 -2
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/port_manager.py +1 -1
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/project/documentation_manager.py +2 -1
- claude_mpm/services/project/project_organizer.py +4 -0
- claude_mpm/services/project/toolchain_analyzer.py +3 -1
- claude_mpm/services/runner_configuration_service.py +17 -3
- claude_mpm/services/self_upgrade_service.py +165 -7
- claude_mpm/services/session_management_service.py +16 -4
- claude_mpm/services/skills/__init__.py +18 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +955 -0
- claude_mpm/services/socketio/handlers/connection.py +1 -1
- claude_mpm/services/socketio/handlers/git.py +2 -2
- claude_mpm/services/socketio/server/core.py +1 -4
- claude_mpm/services/socketio/server/main.py +1 -3
- claude_mpm/services/system_instructions_service.py +1 -3
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
- claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
- claude_mpm/services/unified/unified_deployment.py +1 -5
- claude_mpm/services/version_control/conflict_resolution.py +6 -4
- claude_mpm/services/visualization/__init__.py +1 -5
- claude_mpm/services/visualization/mermaid_generator.py +2 -3
- claude_mpm/skills/__init__.py +3 -3
- claude_mpm/skills/agent_skills_injector.py +42 -49
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +17 -10
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +92 -39
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +13 -12
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +5 -3
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +19 -12
- claude_mpm/skills/bundled/performance-profiling.md +6 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +6 -6
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +13 -9
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +8 -8
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +37 -15
- claude_mpm/skills/skills_registry.py +44 -48
- claude_mpm/skills/skills_service.py +117 -108
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/tools/__main__.py +8 -8
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/utils/agent_dependency_loader.py +80 -13
- claude_mpm/utils/agent_filters.py +288 -0
- claude_mpm/utils/dependency_cache.py +3 -1
- claude_mpm/utils/gitignore.py +244 -0
- claude_mpm/utils/log_cleanup.py +3 -3
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +3 -5
- claude_mpm/utils/structured_questions.py +619 -0
- {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/METADATA +496 -65
- {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/RECORD +328 -416
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
- claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
- claude_mpm/agents/templates/agent-manager.json +0 -273
- claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
- claude_mpm/agents/templates/api_qa.json +0 -180
- claude_mpm/agents/templates/circuit_breakers.md +0 -638
- claude_mpm/agents/templates/clerk-ops.json +0 -235
- claude_mpm/agents/templates/code_analyzer.json +0 -101
- claude_mpm/agents/templates/content-agent.json +0 -358
- claude_mpm/agents/templates/dart_engineer.json +0 -307
- claude_mpm/agents/templates/data_engineer.json +0 -225
- claude_mpm/agents/templates/documentation.json +0 -211
- claude_mpm/agents/templates/engineer.json +0 -210
- claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
- claude_mpm/agents/templates/golang_engineer.json +0 -270
- claude_mpm/agents/templates/imagemagick.json +0 -264
- claude_mpm/agents/templates/java_engineer.json +0 -346
- claude_mpm/agents/templates/local_ops_agent.json +0 -1840
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
- claude_mpm/agents/templates/memory_manager.json +0 -158
- claude_mpm/agents/templates/nextjs_engineer.json +0 -285
- claude_mpm/agents/templates/ops.json +0 -185
- claude_mpm/agents/templates/php-engineer.json +0 -281
- claude_mpm/agents/templates/product_owner.json +0 -338
- claude_mpm/agents/templates/project_organizer.json +0 -140
- claude_mpm/agents/templates/prompt-engineer.json +0 -737
- claude_mpm/agents/templates/python_engineer.json +0 -387
- claude_mpm/agents/templates/qa.json +0 -242
- claude_mpm/agents/templates/react_engineer.json +0 -238
- claude_mpm/agents/templates/refactoring_engineer.json +0 -276
- claude_mpm/agents/templates/research.json +0 -188
- claude_mpm/agents/templates/ruby-engineer.json +0 -280
- claude_mpm/agents/templates/rust_engineer.json +0 -275
- claude_mpm/agents/templates/security.json +0 -202
- claude_mpm/agents/templates/svelte-engineer.json +0 -225
- claude_mpm/agents/templates/ticketing.json +0 -177
- claude_mpm/agents/templates/typescript_engineer.json +0 -285
- claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
- claude_mpm/agents/templates/version_control.json +0 -157
- claude_mpm/agents/templates/web_qa.json +0 -399
- claude_mpm/agents/templates/web_ui.json +0 -189
- claude_mpm/cli/commands/mpm_init.py +0 -2093
- claude_mpm/commands/mpm-tickets.md +0 -102
- claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
- claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
- claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
- claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
- claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
- claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
- claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
- claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
- claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/built/connection-manager.js +0 -536
- claude_mpm/dashboard/static/built/dashboard.js +0 -2
- claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/built/react/events.js +0 -30
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
- claude_mpm/dashboard/static/built/shared/logger.js +0 -385
- claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/built/socket-client.js +0 -2
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/dist/dashboard.js +0 -2
- claude_mpm/dashboard/static/dist/react/events.js +0 -30
- claude_mpm/dashboard/static/dist/socket-client.js +0 -2
- claude_mpm/dashboard/static/events.html +0 -607
- claude_mpm/dashboard/static/index.html +0 -635
- claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/js/shared/logger.js +0 -385
- claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
- claude_mpm/dashboard/static/legacy/activity.html +0 -736
- claude_mpm/dashboard/static/legacy/agents.html +0 -786
- claude_mpm/dashboard/static/legacy/files.html +0 -747
- claude_mpm/dashboard/static/legacy/tools.html +0 -831
- claude_mpm/dashboard/static/monitors.html +0 -431
- claude_mpm/dashboard/static/production/events.html +0 -659
- claude_mpm/dashboard/static/production/main.html +0 -698
- claude_mpm/dashboard/static/production/monitors.html +0 -483
- claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
- claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
- claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
- claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -75
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -184
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -107
- claude_mpm/skills/bundled/collaboration/requesting-code-review/code-reviewer.md +0 -146
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -118
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -177
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -175
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/common-failures.md +0 -213
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -314
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -227
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -74
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -32
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -328
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -209
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -123
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -304
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -96
- claude_mpm/tools/code_tree_analyzer.py +0 -1825
- /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
- /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
- /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
- /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
- {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/WHEEL +0 -0
- {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.20.3.dist-info → claude_mpm-5.1.8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
PreToolUse Hook Template for Claude Code v2.0.30+
|
|
4
|
+
|
|
5
|
+
This template demonstrates how to create PreToolUse hooks that can modify
|
|
6
|
+
tool inputs before execution. Use cases include:
|
|
7
|
+
|
|
8
|
+
1. Context Injection: Add project context to Read/Edit operations
|
|
9
|
+
2. Security Guards: Validate file paths before operations
|
|
10
|
+
3. Logging: Log tool invocations before execution
|
|
11
|
+
4. Parameter Enhancement: Add default parameters to tool calls
|
|
12
|
+
|
|
13
|
+
Requirements:
|
|
14
|
+
- Claude Code v2.0.30 or higher
|
|
15
|
+
- Hook must be configured with "modifyInput": true in settings.json
|
|
16
|
+
|
|
17
|
+
Input Format (stdin):
|
|
18
|
+
{
|
|
19
|
+
"hook_event_name": "PreToolUse",
|
|
20
|
+
"tool_name": "Edit",
|
|
21
|
+
"tool_input": {
|
|
22
|
+
"file_path": "/path/to/file.py",
|
|
23
|
+
"old_string": "foo",
|
|
24
|
+
"new_string": "bar"
|
|
25
|
+
},
|
|
26
|
+
"session_id": "abc123...",
|
|
27
|
+
"cwd": "/working/directory"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
Output Format (stdout):
|
|
31
|
+
{
|
|
32
|
+
"action": "continue",
|
|
33
|
+
"tool_input": {
|
|
34
|
+
"file_path": "/path/to/file.py",
|
|
35
|
+
"old_string": "foo",
|
|
36
|
+
"new_string": "bar_modified"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Or to block execution:
|
|
41
|
+
{
|
|
42
|
+
"action": "block",
|
|
43
|
+
"message": "Reason for blocking"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Or to continue without modification:
|
|
47
|
+
{
|
|
48
|
+
"action": "continue"
|
|
49
|
+
}
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
import json
|
|
53
|
+
import os
|
|
54
|
+
import sys
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
from typing import Any, Dict, Optional
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class PreToolUseHook:
|
|
60
|
+
"""Base class for PreToolUse hooks with input modification support."""
|
|
61
|
+
|
|
62
|
+
def __init__(self):
|
|
63
|
+
"""Initialize the hook."""
|
|
64
|
+
self.debug = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "false").lower() == "true"
|
|
65
|
+
|
|
66
|
+
def log_debug(self, message: str) -> None:
|
|
67
|
+
"""Log debug message to stderr."""
|
|
68
|
+
if self.debug:
|
|
69
|
+
print(f"[PreToolUse Hook] {message}", file=sys.stderr)
|
|
70
|
+
|
|
71
|
+
def read_event(self) -> Optional[Dict[str, Any]]:
|
|
72
|
+
"""Read and parse the hook event from stdin."""
|
|
73
|
+
try:
|
|
74
|
+
event_data = sys.stdin.read()
|
|
75
|
+
if not event_data.strip():
|
|
76
|
+
return None
|
|
77
|
+
return json.loads(event_data)
|
|
78
|
+
except json.JSONDecodeError as e:
|
|
79
|
+
self.log_debug(f"Failed to parse event: {e}")
|
|
80
|
+
return None
|
|
81
|
+
except Exception as e:
|
|
82
|
+
self.log_debug(f"Error reading event: {e}")
|
|
83
|
+
return None
|
|
84
|
+
|
|
85
|
+
def continue_execution(
|
|
86
|
+
self, modified_input: Optional[Dict[str, Any]] = None
|
|
87
|
+
) -> None:
|
|
88
|
+
"""Continue execution with optional modified input."""
|
|
89
|
+
response = {"action": "continue"}
|
|
90
|
+
if modified_input is not None:
|
|
91
|
+
response["tool_input"] = modified_input
|
|
92
|
+
print(json.dumps(response))
|
|
93
|
+
|
|
94
|
+
def block_execution(self, message: str) -> None:
|
|
95
|
+
"""Block execution with a message."""
|
|
96
|
+
response = {"action": "block", "message": message}
|
|
97
|
+
print(json.dumps(response))
|
|
98
|
+
|
|
99
|
+
def modify_input(
|
|
100
|
+
self, tool_name: str, tool_input: Dict[str, Any], event: Dict[str, Any]
|
|
101
|
+
) -> Optional[Dict[str, Any]]:
|
|
102
|
+
"""
|
|
103
|
+
Modify tool input before execution.
|
|
104
|
+
|
|
105
|
+
Override this method in subclasses to implement custom logic.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
tool_name: Name of the tool being invoked
|
|
109
|
+
tool_input: Original tool input parameters
|
|
110
|
+
event: Full event data including session_id, cwd, etc.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
Modified tool input dict, or None to continue without modification
|
|
114
|
+
"""
|
|
115
|
+
# Default: no modification
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
def should_block(
|
|
119
|
+
self, tool_name: str, tool_input: Dict[str, Any], event: Dict[str, Any]
|
|
120
|
+
) -> tuple[bool, str]:
|
|
121
|
+
"""
|
|
122
|
+
Check if execution should be blocked.
|
|
123
|
+
|
|
124
|
+
Override this method in subclasses to implement validation logic.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
tool_name: Name of the tool being invoked
|
|
128
|
+
tool_input: Original tool input parameters
|
|
129
|
+
event: Full event data including session_id, cwd, etc.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Tuple of (should_block, reason)
|
|
133
|
+
"""
|
|
134
|
+
# Default: don't block
|
|
135
|
+
return False, ""
|
|
136
|
+
|
|
137
|
+
def run(self) -> None:
|
|
138
|
+
"""Main entry point for the hook."""
|
|
139
|
+
try:
|
|
140
|
+
# Read event from stdin
|
|
141
|
+
event = self.read_event()
|
|
142
|
+
if not event:
|
|
143
|
+
self.continue_execution()
|
|
144
|
+
return
|
|
145
|
+
|
|
146
|
+
tool_name = event.get("tool_name", "")
|
|
147
|
+
tool_input = event.get("tool_input", {})
|
|
148
|
+
|
|
149
|
+
self.log_debug(
|
|
150
|
+
f"Processing {tool_name} with input: {list(tool_input.keys())}"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# Check if execution should be blocked
|
|
154
|
+
should_block, reason = self.should_block(tool_name, tool_input, event)
|
|
155
|
+
if should_block:
|
|
156
|
+
self.log_debug(f"Blocking {tool_name}: {reason}")
|
|
157
|
+
self.block_execution(reason)
|
|
158
|
+
return
|
|
159
|
+
|
|
160
|
+
# Try to modify input
|
|
161
|
+
modified_input = self.modify_input(tool_name, tool_input, event)
|
|
162
|
+
if modified_input is not None:
|
|
163
|
+
self.log_debug(f"Modified {tool_name} input")
|
|
164
|
+
self.continue_execution(modified_input)
|
|
165
|
+
else:
|
|
166
|
+
self.log_debug(f"No modification for {tool_name}")
|
|
167
|
+
self.continue_execution()
|
|
168
|
+
|
|
169
|
+
except Exception as e:
|
|
170
|
+
self.log_debug(f"Hook error: {e}")
|
|
171
|
+
# Always continue on error to avoid blocking Claude
|
|
172
|
+
self.continue_execution()
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# ============================================================================
|
|
176
|
+
# Example Implementations
|
|
177
|
+
# ============================================================================
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class ContextInjectionHook(PreToolUseHook):
|
|
181
|
+
"""
|
|
182
|
+
Example: Auto-inject project context into Read/Edit tool calls.
|
|
183
|
+
|
|
184
|
+
This hook adds project-specific context as comments to file operations.
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
def __init__(self):
|
|
188
|
+
super().__init__()
|
|
189
|
+
self.project_context = self._load_project_context()
|
|
190
|
+
|
|
191
|
+
def _load_project_context(self) -> str:
|
|
192
|
+
"""Load project context from a file or environment."""
|
|
193
|
+
# Example: Load from .claude-context file
|
|
194
|
+
context_file = Path.cwd() / ".claude-context"
|
|
195
|
+
if context_file.exists():
|
|
196
|
+
return context_file.read_text()
|
|
197
|
+
return ""
|
|
198
|
+
|
|
199
|
+
def modify_input(
|
|
200
|
+
self, tool_name: str, tool_input: Dict[str, Any], event: Dict[str, Any]
|
|
201
|
+
) -> Optional[Dict[str, Any]]:
|
|
202
|
+
"""Inject context into Read operations."""
|
|
203
|
+
if tool_name == "Read" and self.project_context:
|
|
204
|
+
# Add context as a note (this is conceptual - actual implementation depends on use case)
|
|
205
|
+
modified = tool_input.copy()
|
|
206
|
+
# You could add context to a metadata field if the tool supports it
|
|
207
|
+
modified["_context"] = self.project_context[:200]
|
|
208
|
+
return modified
|
|
209
|
+
return None
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class SecurityGuardHook(PreToolUseHook):
|
|
213
|
+
"""
|
|
214
|
+
Example: Validate file paths before file operations.
|
|
215
|
+
|
|
216
|
+
This hook blocks operations on sensitive files or directories.
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
BLOCKED_PATHS = [
|
|
220
|
+
".env",
|
|
221
|
+
"credentials.json",
|
|
222
|
+
"secrets/",
|
|
223
|
+
".ssh/",
|
|
224
|
+
"id_rsa",
|
|
225
|
+
]
|
|
226
|
+
|
|
227
|
+
def should_block(
|
|
228
|
+
self, tool_name: str, tool_input: Dict[str, Any], event: Dict[str, Any]
|
|
229
|
+
) -> tuple[bool, str]:
|
|
230
|
+
"""Block operations on sensitive files."""
|
|
231
|
+
if tool_name in ["Write", "Edit", "Read"]:
|
|
232
|
+
file_path = tool_input.get("file_path", "")
|
|
233
|
+
if any(blocked in file_path for blocked in self.BLOCKED_PATHS):
|
|
234
|
+
return True, f"Access to sensitive file blocked: {file_path}"
|
|
235
|
+
return False, ""
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class LoggingHook(PreToolUseHook):
|
|
239
|
+
"""
|
|
240
|
+
Example: Log all tool invocations before execution.
|
|
241
|
+
|
|
242
|
+
This hook logs tool calls to a file for debugging and audit purposes.
|
|
243
|
+
"""
|
|
244
|
+
|
|
245
|
+
def __init__(self):
|
|
246
|
+
super().__init__()
|
|
247
|
+
self.log_file = Path.home() / ".claude-mpm" / "tool-calls.log"
|
|
248
|
+
self.log_file.parent.mkdir(exist_ok=True)
|
|
249
|
+
|
|
250
|
+
def modify_input(
|
|
251
|
+
self, tool_name: str, tool_input: Dict[str, Any], event: Dict[str, Any]
|
|
252
|
+
) -> Optional[Dict[str, Any]]:
|
|
253
|
+
"""Log the tool call."""
|
|
254
|
+
try:
|
|
255
|
+
from datetime import datetime, timezone
|
|
256
|
+
|
|
257
|
+
log_entry = {
|
|
258
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
259
|
+
"tool_name": tool_name,
|
|
260
|
+
"session_id": event.get("session_id", ""),
|
|
261
|
+
"cwd": event.get("cwd", ""),
|
|
262
|
+
"parameters": list(tool_input.keys()),
|
|
263
|
+
}
|
|
264
|
+
with self.log_file.open("a") as f:
|
|
265
|
+
f.write(json.dumps(log_entry) + "\n")
|
|
266
|
+
except Exception as e:
|
|
267
|
+
self.log_debug(f"Failed to log tool call: {e}")
|
|
268
|
+
|
|
269
|
+
# Don't modify input, just log
|
|
270
|
+
return None
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class ParameterEnhancementHook(PreToolUseHook):
|
|
274
|
+
"""
|
|
275
|
+
Example: Add default parameters to tool calls.
|
|
276
|
+
|
|
277
|
+
This hook adds default values to tool parameters if not provided.
|
|
278
|
+
"""
|
|
279
|
+
|
|
280
|
+
def modify_input(
|
|
281
|
+
self, tool_name: str, tool_input: Dict[str, Any], event: Dict[str, Any]
|
|
282
|
+
) -> Optional[Dict[str, Any]]:
|
|
283
|
+
"""Add default parameters."""
|
|
284
|
+
modified = tool_input.copy()
|
|
285
|
+
|
|
286
|
+
if tool_name == "Bash":
|
|
287
|
+
# Add default timeout if not specified
|
|
288
|
+
if "timeout" not in modified:
|
|
289
|
+
modified["timeout"] = 30000 # 30 seconds
|
|
290
|
+
return modified
|
|
291
|
+
|
|
292
|
+
elif tool_name == "Grep":
|
|
293
|
+
# Add line numbers by default
|
|
294
|
+
if "-n" not in modified:
|
|
295
|
+
modified["-n"] = True
|
|
296
|
+
return modified
|
|
297
|
+
|
|
298
|
+
return None
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
# ============================================================================
|
|
302
|
+
# Main Entry Point
|
|
303
|
+
# ============================================================================
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def main():
|
|
307
|
+
"""Main entry point - choose which hook implementation to use."""
|
|
308
|
+
# Select which hook implementation to use
|
|
309
|
+
# Uncomment the one you want to use:
|
|
310
|
+
|
|
311
|
+
# hook = ContextInjectionHook()
|
|
312
|
+
# hook = SecurityGuardHook()
|
|
313
|
+
# hook = LoggingHook()
|
|
314
|
+
# hook = ParameterEnhancementHook()
|
|
315
|
+
|
|
316
|
+
# Default: use base hook (no modification)
|
|
317
|
+
hook = PreToolUseHook()
|
|
318
|
+
|
|
319
|
+
hook.run()
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
if __name__ == "__main__":
|
|
323
|
+
main()
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""Git repository model for agent sources."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
7
|
+
from urllib.parse import urlparse
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class GitRepository:
|
|
12
|
+
"""Represents a Git repository configuration for agent sources.
|
|
13
|
+
|
|
14
|
+
This model tracks Git repositories that contain agent markdown files.
|
|
15
|
+
Repositories are cached locally and synced using ETag-based HTTP caching.
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
url: Full GitHub repository URL (e.g., https://github.com/owner/repo)
|
|
19
|
+
subdirectory: Optional subdirectory within repository (e.g., "agents/backend")
|
|
20
|
+
enabled: Whether this repository should be synced
|
|
21
|
+
priority: Priority for agent resolution (lower = higher precedence)
|
|
22
|
+
last_synced: Timestamp of last successful sync
|
|
23
|
+
etag: HTTP ETag from last sync for incremental updates
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
url: str
|
|
27
|
+
subdirectory: Optional[str] = None
|
|
28
|
+
enabled: bool = True
|
|
29
|
+
priority: int = 100
|
|
30
|
+
last_synced: Optional[datetime] = None
|
|
31
|
+
etag: Optional[str] = None
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def cache_path(self) -> Path:
|
|
35
|
+
"""Return cache directory path for this repository.
|
|
36
|
+
|
|
37
|
+
Cache structure: ~/.claude-mpm/cache/remote-agents/{owner}/{repo}/{subdirectory}/
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Absolute path to cache directory for this repository
|
|
41
|
+
|
|
42
|
+
Example:
|
|
43
|
+
>>> repo = GitRepository(
|
|
44
|
+
... url="https://github.com/bobmatnyc/claude-mpm-agents",
|
|
45
|
+
... subdirectory="agents"
|
|
46
|
+
... )
|
|
47
|
+
>>> repo.cache_path
|
|
48
|
+
Path('/Users/user/.claude-mpm/cache/remote-agents/bobmatnyc/claude-mpm-agents/agents')
|
|
49
|
+
"""
|
|
50
|
+
home = Path.home()
|
|
51
|
+
base_cache = home / ".claude-mpm" / "cache" / "remote-agents"
|
|
52
|
+
|
|
53
|
+
# Extract owner and repo from URL
|
|
54
|
+
owner, repo = self._parse_github_url(self.url)
|
|
55
|
+
|
|
56
|
+
# Build cache path: base/owner/repo/subdirectory
|
|
57
|
+
cache_path = base_cache / owner / repo
|
|
58
|
+
|
|
59
|
+
if self.subdirectory:
|
|
60
|
+
# Normalize subdirectory path (remove leading/trailing slashes)
|
|
61
|
+
normalized_subdir = self.subdirectory.strip("/")
|
|
62
|
+
cache_path = cache_path / normalized_subdir
|
|
63
|
+
|
|
64
|
+
return cache_path
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def identifier(self) -> str:
|
|
68
|
+
"""Return unique identifier for this repository.
|
|
69
|
+
|
|
70
|
+
Format: {owner}/{repo}/{subdirectory} or {owner}/{repo}
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Unique identifier string
|
|
74
|
+
|
|
75
|
+
Example:
|
|
76
|
+
>>> repo = GitRepository(
|
|
77
|
+
... url="https://github.com/owner/repo",
|
|
78
|
+
... subdirectory="agents"
|
|
79
|
+
... )
|
|
80
|
+
>>> repo.identifier
|
|
81
|
+
'owner/repo/agents'
|
|
82
|
+
"""
|
|
83
|
+
owner, repo = self._parse_github_url(self.url)
|
|
84
|
+
base_id = f"{owner}/{repo}"
|
|
85
|
+
|
|
86
|
+
if self.subdirectory:
|
|
87
|
+
normalized_subdir = self.subdirectory.strip("/")
|
|
88
|
+
return f"{base_id}/{normalized_subdir}"
|
|
89
|
+
|
|
90
|
+
return base_id
|
|
91
|
+
|
|
92
|
+
def validate(self) -> list[str]:
|
|
93
|
+
"""Validate repository configuration.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
List of validation error messages (empty if valid)
|
|
97
|
+
|
|
98
|
+
Validation checks:
|
|
99
|
+
- URL is not empty
|
|
100
|
+
- URL is valid HTTP/HTTPS format
|
|
101
|
+
- URL is a GitHub repository URL
|
|
102
|
+
- Priority is non-negative
|
|
103
|
+
- Priority is reasonable (<= 1000, warning only)
|
|
104
|
+
- Subdirectory is relative path (not absolute)
|
|
105
|
+
"""
|
|
106
|
+
errors = []
|
|
107
|
+
|
|
108
|
+
# Validate URL
|
|
109
|
+
if not self.url or not self.url.strip():
|
|
110
|
+
errors.append("URL cannot be empty")
|
|
111
|
+
return errors # Can't continue validation without URL
|
|
112
|
+
|
|
113
|
+
# Check URL format
|
|
114
|
+
try:
|
|
115
|
+
parsed = urlparse(self.url)
|
|
116
|
+
|
|
117
|
+
# Must be HTTP or HTTPS
|
|
118
|
+
if parsed.scheme not in ("http", "https"):
|
|
119
|
+
errors.append(
|
|
120
|
+
f"URL must use http:// or https:// protocol, got: {parsed.scheme}"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Must be GitHub (for now)
|
|
124
|
+
if not parsed.netloc.endswith("github.com"):
|
|
125
|
+
errors.append(f"URL must be a GitHub repository, got: {parsed.netloc}")
|
|
126
|
+
|
|
127
|
+
# Should have owner/repo path structure
|
|
128
|
+
path_parts = [p for p in parsed.path.strip("/").split("/") if p]
|
|
129
|
+
if len(path_parts) < 2:
|
|
130
|
+
errors.append(f"URL must include owner/repo path, got: {parsed.path}")
|
|
131
|
+
|
|
132
|
+
except Exception as e:
|
|
133
|
+
errors.append(f"Invalid URL format: {e}")
|
|
134
|
+
|
|
135
|
+
# Validate priority
|
|
136
|
+
if self.priority < 0:
|
|
137
|
+
errors.append("Priority must be non-negative (0 or greater)")
|
|
138
|
+
|
|
139
|
+
if self.priority > 1000:
|
|
140
|
+
errors.append(
|
|
141
|
+
f"Priority {self.priority} is unusually high (recommended: 0-1000). "
|
|
142
|
+
"Lower priority numbers have higher precedence."
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Validate subdirectory
|
|
146
|
+
if self.subdirectory:
|
|
147
|
+
# Must be relative path
|
|
148
|
+
if Path(self.subdirectory).is_absolute():
|
|
149
|
+
errors.append(
|
|
150
|
+
f"Subdirectory must be a relative path, got absolute: {self.subdirectory}"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# Should not start with slash
|
|
154
|
+
if self.subdirectory.startswith("/"):
|
|
155
|
+
errors.append(
|
|
156
|
+
f"Subdirectory should not start with '/', got: {self.subdirectory}"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return errors
|
|
160
|
+
|
|
161
|
+
def _parse_github_url(self, url: str) -> tuple[str, str]:
|
|
162
|
+
"""Parse GitHub URL to extract owner and repository name.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
url: GitHub repository URL
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
Tuple of (owner, repository_name)
|
|
169
|
+
|
|
170
|
+
Example:
|
|
171
|
+
>>> repo = GitRepository(url="https://github.com/owner/repo")
|
|
172
|
+
>>> repo._parse_github_url(repo.url)
|
|
173
|
+
('owner', 'repo')
|
|
174
|
+
"""
|
|
175
|
+
# Remove .git suffix if present
|
|
176
|
+
url = url.rstrip("/")
|
|
177
|
+
if url.endswith(".git"):
|
|
178
|
+
url = url[:-4]
|
|
179
|
+
|
|
180
|
+
# Parse URL
|
|
181
|
+
parsed = urlparse(url)
|
|
182
|
+
path_parts = [p for p in parsed.path.strip("/").split("/") if p]
|
|
183
|
+
|
|
184
|
+
if len(path_parts) >= 2:
|
|
185
|
+
owner = path_parts[0]
|
|
186
|
+
repo = path_parts[1]
|
|
187
|
+
return owner, repo
|
|
188
|
+
|
|
189
|
+
# Fallback: Use URL as-is if parsing fails
|
|
190
|
+
# This will be caught by validation
|
|
191
|
+
return "unknown", "unknown"
|
|
192
|
+
|
|
193
|
+
def __repr__(self) -> str:
|
|
194
|
+
"""Return string representation of repository."""
|
|
195
|
+
return (
|
|
196
|
+
f"GitRepository(identifier='{self.identifier}', "
|
|
197
|
+
f"priority={self.priority}, enabled={self.enabled})"
|
|
198
|
+
)
|
|
@@ -89,7 +89,7 @@ fi
|
|
|
89
89
|
# STRATEGY:
|
|
90
90
|
# This function implements a fallback chain to find Python with claude-mpm dependencies:
|
|
91
91
|
# 1. Project-specific virtual environments (venv, .venv)
|
|
92
|
-
# 2. Currently active virtual environment ($VIRTUAL_ENV)
|
|
92
|
+
# 2. Currently active virtual environment ($VIRTUAL_ENV)
|
|
93
93
|
# 3. System python3 (may lack dependencies)
|
|
94
94
|
# 4. System python (last resort)
|
|
95
95
|
#
|
|
@@ -121,7 +121,7 @@ find_python_command() {
|
|
|
121
121
|
return
|
|
122
122
|
fi
|
|
123
123
|
fi
|
|
124
|
-
|
|
124
|
+
|
|
125
125
|
# 2. Check for project-local virtual environment (common in development)
|
|
126
126
|
if [ -f "$CLAUDE_MPM_ROOT/venv/bin/activate" ]; then
|
|
127
127
|
source "$CLAUDE_MPM_ROOT/venv/bin/activate"
|
|
@@ -152,7 +152,7 @@ if [[ "$SCRIPT_DIR" == *"/.local/pipx/venvs/claude-mpm/"* ]]; then
|
|
|
152
152
|
elif [ -d "$CLAUDE_MPM_ROOT/src" ]; then
|
|
153
153
|
# Development install - add src to PYTHONPATH
|
|
154
154
|
export PYTHONPATH="$CLAUDE_MPM_ROOT/src:$PYTHONPATH"
|
|
155
|
-
|
|
155
|
+
|
|
156
156
|
if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
|
|
157
157
|
echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Development environment detected" >> /tmp/claude-mpm-hook.log
|
|
158
158
|
fi
|
|
@@ -51,7 +51,9 @@ if __name__ == "__main__":
|
|
|
51
51
|
|
|
52
52
|
# Initialize aggregator
|
|
53
53
|
aggregator = EventAggregator(
|
|
54
|
-
host="localhost",
|
|
54
|
+
host="localhost",
|
|
55
|
+
port=dashboard_port,
|
|
56
|
+
save_dir=None, # Will use config value
|
|
55
57
|
)
|
|
56
58
|
|
|
57
59
|
# Set up signal handlers
|
|
@@ -8,12 +8,13 @@ This service provides comprehensive agent lifecycle management including:
|
|
|
8
8
|
- Integration with deployment services
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
import json
|
|
12
11
|
import re
|
|
13
12
|
from datetime import datetime, timezone
|
|
14
13
|
from pathlib import Path
|
|
15
14
|
from typing import Any, ClassVar, Dict, List, Optional, Tuple
|
|
16
15
|
|
|
16
|
+
import yaml
|
|
17
|
+
|
|
17
18
|
from claude_mpm.core.exceptions import AgentDeploymentError
|
|
18
19
|
from claude_mpm.core.logging_config import get_logger
|
|
19
20
|
|
|
@@ -285,10 +286,15 @@ class AgentBuilderService:
|
|
|
285
286
|
if not self.templates_dir.exists():
|
|
286
287
|
return templates
|
|
287
288
|
|
|
288
|
-
|
|
289
|
+
# Agent templates migrated to Markdown with YAML frontmatter (v4.26.0+)
|
|
290
|
+
for template_file in self.templates_dir.glob("*.md"):
|
|
289
291
|
try:
|
|
290
|
-
|
|
291
|
-
|
|
292
|
+
# Read markdown content and extract YAML frontmatter
|
|
293
|
+
content = template_file.read_text()
|
|
294
|
+
config = self._extract_yaml_frontmatter(content)
|
|
295
|
+
if not config:
|
|
296
|
+
self.logger.warning(f"No YAML frontmatter in {template_file.name}")
|
|
297
|
+
continue
|
|
292
298
|
|
|
293
299
|
# Use filename stem as ID if not specified in config
|
|
294
300
|
template_id = config.get("id") or template_file.stem
|
|
@@ -308,6 +314,30 @@ class AgentBuilderService:
|
|
|
308
314
|
|
|
309
315
|
return templates
|
|
310
316
|
|
|
317
|
+
def _extract_yaml_frontmatter(self, content: str) -> Optional[Dict[str, Any]]:
|
|
318
|
+
"""
|
|
319
|
+
Extract and parse YAML frontmatter from markdown content.
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
content: File content to parse
|
|
323
|
+
|
|
324
|
+
Returns:
|
|
325
|
+
Parsed YAML frontmatter as dict, or None if not found/invalid
|
|
326
|
+
"""
|
|
327
|
+
if not content.strip().startswith("---"):
|
|
328
|
+
return None
|
|
329
|
+
|
|
330
|
+
# Split on --- delimiters
|
|
331
|
+
parts = content.split("---", 2)
|
|
332
|
+
if len(parts) < 3:
|
|
333
|
+
return None
|
|
334
|
+
|
|
335
|
+
try:
|
|
336
|
+
return yaml.safe_load(parts[1])
|
|
337
|
+
except yaml.YAMLError as e:
|
|
338
|
+
self.logger.warning(f"Failed to parse YAML frontmatter: {e}")
|
|
339
|
+
return None
|
|
340
|
+
|
|
311
341
|
def _validate_agent_id(self, agent_id: str) -> None:
|
|
312
342
|
"""Validate agent ID format.
|
|
313
343
|
|
|
@@ -371,16 +401,22 @@ class AgentBuilderService:
|
|
|
371
401
|
if template_id in self._template_cache:
|
|
372
402
|
return self._template_cache[template_id].copy()
|
|
373
403
|
|
|
374
|
-
|
|
404
|
+
# Agent templates migrated to Markdown with YAML frontmatter (v4.26.0+)
|
|
405
|
+
template_file = self.templates_dir / f"{template_id}.md"
|
|
375
406
|
|
|
376
407
|
if not template_file.exists():
|
|
377
408
|
raise AgentDeploymentError(f"Template '{template_id}' not found")
|
|
378
409
|
|
|
379
410
|
try:
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
411
|
+
# Read markdown content and extract YAML frontmatter
|
|
412
|
+
content = template_file.read_text()
|
|
413
|
+
config = self._extract_yaml_frontmatter(content)
|
|
414
|
+
if not config:
|
|
415
|
+
raise AgentDeploymentError(
|
|
416
|
+
f"No YAML frontmatter in template '{template_id}'"
|
|
417
|
+
)
|
|
418
|
+
self._template_cache[template_id] = config
|
|
419
|
+
return config.copy()
|
|
384
420
|
except Exception as e:
|
|
385
421
|
raise AgentDeploymentError(
|
|
386
422
|
f"Failed to load template '{template_id}': {e}"
|