claude-mpm 5.0.9__py3-none-any.whl → 5.4.41__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 (263) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +4 -0
  3. claude_mpm/agents/BASE_AGENT.md +164 -0
  4. claude_mpm/agents/{PM_INSTRUCTIONS_TEACH.md → CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md} +721 -41
  5. claude_mpm/agents/MEMORY.md +1 -1
  6. claude_mpm/agents/PM_INSTRUCTIONS.md +468 -468
  7. claude_mpm/agents/WORKFLOW.md +5 -254
  8. claude_mpm/agents/agent_loader.py +13 -44
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/frontmatter_validator.py +70 -2
  11. claude_mpm/agents/templates/circuit-breakers.md +431 -45
  12. claude_mpm/cli/__init__.py +0 -1
  13. claude_mpm/cli/__main__.py +4 -0
  14. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  15. claude_mpm/cli/commands/agent_state_manager.py +18 -27
  16. claude_mpm/cli/commands/agents.py +175 -37
  17. claude_mpm/cli/commands/auto_configure.py +723 -236
  18. claude_mpm/cli/commands/config.py +88 -2
  19. claude_mpm/cli/commands/configure.py +1262 -157
  20. claude_mpm/cli/commands/configure_agent_display.py +25 -6
  21. claude_mpm/cli/commands/mpm_init/core.py +225 -46
  22. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  23. claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
  24. claude_mpm/cli/commands/postmortem.py +1 -1
  25. claude_mpm/cli/commands/profile.py +277 -0
  26. claude_mpm/cli/commands/skills.py +214 -189
  27. claude_mpm/cli/commands/summarize.py +413 -0
  28. claude_mpm/cli/executor.py +21 -3
  29. claude_mpm/cli/interactive/agent_wizard.py +85 -10
  30. claude_mpm/cli/parsers/agents_parser.py +54 -9
  31. claude_mpm/cli/parsers/auto_configure_parser.py +13 -138
  32. claude_mpm/cli/parsers/base_parser.py +12 -0
  33. claude_mpm/cli/parsers/config_parser.py +153 -83
  34. claude_mpm/cli/parsers/profile_parser.py +148 -0
  35. claude_mpm/cli/parsers/skills_parser.py +3 -2
  36. claude_mpm/cli/startup.py +879 -149
  37. claude_mpm/commands/mpm-config.md +28 -0
  38. claude_mpm/commands/mpm-doctor.md +9 -22
  39. claude_mpm/commands/mpm-help.md +5 -287
  40. claude_mpm/commands/mpm-init.md +81 -507
  41. claude_mpm/commands/mpm-monitor.md +15 -402
  42. claude_mpm/commands/mpm-organize.md +120 -0
  43. claude_mpm/commands/mpm-postmortem.md +6 -108
  44. claude_mpm/commands/mpm-session-resume.md +12 -363
  45. claude_mpm/commands/mpm-status.md +5 -69
  46. claude_mpm/commands/mpm-ticket-view.md +52 -495
  47. claude_mpm/commands/mpm-version.md +5 -107
  48. claude_mpm/config/agent_sources.py +27 -0
  49. claude_mpm/core/config.py +2 -4
  50. claude_mpm/core/framework/formatters/content_formatter.py +3 -13
  51. claude_mpm/core/framework/loaders/agent_loader.py +8 -5
  52. claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
  53. claude_mpm/core/framework_loader.py +4 -2
  54. claude_mpm/core/logger.py +13 -0
  55. claude_mpm/core/optimized_startup.py +59 -0
  56. claude_mpm/core/output_style_manager.py +173 -43
  57. claude_mpm/core/shared/config_loader.py +1 -1
  58. claude_mpm/core/socketio_pool.py +3 -3
  59. claude_mpm/core/unified_agent_registry.py +134 -16
  60. claude_mpm/core/unified_config.py +22 -0
  61. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  62. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +1 -0
  63. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +1 -0
  64. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +1 -0
  65. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +1 -0
  66. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +1 -0
  67. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +2 -0
  68. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DjhvlsAc.js +1 -0
  69. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/N4qtv3Hx.js +2 -0
  70. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uj46x2Wr.js +1 -0
  71. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +2 -0
  72. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +1 -0
  73. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.CAGBuiOw.js +1 -0
  74. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +1 -0
  75. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +10 -0
  76. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  77. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  78. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  79. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  80. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  81. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  82. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  83. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  84. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  85. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  86. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  87. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  88. claude_mpm/hooks/claude_hooks/event_handlers.py +211 -78
  89. claude_mpm/hooks/claude_hooks/hook_handler.py +155 -1
  90. claude_mpm/hooks/claude_hooks/installer.py +33 -10
  91. claude_mpm/hooks/claude_hooks/memory_integration.py +28 -0
  92. claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
  93. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  94. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  95. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  96. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  97. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  98. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  99. claude_mpm/hooks/claude_hooks/services/connection_manager.py +30 -6
  100. claude_mpm/hooks/memory_integration_hook.py +46 -1
  101. claude_mpm/init.py +63 -19
  102. claude_mpm/models/agent_definition.py +7 -0
  103. claude_mpm/models/git_repository.py +3 -3
  104. claude_mpm/scripts/claude-hook-handler.sh +58 -18
  105. claude_mpm/scripts/launch_monitor.py +93 -13
  106. claude_mpm/scripts/start_activity_logging.py +0 -0
  107. claude_mpm/services/agents/agent_builder.py +3 -3
  108. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  109. claude_mpm/services/agents/agent_review_service.py +280 -0
  110. claude_mpm/services/agents/cache_git_manager.py +6 -6
  111. claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
  112. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -5
  113. claude_mpm/services/agents/deployment/agent_template_builder.py +5 -3
  114. claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
  115. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +320 -29
  116. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +546 -68
  117. claude_mpm/services/agents/git_source_manager.py +36 -2
  118. claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
  119. claude_mpm/services/agents/recommender.py +5 -3
  120. claude_mpm/services/agents/single_tier_deployment_service.py +2 -2
  121. claude_mpm/services/agents/sources/git_source_sync_service.py +13 -6
  122. claude_mpm/services/agents/startup_sync.py +22 -2
  123. claude_mpm/services/agents/toolchain_detector.py +10 -6
  124. claude_mpm/services/analysis/__init__.py +11 -1
  125. claude_mpm/services/analysis/clone_detector.py +1030 -0
  126. claude_mpm/services/command_deployment_service.py +81 -10
  127. claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
  128. claude_mpm/services/diagnostics/checks/agent_sources_check.py +1 -1
  129. claude_mpm/services/event_bus/config.py +3 -1
  130. claude_mpm/services/git/git_operations_service.py +101 -16
  131. claude_mpm/services/monitor/daemon.py +9 -2
  132. claude_mpm/services/monitor/daemon_manager.py +39 -3
  133. claude_mpm/services/monitor/management/lifecycle.py +8 -1
  134. claude_mpm/services/monitor/server.py +698 -22
  135. claude_mpm/services/pm_skills_deployer.py +676 -0
  136. claude_mpm/services/profile_manager.py +331 -0
  137. claude_mpm/services/project/project_organizer.py +4 -0
  138. claude_mpm/services/self_upgrade_service.py +120 -12
  139. claude_mpm/services/skills/__init__.py +3 -0
  140. claude_mpm/services/skills/git_skill_source_manager.py +130 -2
  141. claude_mpm/services/skills/selective_skill_deployer.py +704 -0
  142. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  143. claude_mpm/services/skills_deployer.py +126 -9
  144. claude_mpm/services/socketio/dashboard_server.py +1 -0
  145. claude_mpm/services/socketio/event_normalizer.py +51 -6
  146. claude_mpm/services/socketio/server/core.py +386 -108
  147. claude_mpm/services/version_control/git_operations.py +103 -0
  148. claude_mpm/skills/skill_manager.py +92 -3
  149. claude_mpm/utils/agent_dependency_loader.py +14 -2
  150. claude_mpm/utils/agent_filters.py +17 -44
  151. claude_mpm/utils/gitignore.py +3 -0
  152. claude_mpm/utils/migration.py +4 -4
  153. claude_mpm/utils/robust_installer.py +47 -3
  154. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/METADATA +57 -87
  155. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/RECORD +160 -211
  156. claude_mpm-5.4.41.dist-info/entry_points.txt +5 -0
  157. claude_mpm-5.4.41.dist-info/licenses/LICENSE +94 -0
  158. claude_mpm-5.4.41.dist-info/licenses/LICENSE-FAQ.md +153 -0
  159. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
  160. claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
  161. claude_mpm/agents/BASE_OPS.md +0 -219
  162. claude_mpm/agents/BASE_PM.md +0 -480
  163. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
  164. claude_mpm/agents/BASE_QA.md +0 -167
  165. claude_mpm/agents/BASE_RESEARCH.md +0 -53
  166. claude_mpm/agents/base_agent_loader.py +0 -601
  167. claude_mpm/cli/commands/agents_detect.py +0 -380
  168. claude_mpm/cli/commands/agents_recommend.py +0 -309
  169. claude_mpm/cli/ticket_cli.py +0 -35
  170. claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
  171. claude_mpm/commands/mpm-agents-detect.md +0 -177
  172. claude_mpm/commands/mpm-agents-list.md +0 -131
  173. claude_mpm/commands/mpm-agents-recommend.md +0 -223
  174. claude_mpm/commands/mpm-config-view.md +0 -150
  175. claude_mpm/commands/mpm-ticket-organize.md +0 -304
  176. claude_mpm/dashboard/analysis_runner.py +0 -455
  177. claude_mpm/dashboard/index.html +0 -13
  178. claude_mpm/dashboard/open_dashboard.py +0 -66
  179. claude_mpm/dashboard/static/css/activity.css +0 -1958
  180. claude_mpm/dashboard/static/css/connection-status.css +0 -370
  181. claude_mpm/dashboard/static/css/dashboard.css +0 -4701
  182. claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
  183. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
  184. claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
  185. claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
  186. claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
  187. claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
  188. claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
  189. claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
  190. claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
  191. claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
  192. claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
  193. claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
  194. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
  195. claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
  196. claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
  197. claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
  198. claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
  199. claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
  200. claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
  201. claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
  202. claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
  203. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
  204. claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
  205. claude_mpm/dashboard/static/js/connection-manager.js +0 -536
  206. claude_mpm/dashboard/static/js/dashboard.js +0 -1914
  207. claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
  208. claude_mpm/dashboard/static/js/socket-client.js +0 -1474
  209. claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
  210. claude_mpm/dashboard/static/socket.io.min.js +0 -7
  211. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
  212. claude_mpm/dashboard/templates/code_simple.html +0 -153
  213. claude_mpm/dashboard/templates/index.html +0 -606
  214. claude_mpm/dashboard/test_dashboard.html +0 -372
  215. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  216. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  217. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  218. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  219. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  220. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  221. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  222. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  223. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  224. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  225. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  226. claude_mpm/scripts/mcp_server.py +0 -75
  227. claude_mpm/scripts/mcp_wrapper.py +0 -39
  228. claude_mpm/services/mcp_gateway/__init__.py +0 -159
  229. claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
  230. claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
  231. claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
  232. claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
  233. claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
  234. claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
  235. claude_mpm/services/mcp_gateway/core/base.py +0 -312
  236. claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
  237. claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
  238. claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
  239. claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
  240. claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
  241. claude_mpm/services/mcp_gateway/main.py +0 -589
  242. claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
  243. claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
  244. claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
  245. claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
  246. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
  247. claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
  248. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
  249. claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
  250. claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
  251. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
  252. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
  253. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
  254. claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
  255. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
  256. claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
  257. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
  258. claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
  259. claude_mpm-5.0.9.dist-info/entry_points.txt +0 -10
  260. claude_mpm-5.0.9.dist-info/licenses/LICENSE +0 -21
  261. /claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +0 -0
  262. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/WHEEL +0 -0
  263. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/top_level.txt +0 -0
