claude-mpm 5.4.22__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 (119) 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 +739 -1052
  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 +10 -0
  15. claude_mpm/cli/commands/mpm_init/core.py +65 -0
  16. claude_mpm/cli/commands/postmortem.py +1 -1
  17. claude_mpm/cli/commands/profile.py +277 -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 +148 -0
  23. claude_mpm/cli/parsers/skills_parser.py +0 -6
  24. claude_mpm/cli/startup.py +346 -75
  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 +59 -0
  40. claude_mpm/core/shared/config_loader.py +1 -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.B_FtCwCQ.css +1 -0
  44. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +1 -0
  45. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +1 -0
  46. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +1 -0
  47. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +1 -0
  48. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +2 -0
  49. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DjhvlsAc.js +1 -0
  50. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/N4qtv3Hx.js +2 -0
  51. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uj46x2Wr.js +1 -0
  52. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +2 -0
  53. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +1 -0
  54. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.CAGBuiOw.js +1 -0
  55. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +1 -0
  56. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +10 -0
  57. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  58. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  59. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  60. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  61. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  62. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  63. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  64. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  65. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  66. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  67. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  68. claude_mpm/hooks/claude_hooks/hook_handler.py +149 -1
  69. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  70. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  71. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  72. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  73. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  74. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  75. claude_mpm/hooks/claude_hooks/services/connection_manager.py +26 -6
  76. claude_mpm/hooks/kuzu_memory_hook.py +5 -5
  77. claude_mpm/init.py +63 -0
  78. claude_mpm/models/git_repository.py +3 -3
  79. claude_mpm/scripts/start_activity_logging.py +0 -0
  80. claude_mpm/services/agents/agent_builder.py +3 -3
  81. claude_mpm/services/agents/cache_git_manager.py +6 -6
  82. claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
  83. claude_mpm/services/agents/deployment/agent_discovery_service.py +2 -2
  84. claude_mpm/services/agents/deployment/agent_format_converter.py +23 -13
  85. claude_mpm/services/agents/deployment/agent_template_builder.py +29 -19
  86. claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
  87. claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
  88. claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
  89. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +169 -26
  90. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +98 -75
  91. claude_mpm/services/agents/git_source_manager.py +19 -4
  92. claude_mpm/services/agents/recommender.py +5 -3
  93. claude_mpm/services/agents/single_tier_deployment_service.py +2 -2
  94. claude_mpm/services/agents/sources/git_source_sync_service.py +112 -6
  95. claude_mpm/services/agents/startup_sync.py +22 -2
  96. claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
  97. claude_mpm/services/diagnostics/checks/agent_sources_check.py +1 -1
  98. claude_mpm/services/git/git_operations_service.py +8 -8
  99. claude_mpm/services/monitor/management/lifecycle.py +8 -1
  100. claude_mpm/services/monitor/server.py +473 -3
  101. claude_mpm/services/pm_skills_deployer.py +711 -0
  102. claude_mpm/services/profile_manager.py +331 -0
  103. claude_mpm/services/skills/git_skill_source_manager.py +101 -3
  104. claude_mpm/services/skills_deployer.py +4 -3
  105. claude_mpm/services/socketio/dashboard_server.py +1 -0
  106. claude_mpm/services/socketio/event_normalizer.py +37 -6
  107. claude_mpm/services/socketio/server/core.py +262 -123
  108. claude_mpm/skills/skill_manager.py +92 -3
  109. claude_mpm/utils/agent_dependency_loader.py +14 -2
  110. claude_mpm/utils/agent_filters.py +1 -1
  111. claude_mpm/utils/migration.py +4 -4
  112. claude_mpm/utils/robust_installer.py +47 -3
  113. {claude_mpm-5.4.22.dist-info → claude_mpm-5.4.48.dist-info}/METADATA +7 -4
  114. {claude_mpm-5.4.22.dist-info → claude_mpm-5.4.48.dist-info}/RECORD +118 -79
  115. {claude_mpm-5.4.22.dist-info → claude_mpm-5.4.48.dist-info}/WHEEL +0 -0
  116. {claude_mpm-5.4.22.dist-info → claude_mpm-5.4.48.dist-info}/entry_points.txt +0 -0
  117. {claude_mpm-5.4.22.dist-info → claude_mpm-5.4.48.dist-info}/licenses/LICENSE +0 -0
  118. {claude_mpm-5.4.22.dist-info → claude_mpm-5.4.48.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  119. {claude_mpm-5.4.22.dist-info → claude_mpm-5.4.48.dist-info}/top_level.txt +0 -0
@@ -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,277 @@
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
+ from typing import Any, Dict
17
+
18
+ import yaml
19
+ from rich.console import Console
20
+ from rich.table import Table
21
+
22
+ from ...core.shared.config_loader import ConfigLoader
23
+ from ...services.profile_manager import ProfileManager
24
+ from ...utils.console import console
25
+ from ..shared import BaseCommand, CommandResult
26
+
27
+
28
+ class ProfileCommand(BaseCommand):
29
+ """Profile management command for agents and skills filtering."""
30
+
31
+ def __init__(self):
32
+ super().__init__("profile")
33
+ # ProfileManager will auto-detect project directory
34
+ self.profile_manager = ProfileManager()
35
+ self.config_loader = ConfigLoader()
36
+
37
+ def validate_args(self, args) -> str:
38
+ """Validate command arguments."""
39
+ if not hasattr(args, "profile_command") or not args.profile_command:
40
+ return "Profile command required. Use: list, set, status, or show"
41
+
42
+ valid_commands = ["list", "set", "status", "show"]
43
+ if args.profile_command not in valid_commands:
44
+ return (
45
+ f"Unknown profile command: {args.profile_command}. "
46
+ f"Valid commands: {', '.join(valid_commands)}"
47
+ )
48
+
49
+ # Validate set command has profile name
50
+ if args.profile_command == "set":
51
+ if not hasattr(args, "profile_name") or not args.profile_name:
52
+ return "Profile name required for 'set' command"
53
+
54
+ # Validate show command has profile name
55
+ if args.profile_command == "show":
56
+ if not hasattr(args, "profile_name") or not args.profile_name:
57
+ return "Profile name required for 'show' command"
58
+
59
+ return None
60
+
61
+ def run(self, args) -> CommandResult:
62
+ """Execute the profile command."""
63
+ try:
64
+ if args.profile_command == "list":
65
+ return self._list_profiles(args)
66
+ elif args.profile_command == "set":
67
+ return self._set_profile(args)
68
+ elif args.profile_command == "status":
69
+ return self._show_status(args)
70
+ elif args.profile_command == "show":
71
+ return self._show_profile(args)
72
+ else:
73
+ return CommandResult.error_result(
74
+ f"Unknown profile command: {args.profile_command}"
75
+ )
76
+ except Exception as e:
77
+ return CommandResult.error_result(f"Profile command failed: {e}")
78
+
79
+ def _list_profiles(self, args) -> CommandResult:
80
+ """List all available profiles."""
81
+ profiles = self.profile_manager.list_available_profiles()
82
+
83
+ if not profiles:
84
+ console.print("[yellow]No profiles found in .claude-mpm/profiles/[/yellow]")
85
+ return CommandResult.success_result("No profiles available")
86
+
87
+ # Load current active profile
88
+ main_config = self.config_loader.load_main_config()
89
+ active_profile = main_config.get("active_profile")
90
+
91
+ # Create table
92
+ table = Table(title="Available Deployment Profiles")
93
+ table.add_column("Profile", style="cyan", no_wrap=True)
94
+ table.add_column("Description", style="white")
95
+ table.add_column("Status", style="green")
96
+
97
+ for profile_name in profiles:
98
+ description = self.profile_manager.get_profile_description(profile_name)
99
+ status = "✓ Active" if profile_name == active_profile else ""
100
+
101
+ table.add_row(
102
+ profile_name, description or "(no description)", status or "-"
103
+ )
104
+
105
+ console.print(table)
106
+
107
+ return CommandResult.success_result(
108
+ f"Found {len(profiles)} profile(s)", {"profiles": profiles}
109
+ )
110
+
111
+ def _set_profile(self, args) -> CommandResult:
112
+ """Set active profile."""
113
+ profile_name = args.profile_name
114
+
115
+ # Validate profile exists
116
+ available_profiles = self.profile_manager.list_available_profiles()
117
+ if profile_name not in available_profiles:
118
+ return CommandResult.error_result(
119
+ f"Profile '{profile_name}' not found. "
120
+ f"Available profiles: {', '.join(available_profiles)}"
121
+ )
122
+
123
+ # Load profile to validate it
124
+ success = self.profile_manager.load_profile(profile_name)
125
+ if not success:
126
+ return CommandResult.error_result(
127
+ f"Failed to load profile '{profile_name}'"
128
+ )
129
+
130
+ # Update configuration.yaml
131
+ config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
132
+ if not config_path.exists():
133
+ # Create configuration.yaml if it doesn't exist
134
+ config_path.parent.mkdir(parents=True, exist_ok=True)
135
+ config_data = {"active_profile": profile_name}
136
+ else:
137
+ # Load existing configuration
138
+ with config_path.open("r") as f:
139
+ config_data = yaml.safe_load(f) or {}
140
+ config_data["active_profile"] = profile_name
141
+
142
+ # Save configuration
143
+ with config_path.open("w") as f:
144
+ yaml.safe_dump(config_data, f, default_flow_style=False, sort_keys=False)
145
+
146
+ # Show summary
147
+ summary = self.profile_manager.get_filtering_summary()
148
+ console.print(f"[green]✓[/green] Active profile set to: [cyan]{profile_name}[/cyan]")
149
+ console.print(
150
+ f" Agents enabled: [cyan]{summary['enabled_agents_count']}[/cyan]"
151
+ )
152
+ console.print(
153
+ f" Skills enabled: [cyan]{summary['enabled_skills_count']}[/cyan]"
154
+ )
155
+ console.print(
156
+ f" Skill patterns disabled: [cyan]{summary['disabled_patterns_count']}[/cyan]"
157
+ )
158
+ console.print(
159
+ "\n[yellow]Note:[/yellow] Restart Claude Code or run [cyan]claude-mpm init[/cyan] "
160
+ "to apply profile filtering."
161
+ )
162
+
163
+ return CommandResult.success_result(
164
+ f"Profile '{profile_name}' activated",
165
+ {"profile": profile_name, "summary": summary},
166
+ )
167
+
168
+ def _show_status(self, args) -> CommandResult:
169
+ """Show current profile status."""
170
+ # Load current active profile
171
+ main_config = self.config_loader.load_main_config()
172
+ active_profile = main_config.get("active_profile")
173
+
174
+ if not active_profile:
175
+ console.print(
176
+ "[yellow]No active profile[/yellow] - All agents and skills enabled"
177
+ )
178
+ return CommandResult.success_result(
179
+ "No active profile", {"active_profile": None}
180
+ )
181
+
182
+ # Load profile
183
+ success = self.profile_manager.load_profile(active_profile)
184
+ if not success:
185
+ return CommandResult.error_result(
186
+ f"Failed to load active profile '{active_profile}'"
187
+ )
188
+
189
+ # Get summary
190
+ summary = self.profile_manager.get_filtering_summary()
191
+
192
+ # Display status
193
+ console.print(f"[green]Active Profile:[/green] [cyan]{active_profile}[/cyan]")
194
+ console.print()
195
+
196
+ # Agents section
197
+ console.print("[bold]Agents:[/bold]")
198
+ console.print(f" Enabled: [cyan]{summary['enabled_agents_count']}[/cyan]")
199
+ console.print(f" Disabled: [cyan]{summary['disabled_agents_count']}[/cyan]")
200
+
201
+ # Skills section
202
+ console.print()
203
+ console.print("[bold]Skills:[/bold]")
204
+ console.print(f" Enabled: [cyan]{summary['enabled_skills_count']}[/cyan]")
205
+ console.print(
206
+ f" Disabled patterns: [cyan]{summary['disabled_patterns_count']}[/cyan]"
207
+ )
208
+
209
+ return CommandResult.success_result(
210
+ f"Profile '{active_profile}' status",
211
+ {"active_profile": active_profile, "summary": summary},
212
+ )
213
+
214
+ def _show_profile(self, args) -> CommandResult:
215
+ """Show detailed profile configuration."""
216
+ profile_name = args.profile_name
217
+
218
+ # Validate profile exists
219
+ available_profiles = self.profile_manager.list_available_profiles()
220
+ if profile_name not in available_profiles:
221
+ return CommandResult.error_result(
222
+ f"Profile '{profile_name}' not found. "
223
+ f"Available profiles: {', '.join(available_profiles)}"
224
+ )
225
+
226
+ # Load profile
227
+ success = self.profile_manager.load_profile(profile_name)
228
+ if not success:
229
+ return CommandResult.error_result(
230
+ f"Failed to load profile '{profile_name}'"
231
+ )
232
+
233
+ # Display profile details
234
+ console.print(f"[bold]Profile:[/bold] [cyan]{profile_name}[/cyan]")
235
+ console.print()
236
+
237
+ # Show enabled agents
238
+ enabled_agents = self.profile_manager.get_enabled_agents()
239
+ if enabled_agents:
240
+ console.print("[bold]Enabled Agents:[/bold]")
241
+ for agent in sorted(enabled_agents):
242
+ console.print(f" • {agent}")
243
+ console.print()
244
+
245
+ # Show disabled agents
246
+ disabled_agents = self.profile_manager.get_disabled_agents()
247
+ if disabled_agents:
248
+ console.print("[bold]Disabled Agents:[/bold]")
249
+ for agent in sorted(disabled_agents):
250
+ console.print(f" • {agent}")
251
+ console.print()
252
+
253
+ # Show enabled skills
254
+ enabled_skills = self.profile_manager.get_enabled_skills()
255
+ if enabled_skills:
256
+ console.print("[bold]Enabled Skills:[/bold]")
257
+ for skill in sorted(enabled_skills):
258
+ console.print(f" • {skill}")
259
+ console.print()
260
+
261
+ # Show disabled skill patterns
262
+ disabled_patterns = self.profile_manager.get_disabled_skill_patterns()
263
+ if disabled_patterns:
264
+ console.print("[bold]Disabled Skill Patterns:[/bold]")
265
+ for pattern in disabled_patterns:
266
+ console.print(f" • {pattern}")
267
+
268
+ return CommandResult.success_result(
269
+ f"Profile '{profile_name}' details",
270
+ {
271
+ "profile": profile_name,
272
+ "enabled_agents": list(enabled_agents),
273
+ "disabled_agents": list(disabled_agents),
274
+ "enabled_skills": list(enabled_skills),
275
+ "disabled_patterns": disabled_patterns,
276
+ },
277
+ )
@@ -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,148 @@
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 ...constants import CLICommands
14
+ from .base_parser import add_common_arguments
15
+
16
+
17
+ def add_profile_subparser(subparsers) -> argparse.ArgumentParser:
18
+ """
19
+ Add the profile subparser for deployment profile management.
20
+
21
+ WHY: Users need to manage which agents and skills are deployed to reduce
22
+ context usage and improve performance. Profiles define enabled/disabled
23
+ agents and skills for specific workflows.
24
+
25
+ Args:
26
+ subparsers: The subparsers object from the main parser
27
+
28
+ Returns:
29
+ The configured profile subparser
30
+ """
31
+ # Profile command with subcommands
32
+ profile_parser = subparsers.add_parser(
33
+ "profile",
34
+ help="Manage deployment profiles for agents and skills",
35
+ description="""
36
+ Deployment profile management for Claude MPM.
37
+
38
+ Profiles control which agents and skills are deployed, reducing context usage
39
+ by limiting available agents to only what's needed for your workflow.
40
+
41
+ Available commands:
42
+ list List all available profiles
43
+ set Set the active profile
44
+ status Show current active profile and filtering summary
45
+ show Show detailed configuration of a profile
46
+
47
+ Example workflows:
48
+ # List available profiles
49
+ claude-mpm profile list
50
+
51
+ # Activate a profile
52
+ claude-mpm profile set framework-development
53
+
54
+ # Check current profile status
55
+ claude-mpm profile status
56
+
57
+ # View profile details
58
+ claude-mpm profile show framework-development
59
+ """,
60
+ formatter_class=argparse.RawDescriptionHelpFormatter,
61
+ )
62
+ add_common_arguments(profile_parser)
63
+
64
+ # Add subcommands
65
+ profile_subparsers = profile_parser.add_subparsers(
66
+ dest="profile_command",
67
+ help="Profile management commands",
68
+ metavar="SUBCOMMAND",
69
+ )
70
+
71
+ # List subcommand
72
+ list_parser = profile_subparsers.add_parser(
73
+ "list",
74
+ help="List all available deployment profiles",
75
+ description="""
76
+ List all profiles found in .claude-mpm/profiles/ directory.
77
+
78
+ Shows profile names, descriptions, and indicates which profile is currently active.
79
+ """,
80
+ formatter_class=argparse.RawDescriptionHelpFormatter,
81
+ )
82
+ add_common_arguments(list_parser)
83
+
84
+ # Set subcommand
85
+ set_parser = profile_subparsers.add_parser(
86
+ "set",
87
+ help="Set the active deployment profile",
88
+ description="""
89
+ Set the active deployment profile.
90
+
91
+ This updates configuration.yaml with the selected profile, which will be
92
+ applied on next startup or when running 'claude-mpm init'.
93
+
94
+ Examples:
95
+ # Activate framework development profile
96
+ claude-mpm profile set framework-development
97
+
98
+ # Activate minimal profile for focused work
99
+ claude-mpm profile set minimal
100
+ """,
101
+ formatter_class=argparse.RawDescriptionHelpFormatter,
102
+ )
103
+ add_common_arguments(set_parser)
104
+ set_parser.add_argument(
105
+ "profile_name",
106
+ help="Name of profile to activate (without .yaml extension)",
107
+ )
108
+
109
+ # Status subcommand
110
+ status_parser = profile_subparsers.add_parser(
111
+ "status",
112
+ help="Show current active profile and filtering summary",
113
+ description="""
114
+ Display current active profile with filtering summary.
115
+
116
+ Shows:
117
+ - Active profile name
118
+ - Number of agents enabled/disabled
119
+ - Number of skills enabled/disabled
120
+ - Disabled skill patterns
121
+ """,
122
+ formatter_class=argparse.RawDescriptionHelpFormatter,
123
+ )
124
+ add_common_arguments(status_parser)
125
+
126
+ # Show subcommand
127
+ show_parser = profile_subparsers.add_parser(
128
+ "show",
129
+ help="Show detailed configuration of a profile",
130
+ description="""
131
+ Display detailed configuration of a specific profile.
132
+
133
+ Shows complete lists of enabled/disabled agents and skills, including
134
+ glob patterns for skill filtering.
135
+
136
+ Examples:
137
+ # Show framework development profile details
138
+ claude-mpm profile show framework-development
139
+ """,
140
+ formatter_class=argparse.RawDescriptionHelpFormatter,
141
+ )
142
+ add_common_arguments(show_parser)
143
+ show_parser.add_argument(
144
+ "profile_name",
145
+ help="Name of profile to display (without .yaml extension)",
146
+ )
147
+
148
+ 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(