claude-mpm 5.4.41__py3-none-any.whl → 5.6.72__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/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
- claude_mpm/agents/PM_INSTRUCTIONS.md +161 -298
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/auth/__init__.py +35 -0
- claude_mpm/auth/callback_server.py +328 -0
- claude_mpm/auth/models.py +104 -0
- claude_mpm/auth/oauth_manager.py +266 -0
- claude_mpm/auth/providers/__init__.py +12 -0
- claude_mpm/auth/providers/base.py +165 -0
- claude_mpm/auth/providers/google.py +261 -0
- claude_mpm/auth/token_storage.py +252 -0
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agents.py +2 -4
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/configure.py +620 -21
- claude_mpm/cli/commands/configure_agent_display.py +3 -1
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/mcp.py +29 -17
- claude_mpm/cli/commands/mcp_command_router.py +39 -0
- claude_mpm/cli/commands/mcp_service_commands.py +304 -0
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +15 -8
- claude_mpm/cli/commands/oauth.py +481 -0
- claude_mpm/cli/commands/profile.py +9 -10
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +182 -32
- claude_mpm/cli/executor.py +129 -16
- claude_mpm/cli/helpers.py +1 -1
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +30 -50
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/base_parser.py +89 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/mcp_parser.py +79 -0
- claude_mpm/cli/parsers/oauth_parser.py +165 -0
- claude_mpm/cli/parsers/profile_parser.py +0 -1
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +2 -3
- claude_mpm/cli/startup.py +662 -524
- claude_mpm/cli/startup_display.py +76 -7
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +78 -0
- claude_mpm/commander/adapters/__init__.py +60 -0
- claude_mpm/commander/adapters/auggie.py +260 -0
- claude_mpm/commander/adapters/base.py +288 -0
- claude_mpm/commander/adapters/claude_code.py +392 -0
- claude_mpm/commander/adapters/codex.py +237 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/adapters/example_usage.py +310 -0
- claude_mpm/commander/adapters/mpm.py +389 -0
- claude_mpm/commander/adapters/registry.py +204 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +121 -0
- claude_mpm/commander/api/errors.py +133 -0
- claude_mpm/commander/api/routes/__init__.py +8 -0
- claude_mpm/commander/api/routes/events.py +184 -0
- claude_mpm/commander/api/routes/inbox.py +171 -0
- claude_mpm/commander/api/routes/messages.py +148 -0
- claude_mpm/commander/api/routes/projects.py +271 -0
- claude_mpm/commander/api/routes/sessions.py +226 -0
- claude_mpm/commander/api/routes/work.py +296 -0
- claude_mpm/commander/api/schemas.py +186 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +149 -0
- claude_mpm/commander/chat/commands.py +122 -0
- claude_mpm/commander/chat/repl.py +1821 -0
- claude_mpm/commander/config.py +51 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/core/__init__.py +10 -0
- claude_mpm/commander/core/block_manager.py +325 -0
- claude_mpm/commander/core/response_manager.py +323 -0
- claude_mpm/commander/daemon.py +603 -0
- claude_mpm/commander/env_loader.py +59 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +392 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +233 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +57 -0
- claude_mpm/commander/git/__init__.py +5 -0
- claude_mpm/commander/git/worktree_manager.py +212 -0
- claude_mpm/commander/inbox/__init__.py +16 -0
- claude_mpm/commander/inbox/dedup.py +128 -0
- claude_mpm/commander/inbox/inbox.py +224 -0
- claude_mpm/commander/inbox/models.py +70 -0
- claude_mpm/commander/instance_manager.py +865 -0
- claude_mpm/commander/llm/__init__.py +6 -0
- claude_mpm/commander/llm/openrouter_client.py +167 -0
- claude_mpm/commander/llm/summarizer.py +70 -0
- claude_mpm/commander/memory/__init__.py +45 -0
- claude_mpm/commander/memory/compression.py +347 -0
- claude_mpm/commander/memory/embeddings.py +230 -0
- claude_mpm/commander/memory/entities.py +310 -0
- claude_mpm/commander/memory/example_usage.py +290 -0
- claude_mpm/commander/memory/integration.py +325 -0
- claude_mpm/commander/memory/search.py +381 -0
- claude_mpm/commander/memory/store.py +657 -0
- claude_mpm/commander/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +127 -0
- claude_mpm/commander/models/project.py +162 -0
- claude_mpm/commander/models/work.py +214 -0
- claude_mpm/commander/parsing/__init__.py +20 -0
- claude_mpm/commander/parsing/extractor.py +132 -0
- claude_mpm/commander/parsing/output_parser.py +270 -0
- claude_mpm/commander/parsing/patterns.py +100 -0
- claude_mpm/commander/persistence/__init__.py +11 -0
- claude_mpm/commander/persistence/event_store.py +274 -0
- claude_mpm/commander/persistence/state_store.py +403 -0
- claude_mpm/commander/persistence/work_store.py +164 -0
- claude_mpm/commander/polling/__init__.py +13 -0
- claude_mpm/commander/polling/event_detector.py +104 -0
- claude_mpm/commander/polling/output_buffer.py +49 -0
- claude_mpm/commander/polling/output_poller.py +153 -0
- claude_mpm/commander/project_session.py +268 -0
- claude_mpm/commander/proxy/__init__.py +12 -0
- claude_mpm/commander/proxy/formatter.py +89 -0
- claude_mpm/commander/proxy/output_handler.py +191 -0
- claude_mpm/commander/proxy/relay.py +155 -0
- claude_mpm/commander/registry.py +410 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +346 -0
- claude_mpm/commander/session/__init__.py +6 -0
- claude_mpm/commander/session/context.py +81 -0
- claude_mpm/commander/session/manager.py +59 -0
- claude_mpm/commander/tmux_orchestrator.py +362 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +207 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +241 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +8 -0
- claude_mpm/commands/mpm-doctor.md +8 -0
- claude_mpm/commands/mpm-help.md +8 -0
- claude_mpm/commands/mpm-init.md +8 -0
- claude_mpm/commands/mpm-monitor.md +8 -0
- claude_mpm/commands/mpm-organize.md +8 -0
- claude_mpm/commands/mpm-postmortem.md +8 -0
- claude_mpm/commands/mpm-session-resume.md +9 -1
- claude_mpm/commands/mpm-status.md +8 -0
- claude_mpm/commands/mpm-ticket-view.md +8 -0
- claude_mpm/commands/mpm-version.md +8 -0
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/config/skill_sources.py +16 -0
- claude_mpm/constants.py +6 -0
- claude_mpm/core/claude_runner.py +154 -2
- claude_mpm/core/config.py +35 -22
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/hook_manager.py +53 -4
- claude_mpm/core/interactive_session.py +12 -11
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +39 -13
- claude_mpm/core/network_config.py +148 -0
- claude_mpm/core/oneshot_session.py +7 -6
- claude_mpm/core/optimized_startup.py +3 -1
- claude_mpm/core/output_style_manager.py +66 -18
- claude_mpm/core/shared/config_loader.py +3 -1
- claude_mpm/core/socketio_pool.py +47 -15
- claude_mpm/core/unified_config.py +54 -8
- claude_mpm/core/unified_paths.py +95 -90
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → DR8nis88.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.RgBboRvH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
- claude_mpm/dashboard/static/svelte-build/index.html +11 -11
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
- claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +466 -136
- claude_mpm/hooks/claude_hooks/hook_handler.py +204 -104
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +291 -59
- claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
- claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
- claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
- claude_mpm/hooks/claude_hooks/services/container.py +326 -0
- claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
- claude_mpm/hooks/kuzu_memory_hook.py +5 -5
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
- claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
- claude_mpm/init.py +224 -4
- claude_mpm/mcp/__init__.py +9 -0
- claude_mpm/mcp/google_workspace_server.py +610 -0
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/cache_git_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -1
- claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
- claude_mpm/services/agents/deployment/agent_template_builder.py +37 -17
- claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +36 -8
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +50 -26
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/git_source_manager.py +21 -2
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
- claude_mpm/services/agents/sources/git_source_sync_service.py +116 -5
- claude_mpm/services/agents/startup_sync.py +5 -2
- claude_mpm/services/cli/__init__.py +3 -0
- claude_mpm/services/cli/incremental_pause_manager.py +561 -0
- claude_mpm/services/cli/session_resume_helper.py +10 -2
- claude_mpm/services/command_deployment_service.py +44 -26
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
- claude_mpm/services/diagnostics/models.py +14 -1
- claude_mpm/services/event_log.py +325 -0
- claude_mpm/services/hook_installer_service.py +77 -8
- claude_mpm/services/infrastructure/__init__.py +4 -0
- claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
- claude_mpm/services/mcp_config_manager.py +99 -19
- claude_mpm/services/mcp_service_registry.py +294 -0
- claude_mpm/services/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +8 -3
- claude_mpm/services/monitor/server.py +111 -16
- claude_mpm/services/pm_skills_deployer.py +302 -94
- claude_mpm/services/profile_manager.py +10 -4
- claude_mpm/services/skills/git_skill_source_manager.py +192 -29
- claude_mpm/services/skills/selective_skill_deployer.py +211 -46
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +192 -70
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/skills/__init__.py +2 -1
- 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/git-worktrees.md +317 -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/stacked-prs.md +251 -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/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/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -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/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/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/pm/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
- claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
- claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
- claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
- claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
- claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
- claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
- claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
- claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
- claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
- claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
- claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -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 +112 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -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/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -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/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -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/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +29 -23
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/utils/agent_dependency_loader.py +103 -4
- claude_mpm/utils/robust_installer.py +45 -24
- claude_mpm-5.6.72.dist-info/METADATA +416 -0
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/RECORD +477 -159
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/WHEEL +1 -1
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/entry_points.txt +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- claude_mpm-5.4.41.dist-info/METADATA +0 -998
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/top_level.txt +0 -0
|
@@ -132,7 +132,9 @@ class AgentDisplay:
|
|
|
132
132
|
self.console.print(table)
|
|
133
133
|
|
|
134
134
|
# Display summary count
|
|
135
|
-
self.console.print(
|
|
135
|
+
self.console.print(
|
|
136
|
+
f"\n📊 Agents: {installed_count} Installed / {len(agents)} Total"
|
|
137
|
+
)
|
|
136
138
|
|
|
137
139
|
def display_agents_with_pending_states(self, agents: List[AgentConfig]) -> None:
|
|
138
140
|
"""Display agents table with pending state indicators.
|
|
@@ -57,33 +57,33 @@ def list_errors(format, hook_type):
|
|
|
57
57
|
|
|
58
58
|
if not errors:
|
|
59
59
|
if hook_type:
|
|
60
|
-
click.echo(f"No errors recorded for hook type: {hook_type}")
|
|
60
|
+
click.echo(f"No errors recorded for hook type: {hook_type}", err=True)
|
|
61
61
|
else:
|
|
62
|
-
click.echo("No errors recorded. Hook system is healthy! ✅")
|
|
62
|
+
click.echo("No errors recorded. Hook system is healthy! ✅", err=True)
|
|
63
63
|
return
|
|
64
64
|
|
|
65
65
|
if format == "json":
|
|
66
66
|
# JSON output
|
|
67
|
-
click.echo(json.dumps(errors, indent=2))
|
|
67
|
+
click.echo(json.dumps(errors, indent=2), err=True)
|
|
68
68
|
else:
|
|
69
69
|
# Table output
|
|
70
|
-
click.echo("\n" + "=" * 80)
|
|
71
|
-
click.echo("Hook Error Memory Report")
|
|
72
|
-
click.echo("=" * 80)
|
|
70
|
+
click.echo("\n" + "=" * 80, err=True)
|
|
71
|
+
click.echo("Hook Error Memory Report", err=True)
|
|
72
|
+
click.echo("=" * 80, err=True)
|
|
73
73
|
|
|
74
74
|
for key, data in errors.items():
|
|
75
|
-
click.echo(f"\n🔴 Error: {data['type']}")
|
|
76
|
-
click.echo(f" Hook Type: {data['hook_type']}")
|
|
77
|
-
click.echo(f" Details: {data['details']}")
|
|
78
|
-
click.echo(f" Match: {data['match']}")
|
|
79
|
-
click.echo(f" Count: {data['count']} occurrences")
|
|
80
|
-
click.echo(f" First Seen: {data['first_seen']}")
|
|
81
|
-
click.echo(f" Last Seen: {data['last_seen']}")
|
|
75
|
+
click.echo(f"\n🔴 Error: {data['type']}", err=True)
|
|
76
|
+
click.echo(f" Hook Type: {data['hook_type']}", err=True)
|
|
77
|
+
click.echo(f" Details: {data['details']}", err=True)
|
|
78
|
+
click.echo(f" Match: {data['match']}", err=True)
|
|
79
|
+
click.echo(f" Count: {data['count']} occurrences", err=True)
|
|
80
|
+
click.echo(f" First Seen: {data['first_seen']}", err=True)
|
|
81
|
+
click.echo(f" Last Seen: {data['last_seen']}", err=True)
|
|
82
82
|
|
|
83
|
-
click.echo("\n" + "=" * 80)
|
|
84
|
-
click.echo(f"Total unique errors: {len(errors)}")
|
|
85
|
-
click.echo(f"Memory file: {error_memory.memory_file}")
|
|
86
|
-
click.echo("\nTo clear errors: claude-mpm hook-errors clear")
|
|
83
|
+
click.echo("\n" + "=" * 80, err=True)
|
|
84
|
+
click.echo(f"Total unique errors: {len(errors)}", err=True)
|
|
85
|
+
click.echo(f"Memory file: {error_memory.memory_file}", err=True)
|
|
86
|
+
click.echo("\nTo clear errors: claude-mpm hook-errors clear", err=True)
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
@hook_errors_group.command(name="summary")
|
|
@@ -99,28 +99,28 @@ def show_summary():
|
|
|
99
99
|
summary = error_memory.get_error_summary()
|
|
100
100
|
|
|
101
101
|
if summary["total_errors"] == 0:
|
|
102
|
-
click.echo("No errors recorded. Hook system is healthy! ✅")
|
|
102
|
+
click.echo("No errors recorded. Hook system is healthy! ✅", err=True)
|
|
103
103
|
return
|
|
104
104
|
|
|
105
|
-
click.echo("\n" + "=" * 80)
|
|
106
|
-
click.echo("Hook Error Summary")
|
|
107
|
-
click.echo("=" * 80)
|
|
108
|
-
click.echo("\n📊 Statistics:")
|
|
109
|
-
click.echo(f" Total Errors: {summary['total_errors']}")
|
|
110
|
-
click.echo(f" Unique Errors: {summary['unique_errors']}")
|
|
105
|
+
click.echo("\n" + "=" * 80, err=True)
|
|
106
|
+
click.echo("Hook Error Summary", err=True)
|
|
107
|
+
click.echo("=" * 80, err=True)
|
|
108
|
+
click.echo("\n📊 Statistics:", err=True)
|
|
109
|
+
click.echo(f" Total Errors: {summary['total_errors']}", err=True)
|
|
110
|
+
click.echo(f" Unique Errors: {summary['unique_errors']}", err=True)
|
|
111
111
|
|
|
112
112
|
if summary["errors_by_type"]:
|
|
113
|
-
click.echo("\n🔍 Errors by Type:")
|
|
113
|
+
click.echo("\n🔍 Errors by Type:", err=True)
|
|
114
114
|
for error_type, count in summary["errors_by_type"].items():
|
|
115
|
-
click.echo(f" {error_type}: {count}")
|
|
115
|
+
click.echo(f" {error_type}: {count}", err=True)
|
|
116
116
|
|
|
117
117
|
if summary["errors_by_hook"]:
|
|
118
|
-
click.echo("\n🎣 Errors by Hook Type:")
|
|
118
|
+
click.echo("\n🎣 Errors by Hook Type:", err=True)
|
|
119
119
|
for hook_type, count in summary["errors_by_hook"].items():
|
|
120
|
-
click.echo(f" {hook_type}: {count}")
|
|
120
|
+
click.echo(f" {hook_type}: {count}", err=True)
|
|
121
121
|
|
|
122
|
-
click.echo(f"\n📁 Memory File: {summary['memory_file']}")
|
|
123
|
-
click.echo("\nFor detailed list: claude-mpm hook-errors list")
|
|
122
|
+
click.echo(f"\n📁 Memory File: {summary['memory_file']}", err=True)
|
|
123
|
+
click.echo("\nFor detailed list: claude-mpm hook-errors list", err=True)
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
@hook_errors_group.command(name="clear")
|
|
@@ -158,21 +158,21 @@ def clear_errors(hook_type, yes):
|
|
|
158
158
|
scope = "all hook types"
|
|
159
159
|
|
|
160
160
|
if count == 0:
|
|
161
|
-
click.echo(f"No errors to clear {scope}.")
|
|
161
|
+
click.echo(f"No errors to clear {scope}.", err=True)
|
|
162
162
|
return
|
|
163
163
|
|
|
164
164
|
# Confirm if not using -y flag
|
|
165
165
|
if not yes:
|
|
166
166
|
message = f"Clear {count} error(s) {scope}?"
|
|
167
167
|
if not click.confirm(message):
|
|
168
|
-
click.echo("Cancelled.")
|
|
168
|
+
click.echo("Cancelled.", err=True)
|
|
169
169
|
return
|
|
170
170
|
|
|
171
171
|
# Clear errors
|
|
172
172
|
error_memory.clear_errors(hook_type)
|
|
173
173
|
|
|
174
|
-
click.echo(f"✅ Cleared {count} error(s) {scope}.")
|
|
175
|
-
click.echo("\nHooks will be retried on next execution.")
|
|
174
|
+
click.echo(f"✅ Cleared {count} error(s) {scope}.", err=True)
|
|
175
|
+
click.echo("\nHooks will be retried on next execution.", err=True)
|
|
176
176
|
|
|
177
177
|
|
|
178
178
|
@hook_errors_group.command(name="diagnose")
|
|
@@ -201,19 +201,19 @@ def diagnose_errors(hook_type):
|
|
|
201
201
|
|
|
202
202
|
if not errors:
|
|
203
203
|
if hook_type:
|
|
204
|
-
click.echo(f"No errors to diagnose for hook type: {hook_type}")
|
|
204
|
+
click.echo(f"No errors to diagnose for hook type: {hook_type}", err=True)
|
|
205
205
|
else:
|
|
206
|
-
click.echo("No errors to diagnose. Hook system is healthy! ✅")
|
|
206
|
+
click.echo("No errors to diagnose. Hook system is healthy! ✅", err=True)
|
|
207
207
|
return
|
|
208
208
|
|
|
209
|
-
click.echo("\n" + "=" * 80)
|
|
210
|
-
click.echo("Hook Error Diagnostics")
|
|
211
|
-
click.echo("=" * 80)
|
|
209
|
+
click.echo("\n" + "=" * 80, err=True)
|
|
210
|
+
click.echo("Hook Error Diagnostics", err=True)
|
|
211
|
+
click.echo("=" * 80, err=True)
|
|
212
212
|
|
|
213
213
|
for key, data in errors.items():
|
|
214
|
-
click.echo(f"\n🔴 Error: {data['type']}")
|
|
215
|
-
click.echo(f" Hook: {data['hook_type']}")
|
|
216
|
-
click.echo(f" Count: {data['count']} failures")
|
|
214
|
+
click.echo(f"\n🔴 Error: {data['type']}", err=True)
|
|
215
|
+
click.echo(f" Hook: {data['hook_type']}", err=True)
|
|
216
|
+
click.echo(f" Count: {data['count']} failures", err=True)
|
|
217
217
|
|
|
218
218
|
# Generate and show fix suggestion
|
|
219
219
|
error_info = {
|
|
@@ -223,13 +223,13 @@ def diagnose_errors(hook_type):
|
|
|
223
223
|
}
|
|
224
224
|
suggestion = error_memory.suggest_fix(error_info)
|
|
225
225
|
|
|
226
|
-
click.echo("\n" + "-" * 80)
|
|
227
|
-
click.echo(suggestion)
|
|
228
|
-
click.echo("-" * 80)
|
|
226
|
+
click.echo("\n" + "-" * 80, err=True)
|
|
227
|
+
click.echo(suggestion, err=True)
|
|
228
|
+
click.echo("-" * 80, err=True)
|
|
229
229
|
|
|
230
|
-
click.echo("\n" + "=" * 80)
|
|
231
|
-
click.echo("After fixing issues, clear errors to retry:")
|
|
232
|
-
click.echo(" claude-mpm hook-errors clear")
|
|
230
|
+
click.echo("\n" + "=" * 80, err=True)
|
|
231
|
+
click.echo("After fixing issues, clear errors to retry:", err=True)
|
|
232
|
+
click.echo(" claude-mpm hook-errors clear", err=True)
|
|
233
233
|
|
|
234
234
|
|
|
235
235
|
@hook_errors_group.command(name="status")
|
|
@@ -244,27 +244,27 @@ def show_status():
|
|
|
244
244
|
error_memory = get_hook_error_memory()
|
|
245
245
|
summary = error_memory.get_error_summary()
|
|
246
246
|
|
|
247
|
-
click.echo("\n📊 Hook Error Memory Status")
|
|
248
|
-
click.echo("=" * 80)
|
|
247
|
+
click.echo("\n📊 Hook Error Memory Status", err=True)
|
|
248
|
+
click.echo("=" * 80, err=True)
|
|
249
249
|
|
|
250
250
|
if summary["total_errors"] == 0:
|
|
251
|
-
click.echo("✅ Status: Healthy (no errors recorded)")
|
|
251
|
+
click.echo("✅ Status: Healthy (no errors recorded)", err=True)
|
|
252
252
|
else:
|
|
253
|
-
click.echo(f"⚠️ Status: {summary['total_errors']} error(s) recorded")
|
|
254
|
-
click.echo(f" Unique errors: {summary['unique_errors']}")
|
|
253
|
+
click.echo(f"⚠️ Status: {summary['total_errors']} error(s) recorded", err=True)
|
|
254
|
+
click.echo(f" Unique errors: {summary['unique_errors']}", err=True)
|
|
255
255
|
|
|
256
256
|
# Show which hooks are affected
|
|
257
257
|
if summary["errors_by_hook"]:
|
|
258
258
|
affected_hooks = list(summary["errors_by_hook"].keys())
|
|
259
|
-
click.echo(f" Affected hooks: {', '.join(affected_hooks)}")
|
|
259
|
+
click.echo(f" Affected hooks: {', '.join(affected_hooks)}", err=True)
|
|
260
260
|
|
|
261
|
-
click.echo(f"\n📁 Memory file: {summary['memory_file']}")
|
|
262
|
-
click.echo(f" Exists: {Path(summary['memory_file']).exists()}")
|
|
261
|
+
click.echo(f"\n📁 Memory file: {summary['memory_file']}", err=True)
|
|
262
|
+
click.echo(f" Exists: {Path(summary['memory_file']).exists()}", err=True)
|
|
263
263
|
|
|
264
|
-
click.echo("\nCommands:")
|
|
265
|
-
click.echo(" claude-mpm hook-errors list # View detailed errors")
|
|
266
|
-
click.echo(" claude-mpm hook-errors diagnose # Get fix suggestions")
|
|
267
|
-
click.echo(" claude-mpm hook-errors clear # Clear and retry")
|
|
264
|
+
click.echo("\nCommands:", err=True)
|
|
265
|
+
click.echo(" claude-mpm hook-errors list # View detailed errors", err=True)
|
|
266
|
+
click.echo(" claude-mpm hook-errors diagnose # Get fix suggestions", err=True)
|
|
267
|
+
click.echo(" claude-mpm hook-errors clear # Clear and retry", err=True)
|
|
268
268
|
|
|
269
269
|
|
|
270
270
|
# Register the command group
|
claude_mpm/cli/commands/mcp.py
CHANGED
|
@@ -33,7 +33,27 @@ def manage_mcp(args):
|
|
|
33
33
|
"""
|
|
34
34
|
logger = get_logger("cli.mcp")
|
|
35
35
|
|
|
36
|
-
#
|
|
36
|
+
# Commands that don't require full MCP Gateway or mcp package
|
|
37
|
+
# These only need mcp_service_registry which doesn't require the mcp package
|
|
38
|
+
service_mgmt_commands = {
|
|
39
|
+
MCPCommands.ENABLE.value,
|
|
40
|
+
MCPCommands.DISABLE.value,
|
|
41
|
+
MCPCommands.LIST.value,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Route service management commands directly without any MCP dependencies
|
|
45
|
+
if args.mcp_command in service_mgmt_commands:
|
|
46
|
+
try:
|
|
47
|
+
from .mcp_command_router import MCPCommandRouter
|
|
48
|
+
|
|
49
|
+
router = MCPCommandRouter(logger)
|
|
50
|
+
return router.route_command(args)
|
|
51
|
+
except Exception as e:
|
|
52
|
+
logger.error(f"Error running service command: {e}", exc_info=True)
|
|
53
|
+
print(f"Error: {e}")
|
|
54
|
+
return 1
|
|
55
|
+
|
|
56
|
+
# Now check for mcp package for other commands
|
|
37
57
|
import importlib.util
|
|
38
58
|
|
|
39
59
|
mcp_spec = importlib.util.find_spec("mcp")
|
|
@@ -58,22 +78,14 @@ def manage_mcp(args):
|
|
|
58
78
|
except ImportError as e:
|
|
59
79
|
# Provide minimal fallbacks for basic commands
|
|
60
80
|
logger.warning(f"Some MCP Gateway services not available: {e}")
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
print(
|
|
70
|
-
"\nError: MCP Gateway services not fully available",
|
|
71
|
-
file=sys.stderr,
|
|
72
|
-
)
|
|
73
|
-
print(f"Details: {e}", file=sys.stderr)
|
|
74
|
-
print("\nTry running:", file=sys.stderr)
|
|
75
|
-
print(" claude-mpm mcp install", file=sys.stderr)
|
|
76
|
-
return 1
|
|
81
|
+
print(
|
|
82
|
+
"\nError: MCP Gateway services not fully available",
|
|
83
|
+
file=sys.stderr,
|
|
84
|
+
)
|
|
85
|
+
print(f"Details: {e}", file=sys.stderr)
|
|
86
|
+
print("\nTry running:", file=sys.stderr)
|
|
87
|
+
print(" claude-mpm mcp install", file=sys.stderr)
|
|
88
|
+
return 1
|
|
77
89
|
|
|
78
90
|
if not args.mcp_command:
|
|
79
91
|
# No subcommand - show status by default
|
|
@@ -48,6 +48,15 @@ class MCPCommandRouter:
|
|
|
48
48
|
if args.mcp_command == MCPCommands.EXTERNAL.value:
|
|
49
49
|
return self._manage_external(args)
|
|
50
50
|
|
|
51
|
+
if args.mcp_command == MCPCommands.ENABLE.value:
|
|
52
|
+
return self._enable_service(args)
|
|
53
|
+
|
|
54
|
+
if args.mcp_command == MCPCommands.DISABLE.value:
|
|
55
|
+
return self._disable_service(args)
|
|
56
|
+
|
|
57
|
+
if args.mcp_command == MCPCommands.LIST.value:
|
|
58
|
+
return self._list_services(args)
|
|
59
|
+
|
|
51
60
|
if args.mcp_command == "cleanup":
|
|
52
61
|
return self._cleanup_locks(args)
|
|
53
62
|
|
|
@@ -134,6 +143,27 @@ class MCPCommandRouter:
|
|
|
134
143
|
handler = MCPExternalCommands(self.logger)
|
|
135
144
|
return handler.manage_external(args)
|
|
136
145
|
|
|
146
|
+
def _enable_service(self, args) -> int:
|
|
147
|
+
"""Enable MCP service command handler."""
|
|
148
|
+
from .mcp_service_commands import MCPServiceCommands
|
|
149
|
+
|
|
150
|
+
handler = MCPServiceCommands(self.logger)
|
|
151
|
+
return handler.enable_service(args)
|
|
152
|
+
|
|
153
|
+
def _disable_service(self, args) -> int:
|
|
154
|
+
"""Disable MCP service command handler."""
|
|
155
|
+
from .mcp_service_commands import MCPServiceCommands
|
|
156
|
+
|
|
157
|
+
handler = MCPServiceCommands(self.logger)
|
|
158
|
+
return handler.disable_service(args)
|
|
159
|
+
|
|
160
|
+
def _list_services(self, args) -> int:
|
|
161
|
+
"""List MCP services command handler."""
|
|
162
|
+
from .mcp_service_commands import MCPServiceCommands
|
|
163
|
+
|
|
164
|
+
handler = MCPServiceCommands(self.logger)
|
|
165
|
+
return handler.list_services(args)
|
|
166
|
+
|
|
137
167
|
def _show_help(self):
|
|
138
168
|
"""Show available MCP commands."""
|
|
139
169
|
print("\nAvailable MCP commands:")
|
|
@@ -148,6 +178,10 @@ class MCPCommandRouter:
|
|
|
148
178
|
print(" config - View and manage configuration")
|
|
149
179
|
print(" external - Manage external MCP services")
|
|
150
180
|
print(" cleanup - Clean up legacy files")
|
|
181
|
+
print("\nService management:")
|
|
182
|
+
print(" enable - Enable an MCP service in configuration")
|
|
183
|
+
print(" disable - Disable an MCP service from configuration")
|
|
184
|
+
print(" list - List available and enabled MCP services")
|
|
151
185
|
print("\nFor help with a specific command:")
|
|
152
186
|
print(" claude-mpm mcp <command> --help")
|
|
153
187
|
print("\nExamples:")
|
|
@@ -159,3 +193,8 @@ class MCPCommandRouter:
|
|
|
159
193
|
print(" claude-mpm mcp tools")
|
|
160
194
|
print(" claude-mpm mcp register my-tool")
|
|
161
195
|
print(" claude-mpm mcp test my-tool")
|
|
196
|
+
print("\nService management examples:")
|
|
197
|
+
print(" claude-mpm mcp list --available # List all available services")
|
|
198
|
+
print(" claude-mpm mcp enable kuzu-memory # Enable a service")
|
|
199
|
+
print(" claude-mpm mcp enable mcp-github --interactive # Enable with prompts")
|
|
200
|
+
print(" claude-mpm mcp disable mcp-github # Disable a service")
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"""MCP service management commands for claude-mpm CLI.
|
|
2
|
+
|
|
3
|
+
This module provides enable, disable, and list operations for MCP services
|
|
4
|
+
using the service registry for configuration generation.
|
|
5
|
+
|
|
6
|
+
WHY: Enables users to easily enable/disable MCP services with proper
|
|
7
|
+
credential handling and configuration management.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import getpass
|
|
11
|
+
import json
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from argparse import Namespace
|
|
17
|
+
from logging import Logger
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MCPServiceCommands:
|
|
21
|
+
"""Command handlers for MCP service management."""
|
|
22
|
+
|
|
23
|
+
# Configuration file paths
|
|
24
|
+
GLOBAL_CONFIG = Path.home() / ".claude.json"
|
|
25
|
+
PROJECT_CONFIG = Path(".mcp.json")
|
|
26
|
+
|
|
27
|
+
def __init__(self, logger: "Logger") -> None:
|
|
28
|
+
"""Initialize the command handler.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
logger: Logger instance for output
|
|
32
|
+
"""
|
|
33
|
+
self.logger = logger
|
|
34
|
+
|
|
35
|
+
def enable_service(self, args: "Namespace") -> int:
|
|
36
|
+
"""Enable an MCP service in configuration.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
args: Parsed command arguments with:
|
|
40
|
+
- service_name: Name of service to enable
|
|
41
|
+
- interactive: Whether to prompt for credentials
|
|
42
|
+
- env: List of KEY=VALUE strings
|
|
43
|
+
- use_global: Use global config instead of project
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Exit code (0 for success, 1 for error)
|
|
47
|
+
"""
|
|
48
|
+
from ...services.mcp_service_registry import MCPServiceRegistry
|
|
49
|
+
|
|
50
|
+
service_name = args.service_name
|
|
51
|
+
|
|
52
|
+
# Check if service exists in registry
|
|
53
|
+
service = MCPServiceRegistry.get(service_name)
|
|
54
|
+
if not service:
|
|
55
|
+
available = MCPServiceRegistry.list_names()
|
|
56
|
+
print(f"Error: Unknown service '{service_name}'")
|
|
57
|
+
print(f"Available services: {', '.join(available)}")
|
|
58
|
+
return 1
|
|
59
|
+
|
|
60
|
+
# Parse environment variables from --env flags
|
|
61
|
+
env_vars: dict[str, str] = {}
|
|
62
|
+
if args.env:
|
|
63
|
+
for env_str in args.env:
|
|
64
|
+
if "=" not in env_str:
|
|
65
|
+
print(f"Error: Invalid env format '{env_str}'. Use KEY=VALUE")
|
|
66
|
+
return 1
|
|
67
|
+
key, value = env_str.split("=", 1)
|
|
68
|
+
env_vars[key] = value
|
|
69
|
+
|
|
70
|
+
# Interactive mode: prompt for required env vars
|
|
71
|
+
if args.interactive:
|
|
72
|
+
for var in service.required_env:
|
|
73
|
+
if var not in env_vars:
|
|
74
|
+
# Use getpass for sensitive values (tokens, keys, etc.)
|
|
75
|
+
if any(
|
|
76
|
+
keyword in var.upper()
|
|
77
|
+
for keyword in [
|
|
78
|
+
"TOKEN",
|
|
79
|
+
"KEY",
|
|
80
|
+
"SECRET",
|
|
81
|
+
"PASSWORD",
|
|
82
|
+
"CREDENTIAL",
|
|
83
|
+
]
|
|
84
|
+
):
|
|
85
|
+
value = getpass.getpass(f"Enter {var}: ")
|
|
86
|
+
else:
|
|
87
|
+
value = input(f"Enter {var}: ")
|
|
88
|
+
if value:
|
|
89
|
+
env_vars[var] = value
|
|
90
|
+
|
|
91
|
+
# Validate required environment variables
|
|
92
|
+
is_valid, missing = MCPServiceRegistry.validate_env(service, env_vars)
|
|
93
|
+
if not is_valid:
|
|
94
|
+
print(
|
|
95
|
+
f"Error: Missing required environment variables: {', '.join(missing)}"
|
|
96
|
+
)
|
|
97
|
+
print(f"Use --env {missing[0]}=VALUE or --interactive to provide them")
|
|
98
|
+
return 1
|
|
99
|
+
|
|
100
|
+
# Generate service configuration
|
|
101
|
+
config = MCPServiceRegistry.generate_config(service, env_vars)
|
|
102
|
+
|
|
103
|
+
# Determine config file path
|
|
104
|
+
config_path = self.GLOBAL_CONFIG if args.use_global else self.PROJECT_CONFIG
|
|
105
|
+
|
|
106
|
+
# Load existing config or create new
|
|
107
|
+
existing_config = self._load_config(config_path)
|
|
108
|
+
|
|
109
|
+
# Add/update service in mcpServers section
|
|
110
|
+
if "mcpServers" not in existing_config:
|
|
111
|
+
existing_config["mcpServers"] = {}
|
|
112
|
+
|
|
113
|
+
existing_config["mcpServers"][service_name] = config
|
|
114
|
+
|
|
115
|
+
# Save configuration
|
|
116
|
+
if self._save_config(config_path, existing_config):
|
|
117
|
+
location = (
|
|
118
|
+
"global (~/.claude.json)" if args.use_global else "project (.mcp.json)"
|
|
119
|
+
)
|
|
120
|
+
print(f"Enabled '{service_name}' in {location}")
|
|
121
|
+
print(f"Description: {service.description}")
|
|
122
|
+
|
|
123
|
+
if service.optional_env:
|
|
124
|
+
print(
|
|
125
|
+
f"\nOptional environment variables: {', '.join(service.optional_env)}"
|
|
126
|
+
)
|
|
127
|
+
print("Use --env VAR=VALUE to set them")
|
|
128
|
+
|
|
129
|
+
return 0
|
|
130
|
+
print(f"Error: Failed to save configuration to {config_path}")
|
|
131
|
+
return 1
|
|
132
|
+
|
|
133
|
+
def disable_service(self, args: "Namespace") -> int:
|
|
134
|
+
"""Disable an MCP service from configuration.
|
|
135
|
+
|
|
136
|
+
This removes the service from the configuration file but does NOT
|
|
137
|
+
uninstall the underlying package.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
args: Parsed command arguments with:
|
|
141
|
+
- service_name: Name of service to disable
|
|
142
|
+
- use_global: Use global config instead of project
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
Exit code (0 for success, 1 for error)
|
|
146
|
+
"""
|
|
147
|
+
service_name = args.service_name
|
|
148
|
+
config_path = self.GLOBAL_CONFIG if args.use_global else self.PROJECT_CONFIG
|
|
149
|
+
|
|
150
|
+
# Load existing config
|
|
151
|
+
existing_config = self._load_config(config_path)
|
|
152
|
+
|
|
153
|
+
# Check if service exists in config
|
|
154
|
+
if "mcpServers" not in existing_config:
|
|
155
|
+
print(f"Error: No MCP services configured in {config_path}")
|
|
156
|
+
return 1
|
|
157
|
+
|
|
158
|
+
if service_name not in existing_config["mcpServers"]:
|
|
159
|
+
print(f"Error: Service '{service_name}' is not enabled")
|
|
160
|
+
enabled = list(existing_config["mcpServers"].keys())
|
|
161
|
+
if enabled:
|
|
162
|
+
print(f"Enabled services: {', '.join(enabled)}")
|
|
163
|
+
return 1
|
|
164
|
+
|
|
165
|
+
# Remove service from config
|
|
166
|
+
del existing_config["mcpServers"][service_name]
|
|
167
|
+
|
|
168
|
+
# Save configuration
|
|
169
|
+
if self._save_config(config_path, existing_config):
|
|
170
|
+
location = (
|
|
171
|
+
"global (~/.claude.json)" if args.use_global else "project (.mcp.json)"
|
|
172
|
+
)
|
|
173
|
+
print(f"Disabled '{service_name}' in {location}")
|
|
174
|
+
print(
|
|
175
|
+
"Note: The package is still installed. Use pipx/uvx to uninstall if needed."
|
|
176
|
+
)
|
|
177
|
+
return 0
|
|
178
|
+
print(f"Error: Failed to save configuration to {config_path}")
|
|
179
|
+
return 1
|
|
180
|
+
|
|
181
|
+
def list_services(self, args: "Namespace") -> int:
|
|
182
|
+
"""List MCP services (available and/or enabled).
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
args: Parsed command arguments with:
|
|
186
|
+
- available: Show all available services from registry
|
|
187
|
+
- enabled: Show only enabled services
|
|
188
|
+
- use_global: Check global config instead of project
|
|
189
|
+
- verbose: Show detailed information
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
Exit code (0 for success)
|
|
193
|
+
"""
|
|
194
|
+
from ...services.mcp_service_registry import MCPServiceRegistry
|
|
195
|
+
|
|
196
|
+
config_path = self.GLOBAL_CONFIG if args.use_global else self.PROJECT_CONFIG
|
|
197
|
+
existing_config = self._load_config(config_path)
|
|
198
|
+
enabled_services = existing_config.get("mcpServers", {})
|
|
199
|
+
|
|
200
|
+
# Default: show both available and enabled
|
|
201
|
+
show_available = args.available or not (args.available or args.enabled)
|
|
202
|
+
show_enabled = args.enabled or not (args.available or args.enabled)
|
|
203
|
+
|
|
204
|
+
if show_available:
|
|
205
|
+
print("Available MCP Services:")
|
|
206
|
+
print("-" * 60)
|
|
207
|
+
for service in MCPServiceRegistry.list_all():
|
|
208
|
+
status = "[enabled]" if service.name in enabled_services else ""
|
|
209
|
+
default_marker = " (default)" if service.enabled_by_default else ""
|
|
210
|
+
print(f" {service.name:<25} {status:>10}{default_marker}")
|
|
211
|
+
if args.verbose:
|
|
212
|
+
print(f" Description: {service.description}")
|
|
213
|
+
print(f" Package: {service.package}")
|
|
214
|
+
print(f" Install: {service.install_method.value}")
|
|
215
|
+
if service.required_env:
|
|
216
|
+
print(f" Required env: {', '.join(service.required_env)}")
|
|
217
|
+
if service.optional_env:
|
|
218
|
+
print(f" Optional env: {', '.join(service.optional_env)}")
|
|
219
|
+
print()
|
|
220
|
+
print()
|
|
221
|
+
|
|
222
|
+
if show_enabled:
|
|
223
|
+
location = (
|
|
224
|
+
"global (~/.claude.json)" if args.use_global else "project (.mcp.json)"
|
|
225
|
+
)
|
|
226
|
+
print(f"Enabled Services ({location}):")
|
|
227
|
+
print("-" * 60)
|
|
228
|
+
if not enabled_services:
|
|
229
|
+
print(" No services enabled")
|
|
230
|
+
else:
|
|
231
|
+
for name, config in enabled_services.items():
|
|
232
|
+
registry_service = MCPServiceRegistry.get(name)
|
|
233
|
+
if registry_service:
|
|
234
|
+
print(f" {name:<25} [registered]")
|
|
235
|
+
if args.verbose:
|
|
236
|
+
print(f" Description: {registry_service.description}")
|
|
237
|
+
else:
|
|
238
|
+
print(f" {name:<25} [custom]")
|
|
239
|
+
if args.verbose:
|
|
240
|
+
print(f" Command: {config.get('command', 'N/A')}")
|
|
241
|
+
if "args" in config:
|
|
242
|
+
print(f" Args: {config['args']}")
|
|
243
|
+
if "env" in config:
|
|
244
|
+
# Mask sensitive values
|
|
245
|
+
env_display = {}
|
|
246
|
+
for k, v in config.get("env", {}).items():
|
|
247
|
+
if any(
|
|
248
|
+
keyword in k.upper()
|
|
249
|
+
for keyword in [
|
|
250
|
+
"TOKEN",
|
|
251
|
+
"KEY",
|
|
252
|
+
"SECRET",
|
|
253
|
+
"PASSWORD",
|
|
254
|
+
]
|
|
255
|
+
):
|
|
256
|
+
env_display[k] = "***"
|
|
257
|
+
else:
|
|
258
|
+
env_display[k] = v
|
|
259
|
+
print(f" Env: {env_display}")
|
|
260
|
+
print()
|
|
261
|
+
|
|
262
|
+
return 0
|
|
263
|
+
|
|
264
|
+
def _load_config(self, path: Path) -> dict:
|
|
265
|
+
"""Load configuration from a JSON file.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
path: Path to the configuration file
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
Configuration dictionary (empty if file doesn't exist)
|
|
272
|
+
"""
|
|
273
|
+
if not path.exists():
|
|
274
|
+
return {}
|
|
275
|
+
try:
|
|
276
|
+
with open(path) as f:
|
|
277
|
+
data = json.load(f)
|
|
278
|
+
return dict(data) if isinstance(data, dict) else {}
|
|
279
|
+
except json.JSONDecodeError as e:
|
|
280
|
+
self.logger.warning(f"Invalid JSON in {path}: {e}")
|
|
281
|
+
return {}
|
|
282
|
+
except OSError as e:
|
|
283
|
+
self.logger.warning(f"Failed to read {path}: {e}")
|
|
284
|
+
return {}
|
|
285
|
+
|
|
286
|
+
def _save_config(self, path: Path, config: dict) -> bool:
|
|
287
|
+
"""Save configuration to a JSON file.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
path: Path to the configuration file
|
|
291
|
+
config: Configuration dictionary to save
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
True if saved successfully, False otherwise
|
|
295
|
+
"""
|
|
296
|
+
try:
|
|
297
|
+
# Ensure parent directory exists
|
|
298
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
299
|
+
with open(path, "w") as f:
|
|
300
|
+
json.dump(config, f, indent=2)
|
|
301
|
+
return True
|
|
302
|
+
except OSError as e:
|
|
303
|
+
self.logger.error(f"Failed to write {path}: {e}")
|
|
304
|
+
return False
|
|
@@ -118,7 +118,7 @@ class MonitorCommand(BaseCommand):
|
|
|
118
118
|
# Check if it's actually running
|
|
119
119
|
if not self.daemon.lifecycle.is_running():
|
|
120
120
|
return CommandResult.error_result(
|
|
121
|
-
"Monitor daemon failed to start. Check ~/.claude-mpm/monitor-daemon
|
|
121
|
+
"Monitor daemon failed to start. Check ~/.claude-mpm/logs/monitor-daemon-*.log for details."
|
|
122
122
|
)
|
|
123
123
|
|
|
124
124
|
# Get the actual PID
|
|
@@ -146,7 +146,7 @@ class MonitorCommand(BaseCommand):
|
|
|
146
146
|
pass
|
|
147
147
|
|
|
148
148
|
return CommandResult.error_result(
|
|
149
|
-
"Failed to start unified monitor daemon. Check ~/.claude-mpm/monitor-daemon
|
|
149
|
+
"Failed to start unified monitor daemon. Check ~/.claude-mpm/logs/monitor-daemon-*.log for details."
|
|
150
150
|
)
|
|
151
151
|
|
|
152
152
|
def _stop_monitor(self, args) -> CommandResult:
|