@@ -537,7 +537,7 @@ class SkillsManagementCommand(BaseCommand):
537
537
  toolchain = getattr(args, "toolchain", None)
538
538
  categories = getattr(args, "categories", None)
539
539
  force = getattr(args, "force", False)
540
- all_skills = getattr(args, "all", False)
540
+ all_skills = getattr(args, "all_skills", False)
541
541
 
542
542
  if collection:
543
543
  console.print(
@@ -554,17 +554,36 @@ class SkillsManagementCommand(BaseCommand):
554
554
  "[yellow]No toolchain specified. Use --toolchain to filter by language,[/yellow]"
555
555
  )
556
556
  console.print(
557
- "[yellow]or --all to deploy all available skills.[/yellow]\n"
557
+ "[yellow]or --all-skills to deploy all available skills (not just agent-referenced).[/yellow]\n"
558
558
  )
559
559
 
560
+ # Selective deployment is enabled by default (deploy only agent-referenced skills)
561
+ # Use --all-skills to disable selective mode
560
562
  result = self.skills_deployer.deploy_skills(
561
563
  collection=collection,
562
564
  toolchain=toolchain,
563
565
  categories=categories,
564
566
  force=force,
567
+ selective=not all_skills, # Disable selective mode if --all-skills is set
565
568
  )
