claude-mpm 4.21.3__py3-none-any.whl → 5.1.9__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.

Files changed (517) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +12 -0
  3. claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +3 -48
  4. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +1239 -674
  6. claude_mpm/agents/WORKFLOW.md +75 -2
  7. claude_mpm/agents/__init__.py +6 -0
  8. claude_mpm/agents/agent_loader.py +1 -4
  9. claude_mpm/agents/base_agent.json +6 -3
  10. claude_mpm/agents/base_agent_loader.py +10 -35
  11. claude_mpm/agents/frontmatter_validator.py +69 -1
  12. claude_mpm/agents/templates/circuit-breakers.md +1254 -0
  13. claude_mpm/agents/templates/context-management-examples.md +544 -0
  14. claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +89 -19
  15. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  16. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  17. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  18. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  19. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  20. claude_mpm/cli/__init__.py +37 -2
  21. claude_mpm/cli/commands/__init__.py +2 -0
  22. claude_mpm/cli/commands/agent_source.py +774 -0
  23. claude_mpm/cli/commands/agent_state_manager.py +188 -30
  24. claude_mpm/cli/commands/agents.py +1128 -36
  25. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  26. claude_mpm/cli/commands/agents_discover.py +338 -0
  27. claude_mpm/cli/commands/aggregate.py +1 -1
  28. claude_mpm/cli/commands/analyze.py +3 -3
  29. claude_mpm/cli/commands/auto_configure.py +537 -239
  30. claude_mpm/cli/commands/cleanup.py +1 -1
  31. claude_mpm/cli/commands/config.py +7 -4
  32. claude_mpm/cli/commands/configure.py +935 -45
  33. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  34. claude_mpm/cli/commands/configure_navigation.py +63 -46
  35. claude_mpm/cli/commands/debug.py +12 -12
  36. claude_mpm/cli/commands/doctor.py +10 -2
  37. claude_mpm/cli/commands/hook_errors.py +277 -0
  38. claude_mpm/cli/commands/local_deploy.py +1 -4
  39. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  40. claude_mpm/cli/commands/mpm_init/core.py +50 -2
  41. claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
  42. claude_mpm/cli/commands/mpm_init/prompts.py +6 -6
  43. claude_mpm/cli/commands/postmortem.py +401 -0
  44. claude_mpm/cli/commands/run.py +125 -167
  45. claude_mpm/cli/commands/skill_source.py +694 -0
  46. claude_mpm/cli/commands/skills.py +757 -20
  47. claude_mpm/cli/executor.py +78 -3
  48. claude_mpm/cli/interactive/agent_wizard.py +1032 -47
  49. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  50. claude_mpm/cli/parsers/agents_parser.py +310 -4
  51. claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
  52. claude_mpm/cli/parsers/base_parser.py +53 -0
  53. claude_mpm/cli/parsers/config_parser.py +96 -43
  54. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  55. claude_mpm/cli/parsers/skills_parser.py +145 -0
  56. claude_mpm/cli/parsers/source_parser.py +138 -0
  57. claude_mpm/cli/startup.py +564 -108
  58. claude_mpm/cli/startup_display.py +480 -0
  59. claude_mpm/cli/utils.py +1 -1
  60. claude_mpm/cli_module/commands.py +1 -1
  61. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  62. claude_mpm/commands/mpm-agents-detect.md +9 -0
  63. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  64. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  65. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  66. claude_mpm/commands/mpm-doctor.md +9 -0
  67. claude_mpm/commands/mpm-help.md +14 -2
  68. claude_mpm/commands/mpm-init.md +27 -2
  69. claude_mpm/commands/mpm-monitor.md +9 -0
  70. claude_mpm/commands/mpm-postmortem.md +123 -0
  71. claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
  72. claude_mpm/commands/mpm-status.md +9 -0
  73. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  74. claude_mpm/commands/mpm-ticket-view.md +552 -0
  75. claude_mpm/commands/mpm-version.md +9 -0
  76. claude_mpm/commands/mpm.md +10 -0
  77. claude_mpm/config/agent_presets.py +488 -0
  78. claude_mpm/config/agent_sources.py +325 -0
  79. claude_mpm/config/skill_presets.py +392 -0
  80. claude_mpm/config/skill_sources.py +590 -0
  81. claude_mpm/constants.py +13 -0
  82. claude_mpm/core/api_validator.py +1 -1
  83. claude_mpm/core/claude_runner.py +19 -35
  84. claude_mpm/core/config.py +24 -0
  85. claude_mpm/core/constants.py +1 -1
  86. claude_mpm/core/framework/__init__.py +3 -16
  87. claude_mpm/core/framework/loaders/file_loader.py +54 -101
  88. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  89. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  90. claude_mpm/core/hook_error_memory.py +381 -0
  91. claude_mpm/core/hook_manager.py +41 -2
  92. claude_mpm/core/interactive_session.py +131 -10
  93. claude_mpm/core/logger.py +3 -1
  94. claude_mpm/core/oneshot_session.py +110 -8
  95. claude_mpm/core/output_style_manager.py +173 -43
  96. claude_mpm/core/protocols/__init__.py +23 -0
  97. claude_mpm/core/protocols/runner_protocol.py +103 -0
  98. claude_mpm/core/protocols/session_protocol.py +131 -0
  99. claude_mpm/core/shared/singleton_manager.py +11 -4
  100. claude_mpm/core/system_context.py +38 -0
  101. claude_mpm/core/unified_agent_registry.py +129 -1
  102. claude_mpm/core/unified_config.py +22 -0
  103. claude_mpm/dashboard/static/css/activity.css +69 -69
  104. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  105. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  106. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  107. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  108. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  109. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  110. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  111. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  112. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  113. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  114. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  115. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  116. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  117. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  118. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  119. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  120. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  121. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  122. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  123. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  124. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  125. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  126. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  127. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  128. claude_mpm/dashboard/templates/code_simple.html +23 -23
  129. claude_mpm/dashboard/templates/index.html +18 -18
  130. claude_mpm/experimental/cli_enhancements.py +1 -5
  131. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  132. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  133. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  134. claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
  135. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  136. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  137. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  138. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  139. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  140. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  141. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  142. claude_mpm/models/agent_definition.py +7 -0
  143. claude_mpm/models/git_repository.py +198 -0
  144. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  145. claude_mpm/scripts/start_activity_logging.py +3 -1
  146. claude_mpm/services/agents/agent_builder.py +45 -9
  147. claude_mpm/services/agents/agent_preset_service.py +238 -0
  148. claude_mpm/services/agents/agent_selection_service.py +484 -0
  149. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  150. claude_mpm/services/agents/cache_git_manager.py +621 -0
  151. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  152. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  153. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  154. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  155. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  156. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  157. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  158. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  159. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  160. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  161. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +225 -18
  162. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  163. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  164. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +557 -0
  165. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  166. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  167. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  168. claude_mpm/services/agents/git_source_manager.py +629 -0
  169. claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
  170. claude_mpm/services/agents/local_template_manager.py +50 -10
  171. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  172. claude_mpm/services/agents/sources/__init__.py +13 -0
  173. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  174. claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
  175. claude_mpm/services/agents/startup_sync.py +239 -0
  176. claude_mpm/services/agents/toolchain_detector.py +474 -0
  177. claude_mpm/services/analysis/__init__.py +25 -0
  178. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  179. claude_mpm/services/analysis/postmortem_service.py +765 -0
  180. claude_mpm/services/cli/session_pause_manager.py +1 -1
  181. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  182. claude_mpm/services/command_deployment_service.py +200 -6
  183. claude_mpm/services/core/base.py +7 -2
  184. claude_mpm/services/core/interfaces/__init__.py +1 -3
  185. claude_mpm/services/core/interfaces/health.py +1 -4
  186. claude_mpm/services/core/models/__init__.py +2 -11
  187. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  188. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  189. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  190. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  191. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  192. claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
  193. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  194. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  195. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  196. claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
  197. claude_mpm/services/event_bus/direct_relay.py +3 -3
  198. claude_mpm/services/event_bus/event_bus.py +36 -3
  199. claude_mpm/services/events/consumers/logging.py +1 -2
  200. claude_mpm/services/git/__init__.py +21 -0
  201. claude_mpm/services/git/git_operations_service.py +494 -0
  202. claude_mpm/services/github/__init__.py +21 -0
  203. claude_mpm/services/github/github_cli_service.py +397 -0
  204. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  205. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  206. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  207. claude_mpm/services/instructions/__init__.py +9 -0
  208. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  209. claude_mpm/services/local_ops/__init__.py +3 -13
  210. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  211. claude_mpm/services/local_ops/health_manager.py +1 -4
  212. claude_mpm/services/local_ops/process_manager.py +1 -1
  213. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  214. claude_mpm/services/mcp_config_manager.py +75 -145
  215. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  216. claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
  217. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  218. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  219. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  220. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  221. claude_mpm/services/mcp_service_verifier.py +6 -3
  222. claude_mpm/services/memory/optimizer.py +1 -1
  223. claude_mpm/services/model/model_router.py +8 -9
  224. claude_mpm/services/monitor/daemon.py +29 -9
  225. claude_mpm/services/monitor/daemon_manager.py +96 -19
  226. claude_mpm/services/monitor/server.py +2 -2
  227. claude_mpm/services/native_agent_converter.py +356 -0
  228. claude_mpm/services/port_manager.py +1 -1
  229. claude_mpm/services/pr/__init__.py +14 -0
  230. claude_mpm/services/pr/pr_template_service.py +329 -0
  231. claude_mpm/services/project/documentation_manager.py +2 -1
  232. claude_mpm/services/project/project_organizer.py +4 -0
  233. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  234. claude_mpm/services/runner_configuration_service.py +17 -3
  235. claude_mpm/services/self_upgrade_service.py +165 -7
  236. claude_mpm/services/session_management_service.py +16 -4
  237. claude_mpm/services/skills/__init__.py +18 -0
  238. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  239. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  240. claude_mpm/services/skills_config.py +547 -0
  241. claude_mpm/services/skills_deployer.py +955 -0
  242. claude_mpm/services/socketio/handlers/connection.py +1 -1
  243. claude_mpm/services/socketio/handlers/git.py +2 -2
  244. claude_mpm/services/socketio/server/core.py +1 -4
  245. claude_mpm/services/socketio/server/main.py +1 -3
  246. claude_mpm/services/system_instructions_service.py +1 -3
  247. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  248. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  249. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  250. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  251. claude_mpm/services/unified/unified_deployment.py +1 -5
  252. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  253. claude_mpm/services/visualization/__init__.py +1 -5
  254. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  255. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  256. claude_mpm/skills/bundled/performance-profiling.md +6 -0
  257. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
  258. claude_mpm/skills/skills_registry.py +0 -1
  259. claude_mpm/templates/questions/__init__.py +38 -0
  260. claude_mpm/templates/questions/base.py +193 -0
  261. claude_mpm/templates/questions/pr_strategy.py +311 -0
  262. claude_mpm/templates/questions/project_init.py +385 -0
  263. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  264. claude_mpm/tools/__main__.py +8 -8
  265. claude_mpm/tools/code_tree_analyzer/analysis.py +1 -1
  266. claude_mpm/utils/agent_dependency_loader.py +80 -13
  267. claude_mpm/utils/agent_filters.py +288 -0
  268. claude_mpm/utils/dependency_cache.py +3 -1
  269. claude_mpm/utils/gitignore.py +244 -0
  270. claude_mpm/utils/log_cleanup.py +3 -3
  271. claude_mpm/utils/migration.py +372 -0
  272. claude_mpm/utils/progress.py +387 -0
  273. claude_mpm/utils/robust_installer.py +3 -5
  274. claude_mpm/utils/structured_questions.py +619 -0
  275. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/METADATA +496 -65
  276. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/RECORD +284 -443
  277. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  278. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  279. claude_mpm/agents/templates/agent-manager.json +0 -273
  280. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  281. claude_mpm/agents/templates/api_qa.json +0 -180
  282. claude_mpm/agents/templates/circuit_breakers.md +0 -638
  283. claude_mpm/agents/templates/clerk-ops.json +0 -235
  284. claude_mpm/agents/templates/code_analyzer.json +0 -101
  285. claude_mpm/agents/templates/content-agent.json +0 -358
  286. claude_mpm/agents/templates/dart_engineer.json +0 -307
  287. claude_mpm/agents/templates/data_engineer.json +0 -225
  288. claude_mpm/agents/templates/documentation.json +0 -211
  289. claude_mpm/agents/templates/engineer.json +0 -210
  290. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  291. claude_mpm/agents/templates/golang_engineer.json +0 -270
  292. claude_mpm/agents/templates/imagemagick.json +0 -264
  293. claude_mpm/agents/templates/java_engineer.json +0 -346
  294. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  295. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  296. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  297. claude_mpm/agents/templates/memory_manager.json +0 -158
  298. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  299. claude_mpm/agents/templates/ops.json +0 -185
  300. claude_mpm/agents/templates/php-engineer.json +0 -287
  301. claude_mpm/agents/templates/product_owner.json +0 -338
  302. claude_mpm/agents/templates/project_organizer.json +0 -140
  303. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  304. claude_mpm/agents/templates/python_engineer.json +0 -387
  305. claude_mpm/agents/templates/qa.json +0 -242
  306. claude_mpm/agents/templates/react_engineer.json +0 -238
  307. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  308. claude_mpm/agents/templates/research.json +0 -188
  309. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  310. claude_mpm/agents/templates/rust_engineer.json +0 -275
  311. claude_mpm/agents/templates/security.json +0 -202
  312. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  313. claude_mpm/agents/templates/ticketing.json +0 -177
  314. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  315. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  316. claude_mpm/agents/templates/version_control.json +0 -157
  317. claude_mpm/agents/templates/web_qa.json +0 -399
  318. claude_mpm/agents/templates/web_ui.json +0 -189
  319. claude_mpm/commands/mpm-tickets.md +0 -102
  320. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  321. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  322. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  323. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  324. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  325. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  326. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  327. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  328. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  329. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  330. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  331. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  332. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  333. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  334. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  335. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  336. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  337. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  338. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  339. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  340. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  341. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  342. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  343. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  344. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  345. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  346. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  347. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  348. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  349. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  350. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  351. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  352. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  353. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  354. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  355. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  356. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  357. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  358. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  359. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  360. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  361. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  362. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  363. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  364. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  365. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  366. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  367. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  368. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  369. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  370. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  371. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  372. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  373. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  374. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  375. claude_mpm/dashboard/static/built/react/events.js +0 -30
  376. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  377. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  378. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  379. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  380. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  381. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  382. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  383. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  384. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  385. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  386. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  387. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  388. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  389. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  390. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  391. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  392. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  393. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  394. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  395. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  396. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  397. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  398. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  399. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  400. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  401. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  402. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  403. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  404. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  405. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  406. claude_mpm/dashboard/static/events.html +0 -607
  407. claude_mpm/dashboard/static/index.html +0 -635
  408. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  409. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  410. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  411. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  412. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  413. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  414. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  415. claude_mpm/dashboard/static/legacy/files.html +0 -747
  416. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  417. claude_mpm/dashboard/static/monitors.html +0 -431
  418. claude_mpm/dashboard/static/production/events.html +0 -659
  419. claude_mpm/dashboard/static/production/main.html +0 -698
  420. claude_mpm/dashboard/static/production/monitors.html +0 -483
  421. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  422. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  423. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  424. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  425. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  426. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
  427. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
  428. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
  429. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
  430. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
  431. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
  432. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
  433. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
  434. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
  435. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
  436. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
  437. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
  438. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
  439. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
  440. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
  441. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
  442. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
  443. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  444. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  445. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  446. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  447. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  448. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  449. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  450. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  451. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  452. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  453. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
  454. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
  455. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
  456. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
  457. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
  458. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
  459. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
  460. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  461. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  462. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  463. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  464. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
  465. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
  466. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  467. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  468. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  469. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  470. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
  471. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
  472. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
  473. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
  474. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
  475. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
  476. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
  477. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
  478. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
  479. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
  480. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
  481. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
  482. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
  483. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
  484. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
  485. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
  486. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
  487. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
  488. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
  489. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
  490. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
  491. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
  492. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
  493. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  494. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  495. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  496. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  497. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  498. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  499. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
  500. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
  501. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
  502. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
  503. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
  504. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
  505. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
  506. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
  507. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
  508. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
  509. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
  510. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  511. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  512. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  513. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  514. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/WHEEL +0 -0
  515. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/entry_points.txt +0 -0
  516. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/licenses/LICENSE +0 -0
  517. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/top_level.txt +0 -0
