claude-mpm 4.15.2__py3-none-any.whl → 4.20.3__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.
Files changed (203) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_ENGINEER.md +286 -0
  3. claude_mpm/agents/BASE_PM.md +255 -23
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +40 -0
  5. claude_mpm/agents/agent_loader.py +4 -4
  6. claude_mpm/agents/templates/agentic-coder-optimizer.json +9 -2
  7. claude_mpm/agents/templates/api_qa.json +7 -1
  8. claude_mpm/agents/templates/clerk-ops.json +8 -1
  9. claude_mpm/agents/templates/code_analyzer.json +4 -1
  10. claude_mpm/agents/templates/dart_engineer.json +11 -1
  11. claude_mpm/agents/templates/data_engineer.json +11 -1
  12. claude_mpm/agents/templates/documentation.json +6 -1
  13. claude_mpm/agents/templates/engineer.json +18 -1
  14. claude_mpm/agents/templates/gcp_ops_agent.json +8 -1
  15. claude_mpm/agents/templates/golang_engineer.json +11 -1
  16. claude_mpm/agents/templates/java_engineer.json +12 -2
  17. claude_mpm/agents/templates/local_ops_agent.json +216 -37
  18. claude_mpm/agents/templates/nextjs_engineer.json +11 -1
  19. claude_mpm/agents/templates/ops.json +8 -1
  20. claude_mpm/agents/templates/php-engineer.json +11 -1
  21. claude_mpm/agents/templates/project_organizer.json +9 -2
  22. claude_mpm/agents/templates/prompt-engineer.json +5 -1
  23. claude_mpm/agents/templates/python_engineer.json +19 -4
  24. claude_mpm/agents/templates/qa.json +7 -1
  25. claude_mpm/agents/templates/react_engineer.json +11 -1
  26. claude_mpm/agents/templates/refactoring_engineer.json +8 -1
  27. claude_mpm/agents/templates/research.json +4 -1
  28. claude_mpm/agents/templates/ruby-engineer.json +11 -1
  29. claude_mpm/agents/templates/rust_engineer.json +23 -8
  30. claude_mpm/agents/templates/security.json +6 -1
  31. claude_mpm/agents/templates/svelte-engineer.json +225 -0
  32. claude_mpm/agents/templates/ticketing.json +6 -1
  33. claude_mpm/agents/templates/typescript_engineer.json +11 -1
  34. claude_mpm/agents/templates/vercel_ops_agent.json +8 -1
  35. claude_mpm/agents/templates/version_control.json +8 -1
  36. claude_mpm/agents/templates/web_qa.json +7 -1
  37. claude_mpm/agents/templates/web_ui.json +11 -1
  38. claude_mpm/cli/commands/__init__.py +2 -0
  39. claude_mpm/cli/commands/configure.py +164 -16
  40. claude_mpm/cli/commands/configure_agent_display.py +6 -6
  41. claude_mpm/cli/commands/configure_behavior_manager.py +8 -8
  42. claude_mpm/cli/commands/configure_navigation.py +20 -18
  43. claude_mpm/cli/commands/configure_startup_manager.py +14 -14
  44. claude_mpm/cli/commands/configure_template_editor.py +8 -8
  45. claude_mpm/cli/commands/mpm_init.py +109 -24
  46. claude_mpm/cli/commands/skills.py +434 -0
  47. claude_mpm/cli/executor.py +2 -0
  48. claude_mpm/cli/interactive/__init__.py +3 -0
  49. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  50. claude_mpm/cli/parsers/base_parser.py +7 -0
  51. claude_mpm/cli/parsers/skills_parser.py +137 -0
  52. claude_mpm/cli/startup.py +83 -0
  53. claude_mpm/commands/mpm-auto-configure.md +52 -0
  54. claude_mpm/commands/mpm-help.md +3 -0
  55. claude_mpm/commands/mpm-init.md +112 -6
  56. claude_mpm/commands/mpm-version.md +113 -0
  57. claude_mpm/commands/mpm.md +1 -0
  58. claude_mpm/config/agent_config.py +2 -2
  59. claude_mpm/constants.py +12 -0
  60. claude_mpm/core/config.py +42 -0
  61. claude_mpm/core/enums.py +18 -0
  62. claude_mpm/core/factories.py +1 -1
  63. claude_mpm/core/optimized_agent_loader.py +3 -3
  64. claude_mpm/core/types.py +2 -9
  65. claude_mpm/dashboard/static/js/dashboard.js +0 -14
  66. claude_mpm/dashboard/templates/index.html +3 -41
  67. claude_mpm/hooks/__init__.py +8 -0
  68. claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
  69. claude_mpm/hooks/session_resume_hook.py +121 -0
  70. claude_mpm/models/resume_log.py +340 -0
  71. claude_mpm/services/agents/auto_config_manager.py +1 -1
  72. claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
  73. claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
  74. claude_mpm/services/agents/deployment/agent_validator.py +17 -1
  75. claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
  76. claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
  77. claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
  78. claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
  79. claude_mpm/services/agents/local_template_manager.py +1 -1
  80. claude_mpm/services/agents/recommender.py +47 -0
  81. claude_mpm/services/cli/resume_service.py +617 -0
  82. claude_mpm/services/cli/session_manager.py +87 -0
  83. claude_mpm/services/cli/session_resume_helper.py +352 -0
  84. claude_mpm/services/core/models/health.py +1 -28
  85. claude_mpm/services/core/path_resolver.py +1 -1
  86. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
  87. claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
  88. claude_mpm/services/infrastructure/monitoring/base.py +5 -13
  89. claude_mpm/services/infrastructure/monitoring/network.py +7 -6
  90. claude_mpm/services/infrastructure/monitoring/process.py +13 -12
  91. claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
  92. claude_mpm/services/infrastructure/monitoring/service.py +16 -15
  93. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  94. claude_mpm/services/local_ops/__init__.py +1 -1
  95. claude_mpm/services/local_ops/crash_detector.py +1 -1
  96. claude_mpm/services/local_ops/health_checks/http_check.py +2 -1
  97. claude_mpm/services/local_ops/health_checks/process_check.py +2 -1
  98. claude_mpm/services/local_ops/health_checks/resource_check.py +2 -1
  99. claude_mpm/services/local_ops/health_manager.py +1 -1
  100. claude_mpm/services/local_ops/restart_manager.py +1 -1
  101. claude_mpm/services/mcp_config_manager.py +7 -131
  102. claude_mpm/services/session_manager.py +205 -1
  103. claude_mpm/services/shared/async_service_base.py +16 -27
  104. claude_mpm/services/shared/lifecycle_service_base.py +1 -14
  105. claude_mpm/services/socketio/handlers/__init__.py +5 -2
  106. claude_mpm/services/socketio/handlers/hook.py +10 -0
  107. claude_mpm/services/socketio/handlers/registry.py +4 -2
  108. claude_mpm/services/socketio/server/main.py +7 -7
  109. claude_mpm/services/unified/deployment_strategies/local.py +1 -1
  110. claude_mpm/services/version_service.py +104 -1
  111. claude_mpm/skills/__init__.py +42 -0
  112. claude_mpm/skills/agent_skills_injector.py +331 -0
  113. claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
  114. claude_mpm/skills/bundled/__init__.py +6 -0
  115. claude_mpm/skills/bundled/api-documentation.md +393 -0
  116. claude_mpm/skills/bundled/async-testing.md +571 -0
  117. claude_mpm/skills/bundled/code-review.md +143 -0
  118. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +75 -0
  119. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +184 -0
  120. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +107 -0
  121. claude_mpm/skills/bundled/collaboration/requesting-code-review/code-reviewer.md +146 -0
  122. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +118 -0
  123. claude_mpm/skills/bundled/database-migration.md +199 -0
  124. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +177 -0
  125. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  126. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  127. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  128. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  129. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  130. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  131. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  132. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  133. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  134. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  135. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +175 -0
  136. claude_mpm/skills/bundled/debugging/verification-before-completion/references/common-failures.md +213 -0
  137. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +314 -0
  138. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +227 -0
  139. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  140. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  141. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  142. claude_mpm/skills/bundled/git-workflow.md +414 -0
  143. claude_mpm/skills/bundled/imagemagick.md +204 -0
  144. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  145. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +74 -0
  146. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +32 -0
  147. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  148. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  149. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  150. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  151. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +328 -0
  152. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  153. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  154. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  155. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  156. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +150 -0
  157. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +372 -0
  158. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +209 -0
  159. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +302 -0
  160. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +111 -0
  161. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +65 -0
  162. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  163. claude_mpm/skills/bundled/pdf.md +141 -0
  164. claude_mpm/skills/bundled/performance-profiling.md +567 -0
  165. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  166. claude_mpm/skills/bundled/security-scanning.md +327 -0
  167. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  168. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  169. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +123 -0
  170. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  171. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  172. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  173. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  174. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  175. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  176. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +304 -0
  177. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +96 -0
  178. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
  179. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +40 -0
  180. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
  181. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +107 -0
  182. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  183. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  184. claude_mpm/skills/bundled/xlsx.md +157 -0
  185. claude_mpm/skills/registry.py +286 -0
  186. claude_mpm/skills/skill_manager.py +310 -0
  187. claude_mpm/skills/skills_registry.py +351 -0
  188. claude_mpm/skills/skills_service.py +730 -0
  189. claude_mpm/utils/agent_dependency_loader.py +2 -2
  190. {claude_mpm-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/METADATA +211 -33
  191. {claude_mpm-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/RECORD +195 -115
  192. claude_mpm/agents/INSTRUCTIONS_OLD_DEPRECATED.md +0 -602
  193. claude_mpm/dashboard/static/css/code-tree.css +0 -1639
  194. claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
  195. claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
  196. claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
  197. claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
  198. claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
  199. claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
  200. {claude_mpm-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/WHEEL +0 -0
  201. {claude_mpm-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/entry_points.txt +0 -0
  202. {claude_mpm-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/licenses/LICENSE +0 -0
  203. {claude_mpm-4.15.2.dist-info → claude_mpm-4.20.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,491 @@
1
+ """Interactive Skills Selection Wizard for Claude MPM.
2
+
3
+ This module provides a step-by-step interactive wizard for selecting and configuring
4
+ skills for agents with user-friendly prompts and intelligent auto-linking.
5
+ """
6
+
7
+ from typing import Dict, List, Optional, Tuple
8
+
9
+ from claude_mpm.core.logging_config import get_logger
10
+ from claude_mpm.skills.registry import get_registry
11
+ from claude_mpm.skills.skill_manager import get_manager
12
+
13
+ logger = get_logger(__name__)
14
+
15
+
16
+ # Agent-to-skills auto-linking mappings
17
+ ENGINEER_CORE_SKILLS = [
18
+ "test-driven-development",
19
+ "systematic-debugging",
20
+ "code-review",
21
+ "refactoring-patterns",
22
+ "git-workflow",
23
+ ]
24
+
25
+ PYTHON_SKILLS = ENGINEER_CORE_SKILLS + ["async-testing"]
26
+ TYPESCRIPT_SKILLS = ENGINEER_CORE_SKILLS + ["async-testing"]
27
+ GOLANG_SKILLS = ENGINEER_CORE_SKILLS + ["async-testing"]
28
+ REACT_SKILLS = TYPESCRIPT_SKILLS + ["performance-profiling"]
29
+ NEXTJS_SKILLS = REACT_SKILLS
30
+ VUE_SKILLS = TYPESCRIPT_SKILLS + ["performance-profiling"]
31
+
32
+ OPS_SKILLS = [
33
+ "docker-containerization",
34
+ "database-migration",
35
+ "security-scanning",
36
+ "systematic-debugging",
37
+ ]
38
+
39
+ DOCUMENTATION_SKILLS = [
40
+ "api-documentation",
41
+ "code-review",
42
+ ]
43
+
44
+ QA_SKILLS = [
45
+ "test-driven-development",
46
+ "systematic-debugging",
47
+ "async-testing",
48
+ "performance-profiling",
49
+ ]
50
+
51
+ # Mapping of agent types to their recommended skills
52
+ AGENT_SKILL_MAPPING = {
53
+ # Engineer agents
54
+ "engineer": ENGINEER_CORE_SKILLS,
55
+ "python-engineer": PYTHON_SKILLS,
56
+ "typescript-engineer": TYPESCRIPT_SKILLS,
57
+ "golang-engineer": GOLANG_SKILLS,
58
+ "react-engineer": REACT_SKILLS,
59
+ "nextjs-engineer": NEXTJS_SKILLS,
60
+ "vue-engineer": VUE_SKILLS,
61
+ # Ops agents
62
+ "ops": OPS_SKILLS,
63
+ "devops": OPS_SKILLS,
64
+ "local-ops": OPS_SKILLS,
65
+ # Documentation agents
66
+ "docs": DOCUMENTATION_SKILLS,
67
+ "documentation": DOCUMENTATION_SKILLS,
68
+ "technical-writer": DOCUMENTATION_SKILLS,
69
+ # QA agents
70
+ "qa": QA_SKILLS,
71
+ "web-qa": QA_SKILLS,
72
+ "api-qa": QA_SKILLS,
73
+ "tester": QA_SKILLS,
74
+ }
75
+
76
+
77
+ class SkillsWizard:
78
+ """Interactive wizard for skills selection and configuration."""
79
+
80
+ def __init__(self):
81
+ """Initialize the skills wizard."""
82
+ self.registry = get_registry()
83
+ self.manager = get_manager()
84
+ self.logger = logger
85
+
86
+ def run_interactive_selection(
87
+ self, selected_agents: Optional[List[str]] = None
88
+ ) -> Tuple[bool, Dict[str, List[str]]]:
89
+ """Run interactive skills selection wizard.
90
+
91
+ Args:
92
+ selected_agents: List of agent IDs that were selected in agent wizard
93
+
94
+ Returns:
95
+ Tuple of (success, agent_skills_mapping)
96
+ - success: Boolean indicating if selection was successful
97
+ - agent_skills_mapping: Dict mapping agent IDs to lists of skill names
98
+ """
99
+ try:
100
+ print("\n" + "=" * 60)
101
+ print("🎯 Skills Selection Wizard")
102
+ print("=" * 60)
103
+ print("\nI'll help you select skills for your agents.")
104
+ print("Press Ctrl+C anytime to cancel.\n")
105
+
106
+ # Auto-link skills based on selected agents
107
+ agent_skills_mapping = {}
108
+ if selected_agents:
109
+ print("📋 Auto-linking skills based on selected agents...\n")
110
+ agent_skills_mapping = self._auto_link_skills(selected_agents)
111
+ self._display_auto_linked_skills(agent_skills_mapping)
112
+
113
+ # Ask if user wants to customize
114
+ customize = (
115
+ input("\nWould you like to customize skill selections? [y/N]: ")
116
+ .strip()
117
+ .lower()
118
+ )
119
+
120
+ if customize in ["y", "yes"]:
121
+ agent_skills_mapping = self._run_custom_selection(
122
+ selected_agents, agent_skills_mapping
123
+ )
124
+
125
+ # Preview final configuration
126
+ self._preview_final_configuration(agent_skills_mapping)
127
+
128
+ # Confirm
129
+ confirm = (
130
+ input("\nApply this skills configuration? [Y/n]: ").strip().lower()
131
+ )
132
+ if confirm in ["n", "no"]:
133
+ return False, {}
134
+
135
+ # Apply configuration
136
+ self._apply_skills_configuration(agent_skills_mapping)
137
+
138
+ print("\n✅ Skills configuration complete!")
139
+ return True, agent_skills_mapping
140
+
141
+ except KeyboardInterrupt:
142
+ print("\n\n❌ Skills selection cancelled")
143
+ return False, {}
144
+ except Exception as e:
145
+ error_msg = f"Skills selection error: {e}"
146
+ self.logger.error(error_msg, exc_info=True)
147
+ print(f"\n❌ {error_msg}")
148
+ return False, {}
149
+
150
+ def _auto_link_skills(self, agent_ids: List[str]) -> Dict[str, List[str]]:
151
+ """Auto-link skills to agents based on agent types.
152
+
153
+ Args:
154
+ agent_ids: List of agent IDs
155
+
156
+ Returns:
157
+ Dictionary mapping agent IDs to skill names
158
+ """
159
+ mapping = {}
160
+ for agent_id in agent_ids:
161
+ # Try to match against known patterns
162
+ skills = self._get_recommended_skills_for_agent(agent_id)
163
+ if skills:
164
+ mapping[agent_id] = skills
165
+ else:
166
+ # Default to core engineer skills if no match
167
+ mapping[agent_id] = ENGINEER_CORE_SKILLS.copy()
168
+
169
+ return mapping
170
+
171
+ def _get_recommended_skills_for_agent(self, agent_id: str) -> List[str]:
172
+ """Get recommended skills for an agent based on its ID.
173
+
174
+ Args:
175
+ agent_id: Agent identifier
176
+
177
+ Returns:
178
+ List of recommended skill names
179
+ """
180
+ agent_id_lower = agent_id.lower()
181
+
182
+ # Direct match
183
+ if agent_id_lower in AGENT_SKILL_MAPPING:
184
+ return AGENT_SKILL_MAPPING[agent_id_lower].copy()
185
+
186
+ # Fuzzy matching for common patterns
187
+ if "python" in agent_id_lower:
188
+ return PYTHON_SKILLS.copy()
189
+ if any(js in agent_id_lower for js in ["typescript", "ts", "javascript", "js"]):
190
+ return TYPESCRIPT_SKILLS.copy()
191
+ if "react" in agent_id_lower:
192
+ return REACT_SKILLS.copy()
193
+ if "next" in agent_id_lower:
194
+ return NEXTJS_SKILLS.copy()
195
+ if "vue" in agent_id_lower:
196
+ return VUE_SKILLS.copy()
197
+ if "go" in agent_id_lower or "golang" in agent_id_lower:
198
+ return GOLANG_SKILLS.copy()
199
+ if any(ops in agent_id_lower for ops in ["ops", "devops", "deploy"]):
200
+ return OPS_SKILLS.copy()
201
+ if any(qa in agent_id_lower for qa in ["qa", "test", "quality"]):
202
+ return QA_SKILLS.copy()
203
+ if any(doc in agent_id_lower for doc in ["doc", "writer", "technical"]):
204
+ return DOCUMENTATION_SKILLS.copy()
205
+ if "engineer" in agent_id_lower:
206
+ return ENGINEER_CORE_SKILLS.copy()
207
+
208
+ # Default
209
+ return []
210
+
211
+ def _display_auto_linked_skills(self, mapping: Dict[str, List[str]]):
212
+ """Display auto-linked skills configuration.
213
+
214
+ Args:
215
+ mapping: Agent-to-skills mapping
216
+ """
217
+ for agent_id, skills in mapping.items():
218
+ print(f" • {agent_id}:")
219
+ for skill in skills:
220
+ print(f" - {skill}")
221
+ print()
222
+
223
+ def _run_custom_selection(
224
+ self, agent_ids: Optional[List[str]], initial_mapping: Dict[str, List[str]]
225
+ ) -> Dict[str, List[str]]:
226
+ """Run custom skills selection for each agent.
227
+
228
+ Args:
229
+ agent_ids: List of agent IDs
230
+ initial_mapping: Initial auto-linked mapping
231
+
232
+ Returns:
233
+ Updated agent-to-skills mapping
234
+ """
235
+ mapping = initial_mapping.copy()
236
+
237
+ # Get all available bundled skills
238
+ bundled_skills = self.registry.list_skills(source="bundled")
239
+ skill_list = sorted([skill.name for skill in bundled_skills])
240
+
241
+ print("\n" + "=" * 60)
242
+ print("Available Bundled Skills:")
243
+ print("=" * 60)
244
+ for i, skill in enumerate(bundled_skills, 1):
245
+ description = (
246
+ skill.description[:60] + "..."
247
+ if len(skill.description) > 60
248
+ else skill.description
249
+ )
250
+ print(f" [{i:2d}] {skill.name}")
251
+ print(f" {description}")
252
+ print()
253
+
254
+ # If no agents provided, ask which agents to configure
255
+ if not agent_ids:
256
+ agent_ids = self._get_agents_to_configure()
257
+
258
+ # Configure each agent
259
+ for agent_id in agent_ids:
260
+ print(f"\n🔧 Configuring skills for: {agent_id}")
261
+ current_skills = mapping.get(agent_id, [])
262
+
263
+ print(f" Current skills ({len(current_skills)}):")
264
+ for skill in current_skills:
265
+ print(f" - {skill}")
266
+
267
+ modify = (
268
+ input(f"\n Modify skills for {agent_id}? [y/N]: ").strip().lower()
269
+ )
270
+ if modify not in ["y", "yes"]:
271
+ continue
272
+
273
+ # Let user select skills
274
+ print("\n Enter skill numbers (comma-separated), or:")
275
+ print(" 'all' - Select all skills")
276
+ print(" 'none' - Clear all skills")
277
+ print(" 'keep' - Keep current selection")
278
+ selection = input(" Selection: ").strip().lower()
279
+
280
+ if selection == "keep":
281
+ continue
282
+ if selection == "none":
283
+ mapping[agent_id] = []
284
+ elif selection == "all":
285
+ mapping[agent_id] = skill_list.copy()
286
+ else:
287
+ # Parse comma-separated numbers
288
+ try:
289
+ selected_indices = [
290
+ int(idx.strip()) for idx in selection.split(",")
291
+ ]
292
+ selected_skills = [
293
+ skill_list[idx - 1]
294
+ for idx in selected_indices
295
+ if 1 <= idx <= len(skill_list)
296
+ ]
297
+ mapping[agent_id] = selected_skills
298
+ except (ValueError, IndexError) as e:
299
+ print(f" ⚠️ Invalid selection, keeping current: {e}")
300
+
301
+ return mapping
302
+
303
+ def _get_agents_to_configure(self) -> List[str]:
304
+ """Ask user which agents to configure.
305
+
306
+ Returns:
307
+ List of agent IDs
308
+ """
309
+ agent_ids_input = input("\nEnter agent IDs (comma-separated): ").strip()
310
+ return [aid.strip() for aid in agent_ids_input.split(",") if aid.strip()]
311
+
312
+ def _preview_final_configuration(self, mapping: Dict[str, List[str]]):
313
+ """Display final skills configuration preview.
314
+
315
+ Args:
316
+ mapping: Agent-to-skills mapping
317
+ """
318
+ print("\n" + "=" * 60)
319
+ print("📋 Final Skills Configuration:")
320
+ print("=" * 60)
321
+
322
+ if not mapping:
323
+ print(" (No skills configured)")
324
+ return
325
+
326
+ for agent_id, skills in mapping.items():
327
+ print(f"\n {agent_id} ({len(skills)} skills):")
328
+ if skills:
329
+ for skill in skills:
330
+ print(f" ✓ {skill}")
331
+ else:
332
+ print(" (no skills)")
333
+
334
+ def _apply_skills_configuration(self, mapping: Dict[str, List[str]]):
335
+ """Apply skills configuration to skill manager.
336
+
337
+ Args:
338
+ mapping: Agent-to-skills mapping
339
+ """
340
+ for agent_id, skills in mapping.items():
341
+ # Clear existing mappings for this agent
342
+ if agent_id in self.manager.agent_skill_mapping:
343
+ self.manager.agent_skill_mapping[agent_id] = []
344
+
345
+ # Add each skill
346
+ for skill_name in skills:
347
+ self.manager.add_skill_to_agent(agent_id, skill_name)
348
+
349
+ self.logger.info(f"Applied skills configuration for {len(mapping)} agents")
350
+
351
+ def list_available_skills(self):
352
+ """Display all available skills."""
353
+ print("\n" + "=" * 60)
354
+ print("📚 Available Skills")
355
+ print("=" * 60)
356
+
357
+ # Bundled skills
358
+ bundled_skills = self.registry.list_skills(source="bundled")
359
+ if bundled_skills:
360
+ print(f"\n🔹 Bundled Skills ({len(bundled_skills)}):")
361
+ for skill in sorted(bundled_skills, key=lambda s: s.name):
362
+ print(f" • {skill.name}")
363
+ if skill.description:
364
+ desc = (
365
+ skill.description[:80] + "..."
366
+ if len(skill.description) > 80
367
+ else skill.description
368
+ )
369
+ print(f" {desc}")
370
+
371
+ # User skills
372
+ user_skills = self.registry.list_skills(source="user")
373
+ if user_skills:
374
+ print(f"\n👤 User Skills ({len(user_skills)}):")
375
+ for skill in sorted(user_skills, key=lambda s: s.name):
376
+ print(f" • {skill.name}")
377
+ if skill.description:
378
+ desc = (
379
+ skill.description[:80] + "..."
380
+ if len(skill.description) > 80
381
+ else skill.description
382
+ )
383
+ print(f" {desc}")
384
+
385
+ # Project skills
386
+ project_skills = self.registry.list_skills(source="project")
387
+ if project_skills:
388
+ print(f"\n📂 Project Skills ({len(project_skills)}):")
389
+ for skill in sorted(project_skills, key=lambda s: s.name):
390
+ print(f" • {skill.name}")
391
+ if skill.description:
392
+ desc = (
393
+ skill.description[:80] + "..."
394
+ if len(skill.description) > 80
395
+ else skill.description
396
+ )
397
+ print(f" {desc}")
398
+
399
+ print()
400
+
401
+
402
+ def discover_and_link_runtime_skills():
403
+ """Discover user/project skills and auto-link to agents at runtime.
404
+
405
+ This function is called during startup to:
406
+ 1. Reload the skills registry (picks up new skills from .claude/skills/)
407
+ 2. Auto-link discovered skills to agents based on tags/naming conventions
408
+ """
409
+ try:
410
+ registry = get_registry()
411
+ manager = get_manager()
412
+
413
+ # Reload registry to pick up new skills
414
+ registry.reload()
415
+
416
+ # Get discovered skills (user and project)
417
+ discovered_skills = registry.list_skills(source="user") + registry.list_skills(
418
+ source="project"
419
+ )
420
+
421
+ if not discovered_skills:
422
+ logger.debug("No runtime skills discovered")
423
+ return
424
+
425
+ logger.info(f"Discovered {len(discovered_skills)} runtime skills")
426
+
427
+ # Auto-link based on skill content and naming
428
+ for skill in discovered_skills:
429
+ agents = _infer_agents_for_skill(skill)
430
+ for agent_id in agents:
431
+ manager.add_skill_to_agent(agent_id, skill.name)
432
+ logger.debug(f"Auto-linked skill '{skill.name}' to agent '{agent_id}'")
433
+
434
+ except Exception as e:
435
+ logger.error(f"Error during runtime skills discovery: {e}", exc_info=True)
436
+
437
+
438
+ def _infer_agents_for_skill(skill) -> List[str]:
439
+ """Infer which agents should have this skill based on tags/name.
440
+
441
+ Args:
442
+ skill: Skill object to analyze
443
+
444
+ Returns:
445
+ List of agent IDs that should have this skill
446
+ """
447
+ agents = []
448
+ content_lower = skill.content.lower()
449
+ name_lower = skill.name.lower()
450
+
451
+ # Python-related
452
+ if any(
453
+ tag in content_lower or tag in name_lower
454
+ for tag in ["python", "django", "flask", "fastapi"]
455
+ ):
456
+ agents.append("python-engineer")
457
+
458
+ # TypeScript/JavaScript-related
459
+ if any(
460
+ tag in content_lower or tag in name_lower
461
+ for tag in ["typescript", "javascript", "react", "next", "vue", "node"]
462
+ ):
463
+ agents.extend(["typescript-engineer", "react-engineer", "nextjs-engineer"])
464
+
465
+ # Go-related
466
+ if any(tag in content_lower or tag in name_lower for tag in ["golang", "go "]):
467
+ agents.append("golang-engineer")
468
+
469
+ # Ops-related
470
+ if any(
471
+ tag in content_lower or tag in name_lower
472
+ for tag in ["docker", "kubernetes", "deploy", "devops", "ops"]
473
+ ):
474
+ agents.extend(["ops", "devops", "local-ops"])
475
+
476
+ # Testing/QA-related
477
+ if any(
478
+ tag in content_lower or tag in name_lower
479
+ for tag in ["test", "qa", "quality", "assert"]
480
+ ):
481
+ agents.extend(["qa", "web-qa", "api-qa"])
482
+
483
+ # Documentation-related
484
+ if any(
485
+ tag in content_lower or tag in name_lower
486
+ for tag in ["documentation", "docs", "api doc", "openapi"]
487
+ ):
488
+ agents.extend(["docs", "documentation", "technical-writer"])
489
+
490
+ # Remove duplicates
491
+ return list(set(agents))
@@ -403,6 +403,13 @@ def create_parser(
403
403
  except ImportError:
404
404
  pass
405
405
 
406
+ try:
407
+ from .skills_parser import add_skills_subparser
408
+
409
+ add_skills_subparser(subparsers)
410
+ except ImportError:
411
+ pass
412
+
406
413
  try:
407
414
  from .config_parser import add_config_subparser
408
415
 
@@ -0,0 +1,137 @@
1
+ """
2
+ Skills command parser for claude-mpm CLI.
3
+
4
+ WHY: This module contains all arguments specific to skills management commands,
5
+ providing CLI access to the Skills Integration system.
6
+
7
+ DESIGN DECISION: Skills commands expose the SkillsService functionality via CLI
8
+ for listing, deploying, validating, updating, and configuring Claude Code skills.
9
+ """
10
+
11
+ import argparse
12
+
13
+ from ...constants import CLICommands, SkillsCommands
14
+ from .base_parser import add_common_arguments
15
+
16
+
17
+ def add_skills_subparser(subparsers) -> argparse.ArgumentParser:
18
+ """
19
+ Add the skills subparser with all skills management commands.
20
+
21
+ WHY: Skills management has multiple subcommands for discovery, deployment,
22
+ validation, updates, and configuration that need their own argument structures.
23
+
24
+ Args:
25
+ subparsers: The subparsers object from the main parser
26
+
27
+ Returns:
28
+ The configured skills subparser
29
+ """
30
+ # Skills command with subcommands
31
+ skills_parser = subparsers.add_parser(
32
+ CLICommands.SKILLS.value, help="Manage Claude Code skills"
33
+ )
34
+ add_common_arguments(skills_parser)
35
+
36
+ skills_subparsers = skills_parser.add_subparsers(
37
+ dest="skills_command", help="Skills commands", metavar="SUBCOMMAND"
38
+ )
39
+
40
+ # List command
41
+ list_parser = skills_subparsers.add_parser(
42
+ SkillsCommands.LIST.value, help="List available skills"
43
+ )
44
+ list_parser.add_argument(
45
+ "--category",
46
+ help="Filter by category (e.g., development, infrastructure, web-development)",
47
+ )
48
+ list_parser.add_argument(
49
+ "--agent", help="Show skills for specific agent (e.g., engineer, pm)"
50
+ )
51
+ list_parser.add_argument(
52
+ "--verbose",
53
+ "-v",
54
+ action="store_true",
55
+ help="Show detailed skill information",
56
+ )
57
+
58
+ # Deploy command
59
+ deploy_parser = skills_subparsers.add_parser(
60
+ SkillsCommands.DEPLOY.value, help="Deploy bundled skills to project"
61
+ )
62
+ deploy_parser.add_argument(
63
+ "--force",
64
+ action="store_true",
65
+ help="Force redeployment of already deployed skills",
66
+ )
67
+ deploy_parser.add_argument(
68
+ "--skill",
69
+ action="append",
70
+ dest="skills",
71
+ help="Deploy specific skill(s) only (can be used multiple times)",
72
+ )
73
+
74
+ # Validate command
75
+ validate_parser = skills_subparsers.add_parser(
76
+ SkillsCommands.VALIDATE.value, help="Validate skill structure and metadata"
77
+ )
78
+ validate_parser.add_argument("skill_name", help="Name of the skill to validate")
79
+ validate_parser.add_argument(
80
+ "--strict",
81
+ action="store_true",
82
+ help="Use strict validation (treat warnings as errors)",
83
+ )
84
+
85
+ # Update command
86
+ update_parser = skills_subparsers.add_parser(
87
+ SkillsCommands.UPDATE.value, help="Check for and install skill updates"
88
+ )
89
+ update_parser.add_argument(
90
+ "skill_names",
91
+ nargs="*",
92
+ help="Specific skills to update (default: all)",
93
+ )
94
+ update_parser.add_argument(
95
+ "--check-only",
96
+ action="store_true",
97
+ help="Check for updates without installing them",
98
+ )
99
+ update_parser.add_argument(
100
+ "--force",
101
+ action="store_true",
102
+ help="Force update even if versions match",
103
+ )
104
+
105
+ # Info command
106
+ info_parser = skills_subparsers.add_parser(
107
+ SkillsCommands.INFO.value, help="Show detailed skill information"
108
+ )
109
+ info_parser.add_argument("skill_name", help="Name of the skill")
110
+ info_parser.add_argument(
111
+ "--show-content",
112
+ action="store_true",
113
+ help="Show full skill content (SKILL.md)",
114
+ )
115
+
116
+ # Config command
117
+ config_parser = skills_subparsers.add_parser(
118
+ SkillsCommands.CONFIG.value, help="View or edit skills configuration"
119
+ )
120
+ config_parser.add_argument(
121
+ "--scope",
122
+ choices=["system", "user", "project"],
123
+ default="project",
124
+ help="Configuration scope (default: project)",
125
+ )
126
+ config_parser.add_argument(
127
+ "--edit",
128
+ action="store_true",
129
+ help="Open configuration in $EDITOR",
130
+ )
131
+ config_parser.add_argument(
132
+ "--path",
133
+ action="store_true",
134
+ help="Show configuration file path",
135
+ )
136
+
137
+ return skills_parser