claude-mpm 5.4.21__py3-none-any.whl → 5.4.59__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 (176) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_AGENT.md +164 -0
  3. claude_mpm/agents/BASE_ENGINEER.md +658 -0
  4. claude_mpm/agents/MEMORY.md +1 -1
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +771 -1019
  6. claude_mpm/agents/WORKFLOW.md +5 -254
  7. claude_mpm/agents/agent_loader.py +1 -1
  8. claude_mpm/agents/base_agent.json +31 -0
  9. claude_mpm/agents/frontmatter_validator.py +2 -2
  10. claude_mpm/cli/commands/agent_state_manager.py +10 -10
  11. claude_mpm/cli/commands/agents.py +9 -9
  12. claude_mpm/cli/commands/auto_configure.py +4 -4
  13. claude_mpm/cli/commands/configure.py +1 -1
  14. claude_mpm/cli/commands/configure_agent_display.py +12 -0
  15. claude_mpm/cli/commands/mpm_init/core.py +72 -0
  16. claude_mpm/cli/commands/postmortem.py +1 -1
  17. claude_mpm/cli/commands/profile.py +276 -0
  18. claude_mpm/cli/commands/skills.py +14 -18
  19. claude_mpm/cli/executor.py +10 -0
  20. claude_mpm/cli/interactive/agent_wizard.py +2 -2
  21. claude_mpm/cli/parsers/base_parser.py +7 -0
  22. claude_mpm/cli/parsers/profile_parser.py +147 -0
  23. claude_mpm/cli/parsers/skills_parser.py +0 -6
  24. claude_mpm/cli/startup.py +506 -180
  25. claude_mpm/commands/mpm-config.md +13 -250
  26. claude_mpm/commands/mpm-doctor.md +9 -22
  27. claude_mpm/commands/mpm-help.md +5 -206
  28. claude_mpm/commands/mpm-init.md +81 -507
  29. claude_mpm/commands/mpm-monitor.md +15 -402
  30. claude_mpm/commands/mpm-organize.md +61 -441
  31. claude_mpm/commands/mpm-postmortem.md +6 -108
  32. claude_mpm/commands/mpm-session-resume.md +12 -363
  33. claude_mpm/commands/mpm-status.md +5 -69
  34. claude_mpm/commands/mpm-ticket-view.md +52 -495
  35. claude_mpm/commands/mpm-version.md +5 -107
  36. claude_mpm/core/config.py +2 -4
  37. claude_mpm/core/framework/loaders/agent_loader.py +1 -1
  38. claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
  39. claude_mpm/core/optimized_startup.py +61 -0
  40. claude_mpm/core/shared/config_loader.py +3 -1
  41. claude_mpm/core/unified_agent_registry.py +1 -1
  42. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  43. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
  44. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
  45. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
  46. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
  47. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
  48. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
  49. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
  50. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
  51. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
  52. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
  53. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  54. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
  55. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
  56. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
  57. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
  58. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
  59. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
  60. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
  61. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
  62. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
  63. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
  64. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
  65. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
  66. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
  67. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  68. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
  69. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
  70. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  71. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
  72. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
  73. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
  74. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
  75. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
  76. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
  77. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
  78. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
  79. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
  80. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  81. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
  82. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
  83. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
  84. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
  85. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
  86. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
  87. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
  88. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
  89. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
  90. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
  91. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  92. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
  93. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
  94. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
  95. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
  96. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
  97. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
  98. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
  99. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
  100. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
  101. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
  102. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
  103. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
  104. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
  105. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
  106. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
  107. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  108. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  109. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  110. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  111. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  112. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  113. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  114. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  115. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  116. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  117. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  118. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  119. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  120. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  121. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  122. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  123. claude_mpm/hooks/claude_hooks/hook_handler.py +149 -1
  124. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  125. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  126. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  127. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  128. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  129. claude_mpm/hooks/claude_hooks/services/connection_manager.py +26 -6
  130. claude_mpm/hooks/kuzu_memory_hook.py +5 -5
  131. claude_mpm/init.py +276 -0
  132. claude_mpm/models/git_repository.py +3 -3
  133. claude_mpm/scripts/start_activity_logging.py +0 -0
  134. claude_mpm/services/agents/agent_builder.py +3 -3
  135. claude_mpm/services/agents/cache_git_manager.py +6 -6
  136. claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
  137. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -2
  138. claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
  139. claude_mpm/services/agents/deployment/agent_template_builder.py +31 -19
  140. claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
  141. claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
  142. claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
  143. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +169 -26
  144. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +98 -75
  145. claude_mpm/services/agents/git_source_manager.py +23 -4
  146. claude_mpm/services/agents/recommender.py +5 -3
  147. claude_mpm/services/agents/single_tier_deployment_service.py +2 -2
  148. claude_mpm/services/agents/sources/git_source_sync_service.py +121 -10
  149. claude_mpm/services/agents/startup_sync.py +22 -2
  150. claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
  151. claude_mpm/services/diagnostics/checks/agent_sources_check.py +1 -1
  152. claude_mpm/services/git/git_operations_service.py +8 -8
  153. claude_mpm/services/monitor/management/lifecycle.py +7 -1
  154. claude_mpm/services/monitor/server.py +473 -3
  155. claude_mpm/services/pm_skills_deployer.py +711 -0
  156. claude_mpm/services/profile_manager.py +337 -0
  157. claude_mpm/services/skills/git_skill_source_manager.py +148 -11
  158. claude_mpm/services/skills/selective_skill_deployer.py +97 -48
  159. claude_mpm/services/skills_deployer.py +161 -65
  160. claude_mpm/services/socketio/dashboard_server.py +1 -0
  161. claude_mpm/services/socketio/event_normalizer.py +37 -6
  162. claude_mpm/services/socketio/server/core.py +262 -123
  163. claude_mpm/skills/bundled/security-scanning.md +112 -0
  164. claude_mpm/skills/skill_manager.py +98 -3
  165. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  166. claude_mpm/utils/agent_dependency_loader.py +14 -2
  167. claude_mpm/utils/agent_filters.py +1 -1
  168. claude_mpm/utils/migration.py +4 -4
  169. claude_mpm/utils/robust_installer.py +47 -3
  170. {claude_mpm-5.4.21.dist-info → claude_mpm-5.4.59.dist-info}/METADATA +7 -4
  171. {claude_mpm-5.4.21.dist-info → claude_mpm-5.4.59.dist-info}/RECORD +175 -81
  172. {claude_mpm-5.4.21.dist-info → claude_mpm-5.4.59.dist-info}/WHEEL +0 -0
  173. {claude_mpm-5.4.21.dist-info → claude_mpm-5.4.59.dist-info}/entry_points.txt +0 -0
  174. {claude_mpm-5.4.21.dist-info → claude_mpm-5.4.59.dist-info}/licenses/LICENSE +0 -0
  175. {claude_mpm-5.4.21.dist-info → claude_mpm-5.4.59.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  176. {claude_mpm-5.4.21.dist-info → claude_mpm-5.4.59.dist-info}/top_level.txt +0 -0
@@ -203,6 +203,10 @@ class MPMInitCommand:
203
203
  if update_mode and result.get("status") == OperationResult.SUCCESS:
204
204
  self._handle_update_post_processing()
205
205
 
206
+ # Deploy PM skills after successful initialization
207
+ if result.get("status") == OperationResult.SUCCESS:
208
+ self._deploy_pm_skills()
209
+
206
210
  return result
207
211
 
208
212
  except Exception as e:
@@ -683,5 +687,73 @@ class MPMInitCommand:
683
687
  """
684
688
  return len(text) // 4
685
689
 
690
+ def _deploy_pm_skills(self) -> None:
691
+ """Deploy PM skills templates to project .claude-mpm directory.
692
+
693
+ Copies PM skills from bundled templates to .claude-mpm/skills/pm/
694
+ with version tracking and checksum validation.
695
+ """
696
+ try:
697
+ from rich.progress import (
698
+ BarColumn,
699
+ Progress,
700
+ TaskProgressColumn,
701
+ TextColumn,
702
+ )
703
+
704
+ from claude_mpm.services.pm_skills_deployer import PMSkillsDeployerService
705
+
706
+ deployer = PMSkillsDeployerService()
707
+
708
+ # Use progress bar for deployment
709
+ with Progress(
710
+ TextColumn("[cyan]Deploying PM skills[/cyan]"),
711
+ BarColumn(bar_width=30),
712
+ TaskProgressColumn(),
713
+ TextColumn("[dim]{task.description}[/dim]"),
714
+ console=self.console,
715
+ ) as progress:
716
+ task = progress.add_task("", total=None) # Unknown total initially
717
+
718
+ def update_progress(skill_name: str, current: int, total: int) -> None:
719
+ progress.update(
720
+ task, total=total, completed=current, description=skill_name
721
+ )
722
+
723
+ result = deployer.deploy_pm_skills(
724
+ self.project_path, progress_callback=update_progress
725
+ )
726
+
727
+ if result.success:
728
+ if result.deployed:
729
+ self.console.print(
730
+ f"[green]✓ Deployed {len(result.deployed)} PM skills[/green]"
731
+ )
732
+
733
+ if result.skipped:
734
+ self.console.print(
735
+ f"[dim] Skipped {len(result.skipped)} (already deployed)[/dim]"
736
+ )
737
+
738
+ if result.errors:
739
+ self.console.print(
740
+ f"[yellow]⚠️ {len(result.errors)} errors:[/yellow]"
741
+ )
742
+ for error in result.errors[:3]: # Show first 3 errors
743
+ self.console.print(f" • {error['skill']}: {error['error']}")
744
+ else:
745
+ self.console.print(
746
+ f"[yellow]⚠️ PM skills deployment had errors: {result.message}[/yellow]"
747
+ )
748
+
749
+ except ImportError as e:
750
+ logger.warning(f"PM skills deployer not available: {e}")
751
+ self.console.print(
752
+ "[yellow]⚠️ PM skills deployment skipped (service not available)[/yellow]"
753
+ )
754
+ except Exception as e:
755
+ logger.error(f"Failed to deploy PM skills: {e}")
756
+ self.console.print(f"[yellow]⚠️ PM skills deployment failed: {e}[/yellow]")
757
+
686
758
 
687
759
  __all__ = ["MPMInitCommand"]
@@ -317,7 +317,7 @@ def _create_prs(report, verbose: bool) -> int:
317
317
  print(f"\n🤖 Creating {len(pr_actions)} PR(s) for agent improvements...")
318
318
 
319
319
  # Check if we're in the agent cache git repo
320
- agent_cache_path = Path.home() / ".claude-mpm" / "cache" / "remote-agents"
320
+ agent_cache_path = Path.home() / ".claude-mpm" / "cache" / "agents"
321
321
 
322
322
  if not agent_cache_path.exists():
323
323
  print(f"❌ Agent cache not found at: {agent_cache_path}")
@@ -0,0 +1,276 @@
1
+ """
2
+ Profile management commands for claude-mpm CLI.
3
+
4
+ WHY: Users need a simple way to manage deployment profiles from the command
5
+ line. Profiles control which agents and skills are deployed, reducing context
6
+ usage by limiting available agents to only what's needed.
7
+
8
+ DESIGN DECISIONS:
9
+ - Use BaseCommand for consistent CLI patterns
10
+ - Provide clear, actionable output with standardized error handling
11
+ - Support profile listing, activation, and status reporting
12
+ - Integrate with ConfigLoader for profile persistence
13
+ """
14
+
15
+ from pathlib import Path
16
+
17
+ import yaml
18
+ from rich.table import Table
19
+
20
+ from ...core.shared.config_loader import ConfigLoader
21
+ from ...services.profile_manager import ProfileManager
22
+ from ...utils.console import console
23
+ from ..shared import BaseCommand, CommandResult
24
+
25
+
26
+ class ProfileCommand(BaseCommand):
27
+ """Profile management command for agents and skills filtering."""
28
+
29
+ def __init__(self):
30
+ super().__init__("profile")
31
+ # ProfileManager will auto-detect project directory
32
+ self.profile_manager = ProfileManager()
33
+ self.config_loader = ConfigLoader()
34
+
35
+ def validate_args(self, args) -> str:
36
+ """Validate command arguments."""
37
+ if not hasattr(args, "profile_command") or not args.profile_command:
38
+ return "Profile command required. Use: list, set, status, or show"
39
+
40
+ valid_commands = ["list", "set", "status", "show"]
41
+ if args.profile_command not in valid_commands:
42
+ return (
43
+ f"Unknown profile command: {args.profile_command}. "
44
+ f"Valid commands: {', '.join(valid_commands)}"
45
+ )
46
+
47
+ # Validate set command has profile name
48
+ if args.profile_command == "set":
49
+ if not hasattr(args, "profile_name") or not args.profile_name:
50
+ return "Profile name required for 'set' command"
51
+
52
+ # Validate show command has profile name
53
+ if args.profile_command == "show":
54
+ if not hasattr(args, "profile_name") or not args.profile_name:
55
+ return "Profile name required for 'show' command"
56
+
57
+ return None
58
+
59
+ def run(self, args) -> CommandResult:
60
+ """Execute the profile command."""
61
+ try:
62
+ if args.profile_command == "list":
63
+ return self._list_profiles(args)
64
+ if args.profile_command == "set":
65
+ return self._set_profile(args)
66
+ if args.profile_command == "status":
67
+ return self._show_status(args)
68
+ if args.profile_command == "show":
69
+ return self._show_profile(args)
70
+ return CommandResult.error_result(
71
+ f"Unknown profile command: {args.profile_command}"
72
+ )
73
+ except Exception as e:
74
+ return CommandResult.error_result(f"Profile command failed: {e}")
75
+
76
+ def _list_profiles(self, args) -> CommandResult:
77
+ """List all available profiles."""
78
+ profiles = self.profile_manager.list_available_profiles()
79
+
80
+ if not profiles:
81
+ console.print("[yellow]No profiles found in .claude-mpm/profiles/[/yellow]")
82
+ return CommandResult.success_result("No profiles available")
83
+
84
+ # Load current active profile
85
+ main_config = self.config_loader.load_main_config()
86
+ active_profile = main_config.get("active_profile")
87
+
88
+ # Create table
89
+ table = Table(title="Available Deployment Profiles")
90
+ table.add_column("Profile", style="cyan", no_wrap=True)
91
+ table.add_column("Description", style="white")
92
+ table.add_column("Status", style="green")
93
+
94
+ for profile_name in profiles:
95
+ description = self.profile_manager.get_profile_description(profile_name)
96
+ status = "✓ Active" if profile_name == active_profile else ""
97
+
98
+ table.add_row(
99
+ profile_name, description or "(no description)", status or "-"
100
+ )
101
+
102
+ console.print(table)
103
+
104
+ return CommandResult.success_result(
105
+ f"Found {len(profiles)} profile(s)", {"profiles": profiles}
106
+ )
107
+
108
+ def _set_profile(self, args) -> CommandResult:
109
+ """Set active profile."""
110
+ profile_name = args.profile_name
111
+
112
+ # Validate profile exists
113
+ available_profiles = self.profile_manager.list_available_profiles()
114
+ if profile_name not in available_profiles:
115
+ return CommandResult.error_result(
116
+ f"Profile '{profile_name}' not found. "
117
+ f"Available profiles: {', '.join(available_profiles)}"
118
+ )
119
+
120
+ # Load profile to validate it
121
+ success = self.profile_manager.load_profile(profile_name)
122
+ if not success:
123
+ return CommandResult.error_result(
124
+ f"Failed to load profile '{profile_name}'"
125
+ )
126
+
127
+ # Update configuration.yaml
128
+ config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
129
+ if not config_path.exists():
130
+ # Create configuration.yaml if it doesn't exist
131
+ config_path.parent.mkdir(parents=True, exist_ok=True)
132
+ config_data = {"active_profile": profile_name}
133
+ else:
134
+ # Load existing configuration
135
+ with config_path.open("r") as f:
136
+ config_data = yaml.safe_load(f) or {}
137
+ config_data["active_profile"] = profile_name
138
+
139
+ # Save configuration
140
+ with config_path.open("w") as f:
141
+ yaml.safe_dump(config_data, f, default_flow_style=False, sort_keys=False)
142
+
143
+ # Show summary
144
+ summary = self.profile_manager.get_filtering_summary()
145
+ console.print(
146
+ f"[green]✓[/green] Active profile set to: [cyan]{profile_name}[/cyan]"
147
+ )
148
+ console.print(
149
+ f" Agents enabled: [cyan]{summary['enabled_agents_count']}[/cyan]"
150
+ )
151
+ console.print(
152
+ f" Skills enabled: [cyan]{summary['enabled_skills_count']}[/cyan]"
153
+ )
154
+ console.print(
155
+ f" Skill patterns disabled: [cyan]{summary['disabled_patterns_count']}[/cyan]"
156
+ )
157
+ console.print(
158
+ "\n[yellow]Note:[/yellow] Restart Claude Code or run [cyan]claude-mpm init[/cyan] "
159
+ "to apply profile filtering."
160
+ )
161
+
162
+ return CommandResult.success_result(
163
+ f"Profile '{profile_name}' activated",
164
+ {"profile": profile_name, "summary": summary},
165
+ )
166
+
167
+ def _show_status(self, args) -> CommandResult:
168
+ """Show current profile status."""
169
+ # Load current active profile
170
+ main_config = self.config_loader.load_main_config()
171
+ active_profile = main_config.get("active_profile")
172
+
173
+ if not active_profile:
174
+ console.print(
175
+ "[yellow]No active profile[/yellow] - All agents and skills enabled"
176
+ )
177
+ return CommandResult.success_result(
178
+ "No active profile", {"active_profile": None}
179
+ )
180
+
181
+ # Load profile
182
+ success = self.profile_manager.load_profile(active_profile)
183
+ if not success:
184
+ return CommandResult.error_result(
185
+ f"Failed to load active profile '{active_profile}'"
186
+ )
187
+
188
+ # Get summary
189
+ summary = self.profile_manager.get_filtering_summary()
190
+
191
+ # Display status
192
+ console.print(f"[green]Active Profile:[/green] [cyan]{active_profile}[/cyan]")
193
+ console.print()
194
+
195
+ # Agents section
196
+ console.print("[bold]Agents:[/bold]")
197
+ console.print(f" Enabled: [cyan]{summary['enabled_agents_count']}[/cyan]")
198
+ console.print(f" Disabled: [cyan]{summary['disabled_agents_count']}[/cyan]")
199
+
200
+ # Skills section
201
+ console.print()
202
+ console.print("[bold]Skills:[/bold]")
203
+ console.print(f" Enabled: [cyan]{summary['enabled_skills_count']}[/cyan]")
204
+ console.print(
205
+ f" Disabled patterns: [cyan]{summary['disabled_patterns_count']}[/cyan]"
206
+ )
207
+
208
+ return CommandResult.success_result(
209
+ f"Profile '{active_profile}' status",
210
+ {"active_profile": active_profile, "summary": summary},
211
+ )
212
+
213
+ def _show_profile(self, args) -> CommandResult:
214
+ """Show detailed profile configuration."""
215
+ profile_name = args.profile_name
216
+
217
+ # Validate profile exists
218
+ available_profiles = self.profile_manager.list_available_profiles()
219
+ if profile_name not in available_profiles:
220
+ return CommandResult.error_result(
221
+ f"Profile '{profile_name}' not found. "
222
+ f"Available profiles: {', '.join(available_profiles)}"
223
+ )
224
+
225
+ # Load profile
226
+ success = self.profile_manager.load_profile(profile_name)
227
+ if not success:
228
+ return CommandResult.error_result(
229
+ f"Failed to load profile '{profile_name}'"
230
+ )
231
+
232
+ # Display profile details
233
+ console.print(f"[bold]Profile:[/bold] [cyan]{profile_name}[/cyan]")
234
+ console.print()
235
+
236
+ # Show enabled agents
237
+ enabled_agents = self.profile_manager.get_enabled_agents()
238
+ if enabled_agents:
239
+ console.print("[bold]Enabled Agents:[/bold]")
240
+ for agent in sorted(enabled_agents):
241
+ console.print(f" • {agent}")
242
+ console.print()
243
+
244
+ # Show disabled agents
245
+ disabled_agents = self.profile_manager.get_disabled_agents()
246
+ if disabled_agents:
247
+ console.print("[bold]Disabled Agents:[/bold]")
248
+ for agent in sorted(disabled_agents):
249
+ console.print(f" • {agent}")
250
+ console.print()
251
+
252
+ # Show enabled skills
253
+ enabled_skills = self.profile_manager.get_enabled_skills()
254
+ if enabled_skills:
255
+ console.print("[bold]Enabled Skills:[/bold]")
256
+ for skill in sorted(enabled_skills):
257
+ console.print(f" • {skill}")
258
+ console.print()
259
+
260
+ # Show disabled skill patterns
261
+ disabled_patterns = self.profile_manager.get_disabled_skill_patterns()
262
+ if disabled_patterns:
263
+ console.print("[bold]Disabled Skill Patterns:[/bold]")
264
+ for pattern in disabled_patterns:
265
+ console.print(f" • {pattern}")
266
+
267
+ return CommandResult.success_result(
268
+ f"Profile '{profile_name}' details",
269
+ {
270
+ "profile": profile_name,
271
+ "enabled_agents": list(enabled_agents),
272
+ "disabled_agents": list(disabled_agents),
273
+ "enabled_skills": list(enabled_skills),
274
+ "disabled_patterns": disabled_patterns,
275
+ },
276
+ )
@@ -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_skills", False)
541
540
 
542
541
  if collection:
543
542
  console.print(
@@ -548,23 +547,14 @@ 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-skills to deploy all available skills (not just agent-referenced).[/yellow]\n"
558
- )
559
-
560
- # Selective deployment is enabled by default (deploy only agent-referenced skills)
561
- # Use --all-skills to disable selective mode
550
+ # Selective deployment is ALWAYS enabled (deploy only agent-referenced skills)
551
+ # This ensures only skills linked to deployed agents are deployed
562
552
  result = self.skills_deployer.deploy_skills(
563
553
  collection=collection,
564
554
  toolchain=toolchain,
565
555
  categories=categories,
566
556
  force=force,
567
- selective=not all_skills, # Disable selective mode if --all-skills is set
557
+ selective=True, # Always use selective deployment
568
558
  )
569
559
 
570
560
  # Display results
@@ -577,11 +567,7 @@ class SkillsManagementCommand(BaseCommand):
577
567
  f"(out of {total_available} available)[/cyan]"
578
568
  )
579
569
  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"
570
+ "[dim]Use 'claude-mpm skills configure' to manually select skills[/dim]\n"
585
571
  )
586
572
 
587
573
  if result["deployed_count"] > 0:
@@ -606,6 +592,16 @@ class SkillsManagementCommand(BaseCommand):
606
592
  console.print(f" • {error}")
607
593
  console.print()
608
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
+
609
605
  # Show restart instructions
610
606
  if result["restart_instructions"]:
611
607
  console.print(
@@ -150,6 +150,16 @@ def execute_command(command: str, args) -> int:
150
150
  result = summarize_command(args)
151
151
  return result if result is not None else 0
152
152
 
153
+ # Handle profile command with lazy import
154
+ if command == "profile":
155
+ # Lazy import to avoid loading unless needed
156
+ from .commands.profile import ProfileCommand
157
+
158
+ cmd = ProfileCommand()
159
+ result = cmd.run(args)
160
+ # Convert CommandResult to exit code
161
+ return result.exit_code if result else 0
162
+
153
163
  # Handle auto-configure command with lazy import
154
164
  if command == "auto-configure":
155
165
  # Lazy import to avoid loading unless needed
@@ -1374,7 +1374,7 @@ class AgentWizard:
1374
1374
  Path.home()
1375
1375
  / ".claude-mpm"
1376
1376
  / "cache"
1377
- / "remote-agents"
1377
+ / "agents"
1378
1378
  / "bobmatnyc"
1379
1379
  / "claude-mpm-agents"
1380
1380
  / "AUTO-DEPLOY-INDEX.md"
@@ -1419,7 +1419,7 @@ class AgentWizard:
1419
1419
  Path.home()
1420
1420
  / ".claude-mpm"
1421
1421
  / "cache"
1422
- / "remote-agents"
1422
+ / "agents"
1423
1423
  / "bobmatnyc"
1424
1424
  / "claude-mpm-agents"
1425
1425
  / "AUTO-DEPLOY-INDEX.md"
@@ -438,6 +438,13 @@ def create_parser(
438
438
  except ImportError:
439
439
  pass
440
440
 
441
+ try:
442
+ from .profile_parser import add_profile_subparser
443
+
444
+ add_profile_subparser(subparsers)
445
+ except ImportError:
446
+ pass
447
+
441
448
  try:
442
449
  from .monitor_parser import add_monitor_subparser
443
450
 
@@ -0,0 +1,147 @@
1
+ """
2
+ Profile command parser for claude-mpm CLI.
3
+
4
+ WHY: This module provides the profile command for managing deployment profiles
5
+ that control which agents and skills are deployed.
6
+
7
+ DESIGN DECISION: Provides intuitive subcommands for listing, activating,
8
+ and inspecting profiles to reduce context usage by limiting deployed components.
9
+ """
10
+
11
+ import argparse
12
+
13
+ from .base_parser import add_common_arguments
14
+
15
+
16
+ def add_profile_subparser(subparsers) -> argparse.ArgumentParser:
17
+ """
18
+ Add the profile subparser for deployment profile management.
19
+
20
+ WHY: Users need to manage which agents and skills are deployed to reduce
21
+ context usage and improve performance. Profiles define enabled/disabled
22
+ agents and skills for specific workflows.
23
+
24
+ Args:
25
+ subparsers: The subparsers object from the main parser
26
+
27
+ Returns:
28
+ The configured profile subparser
29
+ """
30
+ # Profile command with subcommands
31
+ profile_parser = subparsers.add_parser(
32
+ "profile",
33
+ help="Manage deployment profiles for agents and skills",
34
+ description="""
35
+ Deployment profile management for Claude MPM.
36
+
37
+ Profiles control which agents and skills are deployed, reducing context usage
38
+ by limiting available agents to only what's needed for your workflow.
39
+
40
+ Available commands:
41
+ list List all available profiles
42
+ set Set the active profile
43
+ status Show current active profile and filtering summary
44
+ show Show detailed configuration of a profile
45
+
46
+ Example workflows:
47
+ # List available profiles
48
+ claude-mpm profile list
49
+
50
+ # Activate a profile
51
+ claude-mpm profile set framework-development
52
+
53
+ # Check current profile status
54
+ claude-mpm profile status
55
+
56
+ # View profile details
57
+ claude-mpm profile show framework-development
58
+ """,
59
+ formatter_class=argparse.RawDescriptionHelpFormatter,
60
+ )
61
+ add_common_arguments(profile_parser)
62
+
63
+ # Add subcommands
64
+ profile_subparsers = profile_parser.add_subparsers(
65
+ dest="profile_command",
66
+ help="Profile management commands",
67
+ metavar="SUBCOMMAND",
68
+ )
69
+
70
+ # List subcommand
71
+ list_parser = profile_subparsers.add_parser(
72
+ "list",
73
+ help="List all available deployment profiles",
74
+ description="""
75
+ List all profiles found in .claude-mpm/profiles/ directory.
76
+
77
+ Shows profile names, descriptions, and indicates which profile is currently active.
78
+ """,
79
+ formatter_class=argparse.RawDescriptionHelpFormatter,
80
+ )
81
+ add_common_arguments(list_parser)
82
+
83
+ # Set subcommand
84
+ set_parser = profile_subparsers.add_parser(
85
+ "set",
86
+ help="Set the active deployment profile",
87
+ description="""
88
+ Set the active deployment profile.
89
+
90
+ This updates configuration.yaml with the selected profile, which will be
91
+ applied on next startup or when running 'claude-mpm init'.
92
+
93
+ Examples:
94
+ # Activate framework development profile
95
+ claude-mpm profile set framework-development
96
+
97
+ # Activate minimal profile for focused work
98
+ claude-mpm profile set minimal
99
+ """,
100
+ formatter_class=argparse.RawDescriptionHelpFormatter,
101
+ )
102
+ add_common_arguments(set_parser)
103
+ set_parser.add_argument(
104
+ "profile_name",
105
+ help="Name of profile to activate (without .yaml extension)",
106
+ )
107
+
108
+ # Status subcommand
109
+ status_parser = profile_subparsers.add_parser(
110
+ "status",
111
+ help="Show current active profile and filtering summary",
112
+ description="""
113
+ Display current active profile with filtering summary.
114
+
115
+ Shows:
116
+ - Active profile name
117
+ - Number of agents enabled/disabled
118
+ - Number of skills enabled/disabled
119
+ - Disabled skill patterns
120
+ """,
121
+ formatter_class=argparse.RawDescriptionHelpFormatter,
122
+ )
123
+ add_common_arguments(status_parser)
124
+
125
+ # Show subcommand
126
+ show_parser = profile_subparsers.add_parser(
127
+ "show",
128
+ help="Show detailed configuration of a profile",
129
+ description="""
130
+ Display detailed configuration of a specific profile.
131
+
132
+ Shows complete lists of enabled/disabled agents and skills, including
133
+ glob patterns for skill filtering.
134
+
135
+ Examples:
136
+ # Show framework development profile details
137
+ claude-mpm profile show framework-development
138
+ """,
139
+ formatter_class=argparse.RawDescriptionHelpFormatter,
140
+ )
141
+ add_common_arguments(show_parser)
142
+ show_parser.add_argument(
143
+ "profile_name",
144
+ help="Name of profile to display (without .yaml extension)",
145
+ )
146
+
147
+ return profile_parser
@@ -167,12 +167,6 @@ def add_skills_subparser(subparsers) -> argparse.ArgumentParser:
167
167
  action="store_true",
168
168
  help="Force redeployment of already deployed skills",
169
169
  )
170
- deploy_github_parser.add_argument(
171
- "--all-skills",
172
- action="store_true",
173
- dest="all_skills",
174
- help="Deploy ALL available skills (not just agent-referenced). By default, only skills referenced in agent frontmatter are deployed.",
175
- )
176
170
 
177
171
  # List available GitHub skills
178
172
  list_available_parser = skills_subparsers.add_parser(