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