566
569
 
567
570
  # Display results
571
+ # Show selective mode summary
572
+ if result.get("selective_mode"):
573
+ total_available = result.get("total_available", 0)
574
+ deployed_count = result["deployed_count"]
575
+ console.print(
576
+ f"[cyan]📌 Selective deployment: {deployed_count} agent-referenced skills "
577
+ f"(out of {total_available} available)[/cyan]"
578
+ )
579
+ console.print(
580
+ "[dim]Use --all-skills to deploy all available skills[/dim]\n"
581
+ )
582
+ else:
583
+ console.print(
584
+ "[cyan]📦 Deploying all available skills (selective mode disabled)[/cyan]\n"
585
+ )
586
+
568
587
  if result["deployed_count"] > 0:
569
588
  console.print(
570
589
  f"[green]✓ Deployed {result['deployed_count']} skill(s):[/green]"
@@ -953,23 +972,37 @@ class SkillsManagementCommand(BaseCommand):
953
972
  console.print(f"[red]Unexpected error: {e}[/red]")
954
973
 
955
974
  def _configure_skills(self, args) -> CommandResult:
956
- """Interactive skills configuration with checkbox selection.
975
+ """Interactive skills configuration using configuration.yaml.
957
976
 
958
977
  Provides checkbox-based selection interface matching agents configure UX:
959
- - Status column showing Installed/Available
960
- - Pre-selection for installed skills
961
- - Apply/Adjust/Cancel menu
962
- - While loop for adjustment
963
- - Simplified labels (checkbox state only)
964
-
965
- This is Option 3 (Hybrid approach): Separate command for interactive mode
966
- while keeping deploy-github for CLI automation.
978
+ - Shows current mode (user_defined vs agent_referenced)
979
+ - If agent mode: shows agent-scanned skills
980
+ - Allows switching to user_defined mode and selecting skills
981
+ - Can reset to agent mode (clears user_defined)
982
+ - Saves selections to configuration.yaml
983
+
984
+ Configuration structure:
985
+ ```yaml
986
+ skills:
987
+ agent_referenced: # Auto-populated from agent scan (read-only)
988
+ - systematic-debugging
989
+ - typescript-core
990
+ user_defined: # User override - if set, ONLY these are deployed
991
+ [] # Empty = use agent_referenced
992
+ ```
967
993
  """
968
994
  try:
995
+ from pathlib import Path
996
+
969
997
  import questionary
998
+ import yaml
970
999
  from questionary import Choice, Style
971
1000
  from rich.prompt import Prompt
972
1001
 
1002
+ from ...services.skills.selective_skill_deployer import (
1003
+ get_skills_to_deploy,
1004
+ )
1005
+
973
1006
  # Questionary style (matching agents configure)
974
1007
  QUESTIONARY_STYLE = Style(
975
1008
  [
@@ -994,203 +1027,197 @@ class SkillsManagementCommand(BaseCommand):
994
1027
  ]
995
1028
  )
996
1029
 
997
- console.print("\n[bold cyan]Interactive Skills Configuration[/bold cyan]\n")
998
- console.print(
999
- "[dim]Select skills to install/uninstall using checkboxes[/dim]"
1000
- )
1001
- console.print("[dim]● = Installed, ○ = Available[/dim]\n")
1030
+ console.print("\n[bold cyan]Skills Configuration Manager[/bold cyan]\n")
1002
1031
 
1003
- # Get deployed skills for status detection
1004
- deployed_result = self.skills_deployer.check_deployed_skills()
1005
- deployed_skills = {
1006
- skill["name"] for skill in deployed_result.get("skills", [])
1007
- }
1032
+ # Load current configuration
1033
+ project_config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
1034
+ skills_to_deploy, current_mode = get_skills_to_deploy(project_config_path)
1008
1035
 
1009
- # Get available skills from GitHub
1010
- console.print("[dim]Fetching available skills from GitHub...[/dim]\n")
1011
- available_result = self.skills_deployer.list_available_skills()
1036
+ # Display current mode and skill count
1037
+ console.print(f"[bold]Current Mode:[/bold] [cyan]{current_mode}[/cyan]")
1038
+ console.print(
1039
+ f"[bold]Active Skills:[/bold] {len(skills_to_deploy)} skills\n"
1040
+ )
1012
1041
 
1013
- if available_result.get("error"):
1014
- console.print(f"[red]Error: {available_result['error']}[/red]")
1015
- return CommandResult(
1016
- success=False, message=available_result["error"], exit_code=1
1042
+ if current_mode == "agent_referenced":
1043
+ console.print(
1044
+ "[dim]Agent mode: Skills are auto-detected from deployed agents[/dim]"
1045
+ )
1046
+ console.print(
1047
+ "[dim]Switch to user mode to manually select skills[/dim]\n"
1017
1048
  )
1049
+ else:
1050
+ console.print(
1051
+ "[dim]User mode: You've manually selected which skills to deploy[/dim]"
1052
+ )
1053
+ console.print("[dim]Reset to agent mode to use auto-detection[/dim]\n")
1054
+
1055
+ # Offer mode switching
1056
+ action_choices = [
1057
+ Choice("View current skills", value="view"),
1058
+ Choice("Switch to user mode (manual selection)", value="switch_user"),
1059
+ Choice("Reset to agent mode (auto-detection)", value="reset_agent"),
1060
+ Choice("Cancel", value="cancel"),
1061
+ ]
1062
+
1063
+ action = questionary.select(
1064
+ "What would you like to do?",
1065
+ choices=action_choices,
1066
+ style=QUESTIONARY_STYLE,
1067
+ ).ask()
1068
+
1069
+ if action == "cancel" or action is None:
1070
+ console.print("[yellow]Configuration cancelled[/yellow]")
1071
+ return CommandResult(success=True, exit_code=0)
1018
1072
 
1019
- # Flatten skills by category
1020
- all_skills = []
1021
- for category, skills in available_result.get("by_category", {}).items():
1022
- for skill in skills:
1023
- skill_info = {
1024
- "name": skill.get("name", "unknown"),
1025
- "category": category,
1026
- "is_deployed": skill.get("name", "unknown") in deployed_skills,
1027
- }
1028
- all_skills.append(skill_info)
1029
-
1030
- # Sort by deployed status (deployed first), then by name
1031
- all_skills.sort(key=lambda s: (not s["is_deployed"], s["name"]))
1032
-
1033
- # Build checkbox choices with pre-selection
1034
- # Loop to allow adjusting selection
1035
- while True:
1036
- skill_choices = []
1037
- skill_map = {} # For lookup after selection
1038
-
1039
- for skill in all_skills:
1040
- skill_name = skill["name"]
1041
- category = skill["category"]
1042
- is_deployed = skill["is_deployed"]
1043
-
1044
- # Simple format: "skill-name (category)"
1045
- # Checkbox state (checked/unchecked) indicates installed status
1046
- choice_text = f"{skill_name} ({category})"
1047
-
1048
- # Pre-select if deployed
1049
- choice = Choice(
1050
- title=choice_text, value=skill_name, checked=is_deployed
1051
- )
1073
+ if action == "view":
1074
+ # Display current skills
1075
+ console.print("\n[bold]Current Skills:[/bold]\n")
1076
+ for skill in sorted(skills_to_deploy):
1077
+ console.print(f" • {skill}")
1078
+ console.print()
1079
+ Prompt.ask("\nPress Enter to continue")
1080
+ return CommandResult(success=True, exit_code=0)
1052
1081
 
1053
- skill_choices.append(choice)
1054
- skill_map[skill_name] = skill
1082
+ if action == "reset_agent":
1083
+ # Reset to agent mode by clearing user_defined
1084
+ with open(project_config_path, encoding="utf-8") as f:
1085
+ config = yaml.safe_load(f) or {}
1055
1086
 
1056
- # Display checkbox selection
1057
- selected_skills = questionary.checkbox(
1058
- "Select skills (Space to toggle, Enter to confirm):",
1059
- choices=skill_choices,
1060
- style=QUESTIONARY_STYLE,
1061
- ).ask()
1087
+ if "skills" not in config:
1088
+ config["skills"] = {}
1062
1089
 
1063
- if selected_skills is None:
1064
- # User cancelled (Ctrl+C)
1065
- console.print("[yellow]Skills configuration cancelled[/yellow]")
1066
- return CommandResult(success=True, exit_code=0)
1090
+ config["skills"]["user_defined"] = []
1067
1091
 
1068
- # Determine changes
1069
- to_install = []
1070
- to_remove = []
1092
+ with open(project_config_path, "w", encoding="utf-8") as f:
1093
+ yaml.dump(config, f, default_flow_style=False, sort_keys=False)
1071
1094
 
1072
- for skill in all_skills:
1073
- skill_name = skill["name"]
1074
- is_deployed = skill["is_deployed"]
1075
- is_selected = skill_name in selected_skills
1095
+ console.print(
1096
+ "\n[green]✓ Reset to agent mode - skills will be auto-detected from agents[/green]\n"
1097
+ )
1098
+ Prompt.ask("\nPress Enter to continue")
1099
+ return CommandResult(success=True, exit_code=0)
1076
1100
 
1077
- if is_selected and not is_deployed:
1078
- to_install.append(skill_name)
1079
- elif not is_selected and is_deployed:
1080
- to_remove.append(skill_name)
1101
+ # Switch to user mode - manual skill selection
1102
+ if action == "switch_user":
1103
+ console.print(
1104
+ "\n[bold cyan]Switching to User Mode - Manual Skill Selection[/bold cyan]\n"
1105
+ )
1106
+ console.print("[dim]Fetching available skills from GitHub...[/dim]\n")
1081
1107
 
1082
- # Show summary of changes
1083
- console.print("\n[bold]Changes to apply:[/bold]")
1084
- if to_install:
1085
- console.print(
1086
- f"\n[green]✓ Install ({len(to_install)} skills):[/green]"
1087
- )
1088
- for skill in to_install:
1089
- console.print(f" • {skill}")
1108
+ # Get available skills
1109
+ available_result = self.skills_deployer.list_available_skills()
1090
1110
 
1091
- if to_remove:
1092
- console.print(
1093
- f"\n[yellow]✗ Remove ({len(to_remove)} skills):[/yellow]"
1111
+ if available_result.get("error"):
1112
+ console.print(f"[red]Error: {available_result['error']}[/red]")
1113
+ return CommandResult(
1114
+ success=False, message=available_result["error"], exit_code=1
1094
1115
  )
1095
- for skill in to_remove:
1096
- console.print(f" • {skill}")
1097
1116
 
1098
- if not to_install and not to_remove:
1099
- console.print(
1100
- "\n[dim]No changes (selection matches current deployment)[/dim]"
1101
- )
1117
+ # Flatten skills by category
1118
+ all_skills = []
1119
+ for category, skills in available_result.get("by_category", {}).items():
1120
+ for skill in skills:
1121
+ skill_name = skill.get("name", "unknown")
1122
+ is_currently_selected = skill_name in skills_to_deploy
1123
+ skill_info = {
1124
+ "name": skill_name,
1125
+ "category": category,
1126
+ "is_selected": is_currently_selected,
1127
+ }
1128
+ all_skills.append(skill_info)
1129
+
1130
+ # Sort by selection status (selected first), then by name
1131
+ all_skills.sort(key=lambda s: (not s["is_selected"], s["name"]))
1132
+
1133
+ # Build checkbox choices
1134
+ while True:
1135
+ skill_choices = []
1136
+
1137
+ for skill in all_skills:
1138
+ skill_name = skill["name"]
1139
+ category = skill["category"]
1140
+ is_selected = skill["is_selected"]
1141
+
1142
+ # Format: "skill-name (category)"
1143
+ choice_text = f"{skill_name} ({category})"
1144
+
1145
+ # Pre-select if currently in skills_to_deploy
1146
+ choice = Choice(
1147
+ title=choice_text, value=skill_name, checked=is_selected
1148
+ )
1102
1149
 
1103
- console.print()
1150
+ skill_choices.append(choice)
1151
+
1152
+ # Display checkbox selection
1153
+ selected_skills = questionary.checkbox(
1154
+ "Select skills (Space to toggle, Enter to confirm):",
1155
+ choices=skill_choices,
1156
+ style=QUESTIONARY_STYLE,
1157
+ ).ask()
1158
+
1159
+ if selected_skills is None:
1160
+ # User cancelled (Ctrl+C)
1161
+ console.print("[yellow]Skills configuration cancelled[/yellow]")
1162
+ return CommandResult(success=True, exit_code=0)
1163
+
1164
+ # Show summary
1165
+ console.print("\n[bold]Selected Skills:[/bold]")
1166
+ console.print(f" {len(selected_skills)} skills selected\n")
1167
+
1168
+ if selected_skills:
1169
+ for skill in sorted(selected_skills):
1170
+ console.print(f" • {skill}")
1171
+ console.print()
1172
+
1173
+ # Ask user to confirm, adjust, or cancel
1174
+ confirm_action = questionary.select(
1175
+ "\nWhat would you like to do?",
1176
+ choices=[
1177
+ Choice("Save to configuration", value="apply"),
1178
+ Choice("Adjust selection", value="adjust"),
1179
+ Choice("Cancel", value="cancel"),
1180
+ ],
1181
+ default="apply",
1182
+ style=QUESTIONARY_STYLE,
1183
+ ).ask()
1184
+
1185
+ if confirm_action == "cancel":
1186
+ console.print("[yellow]Configuration cancelled[/yellow]")
1187
+ Prompt.ask("\nPress Enter to continue")
1188
+ return CommandResult(success=True, exit_code=0)
1189
+
1190
+ if confirm_action == "adjust":
1191
+ # Update selection state and loop back
1192
+ for skill in all_skills:
1193
+ skill["is_selected"] = skill["name"] in selected_skills
1194
+ console.print("\n[dim]Adjusting selection...[/dim]\n")
1195
+ continue
1196
+
1197
+ # Save to configuration.yaml
1198
+ with open(project_config_path, encoding="utf-8") as f:
1199
+ config = yaml.safe_load(f) or {}
1200
+
1201
+ if "skills" not in config:
1202
+ config["skills"] = {}
1203
+
1204
+ config["skills"]["user_defined"] = sorted(selected_skills)
1205
+
1206
+ with open(project_config_path, "w", encoding="utf-8") as f:
1207
+ yaml.dump(config, f, default_flow_style=False, sort_keys=False)
1104
1208
 
1105
- # Ask user to confirm, adjust, or cancel
1106
- action = questionary.select(
1107
- "\nWhat would you like to do?",
1108
- choices=[
1109
- Choice("Apply these changes", value="apply"),
1110
- Choice("Adjust selection", value="adjust"),
1111
- Choice("Cancel", value="cancel"),
1112
- ],
1113
- default="apply",
1114
- style=QUESTIONARY_STYLE,
1115
- ).ask()
1116
-
1117
- if action == "cancel":
1118
- console.print("[yellow]Changes cancelled[/yellow]")
1119
- Prompt.ask("\nPress Enter to continue")
1120
- return CommandResult(success=True, exit_code=0)
1121
- if action == "adjust":
1122
- # Loop back to skill selection
1123
- console.print("\n[dim]Adjusting selection...[/dim]\n")
1124
- continue
1125
-
1126
- # Apply changes
1127
- success = True
1128
- errors = []
1129
-
1130
- # Install skills
1131
- if to_install:
1132
- console.print("\n[bold cyan]Installing skills...[/bold cyan]\n")
1133
- for skill_name in to_install:
1134
- try:
1135
- # Deploy single skill
1136
- result = self.skills_deployer.deploy_skills(
1137
- skill_names=[skill_name], force=False
1138
- )
1139
-
1140
- if result.get("errors"):
1141
- errors.extend(result["errors"])
1142
- success = False
1143
- else:
1144
- console.print(
1145
- f"[green]✓ Installed: {skill_name}[/green]"
1146
- )
1147
- except Exception as e:
1148
- errors.append(f"Failed to install {skill_name}: {e}")
1149
- success = False
1150
-
1151
- # Remove skills
1152
- if to_remove:
1153
- console.print("\n[bold yellow]Removing skills...[/bold yellow]\n")
1154
- for skill_name in to_remove:
1155
- try:
1156
- # Remove single skill
1157
- result = self.skills_deployer.remove_skills(
1158
- skill_names=[skill_name]
1159
- )
1160
-
1161
- if result.get("errors"):
1162
- errors.extend(result["errors"])
1163
- success = False
1164
- else:
1165
- console.print(
1166
- f"[yellow]✗ Removed: {skill_name}[/yellow]"
1167
- )
1168
- except Exception as e:
1169
- errors.append(f"Failed to remove {skill_name}: {e}")
1170
- success = False
1171
-
1172
- # Show errors if any
1173
- if errors:
1174
- console.print(f"\n[red]✗ {len(errors)} error(s):[/red]")
1175
- for error in errors:
1176
- console.print(f" • {error}")
1177
-
1178
- # Show restart instructions
1179
- if success and (to_install or to_remove):
1180
1209
  console.print(
1181
- "\n[bold green]✓ Changes applied successfully![/bold green]"
1210
+ f"\n[green]✓ Saved {len(selected_skills)} skills to user_defined mode[/green]"
1182
1211
  )
1183
- console.print("\n[yellow]⚠️ Important:[/yellow]")
1184
- console.print(" Restart Claude Code for changes to take effect")
1185
-
1186
- console.print()
1187
- Prompt.ask("\nPress Enter to continue")
1212
+ console.print(
1213
+ "[yellow]⚠️ Important:[/yellow] Run [cyan]claude-mpm init[/cyan] to deploy these skills\n"
1214
+ )
1215
+ Prompt.ask("\nPress Enter to continue")
1188
1216
 
1189
- # Exit the loop after successful execution
1190
- break
1217
+ # Exit the loop after successful save
1218
+ break
1191
1219
 
1192
- exit_code = 0 if success else 1
1193
- return CommandResult(success=success, exit_code=exit_code)
1220
+ return CommandResult(success=True, exit_code=0)
1194
1221
 
1195
1222
  except Exception as e:
1196
1223
  console.print(f"[red]Error in skills configuration: {e}[/red]")
@@ -1199,8 +1226,6 @@ class SkillsManagementCommand(BaseCommand):
1199
1226
  console.print(f"[dim]{traceback.format_exc()}[/dim]")
1200
1227
  return CommandResult(success=False, message=str(e), exit_code=1)
1201
1228
 
1202
- return CommandResult(success=False, message=str(e), exit_code=1)
1203
-
1204
1229
 
1205
1230
  def manage_skills(args) -> int:
1206
1231
  """