@@ -12,15 +12,21 @@ DESIGN DECISIONS:
12
12
  """
13
13
 
14
14
  import json
15
+ import shutil
15
16
  from pathlib import Path
16
17
  from typing import Dict, List, Optional
17
18
 
19
+ import questionary
20
+ import questionary.constants
21
+ import questionary.prompts.common # For checkbox symbol customization
22
+ from questionary import Style
18
23
  from rich.console import Console
19
24
  from rich.prompt import Confirm, Prompt
20
25
  from rich.text import Text
21
26
 
22
27
  from ...core.config import Config
23
28
  from ...services.version_service import VersionService
29
+ from ...utils.agent_filters import apply_all_filters, get_deployed_agent_ids
24
30
  from ...utils.console import console as default_console
25
31
  from ..shared import BaseCommand, CommandResult
26
32
  from .agent_state_manager import SimpleAgentManager
@@ -41,6 +47,21 @@ from .configure_validators import (
41
47
  class ConfigureCommand(BaseCommand):
42
48
  """Interactive configuration management command."""
43
49
 
50
+ # Questionary style optimized for dark terminals (WCAG AAA compliant)
51
+ QUESTIONARY_STYLE = Style(
52
+ [
53
+ ("selected", "fg:#e0e0e0 bold"), # Light gray - excellent readability
54
+ ("pointer", "fg:#ffd700 bold"), # Gold/yellow - highly visible pointer
55
+ ("highlighted", "fg:#e0e0e0"), # Light gray - clear hover state
56
+ ("question", "fg:#e0e0e0 bold"), # Light gray bold - prominent questions
57
+ ("checkbox", "fg:#00ff00"), # Green - for checked boxes
58
+ (
59
+ "checkbox-selected",
60
+ "fg:#00ff00 bold",
61
+ ), # Green bold - for checked selected boxes
62
+ ]
63
+ )
64
+
44
65
  def __init__(self):
45
66
  super().__init__("configure")
46
67
  self.console = default_console
@@ -284,61 +305,140 @@ class ConfigureCommand(BaseCommand):
284
305
  return self.navigation.show_main_menu()
285
306
 
286
307
  def _manage_agents(self) -> None:
287
- """Agent management interface."""
308
+ """Enhanced agent management with remote agent discovery and installation."""
288
309
  while True:
289
310
  self.console.clear()
290
- self._display_header()
311
+ self.navigation.display_header()
312
+ self.console.print("\n[bold blue]═══ Agent Management ═══[/bold blue]\n")
313
+
314
+ # Step 1: Show configured sources
315
+ self.console.print("[bold white]═══ Agent Sources ═══[/bold white]\n")
316
+
317
+ sources = self._get_configured_sources()
318
+ if sources:
319
+ from rich.table import Table
320
+
321
+ sources_table = Table(show_header=True, header_style="bold white")
322
+ sources_table.add_column(
323
+ "Source",
324
+ style="bright_yellow",
325
+ width=40,
326
+ no_wrap=True,
327
+ overflow="ellipsis",
328
+ )
329
+ sources_table.add_column(
330
+ "Status", style="green", width=15, no_wrap=True
331
+ )
332
+ sources_table.add_column(
333
+ "Agents", style="yellow", width=10, no_wrap=True
334
+ )
291
335
 
292
- # Display available agents
293
- agents = self.agent_manager.discover_agents()
294
- self._display_agents_table(agents)
336
+ for source in sources:
337
+ status = "✓ Active" if source.get("enabled", True) else "Disabled"
338
+ agent_count = source.get("agent_count", "?")
339
+ sources_table.add_row(
340
+ source["identifier"], status, str(agent_count)
341
+ )
295
342
 
296
- # Show agent menu
297
- self.console.print("\n[bold]Agent Management Options:[/bold]")
343
+ self.console.print(sources_table)
344
+ else:
345
+ self.console.print("[yellow]No agent sources configured[/yellow]")
346
+ self.console.print(
347
+ "[dim]Default source 'bobmatnyc/claude-mpm-agents' will be used[/dim]\n"
348
+ )
298
349
 
299
- # Use Text objects to properly display shortcuts with styling
300
- text_t = Text(" ")
301
- text_t.append("[t]", style="bold blue")
302
- text_t.append(" Toggle agents (enable/disable multiple)")
303
- self.console.print(text_t)
350
+ # Step 2: Discover and display available agents
351
+ self.console.print("\n[bold white]═══ Available Agents ═══[/bold white]\n")
304
352
 
305
- text_c = Text(" ")
306
- text_c.append("[c]", style="bold blue")
307
- text_c.append(" Customize agent template")
308
- self.console.print(text_c)
353
+ try:
354
+ # Discover agents (includes both local and remote)
355
+ agents = self.agent_manager.discover_agents(include_remote=True)
309
356
 
310
- text_v = Text(" ")
311
- text_v.append("[v]", style="bold blue")
312
- text_v.append(" View agent details")
313
- self.console.print(text_v)
357
+ # Set deployment status on each agent for display
358
+ deployed_ids = get_deployed_agent_ids()
359
+ for agent in agents:
360
+ # Extract leaf name for comparison
361
+ agent_leaf_name = agent.name.split("/")[-1]
362
+ agent.is_deployed = agent_leaf_name in deployed_ids
314
363
 
315
- text_r = Text(" ")
316
- text_r.append("[r]", style="bold blue")
317
- text_r.append(" Reset agent to defaults")
318
- self.console.print(text_r)
364
+ # Filter BASE_AGENT from display (1M-502 Phase 1)
365
+ agents = self._filter_agent_configs(agents, filter_deployed=False)
319
366
 
320
- text_b = Text(" ")
321
- text_b.append("[b]", style="bold blue")
322
- text_b.append(" Back to main menu")
323
- self.console.print(text_b)
367
+ if not agents:
368
+ self.console.print("[yellow]No agents found[/yellow]")
369
+ self.console.print(
370
+ "[dim]Configure sources with 'claude-mpm agent-source add'[/dim]\n"
371
+ )
372
+ else:
373
+ # Display agents in a table (already filtered at line 339)
374
+ self._display_agents_with_source_info(agents)
324
375
 
325
- self.console.print()
376
+ except Exception as e:
377
+ self.console.print(f"[red]Error discovering agents: {e}[/red]")
378
+ self.logger.error(f"Agent discovery failed: {e}", exc_info=True)
326
379
 
327
- choice = Prompt.ask("[bold blue]Select an option[/bold blue]", default="b")
380
+ # Step 3: Menu options with arrow-key navigation
381
+ self.console.print()
382
+ self.logger.debug("About to show agent management menu")
383
+ try:
384
+ choice = questionary.select(
385
+ "Agent Management:",
386
+ choices=[
387
+ "Manage sources (add/remove repositories)",
388
+ "Select Agents",
389
+ "Install preset (predefined sets)",
390
+ "Remove agents",
391
+ "View agent details",
392
+ "Toggle agents (legacy enable/disable)",
393
+ questionary.Separator(),
394
+ "← Back to main menu",
395
+ ],
396
+ style=self.QUESTIONARY_STYLE,
397
+ ).ask()
398
+
399
+ if choice is None or choice == "← Back to main menu":
400
+ break
328
401
 
329
- if choice == "b":
402
+ agents_var = agents if "agents" in locals() else []
403
+
404
+ # Map selection to action
405
+ if choice == "Manage sources (add/remove repositories)":
406
+ self._manage_sources()
407
+ elif choice == "Select Agents":
408
+ self.logger.debug("User selected 'Select Agents' from menu")
409
+ self._deploy_agents_individual(agents_var)
410
+ elif choice == "Install preset (predefined sets)":
411
+ self._deploy_agents_preset()
412
+ elif choice == "Remove agents":
413
+ self._remove_agents(agents_var)
414
+ elif choice == "View agent details":
415
+ self._view_agent_details_enhanced(agents_var)
416
+ elif choice == "Toggle agents (legacy enable/disable)":
417
+ self._toggle_agents_interactive(agents_var)
418
+
419
+ except KeyboardInterrupt:
420
+ self.console.print("\n[yellow]Operation cancelled[/yellow]")
421
+ break
422
+ except Exception as e:
423
+ # Handle questionary menu failure
424
+ import sys
425
+
426
+ self.logger.error(f"Agent management menu failed: {e}", exc_info=True)
427
+ self.console.print("[red]Error: Interactive menu failed[/red]")
428
+ self.console.print(f"[dim]Reason: {e}[/dim]")
429
+ if not sys.stdin.isatty():
430
+ self.console.print(
431
+ "[dim]Interactive terminal required for this operation[/dim]"
432
+ )
433
+ self.console.print("[dim]Use command-line options instead:[/dim]")
434
+ self.console.print(
435
+ "[dim] claude-mpm configure --list-agents[/dim]"
436
+ )
437
+ self.console.print(
438
+ "[dim] claude-mpm configure --enable-agent <id>[/dim]"
439
+ )
440
+ Prompt.ask("\nPress Enter to continue")
330
441
  break
331
- if choice == "t":
332
- self._toggle_agents_interactive(agents)
333
- elif choice == "c":
334
- self._customize_agent_template(agents)
335
- elif choice == "v":
336
- self._view_agent_details(agents)
337
- elif choice == "r":
338
- self._reset_agent_defaults(agents)
339
- else:
340
- self.console.print("[red]Invalid choice.[/red]")
341
- Prompt.ask("Press Enter to continue")
342
442
 
343
443
  def _display_agents_table(self, agents: List[AgentConfig]) -> None:
344
444
  """Display a table of available agents."""
@@ -511,6 +611,8 @@ class ConfigureCommand(BaseCommand):
511
611
 
512
612
  # Get list of enabled agents
513
613
  agents = self.agent_manager.discover_agents()
614
+ # Filter BASE_AGENT from all agent operations (1M-502 Phase 1)
615
+ agents = self._filter_agent_configs(agents, filter_deployed=False)
514
616
  enabled_agents = [
515
617
  a.name
516
618
  for a in agents
@@ -554,9 +656,9 @@ class ConfigureCommand(BaseCommand):
554
656
  else:
555
657
  from rich.table import Table
556
658
 
557
- table = Table(show_header=True, header_style="bold cyan")
558
- table.add_column("Agent", style="yellow")
559
- table.add_column("Skills", style="green")
659
+ table = Table(show_header=True, header_style="bold white")
660
+ table.add_column("Agent", style="white", no_wrap=True)
661
+ table.add_column("Skills", style="green", no_wrap=True)
560
662
 
561
663
  for agent_id, skills in mappings.items():
562
664
  skills_str = (
@@ -577,6 +679,8 @@ class ConfigureCommand(BaseCommand):
577
679
 
578
680
  # Get enabled agents
579
681
  agents = self.agent_manager.discover_agents()
682
+ # Filter BASE_AGENT from all agent operations (1M-502 Phase 1)
683
+ agents = self._filter_agent_configs(agents, filter_deployed=False)
580
684
  enabled_agents = [
581
685
  a.name
582
686
  for a in agents
@@ -708,6 +812,8 @@ class ConfigureCommand(BaseCommand):
708
812
  def _list_agents_non_interactive(self) -> CommandResult:
709
813
  """List agents in non-interactive mode."""
710
814
  agents = self.agent_manager.discover_agents()
815
+ # Filter BASE_AGENT from all agent lists (1M-502 Phase 1)
816
+ agents = self._filter_agent_configs(agents, filter_deployed=False)
711
817
 
712
818
  data = []
713
819
  for agent in agents:
@@ -809,6 +915,790 @@ class ConfigureCommand(BaseCommand):
809
915
  except Exception as e:
810
916
  return CommandResult.error_result(f"Startup configuration failed: {e}")
811
917
 
918
+ # ========================================================================
919
+ # Enhanced Agent Management Methods (Remote Agent Discovery Integration)
920
+ # ========================================================================
921
+
922
+ def _get_configured_sources(self) -> List[Dict]:
923
+ """Get list of configured agent sources with agent counts."""
924
+ try:
925
+ from claude_mpm.config.agent_sources import AgentSourceConfiguration
926
+
927
+ config = AgentSourceConfiguration.load()
928
+
929
+ # Convert repositories to source dictionaries
930
+ sources = []
931
+ for repo in config.repositories:
932
+ # Extract identifier from repository
933
+ identifier = repo.identifier
934
+
935
+ # Count agents in cache
936
+ cache_dir = (
937
+ Path.home() / ".claude-mpm" / "cache" / "remote-agents" / identifier
938
+ )
939
+ agent_count = 0
940
+ if cache_dir.exists():
941
+ agents_dir = cache_dir / "agents"
942
+ if agents_dir.exists():
943
+ agent_count = len(list(agents_dir.rglob("*.md")))
944
+
945
+ sources.append(
946
+ {
947
+ "identifier": identifier,
948
+ "url": repo.url,
949
+ "enabled": repo.enabled,
950
+ "priority": repo.priority,
951
+ "agent_count": agent_count,
952
+ }
953
+ )
954
+
955
+ return sources
956
+ except Exception as e:
957
+ self.logger.warning(f"Failed to get configured sources: {e}")
958
+ return []
959
+
960
+ def _filter_agent_configs(
961
+ self, agents: List[AgentConfig], filter_deployed: bool = False
962
+ ) -> List[AgentConfig]:
963
+ """Filter AgentConfig objects using agent_filters utilities.
964
+
965
+ Converts AgentConfig objects to dictionaries for filtering,
966
+ then back to AgentConfig. Always filters BASE_AGENT.
967
+ Optionally filters deployed agents.
968
+
969
+ Args:
970
+ agents: List of AgentConfig objects
971
+ filter_deployed: Whether to filter out deployed agents (default: False)
972
+
973
+ Returns:
974
+ Filtered list of AgentConfig objects
975
+ """
976
+ # Convert AgentConfig to dict format for filtering
977
+ agent_dicts = []
978
+ for agent in agents:
979
+ agent_dicts.append(
980
+ {
981
+ "agent_id": agent.name,
982
+ "name": agent.name,
983
+ "description": agent.description,
984
+ "deployed": getattr(agent, "is_deployed", False),
985
+ }
986
+ )
987
+
988
+ # Apply filters (always filter BASE_AGENT)
989
+ filtered_dicts = apply_all_filters(
990
+ agent_dicts, filter_base=True, filter_deployed=filter_deployed
991
+ )
992
+
993
+ # Convert back to AgentConfig objects
994
+ filtered_names = {d["agent_id"] for d in filtered_dicts}
995
+ return [a for a in agents if a.name in filtered_names]
996
+
997
+ @staticmethod
998
+ def _calculate_column_widths(
999
+ terminal_width: int, columns: Dict[str, int]
1000
+ ) -> Dict[str, int]:
1001
+ """Calculate dynamic column widths based on terminal size.
1002
+
1003
+ Args:
1004
+ terminal_width: Current terminal width in characters
1005
+ columns: Dict mapping column names to minimum widths
1006
+
1007
+ Returns:
1008
+ Dict mapping column names to calculated widths
1009
+
1010
+ Design:
1011
+ - Ensures minimum widths are respected
1012
+ - Distributes extra space proportionally
1013
+ - Handles narrow terminals gracefully (minimum 80 chars)
1014
+ """
1015
+ # Ensure minimum terminal width
1016
+ min_terminal_width = 80
1017
+ terminal_width = max(terminal_width, min_terminal_width)
1018
+
1019
+ # Calculate total minimum width needed
1020
+ total_min_width = sum(columns.values())
1021
+
1022
+ # Account for table borders and padding (2 chars per column + 2 for edges)
1023
+ overhead = (len(columns) * 2) + 2
1024
+ available_width = terminal_width - overhead
1025
+
1026
+ # If we have extra space, distribute proportionally
1027
+ if available_width > total_min_width:
1028
+ extra_space = available_width - total_min_width
1029
+ total_weight = sum(columns.values())
1030
+
1031
+ result = {}
1032
+ for col_name, min_width in columns.items():
1033
+ # Distribute extra space based on minimum width proportion
1034
+ proportion = min_width / total_weight
1035
+ extra = int(extra_space * proportion)
1036
+ result[col_name] = min_width + extra
1037
+ return result
1038
+ # Terminal too narrow, use minimum widths
1039
+ return columns.copy()
1040
+
1041
+ def _display_agents_with_source_info(self, agents: List[AgentConfig]) -> None:
1042
+ """Display agents table with source information and installation status."""
1043
+ from rich.table import Table
1044
+
1045
+ # Get terminal width and calculate dynamic column widths
1046
+ terminal_width = shutil.get_terminal_size().columns
1047
+ min_widths = {
1048
+ "#": 4,
1049
+ "Agent ID": 30,
1050
+ "Name": 20,
1051
+ "Source": 15,
1052
+ "Status": 10,
1053
+ }
1054
+ widths = self._calculate_column_widths(terminal_width, min_widths)
1055
+
1056
+ agents_table = Table(show_header=True, header_style="bold white")
1057
+ agents_table.add_column("#", style="dim", width=widths["#"], no_wrap=True)
1058
+ agents_table.add_column(
1059
+ "Agent ID",
1060
+ style="white",
1061
+ width=widths["Agent ID"],
1062
+ no_wrap=True,
1063
+ overflow="ellipsis",
1064
+ )
1065
+ agents_table.add_column(
1066
+ "Name",
1067
+ style="white",
1068
+ width=widths["Name"],
1069
+ no_wrap=True,
1070
+ overflow="ellipsis",
1071
+ )
1072
+ agents_table.add_column(
1073
+ "Source",
1074
+ style="bright_yellow",
1075
+ width=widths["Source"],
1076
+ no_wrap=True,
1077
+ )
1078
+ agents_table.add_column(
1079
+ "Status", style="white", width=widths["Status"], no_wrap=True
1080
+ )
1081
+
1082
+ for idx, agent in enumerate(agents, 1):
1083
+ # Determine source with repo name
1084
+ source_type = getattr(agent, "source_type", "local")
1085
+
1086
+ if source_type == "remote":
1087
+ # Get repo name from agent metadata
1088
+ source_dict = getattr(agent, "source_dict", {})
1089
+ repo_url = source_dict.get("source", "")
1090
+
1091
+ # Extract repo name from URL
1092
+ if (
1093
+ "bobmatnyc/claude-mpm" in repo_url
1094
+ or "claude-mpm" in repo_url.lower()
1095
+ ):
1096
+ source_label = "MPM Agents"
1097
+ elif "/" in repo_url:
1098
+ # Extract last part of org/repo
1099
+ parts = repo_url.rstrip("/").split("/")
1100
+ if len(parts) >= 2:
1101
+ source_label = f"{parts[-2]}/{parts[-1]}"
1102
+ else:
1103
+ source_label = "Community"
1104
+ else:
1105
+ source_label = "Community"
1106
+ else:
1107
+ source_label = "Local"
1108
+
1109
+ # Determine installation status (removed symbols for cleaner look)
1110
+ is_installed = getattr(agent, "is_deployed", False)
1111
+ if is_installed:
1112
+ status = "[green]Installed[/green]"
1113
+ else:
1114
+ status = "Available"
1115
+
1116
+ # Get display name (for remote agents, use display_name instead of agent_id)
1117
+ display_name = getattr(agent, "display_name", agent.name)
1118
+ # Let overflow="ellipsis" handle truncation automatically
1119
+
1120
+ agents_table.add_row(
1121
+ str(idx), agent.name, display_name, source_label, status
1122
+ )
1123
+
1124
+ self.console.print(agents_table)
1125
+
1126
+ # Show installed vs available count
1127
+ installed_count = sum(1 for a in agents if getattr(a, "is_deployed", False))
1128
+ available_count = len(agents) - installed_count
1129
+ self.console.print(
1130
+ f"\n[green]✓ {installed_count} installed[/green] | "
1131
+ f"[dim]{available_count} available[/dim] | "
1132
+ f"[dim]Total: {len(agents)}[/dim]"
1133
+ )
1134
+
1135
+ def _manage_sources(self) -> None:
1136
+ """Interactive source management."""
1137
+ self.console.print("\n[bold white]═══ Manage Agent Sources ═══[/bold white]\n")
1138
+ self.console.print(
1139
+ "[dim]Use 'claude-mpm agent-source' command to add/remove sources[/dim]"
1140
+ )
1141
+ self.console.print("\nExamples:")
1142
+ self.console.print(" claude-mpm agent-source add <git-url>")
1143
+ self.console.print(" claude-mpm agent-source remove <identifier>")
1144
+ self.console.print(" claude-mpm agent-source list")
1145
+ Prompt.ask("\nPress Enter to continue")
1146
+
1147
+ def _deploy_agents_individual(self, agents: List[AgentConfig]) -> None:
1148
+ """Manage agent installation state (unified install/remove interface)."""
1149
+ if not agents:
1150
+ self.console.print("[yellow]No agents available[/yellow]")
1151
+ Prompt.ask("\nPress Enter to continue")
1152
+ return
1153
+
1154
+ # Get ALL agents (filter BASE_AGENT but keep deployed agents visible)
1155
+ from claude_mpm.utils.agent_filters import (
1156
+ filter_base_agents,
1157
+ get_deployed_agent_ids,
1158
+ )
1159
+
1160
+ # Filter BASE_AGENT but keep deployed agents visible
1161
+ all_agents = filter_base_agents(
1162
+ [
1163
+ {
1164
+ "agent_id": a.name,
1165
+ "name": a.name,
1166
+ "description": a.description,
1167
+ "deployed": getattr(a, "is_deployed", False),
1168
+ }
1169
+ for a in agents
1170
+ ]
1171
+ )
1172
+
1173
+ # Get deployed agent IDs (original state - for calculating final changes)
1174
+ # NOTE: deployed_ids contains LEAF NAMES (e.g., "python-engineer")
1175
+ deployed_ids = get_deployed_agent_ids()
1176
+
1177
+ if not all_agents:
1178
+ self.console.print("[yellow]No agents available[/yellow]")
1179
+ Prompt.ask("\nPress Enter to continue")
1180
+ return
1181
+
1182
+ # Build mapping: leaf name -> full path for deployed agents
1183
+ # This allows comparing deployed_ids (leaf names) with agent.name (full paths)
1184
+ deployed_full_paths = set()
1185
+ for agent in agents:
1186
+ agent_leaf_name = agent.name.split("/")[-1]
1187
+ if agent_leaf_name in deployed_ids:
1188
+ deployed_full_paths.add(agent.name)
1189
+
1190
+ # Track current selection state (starts with deployed full paths, updated after each iteration)
1191
+ current_selection = deployed_full_paths.copy()
1192
+
1193
+ # Loop to allow adjusting selection
1194
+ while True:
1195
+ # Build checkbox choices with pre-selection based on current_selection
1196
+ agent_choices = []
1197
+ agent_map = {} # For lookup after selection
1198
+
1199
+ for agent in agents:
1200
+ if agent.name in {a["agent_id"] for a in all_agents}:
1201
+ display_name = getattr(agent, "display_name", agent.name)
1202
+
1203
+ # Pre-check based on current_selection (full paths)
1204
+ # current_selection contains full paths like "engineer/backend/python-engineer"
1205
+ is_selected = agent.name in current_selection
1206
+
1207
+ # Simple format: "agent/path - Display Name"
1208
+ # Checkbox state (checked/unchecked) indicates installed status
1209
+ choice_text = f"{agent.name}"
1210
+ if display_name and display_name != agent.name:
1211
+ choice_text += f" - {display_name}"
1212
+
1213
+ # Create choice with checked based on current_selection
1214
+ choice = questionary.Choice(
1215
+ title=choice_text, value=agent.name, checked=is_selected
1216
+ )
1217
+
1218
+ agent_choices.append(choice)
1219
+ agent_map[agent.name] = agent
1220
+
1221
+ # Multi-select with pre-selection
1222
+ self.console.print("\n[bold cyan]Manage Agent Installation[/bold cyan]")
1223
+ self.console.print("[dim][✓] Checked = Installed (uncheck to remove)[/dim]")
1224
+ self.console.print(
1225
+ "[dim][ ] Unchecked = Available (check to install)[/dim]"
1226
+ )
1227
+ self.console.print(
1228
+ "[dim]Use arrow keys to navigate, space to toggle, "
1229
+ "Enter to apply changes[/dim]\n"
1230
+ )
1231
+
1232
+ # Monkey-patch questionary symbols for better visibility
1233
+ # Must patch common module directly since it imports constants at load time
1234
+ questionary.prompts.common.INDICATOR_SELECTED = "[✓]"
1235
+ questionary.prompts.common.INDICATOR_UNSELECTED = "[ ]"
1236
+
1237
+ # Pre-selection via checked=True on Choice objects
1238
+ self.logger.debug(
1239
+ "About to show checkbox selection with %d agents", len(agent_choices)
1240
+ )
1241
+
1242
+ try:
1243
+ selected_agent_ids = questionary.checkbox(
1244
+ "Agents:", choices=agent_choices, style=self.QUESTIONARY_STYLE
1245
+ ).ask()
1246
+ except Exception as e:
1247
+ # Handle questionary failure (non-TTY, broken pipe, keyboard interrupt, etc.)
1248
+ import sys
1249
+
1250
+ self.logger.error(f"Questionary checkbox failed: {e}", exc_info=True)
1251
+ self.console.print(
1252
+ "[red]Error: Could not display interactive menu[/red]"
1253
+ )
1254
+ self.console.print(f"[dim]Reason: {e}[/dim]")
1255
+ if not sys.stdin.isatty():
1256
+ self.console.print("[dim]Interactive terminal required. Use:[/dim]")
1257
+ self.console.print(
1258
+ "[dim] --list-agents to see available agents[/dim]"
1259
+ )
1260
+ self.console.print(
1261
+ "[dim] --enable-agent/--disable-agent for scripting[/dim]"
1262
+ )
1263
+ else:
1264
+ self.console.print(
1265
+ "[dim]This might be a terminal compatibility issue.[/dim]"
1266
+ )
1267
+ Prompt.ask("\nPress Enter to continue")
1268
+ return
1269
+
1270
+ # Handle Esc OR non-interactive terminal
1271
+ if selected_agent_ids is None:
1272
+ # Check if we're in a non-interactive environment
1273
+ import sys
1274
+
1275
+ if not sys.stdin.isatty():
1276
+ self.console.print(
1277
+ "[red]Error: Interactive terminal required for agent selection[/red]"
1278
+ )
1279
+ self.console.print(
1280
+ "[dim]Use --list-agents to see available agents[/dim]"
1281
+ )
1282
+ self.console.print(
1283
+ "[dim]Use --enable-agent/--disable-agent for non-interactive mode[/dim]"
1284
+ )
1285
+ else:
1286
+ self.console.print("[yellow]No changes made[/yellow]")
1287
+ Prompt.ask("\nPress Enter to continue")
1288
+ return
1289
+
1290
+ # Update current_selection based on user's choices (full paths)
1291
+ current_selection = set(selected_agent_ids)
1292
+
1293
+ # Determine actions based on ORIGINAL deployed state
1294
+ # Compare full paths to full paths (deployed_full_paths was built from deployed_ids)
1295
+ to_deploy = (
1296
+ current_selection - deployed_full_paths
1297
+ ) # Selected but not originally deployed
1298
+ to_remove = (
1299
+ deployed_full_paths - current_selection
1300
+ ) # Originally deployed but not selected
1301
+
1302
+ if not to_deploy and not to_remove:
1303
+ self.console.print(
1304
+ "[yellow]No changes needed - all selected agents are already installed[/yellow]"
1305
+ )
1306
+ Prompt.ask("\nPress Enter to continue")
1307
+ return
1308
+
1309
+ # Show what will happen
1310
+ self.console.print("\n[bold]Changes to apply:[/bold]")
1311
+ if to_deploy:
1312
+ self.console.print(f"[green]Install {len(to_deploy)} agent(s)[/green]")
1313
+ for agent_id in to_deploy:
1314
+ self.console.print(f" + {agent_id}")
1315
+ if to_remove:
1316
+ self.console.print(f"[red]Remove {len(to_remove)} agent(s)[/red]")
1317
+ for agent_id in to_remove:
1318
+ self.console.print(f" - {agent_id}")
1319
+
1320
+ # Ask user to confirm, adjust, or cancel
1321
+ action = questionary.select(
1322
+ "\nWhat would you like to do?",
1323
+ choices=[
1324
+ questionary.Choice("Apply these changes", value="apply"),
1325
+ questionary.Choice("Adjust selection", value="adjust"),
1326
+ questionary.Choice("Cancel", value="cancel"),
1327
+ ],
1328
+ default="apply",
1329
+ style=self.QUESTIONARY_STYLE,
1330
+ ).ask()
1331
+
1332
+ if action == "cancel":
1333
+ self.console.print("[yellow]Changes cancelled[/yellow]")
1334
+ Prompt.ask("\nPress Enter to continue")
1335
+ return
1336
+ if action == "adjust":
1337
+ # current_selection is already updated, loop will use it
1338
+ continue
1339
+
1340
+ # Execute changes
1341
+ deploy_success = 0
1342
+ deploy_fail = 0
1343
+ remove_success = 0
1344
+ remove_fail = 0
1345
+
1346
+ # Install new agents
1347
+ for agent_id in to_deploy:
1348
+ agent = agent_map.get(agent_id)
1349
+ if agent and self._deploy_single_agent(agent, show_feedback=False):
1350
+ deploy_success += 1
1351
+ self.console.print(f"[green]✓ Installed: {agent_id}[/green]")
1352
+ else:
1353
+ deploy_fail += 1
1354
+ self.console.print(f"[red]✗ Failed to install: {agent_id}[/red]")
1355
+
1356
+ # Remove agents
1357
+ for agent_id in to_remove:
1358
+ try:
1359
+ import json
1360
+ from pathlib import Path
1361
+
1362
+ # Remove from project, legacy, and user locations
1363
+ project_path = (
1364
+ Path.cwd() / ".claude-mpm" / "agents" / f"{agent_id}.md"
1365
+ )
1366
+ legacy_path = Path.cwd() / ".claude" / "agents" / f"{agent_id}.md"
1367
+ user_path = Path.home() / ".claude" / "agents" / f"{agent_id}.md"
1368
+
1369
+ removed = False
1370
+ for path in [project_path, legacy_path, user_path]:
1371
+ if path.exists():
1372
+ path.unlink()
1373
+ removed = True
1374
+
1375
+ # Also remove from virtual deployment state
1376
+ deployment_state_paths = [
1377
+ Path.cwd() / ".claude" / "agents" / ".mpm_deployment_state",
1378
+ Path.home() / ".claude" / "agents" / ".mpm_deployment_state",
1379
+ ]
1380
+
1381
+ for state_path in deployment_state_paths:
1382
+ if state_path.exists():
1383
+ try:
1384
+ with state_path.open() as f:
1385
+ state = json.load(f)
1386
+
1387
+ # Remove agent from deployment state
1388
+ agents = state.get("last_check_results", {}).get(
1389
+ "agents", {}
1390
+ )
1391
+ if agent_id in agents:
1392
+ del agents[agent_id]
1393
+ removed = True
1394
+
1395
+ # Save updated state
1396
+ with state_path.open("w") as f:
1397
+ json.dump(state, f, indent=2)
1398
+ except (json.JSONDecodeError, KeyError) as e:
1399
+ # Log but don't fail - physical removal still counts
1400
+ self.logger.debug(
1401
+ f"Failed to update deployment state at {state_path}: {e}"
1402
+ )
1403
+
1404
+ if removed:
1405
+ remove_success += 1
1406
+ self.console.print(f"[green]✓ Removed: {agent_id}[/green]")
1407
+ else:
1408
+ remove_fail += 1
1409
+ self.console.print(f"[yellow]⚠ Not found: {agent_id}[/yellow]")
1410
+ except Exception as e:
1411
+ remove_fail += 1
1412
+ self.console.print(f"[red]✗ Failed to remove {agent_id}: {e}[/red]")
1413
+
1414
+ # Show summary
1415
+ self.console.print()
1416
+ if deploy_success > 0:
1417
+ self.console.print(
1418
+ f"[green]✓ Installed {deploy_success} agent(s)[/green]"
1419
+ )
1420
+ if deploy_fail > 0:
1421
+ self.console.print(
1422
+ f"[red]✗ Failed to install {deploy_fail} agent(s)[/red]"
1423
+ )
1424
+ if remove_success > 0:
1425
+ self.console.print(
1426
+ f"[green]✓ Removed {remove_success} agent(s)[/green]"
1427
+ )
1428
+ if remove_fail > 0:
1429
+ self.console.print(
1430
+ f"[red]✗ Failed to remove {remove_fail} agent(s)[/red]"
1431
+ )
1432
+
1433
+ Prompt.ask("\nPress Enter to continue")
1434
+ # Exit the loop after successful execution
1435
+ break
1436
+
1437
+ def _deploy_agents_preset(self) -> None:
1438
+ """Install agents using preset configuration."""
1439
+ try:
1440
+ from claude_mpm.services.agents.agent_preset_service import (
1441
+ AgentPresetService,
1442
+ )
1443
+ from claude_mpm.services.agents.git_source_manager import GitSourceManager
1444
+
1445
+ source_manager = GitSourceManager()
1446
+ preset_service = AgentPresetService(source_manager)
1447
+
1448
+ presets = preset_service.list_presets()
1449
+
1450
+ if not presets:
1451
+ self.console.print("[yellow]No presets available[/yellow]")
1452
+ Prompt.ask("\nPress Enter to continue")
1453
+ return
1454
+
1455
+ self.console.print("\n[bold white]═══ Available Presets ═══[/bold white]\n")
1456
+ for idx, preset in enumerate(presets, 1):
1457
+ self.console.print(f" {idx}. [white]{preset['name']}[/white]")
1458
+ self.console.print(f" {preset['description']}")
1459
+ self.console.print(f" [dim]Agents: {len(preset['agents'])}[/dim]\n")
1460
+
1461
+ selection = Prompt.ask("\nEnter preset number (or 'c' to cancel)")
1462
+ if selection.lower() == "c":
1463
+ return
1464
+
1465
+ idx = int(selection) - 1
1466
+ if 0 <= idx < len(presets):
1467
+ preset_name = presets[idx]["name"]
1468
+
1469
+ # Resolve and deploy preset
1470
+ resolution = preset_service.resolve_agents(preset_name)
1471
+
1472
+ if resolution.get("missing_agents"):
1473
+ self.console.print(
1474
+ f"[red]Missing agents: {len(resolution['missing_agents'])}[/red]"
1475
+ )
1476
+ for agent_id in resolution["missing_agents"]:
1477
+ self.console.print(f" • {agent_id}")
1478
+ Prompt.ask("\nPress Enter to continue")
1479
+ return
1480
+
1481
+ # Confirm installation
1482
+ self.console.print(
1483
+ f"\n[bold]Preset '{preset_name}' includes {len(resolution['agents'])} agents[/bold]"
1484
+ )
1485
+ if Confirm.ask("Install all agents?", default=True):
1486
+ installed = 0
1487
+ for agent in resolution["agents"]:
1488
+ # Convert dict to AgentConfig-like object for installation
1489
+ agent_config = AgentConfig(
1490
+ name=agent.get("agent_id", "unknown"),
1491
+ description=agent.get("metadata", {}).get(
1492
+ "description", ""
1493
+ ),
1494
+ dependencies=[],
1495
+ )
1496
+ agent_config.source_dict = agent
1497
+ agent_config.full_agent_id = agent.get("agent_id", "unknown")
1498
+
1499
+ if self._deploy_single_agent(agent_config, show_feedback=False):
1500
+ installed += 1
1501
+
1502
+ self.console.print(
1503
+ f"\n[green]✓ Installed {installed}/{len(resolution['agents'])} agents[/green]"
1504
+ )
1505
+
1506
+ Prompt.ask("\nPress Enter to continue")
1507
+ else:
1508
+ self.console.print("[red]Invalid selection[/red]")
1509
+ Prompt.ask("\nPress Enter to continue")
1510
+
1511
+ except Exception as e:
1512
+ self.console.print(f"[red]Error installing preset: {e}[/red]")
1513
+ self.logger.error(f"Preset installation failed: {e}", exc_info=True)
1514
+ Prompt.ask("\nPress Enter to continue")
1515
+
1516
+ def _deploy_single_agent(
1517
+ self, agent: AgentConfig, show_feedback: bool = True
1518
+ ) -> bool:
1519
+ """Install a single agent to the appropriate location."""
1520
+ try:
1521
+ # Check if this is a remote agent with source_dict
1522
+ source_dict = getattr(agent, "source_dict", None)
1523
+ full_agent_id = getattr(agent, "full_agent_id", agent.name)
1524
+
1525
+ if source_dict:
1526
+ # Deploy remote agent using its source file
1527
+ source_file = Path(source_dict.get("source_file", ""))
1528
+ if not source_file.exists():
1529
+ if show_feedback:
1530
+ self.console.print(
1531
+ f"[red]✗ Source file not found: {source_file}[/red]"
1532
+ )
1533
+ return False
1534
+
1535
+ # Determine target file name (use leaf name from hierarchical ID)
1536
+ if "/" in full_agent_id:
1537
+ target_name = full_agent_id.split("/")[-1] + ".md"
1538
+ else:
1539
+ target_name = full_agent_id + ".md"
1540
+
1541
+ # Deploy to user-level agents directory
1542
+ target_dir = Path.home() / ".claude" / "agents"
1543
+ target_dir.mkdir(parents=True, exist_ok=True)
1544
+ target_file = target_dir / target_name
1545
+
1546
+ if show_feedback:
1547
+ self.console.print(
1548
+ f"\n[white]Installing {full_agent_id}...[/white]"
1549
+ )
1550
+
1551
+ # Copy the agent file
1552
+ import shutil
1553
+
1554
+ shutil.copy2(source_file, target_file)
1555
+
1556
+ if show_feedback:
1557
+ self.console.print(
1558
+ f"[green]✓ Successfully installed {full_agent_id} to {target_file}[/green]"
1559
+ )
1560
+ Prompt.ask("\nPress Enter to continue")
1561
+
1562
+ return True
1563
+ # Legacy local template installation (not implemented here)
1564
+ if show_feedback:
1565
+ self.console.print(
1566
+ "[yellow]Local template installation not yet implemented[/yellow]"
1567
+ )
1568
+ Prompt.ask("\nPress Enter to continue")
1569
+ return False
1570
+
1571
+ except Exception as e:
1572
+ if show_feedback:
1573
+ self.console.print(f"[red]Error installing agent: {e}[/red]")
1574
+ self.logger.error(f"Agent installation failed: {e}", exc_info=True)
1575
+ Prompt.ask("\nPress Enter to continue")
1576
+ return False
1577
+
1578
+ def _remove_agents(self, agents: List[AgentConfig]) -> None:
1579
+ """Remove installed agents."""
1580
+ # Filter to installed agents only
1581
+ installed = [a for a in agents if getattr(a, "is_deployed", False)]
1582
+
1583
+ if not installed:
1584
+ self.console.print("[yellow]No agents are currently installed[/yellow]")
1585
+ Prompt.ask("\nPress Enter to continue")
1586
+ return
1587
+
1588
+ self.console.print(f"\n[bold]Installed agents ({len(installed)}):[/bold]")
1589
+ for idx, agent in enumerate(installed, 1):
1590
+ display_name = getattr(agent, "display_name", agent.name)
1591
+ self.console.print(f" {idx}. {agent.name} - {display_name}")
1592
+
1593
+ selection = Prompt.ask("\nEnter agent number to remove (or 'c' to cancel)")
1594
+ if selection.lower() == "c":
1595
+ return
1596
+
1597
+ try:
1598
+ idx = int(selection) - 1
1599
+ if 0 <= idx < len(installed):
1600
+ agent = installed[idx]
1601
+ full_agent_id = getattr(agent, "full_agent_id", agent.name)
1602
+
1603
+ # Determine possible file names (hierarchical and leaf)
1604
+ file_names = [f"{full_agent_id}.md"]
1605
+ if "/" in full_agent_id:
1606
+ leaf_name = full_agent_id.split("/")[-1]
1607
+ file_names.append(f"{leaf_name}.md")
1608
+
1609
+ # Remove from both project and user directories
1610
+ removed = False
1611
+ project_agent_dir = Path.cwd() / ".claude-mpm" / "agents"
1612
+ user_agent_dir = Path.home() / ".claude" / "agents"
1613
+
1614
+ for file_name in file_names:
1615
+ project_file = project_agent_dir / file_name
1616
+ user_file = user_agent_dir / file_name
1617
+
1618
+ if project_file.exists():
1619
+ project_file.unlink()
1620
+ removed = True
1621
+ self.console.print(f"[green]✓ Removed {project_file}[/green]")
1622
+
1623
+ if user_file.exists():
1624
+ user_file.unlink()
1625
+ removed = True
1626
+ self.console.print(f"[green]✓ Removed {user_file}[/green]")
1627
+
1628
+ if removed:
1629
+ self.console.print(
1630
+ f"[green]✓ Successfully removed {full_agent_id}[/green]"
1631
+ )
1632
+ else:
1633
+ self.console.print("[yellow]Agent files not found[/yellow]")
1634
+
1635
+ Prompt.ask("\nPress Enter to continue")
1636
+ else:
1637
+ self.console.print("[red]Invalid selection[/red]")
1638
+ Prompt.ask("\nPress Enter to continue")
1639
+
1640
+ except (ValueError, IndexError):
1641
+ self.console.print("[red]Invalid selection[/red]")
1642
+ Prompt.ask("\nPress Enter to continue")
1643
+
1644
+ def _view_agent_details_enhanced(self, agents: List[AgentConfig]) -> None:
1645
+ """View detailed agent information with enhanced remote agent details."""
1646
+ if not agents:
1647
+ self.console.print("[yellow]No agents available[/yellow]")
1648
+ Prompt.ask("\nPress Enter to continue")
1649
+ return
1650
+
1651
+ self.console.print(f"\n[bold]Available agents ({len(agents)}):[/bold]")
1652
+ for idx, agent in enumerate(agents, 1):
1653
+ display_name = getattr(agent, "display_name", agent.name)
1654
+ self.console.print(f" {idx}. {agent.name} - {display_name}")
1655
+
1656
+ selection = Prompt.ask("\nEnter agent number to view (or 'c' to cancel)")
1657
+ if selection.lower() == "c":
1658
+ return
1659
+
1660
+ try:
1661
+ idx = int(selection) - 1
1662
+ if 0 <= idx < len(agents):
1663
+ agent = agents[idx]
1664
+
1665
+ self.console.clear()
1666
+ self.console.print("\n[bold white]═══ Agent Details ═══[/bold white]\n")
1667
+
1668
+ # Basic info
1669
+ self.console.print(f"[bold]ID:[/bold] {agent.name}")
1670
+ display_name = getattr(agent, "display_name", "N/A")
1671
+ self.console.print(f"[bold]Name:[/bold] {display_name}")
1672
+ self.console.print(f"[bold]Description:[/bold] {agent.description}")
1673
+
1674
+ # Source info
1675
+ source_type = getattr(agent, "source_type", "local")
1676
+ self.console.print(f"[bold]Source Type:[/bold] {source_type}")
1677
+
1678
+ if source_type == "remote":
1679
+ source_dict = getattr(agent, "source_dict", {})
1680
+ category = source_dict.get("category", "N/A")
1681
+ source = source_dict.get("source", "N/A")
1682
+ version = source_dict.get("version", "N/A")
1683
+
1684
+ self.console.print(f"[bold]Category:[/bold] {category}")
1685
+ self.console.print(f"[bold]Source:[/bold] {source}")
1686
+ self.console.print(f"[bold]Version:[/bold] {version[:16]}...")
1687
+
1688
+ # Installation status
1689
+ is_installed = getattr(agent, "is_deployed", False)
1690
+ status = "Installed" if is_installed else "Available"
1691
+ self.console.print(f"[bold]Status:[/bold] {status}")
1692
+
1693
+ Prompt.ask("\nPress Enter to continue")
1694
+ else:
1695
+ self.console.print("[red]Invalid selection[/red]")
1696
+ Prompt.ask("\nPress Enter to continue")
1697
+
1698
+ except (ValueError, IndexError):
1699
+ self.console.print("[red]Invalid selection[/red]")
1700
+ Prompt.ask("\nPress Enter to continue")
1701
+
812
1702
 
813
1703
  def manage_configure(args) -> int:
814
1704
  """Main entry point for configuration management command.