claude-mpm 4.21.3__py3-none-any.whl → 5.1.9__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 (517) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +12 -0
  3. claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +3 -48
  4. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +1239 -674
  6. claude_mpm/agents/WORKFLOW.md +75 -2
  7. claude_mpm/agents/__init__.py +6 -0
  8. claude_mpm/agents/agent_loader.py +1 -4
  9. claude_mpm/agents/base_agent.json +6 -3
  10. claude_mpm/agents/base_agent_loader.py +10 -35
  11. claude_mpm/agents/frontmatter_validator.py +69 -1
  12. claude_mpm/agents/templates/circuit-breakers.md +1254 -0
  13. claude_mpm/agents/templates/context-management-examples.md +544 -0
  14. claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +89 -19
  15. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  16. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  17. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  18. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  19. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  20. claude_mpm/cli/__init__.py +37 -2
  21. claude_mpm/cli/commands/__init__.py +2 -0
  22. claude_mpm/cli/commands/agent_source.py +774 -0
  23. claude_mpm/cli/commands/agent_state_manager.py +188 -30
  24. claude_mpm/cli/commands/agents.py +1128 -36
  25. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  26. claude_mpm/cli/commands/agents_discover.py +338 -0
  27. claude_mpm/cli/commands/aggregate.py +1 -1
  28. claude_mpm/cli/commands/analyze.py +3 -3
  29. claude_mpm/cli/commands/auto_configure.py +537 -239
  30. claude_mpm/cli/commands/cleanup.py +1 -1
  31. claude_mpm/cli/commands/config.py +7 -4
  32. claude_mpm/cli/commands/configure.py +935 -45
  33. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  34. claude_mpm/cli/commands/configure_navigation.py +63 -46
  35. claude_mpm/cli/commands/debug.py +12 -12
  36. claude_mpm/cli/commands/doctor.py +10 -2
  37. claude_mpm/cli/commands/hook_errors.py +277 -0
  38. claude_mpm/cli/commands/local_deploy.py +1 -4
  39. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  40. claude_mpm/cli/commands/mpm_init/core.py +50 -2
  41. claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
  42. claude_mpm/cli/commands/mpm_init/prompts.py +6 -6
  43. claude_mpm/cli/commands/postmortem.py +401 -0
  44. claude_mpm/cli/commands/run.py +125 -167
  45. claude_mpm/cli/commands/skill_source.py +694 -0
  46. claude_mpm/cli/commands/skills.py +757 -20
  47. claude_mpm/cli/executor.py +78 -3
  48. claude_mpm/cli/interactive/agent_wizard.py +1032 -47
  49. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  50. claude_mpm/cli/parsers/agents_parser.py +310 -4
  51. claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
  52. claude_mpm/cli/parsers/base_parser.py +53 -0
  53. claude_mpm/cli/parsers/config_parser.py +96 -43
  54. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  55. claude_mpm/cli/parsers/skills_parser.py +145 -0
  56. claude_mpm/cli/parsers/source_parser.py +138 -0
  57. claude_mpm/cli/startup.py +564 -108
  58. claude_mpm/cli/startup_display.py +480 -0
  59. claude_mpm/cli/utils.py +1 -1
  60. claude_mpm/cli_module/commands.py +1 -1
  61. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  62. claude_mpm/commands/mpm-agents-detect.md +9 -0
  63. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  64. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  65. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  66. claude_mpm/commands/mpm-doctor.md +9 -0
  67. claude_mpm/commands/mpm-help.md +14 -2
  68. claude_mpm/commands/mpm-init.md +27 -2
  69. claude_mpm/commands/mpm-monitor.md +9 -0
  70. claude_mpm/commands/mpm-postmortem.md +123 -0
  71. claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
  72. claude_mpm/commands/mpm-status.md +9 -0
  73. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  74. claude_mpm/commands/mpm-ticket-view.md +552 -0
  75. claude_mpm/commands/mpm-version.md +9 -0
  76. claude_mpm/commands/mpm.md +10 -0
  77. claude_mpm/config/agent_presets.py +488 -0
  78. claude_mpm/config/agent_sources.py +325 -0
  79. claude_mpm/config/skill_presets.py +392 -0
  80. claude_mpm/config/skill_sources.py +590 -0
  81. claude_mpm/constants.py +13 -0
  82. claude_mpm/core/api_validator.py +1 -1
  83. claude_mpm/core/claude_runner.py +19 -35
  84. claude_mpm/core/config.py +24 -0
  85. claude_mpm/core/constants.py +1 -1
  86. claude_mpm/core/framework/__init__.py +3 -16
  87. claude_mpm/core/framework/loaders/file_loader.py +54 -101
  88. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  89. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  90. claude_mpm/core/hook_error_memory.py +381 -0
  91. claude_mpm/core/hook_manager.py +41 -2
  92. claude_mpm/core/interactive_session.py +131 -10
  93. claude_mpm/core/logger.py +3 -1
  94. claude_mpm/core/oneshot_session.py +110 -8
  95. claude_mpm/core/output_style_manager.py +173 -43
  96. claude_mpm/core/protocols/__init__.py +23 -0
  97. claude_mpm/core/protocols/runner_protocol.py +103 -0
  98. claude_mpm/core/protocols/session_protocol.py +131 -0
  99. claude_mpm/core/shared/singleton_manager.py +11 -4
  100. claude_mpm/core/system_context.py +38 -0
  101. claude_mpm/core/unified_agent_registry.py +129 -1
  102. claude_mpm/core/unified_config.py +22 -0
  103. claude_mpm/dashboard/static/css/activity.css +69 -69
  104. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  105. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  106. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  107. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  108. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  109. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  110. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  111. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  112. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  113. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  114. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  115. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  116. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  117. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  118. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  119. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  120. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  121. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  122. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  123. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  124. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  125. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  126. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  127. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  128. claude_mpm/dashboard/templates/code_simple.html +23 -23
  129. claude_mpm/dashboard/templates/index.html +18 -18
  130. claude_mpm/experimental/cli_enhancements.py +1 -5
  131. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  132. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  133. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  134. claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
  135. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  136. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  137. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  138. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  139. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  140. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  141. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  142. claude_mpm/models/agent_definition.py +7 -0
  143. claude_mpm/models/git_repository.py +198 -0
  144. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  145. claude_mpm/scripts/start_activity_logging.py +3 -1
  146. claude_mpm/services/agents/agent_builder.py +45 -9
  147. claude_mpm/services/agents/agent_preset_service.py +238 -0
  148. claude_mpm/services/agents/agent_selection_service.py +484 -0
  149. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  150. claude_mpm/services/agents/cache_git_manager.py +621 -0
  151. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  152. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  153. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  154. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  155. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  156. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  157. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  158. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  159. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  160. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  161. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +225 -18
  162. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  163. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  164. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +557 -0
  165. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  166. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  167. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  168. claude_mpm/services/agents/git_source_manager.py +629 -0
  169. claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
  170. claude_mpm/services/agents/local_template_manager.py +50 -10
  171. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  172. claude_mpm/services/agents/sources/__init__.py +13 -0
  173. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  174. claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
  175. claude_mpm/services/agents/startup_sync.py +239 -0
  176. claude_mpm/services/agents/toolchain_detector.py +474 -0
  177. claude_mpm/services/analysis/__init__.py +25 -0
  178. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  179. claude_mpm/services/analysis/postmortem_service.py +765 -0
  180. claude_mpm/services/cli/session_pause_manager.py +1 -1
  181. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  182. claude_mpm/services/command_deployment_service.py +200 -6
  183. claude_mpm/services/core/base.py +7 -2
  184. claude_mpm/services/core/interfaces/__init__.py +1 -3
  185. claude_mpm/services/core/interfaces/health.py +1 -4
  186. claude_mpm/services/core/models/__init__.py +2 -11
  187. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  188. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  189. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  190. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  191. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  192. claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
  193. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  194. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  195. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  196. claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
  197. claude_mpm/services/event_bus/direct_relay.py +3 -3
  198. claude_mpm/services/event_bus/event_bus.py +36 -3
  199. claude_mpm/services/events/consumers/logging.py +1 -2
  200. claude_mpm/services/git/__init__.py +21 -0
  201. claude_mpm/services/git/git_operations_service.py +494 -0
  202. claude_mpm/services/github/__init__.py +21 -0
  203. claude_mpm/services/github/github_cli_service.py +397 -0
  204. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  205. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  206. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  207. claude_mpm/services/instructions/__init__.py +9 -0
  208. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  209. claude_mpm/services/local_ops/__init__.py +3 -13
  210. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  211. claude_mpm/services/local_ops/health_manager.py +1 -4
  212. claude_mpm/services/local_ops/process_manager.py +1 -1
  213. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  214. claude_mpm/services/mcp_config_manager.py +75 -145
  215. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  216. claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
  217. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  218. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  219. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  220. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  221. claude_mpm/services/mcp_service_verifier.py +6 -3
  222. claude_mpm/services/memory/optimizer.py +1 -1
  223. claude_mpm/services/model/model_router.py +8 -9
  224. claude_mpm/services/monitor/daemon.py +29 -9
  225. claude_mpm/services/monitor/daemon_manager.py +96 -19
  226. claude_mpm/services/monitor/server.py +2 -2
  227. claude_mpm/services/native_agent_converter.py +356 -0
  228. claude_mpm/services/port_manager.py +1 -1
  229. claude_mpm/services/pr/__init__.py +14 -0
  230. claude_mpm/services/pr/pr_template_service.py +329 -0
  231. claude_mpm/services/project/documentation_manager.py +2 -1
  232. claude_mpm/services/project/project_organizer.py +4 -0
  233. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  234. claude_mpm/services/runner_configuration_service.py +17 -3
  235. claude_mpm/services/self_upgrade_service.py +165 -7
  236. claude_mpm/services/session_management_service.py +16 -4
  237. claude_mpm/services/skills/__init__.py +18 -0
  238. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  239. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  240. claude_mpm/services/skills_config.py +547 -0
  241. claude_mpm/services/skills_deployer.py +955 -0
  242. claude_mpm/services/socketio/handlers/connection.py +1 -1
  243. claude_mpm/services/socketio/handlers/git.py +2 -2
  244. claude_mpm/services/socketio/server/core.py +1 -4
  245. claude_mpm/services/socketio/server/main.py +1 -3
  246. claude_mpm/services/system_instructions_service.py +1 -3
  247. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  248. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  249. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  250. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  251. claude_mpm/services/unified/unified_deployment.py +1 -5
  252. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  253. claude_mpm/services/visualization/__init__.py +1 -5
  254. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  255. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  256. claude_mpm/skills/bundled/performance-profiling.md +6 -0
  257. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
  258. claude_mpm/skills/skills_registry.py +0 -1
  259. claude_mpm/templates/questions/__init__.py +38 -0
  260. claude_mpm/templates/questions/base.py +193 -0
  261. claude_mpm/templates/questions/pr_strategy.py +311 -0
  262. claude_mpm/templates/questions/project_init.py +385 -0
  263. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  264. claude_mpm/tools/__main__.py +8 -8
  265. claude_mpm/tools/code_tree_analyzer/analysis.py +1 -1
  266. claude_mpm/utils/agent_dependency_loader.py +80 -13
  267. claude_mpm/utils/agent_filters.py +288 -0
  268. claude_mpm/utils/dependency_cache.py +3 -1
  269. claude_mpm/utils/gitignore.py +244 -0
  270. claude_mpm/utils/log_cleanup.py +3 -3
  271. claude_mpm/utils/migration.py +372 -0
  272. claude_mpm/utils/progress.py +387 -0
  273. claude_mpm/utils/robust_installer.py +3 -5
  274. claude_mpm/utils/structured_questions.py +619 -0
  275. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/METADATA +496 -65
  276. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/RECORD +284 -443
  277. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  278. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  279. claude_mpm/agents/templates/agent-manager.json +0 -273
  280. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  281. claude_mpm/agents/templates/api_qa.json +0 -180
  282. claude_mpm/agents/templates/circuit_breakers.md +0 -638
  283. claude_mpm/agents/templates/clerk-ops.json +0 -235
  284. claude_mpm/agents/templates/code_analyzer.json +0 -101
  285. claude_mpm/agents/templates/content-agent.json +0 -358
  286. claude_mpm/agents/templates/dart_engineer.json +0 -307
  287. claude_mpm/agents/templates/data_engineer.json +0 -225
  288. claude_mpm/agents/templates/documentation.json +0 -211
  289. claude_mpm/agents/templates/engineer.json +0 -210
  290. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  291. claude_mpm/agents/templates/golang_engineer.json +0 -270
  292. claude_mpm/agents/templates/imagemagick.json +0 -264
  293. claude_mpm/agents/templates/java_engineer.json +0 -346
  294. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  295. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  296. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  297. claude_mpm/agents/templates/memory_manager.json +0 -158
  298. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  299. claude_mpm/agents/templates/ops.json +0 -185
  300. claude_mpm/agents/templates/php-engineer.json +0 -287
  301. claude_mpm/agents/templates/product_owner.json +0 -338
  302. claude_mpm/agents/templates/project_organizer.json +0 -140
  303. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  304. claude_mpm/agents/templates/python_engineer.json +0 -387
  305. claude_mpm/agents/templates/qa.json +0 -242
  306. claude_mpm/agents/templates/react_engineer.json +0 -238
  307. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  308. claude_mpm/agents/templates/research.json +0 -188
  309. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  310. claude_mpm/agents/templates/rust_engineer.json +0 -275
  311. claude_mpm/agents/templates/security.json +0 -202
  312. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  313. claude_mpm/agents/templates/ticketing.json +0 -177
  314. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  315. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  316. claude_mpm/agents/templates/version_control.json +0 -157
  317. claude_mpm/agents/templates/web_qa.json +0 -399
  318. claude_mpm/agents/templates/web_ui.json +0 -189
  319. claude_mpm/commands/mpm-tickets.md +0 -102
  320. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  321. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  322. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  323. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  324. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  325. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  326. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  327. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  328. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  329. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  330. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  331. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  332. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  333. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  334. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  335. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  336. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  337. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  338. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  339. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  340. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  341. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  342. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  343. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  344. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  345. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  346. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  347. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  348. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  349. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  350. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  351. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  352. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  353. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  354. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  355. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  356. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  357. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  358. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  359. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  360. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  361. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  362. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  363. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  364. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  365. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  366. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  367. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  368. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  369. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  370. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  371. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  372. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  373. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  374. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  375. claude_mpm/dashboard/static/built/react/events.js +0 -30
  376. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  377. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  378. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  379. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  380. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  381. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  382. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  383. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  384. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  385. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  386. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  387. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  388. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  389. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  390. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  391. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  392. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  393. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  394. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  395. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  396. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  397. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  398. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  399. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  400. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  401. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  402. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  403. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  404. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  405. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  406. claude_mpm/dashboard/static/events.html +0 -607
  407. claude_mpm/dashboard/static/index.html +0 -635
  408. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  409. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  410. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  411. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  412. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  413. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  414. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  415. claude_mpm/dashboard/static/legacy/files.html +0 -747
  416. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  417. claude_mpm/dashboard/static/monitors.html +0 -431
  418. claude_mpm/dashboard/static/production/events.html +0 -659
  419. claude_mpm/dashboard/static/production/main.html +0 -698
  420. claude_mpm/dashboard/static/production/monitors.html +0 -483
  421. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  422. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  423. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  424. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  425. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  426. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
  427. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
  428. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
  429. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
  430. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
  431. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
  432. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
  433. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
  434. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
  435. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
  436. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
  437. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
  438. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
  439. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
  440. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
  441. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
  442. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
  443. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  444. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  445. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  446. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  447. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  448. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  449. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  450. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  451. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  452. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  453. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
  454. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
  455. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
  456. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
  457. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
  458. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
  459. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
  460. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  461. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  462. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  463. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  464. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
  465. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
  466. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  467. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  468. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  469. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  470. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
  471. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
  472. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
  473. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
  474. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
  475. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
  476. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
  477. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
  478. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
  479. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
  480. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
  481. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
  482. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
  483. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
  484. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
  485. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
  486. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
  487. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
  488. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
  489. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
  490. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
  491. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
  492. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
  493. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  494. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  495. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  496. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  497. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  498. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  499. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
  500. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
  501. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
  502. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
  503. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
  504. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
  505. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
  506. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
  507. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
  508. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
  509. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
  510. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  511. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  512. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  513. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  514. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/WHEEL +0 -0
  515. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/entry_points.txt +0 -0
  516. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/licenses/LICENSE +0 -0
  517. {claude_mpm-4.21.3.dist-info → claude_mpm-5.1.9.dist-info}/top_level.txt +0 -0
@@ -3,13 +3,18 @@ Skills command implementation for claude-mpm.
3
3
 
4
4
  WHY: This module provides CLI commands for managing Claude Code skills,
5
5
  exposing SkillsService functionality for skill discovery, deployment, validation,
6
- updates, and configuration.
6
+ updates, and configuration. Also provides GitHub skills deployment via SkillsDeployer.
7
7
 
8
8
  DESIGN DECISIONS:
9
9
  - Use BaseCommand pattern for consistency with other CLI commands
10
10
  - Rich output formatting for user-friendly display
11
11
  - Graceful error handling with informative messages
12
12
  - Support for verbose output and structured formats
13
+ - Dual service approach: SkillsService for bundled, SkillsDeployer for GitHub
14
+
15
+ ARCHITECTURE:
16
+ - SkillsService: Manages bundled skills (in project .claude/skills/)
17
+ - SkillsDeployer: Downloads from GitHub to ~/.claude/skills/ for Claude Code
13
18
  """
14
19
 
15
20
  import os
@@ -19,8 +24,10 @@ from typing import Optional
19
24
  from rich.console import Console
20
25
  from rich.markdown import Markdown
21
26
  from rich.panel import Panel
27
+ from rich.table import Table
22
28
 
23
29
  from ...constants import SkillsCommands
30
+ from ...services.skills_deployer import SkillsDeployerService
24
31
  from ...skills.skills_service import SkillsService
25
32
  from ..shared import BaseCommand, CommandResult
26
33
 
@@ -33,6 +40,7 @@ class SkillsManagementCommand(BaseCommand):
33
40
  def __init__(self):
34
41
  super().__init__("skills")
35
42
  self._skills_service = None
43
+ self._skills_deployer = None
36
44
 
37
45
  @property
38
46
  def skills_service(self) -> SkillsService:
@@ -41,6 +49,13 @@ class SkillsManagementCommand(BaseCommand):
41
49
  self._skills_service = SkillsService()
42
50
  return self._skills_service
43
51
 
52
+ @property
53
+ def skills_deployer(self) -> SkillsDeployerService:
54
+ """Get skills deployer instance (lazy loaded)."""
55
+ if self._skills_deployer is None:
56
+ self._skills_deployer = SkillsDeployerService()
57
+ return self._skills_deployer
58
+
44
59
  def validate_args(self, args) -> Optional[str]:
45
60
  """Validate command arguments."""
46
61
  # Most skills commands are optional, basic validation
@@ -68,6 +83,19 @@ class SkillsManagementCommand(BaseCommand):
68
83
  SkillsCommands.UPDATE.value: self._update_skills,
69
84
  SkillsCommands.INFO.value: self._show_skill_info,
70
85
  SkillsCommands.CONFIG.value: self._manage_config,
86
+ SkillsCommands.CONFIGURE.value: self._configure_skills,
87
+ # GitHub deployment commands
88
+ SkillsCommands.DEPLOY_FROM_GITHUB.value: self._deploy_from_github,
89
+ SkillsCommands.LIST_AVAILABLE.value: self._list_available_github_skills,
90
+ SkillsCommands.CHECK_DEPLOYED.value: self._check_deployed_skills,
91
+ SkillsCommands.REMOVE.value: self._remove_skills,
92
+ # Collection management commands
93
+ SkillsCommands.COLLECTION_LIST.value: self._collection_list,
94
+ SkillsCommands.COLLECTION_ADD.value: self._collection_add,
95
+ SkillsCommands.COLLECTION_REMOVE.value: self._collection_remove,
96
+ SkillsCommands.COLLECTION_ENABLE.value: self._collection_enable,
97
+ SkillsCommands.COLLECTION_DISABLE.value: self._collection_disable,
98
+ SkillsCommands.COLLECTION_SET_DEFAULT.value: self._collection_set_default,
71
99
  }
72
100
 
73
101
  handler = command_map.get(args.skills_command)
@@ -168,55 +196,109 @@ class SkillsManagementCommand(BaseCommand):
168
196
  return CommandResult(success=False, message=str(e), exit_code=1)
169
197
 
170
198
  def _deploy_skills(self, args) -> CommandResult:
171
- """Deploy bundled skills to project."""
199
+ """Deploy skills using two-phase sync: cache → deploy.
200
+
201
+ Phase 3 Integration (1M-486): Uses Git skill source manager for deployment.
202
+ - Phase 1: Sync skills to ~/.claude-mpm/cache/skills/ (if needed)
203
+ - Phase 2: Deploy from cache to project .claude-mpm/skills/
204
+
205
+ This replaces bundled skill deployment with a multi-project
206
+ architecture where one cache serves multiple project deployments.
207
+ """
172
208
  try:
209
+ from pathlib import Path
210
+
211
+ from ...config.skill_sources import SkillSourceConfiguration
212
+ from ...services.skills.git_skill_source_manager import (
213
+ GitSkillSourceManager,
214
+ )
215
+
173
216
  force = getattr(args, "force", False)
174
217
  specific_skills = getattr(args, "skills", None)
175
218
 
176
219
  console.print("\n[bold cyan]Deploying skills...[/bold cyan]\n")
177
220
 
178
- result = self.skills_service.deploy_bundled_skills(
179
- force=force, skill_names=specific_skills
221
+ # Initialize git skill source manager
222
+ config = SkillSourceConfiguration.load()
223
+ git_skill_manager = GitSkillSourceManager(config)
224
+ project_dir = Path.cwd()
225
+
226
+ # Phase 1: Sync skills to cache
227
+ console.print("[dim]Phase 1: Syncing skills to cache...[/dim]")
228
+ sync_results = git_skill_manager.sync_all_sources(force=force)
229
+
230
+ synced_count = sum(
231
+ 1 for result in sync_results.values() if result.get("synced")
232
+ )
233
+ console.print(f"[dim]Synced {synced_count} skill source(s)[/dim]\n")
234
+
235
+ # Phase 2: Deploy from cache to project
236
+ console.print("[dim]Phase 2: Deploying from cache to project...[/dim]\n")
237
+ deploy_result = git_skill_manager.deploy_skills_to_project(
238
+ project_dir=project_dir,
239
+ skill_list=specific_skills,
240
+ force=force,
180
241
  )
181
242
 
182
243
  # Display results
183
- if result["deployed"]:
244
+ if deploy_result["deployed"]:
184
245
  console.print(
185
- f"[green]✓ Deployed {len(result['deployed'])} skill(s):[/green]"
246
+ f"[green]✓ Deployed {len(deploy_result['deployed'])} skill(s):[/green]"
186
247
  )
187
- for skill in result["deployed"]:
248
+ for skill in deploy_result["deployed"]:
188
249
  console.print(f" • {skill}")
189
250
  console.print()
190
251
 
191
- if result["skipped"]:
252
+ if deploy_result["updated"]:
192
253
  console.print(
193
- f"[yellow] Skipped {len(result['skipped'])} skill(s) (already deployed):[/yellow]"
254
+ f"[green] Updated {len(deploy_result['updated'])} skill(s):[/green]"
194
255
  )
195
- for skill in result["skipped"]:
256
+ for skill in deploy_result["updated"]:
257
+ console.print(f" • {skill}")
258
+ console.print()
259
+
260
+ if deploy_result["skipped"]:
261
+ console.print(
262
+ f"[yellow]⊘ Skipped {len(deploy_result['skipped'])} skill(s) (already up-to-date):[/yellow]"
263
+ )
264
+ for skill in deploy_result["skipped"]:
196
265
  console.print(f" • {skill}")
197
266
  console.print("[dim]Use --force to redeploy[/dim]\n")
198
267
 
199
- if result["errors"]:
268
+ if deploy_result["failed"]:
200
269
  console.print(
201
- f"[red]✗ Failed to deploy {len(result['errors'])} skill(s):[/red]"
270
+ f"[red]✗ Failed to deploy {len(deploy_result['failed'])} skill(s):[/red]"
202
271
  )
203
- for skill, error in result["errors"].items():
204
- console.print(f" • {skill}: {error}")
272
+ for skill in deploy_result["failed"]:
273
+ console.print(f" • {skill}")
205
274
  console.print()
206
275
 
207
276
  # Summary
277
+ success_count = len(deploy_result["deployed"]) + len(
278
+ deploy_result["updated"]
279
+ )
208
280
  total = (
209
- len(result["deployed"]) + len(result["skipped"]) + len(result["errors"])
281
+ success_count
282
+ + len(deploy_result["skipped"])
283
+ + len(deploy_result["failed"])
210
284
  )
211
285
  console.print(
212
- f"[bold]Summary:[/bold] {len(result['deployed'])} deployed, "
213
- f"{len(result['skipped'])} skipped, {len(result['errors'])} errors "
214
- f"(Total: {total})\n"
286
+ f"[bold]Summary:[/bold] {success_count} deployed/updated, "
287
+ f"{len(deploy_result['skipped'])} skipped, "
288
+ f"{len(deploy_result['failed'])} errors (Total: {total})\n"
289
+ )
290
+
291
+ console.print(
292
+ f"[dim]Deployment directory: {deploy_result['deployment_dir']}[/dim]\n"
215
293
  )
216
294
 
217
295
  # Exit with error if any deployments failed
218
- exit_code = 1 if result["errors"] else 0
219
- return CommandResult(success=not result["errors"], exit_code=exit_code)
296
+ exit_code = 1 if deploy_result["failed"] else 0
297
+ return CommandResult(
298
+ success=not deploy_result["failed"],
299
+ message=f"Deployed {success_count} skills from cache",
300
+ exit_code=exit_code,
301
+ )
220
302
 
221
303
  except Exception as e:
222
304
  console.print(f"[red]Error deploying skills: {e}[/red]")
@@ -448,6 +530,209 @@ class SkillsManagementCommand(BaseCommand):
448
530
  console.print(f"[red]Error managing configuration: {e}[/red]")
449
531
  return CommandResult(success=False, message=str(e), exit_code=1)
450
532
 
533
+ def _deploy_from_github(self, args) -> CommandResult:
534
+ """Deploy skills from GitHub repository."""
535
+ try:
536
+ collection = getattr(args, "collection", None)
537
+ toolchain = getattr(args, "toolchain", None)
538
+ categories = getattr(args, "categories", None)
539
+ force = getattr(args, "force", False)
540
+ all_skills = getattr(args, "all", False)
541
+
542
+ if collection:
543
+ console.print(
544
+ f"\n[bold cyan]Deploying skills from collection '{collection}'...[/bold cyan]\n"
545
+ )
546
+ else:
547
+ console.print(
548
+ "\n[bold cyan]Deploying skills from default collection...[/bold cyan]\n"
549
+ )
550
+
551
+ # Auto-detect toolchain if not specified and not deploying all
552
+ if not toolchain and not all_skills:
553
+ console.print(
554
+ "[yellow]No toolchain specified. Use --toolchain to filter by language,[/yellow]"
555
+ )
556
+ console.print(
557
+ "[yellow]or --all to deploy all available skills.[/yellow]\n"
558
+ )
559
+
560
+ result = self.skills_deployer.deploy_skills(
561
+ collection=collection,
562
+ toolchain=toolchain,
563
+ categories=categories,
564
+ force=force,
565
+ )
566
+
567
+ # Display results
568
+ if result["deployed_count"] > 0:
569
+ console.print(
570
+ f"[green]✓ Deployed {result['deployed_count']} skill(s):[/green]"
571
+ )
572
+ for skill in result["deployed_skills"]:
573
+ console.print(f" • {skill}")
574
+ console.print()
575
+
576
+ if result["skipped_count"] > 0:
577
+ console.print(
578
+ f"[yellow]⊘ Skipped {result['skipped_count']} skill(s) (already deployed):[/yellow]"
579
+ )
580
+ for skill in result["skipped_skills"]:
581
+ console.print(f" • {skill}")
582
+ console.print("[dim]Use --force to redeploy[/dim]\n")
583
+
584
+ if result["errors"]:
585
+ console.print(f"[red]✗ {len(result['errors'])} error(s):[/red]")
586
+ for error in result["errors"]:
587
+ console.print(f" • {error}")
588
+ console.print()
589
+
590
+ # Show restart instructions
591
+ if result["restart_instructions"]:
592
+ console.print(
593
+ Panel(
594
+ result["restart_instructions"],
595
+ title="⚠️ Important",
596
+ border_style="yellow",
597
+ )
598
+ )
599
+ console.print()
600
+
601
+ exit_code = 1 if result["errors"] else 0
602
+ return CommandResult(success=not result["errors"], exit_code=exit_code)
603
+
604
+ except Exception as e:
605
+ console.print(f"[red]Error deploying from GitHub: {e}[/red]")
606
+ return CommandResult(success=False, message=str(e), exit_code=1)
607
+
608
+ def _list_available_github_skills(self, args) -> CommandResult:
609
+ """List available skills from GitHub repository."""
610
+ try:
611
+ collection = getattr(args, "collection", None)
612
+
613
+ if collection:
614
+ console.print(
615
+ f"\n[bold cyan]Fetching skills from collection '{collection}'...[/bold cyan]\n"
616
+ )
617
+ else:
618
+ console.print(
619
+ "\n[bold cyan]Fetching skills from default collection...[/bold cyan]\n"
620
+ )
621
+
622
+ result = self.skills_deployer.list_available_skills(collection=collection)
623
+
624
+ if result.get("error"):
625
+ console.print(f"[red]Error: {result['error']}[/red]")
626
+ return CommandResult(
627
+ success=False, message=result["error"], exit_code=1
628
+ )
629
+
630
+ console.print(
631
+ f"[green]Found {result['total_skills']} available skills[/green]\n"
632
+ )
633
+
634
+ # Display by category
635
+ console.print("[bold yellow]By Category:[/bold yellow]\n")
636
+ for category, skills in sorted(result["by_category"].items()):
637
+ console.print(f" [cyan]{category}[/cyan] ({len(skills)} skills)")
638
+ if hasattr(args, "verbose") and args.verbose:
639
+ for skill in sorted(skills, key=lambda s: s.get("name", "")):
640
+ console.print(f" • {skill.get('name', 'unknown')}")
641
+ console.print()
642
+
643
+ # Display by toolchain
644
+ console.print("[bold yellow]By Toolchain:[/bold yellow]\n")
645
+ for toolchain, skills in sorted(result["by_toolchain"].items()):
646
+ console.print(f" [cyan]{toolchain}[/cyan] ({len(skills)} skills)")
647
+ if hasattr(args, "verbose") and args.verbose:
648
+ for skill in sorted(skills, key=lambda s: s.get("name", "")):
649
+ console.print(f" • {skill.get('name', 'unknown')}")
650
+ console.print()
651
+
652
+ return CommandResult(success=True, exit_code=0)
653
+
654
+ except Exception as e:
655
+ console.print(f"[red]Error listing available skills: {e}[/red]")
656
+ return CommandResult(success=False, message=str(e), exit_code=1)
657
+
658
+ def _check_deployed_skills(self, args) -> CommandResult:
659
+ """Check currently deployed skills in ~/.claude/skills/."""
660
+ try:
661
+ result = self.skills_deployer.check_deployed_skills()
662
+
663
+ console.print("\n[bold cyan]Claude Code Skills Status:[/bold cyan]\n")
664
+ console.print(f"[dim]Directory: {result['claude_skills_dir']}[/dim]\n")
665
+
666
+ if result["deployed_count"] == 0:
667
+ console.print("[yellow]No skills currently deployed.[/yellow]")
668
+ console.print(
669
+ "[dim]Use 'claude-mpm skills deploy-github' to deploy skills.[/dim]\n"
670
+ )
671
+ return CommandResult(success=True, exit_code=0)
672
+
673
+ console.print(
674
+ f"[green]{result['deployed_count']} skill(s) deployed:[/green]\n"
675
+ )
676
+
677
+ # Create table for deployed skills
678
+ table = Table(show_header=True, header_style="bold cyan")
679
+ table.add_column("Skill Name", style="green")
680
+ table.add_column("Path", style="dim")
681
+
682
+ for skill in sorted(result["skills"], key=lambda s: s["name"]):
683
+ table.add_row(skill["name"], skill["path"])
684
+
685
+ console.print(table)
686
+ console.print()
687
+
688
+ return CommandResult(success=True, exit_code=0)
689
+
690
+ except Exception as e:
691
+ console.print(f"[red]Error checking deployed skills: {e}[/red]")
692
+ return CommandResult(success=False, message=str(e), exit_code=1)
693
+
694
+ def _remove_skills(self, args) -> CommandResult:
695
+ """Remove deployed skills."""
696
+ try:
697
+ skill_names = getattr(args, "skill_names", None)
698
+ remove_all = getattr(args, "all", False)
699
+
700
+ if remove_all:
701
+ skill_names = None
702
+ console.print(
703
+ "\n[bold yellow]Removing ALL deployed skills...[/bold yellow]\n"
704
+ )
705
+ elif skill_names:
706
+ console.print(
707
+ f"\n[bold cyan]Removing {len(skill_names)} skill(s)...[/bold cyan]\n"
708
+ )
709
+ else:
710
+ console.print("[red]Error: Specify skill names or use --all[/red]")
711
+ return CommandResult(success=False, exit_code=1)
712
+
713
+ result = self.skills_deployer.remove_skills(skill_names)
714
+
715
+ if result["removed_count"] > 0:
716
+ console.print(
717
+ f"[green]✓ Removed {result['removed_count']} skill(s):[/green]"
718
+ )
719
+ for skill in result["removed_skills"]:
720
+ console.print(f" • {skill}")
721
+ console.print()
722
+
723
+ if result["errors"]:
724
+ console.print(f"[red]✗ {len(result['errors'])} error(s):[/red]")
725
+ for error in result["errors"]:
726
+ console.print(f" • {error}")
727
+ console.print()
728
+
729
+ exit_code = 1 if result["errors"] else 0
730
+ return CommandResult(success=not result["errors"], exit_code=exit_code)
731
+
732
+ except Exception as e:
733
+ console.print(f"[red]Error removing skills: {e}[/red]")
734
+ return CommandResult(success=False, message=str(e), exit_code=1)
735
+
451
736
  def _get_skill_metadata(self, skill_name: str) -> Optional[dict]:
452
737
  """Get skill metadata from SKILL.md file."""
453
738
  try:
@@ -464,6 +749,458 @@ class SkillsManagementCommand(BaseCommand):
464
749
  except Exception:
465
750
  return None
466
751
 
752
+ # === Collection Management Commands ===
753
+
754
+ def _collection_list(self, args) -> CommandResult:
755
+ """List all configured skill collections."""
756
+ try:
757
+ result = self.skills_deployer.list_collections()
758
+
759
+ console.print("\n[bold cyan]Skill Collections:[/bold cyan]\n")
760
+ console.print(
761
+ f"[dim]Default collection: {result['default_collection']}[/dim]"
762
+ )
763
+ console.print(
764
+ f"[dim]Enabled: {result['enabled_count']} / {result['total_count']}[/dim]\n"
765
+ )
766
+
767
+ if not result["collections"]:
768
+ console.print("[yellow]No collections configured.[/yellow]")
769
+ console.print(
770
+ "[dim]Use 'claude-mpm skills collection-add' to add a collection.[/dim]\n"
771
+ )
772
+ return CommandResult(success=True, exit_code=0)
773
+
774
+ # Create table for collections
775
+ table = Table(show_header=True, header_style="bold cyan")
776
+ table.add_column("Name", style="green")
777
+ table.add_column("URL", style="white")
778
+ table.add_column("Priority", justify="center")
779
+ table.add_column("Enabled", justify="center")
780
+ table.add_column("Last Update", style="dim")
781
+ table.add_column("Default", justify="center")
782
+
783
+ # Sort by priority
784
+ sorted_collections = sorted(
785
+ result["collections"].items(), key=lambda x: x[1].get("priority", 999)
786
+ )
787
+
788
+ for name, config in sorted_collections:
789
+ enabled_icon = "✓" if config.get("enabled", True) else "✗"
790
+ default_icon = "⭐" if name == result["default_collection"] else ""
791
+ last_update = config.get("last_update") or "Never"
792
+
793
+ table.add_row(
794
+ name,
795
+ config["url"],
796
+ str(config.get("priority", "N/A")),
797
+ enabled_icon,
798
+ last_update,
799
+ default_icon,
800
+ )
801
+
802
+ console.print(table)
803
+ console.print()
804
+
805
+ return CommandResult(success=True, exit_code=0)
806
+
807
+ except Exception as e:
808
+ console.print(f"[red]Error listing collections: {e}[/red]")
809
+ return CommandResult(success=False, message=str(e), exit_code=1)
810
+
811
+ def _collection_add(self, args) -> CommandResult:
812
+ """Add a new skill collection."""
813
+ try:
814
+ name = getattr(args, "collection_name", None)
815
+ url = getattr(args, "collection_url", None)
816
+ priority = getattr(args, "priority", 99)
817
+
818
+ if not name or not url:
819
+ console.print("[red]Error: Collection name and URL are required[/red]")
820
+ console.print(
821
+ "[dim]Usage: claude-mpm skills collection-add NAME URL [--priority N][/dim]"
822
+ )
823
+ return CommandResult(success=False, exit_code=1)
824
+
825
+ console.print(f"\n[bold cyan]Adding collection '{name}'...[/bold cyan]\n")
826
+
827
+ result = self.skills_deployer.add_collection(name, url, priority)
828
+
829
+ console.print(f"[green]✓ {result['message']}[/green]")
830
+ console.print(f" [dim]URL: {url}[/dim]")
831
+ console.print(f" [dim]Priority: {priority}[/dim]\n")
832
+
833
+ return CommandResult(success=True, exit_code=0)
834
+
835
+ except ValueError as e:
836
+ console.print(f"[red]Error: {e}[/red]")
837
+ return CommandResult(success=False, message=str(e), exit_code=1)
838
+ except Exception as e:
839
+ console.print(f"[red]Unexpected error: {e}[/red]")
840
+ return CommandResult(success=False, message=str(e), exit_code=1)
841
+
842
+ def _collection_remove(self, args) -> CommandResult:
843
+ """Remove a skill collection."""
844
+ try:
845
+ name = getattr(args, "collection_name", None)
846
+
847
+ if not name:
848
+ console.print("[red]Error: Collection name is required[/red]")
849
+ console.print(
850
+ "[dim]Usage: claude-mpm skills collection-remove NAME[/dim]"
851
+ )
852
+ return CommandResult(success=False, exit_code=1)
853
+
854
+ console.print(
855
+ f"\n[bold yellow]Removing collection '{name}'...[/bold yellow]\n"
856
+ )
857
+
858
+ result = self.skills_deployer.remove_collection(name)
859
+
860
+ console.print(f"[green]✓ {result['message']}[/green]")
861
+ if result.get("directory_removed"):
862
+ console.print(" [dim]Collection directory removed[/dim]")
863
+ elif result.get("directory_error"):
864
+ console.print(
865
+ f" [yellow]Warning: {result['directory_error']}[/yellow]"
866
+ )
867
+ console.print()
868
+
869
+ return CommandResult(success=True, exit_code=0)
870
+
871
+ except ValueError as e:
872
+ console.print(f"[red]Error: {e}[/red]")
873
+ return CommandResult(success=False, message=str(e), exit_code=1)
874
+ except Exception as e:
875
+ console.print(f"[red]Unexpected error: {e}[/red]")
876
+ return CommandResult(success=False, message=str(e), exit_code=1)
877
+
878
+ def _collection_enable(self, args) -> CommandResult:
879
+ """Enable a disabled collection."""
880
+ try:
881
+ name = getattr(args, "collection_name", None)
882
+
883
+ if not name:
884
+ console.print("[red]Error: Collection name is required[/red]")
885
+ console.print(
886
+ "[dim]Usage: claude-mpm skills collection-enable NAME[/dim]"
887
+ )
888
+ return CommandResult(success=False, exit_code=1)
889
+
890
+ result = self.skills_deployer.enable_collection(name)
891
+
892
+ console.print(f"\n[green]✓ {result['message']}[/green]\n")
893
+
894
+ return CommandResult(success=True, exit_code=0)
895
+
896
+ except ValueError as e:
897
+ console.print(f"[red]Error: {e}[/red]")
898
+ return CommandResult(success=False, message=str(e), exit_code=1)
899
+ except Exception as e:
900
+ console.print(f"[red]Unexpected error: {e}[/red]")
901
+ return CommandResult(success=False, message=str(e), exit_code=1)
902
+
903
+ def _collection_disable(self, args) -> CommandResult:
904
+ """Disable a collection."""
905
+ try:
906
+ name = getattr(args, "collection_name", None)
907
+
908
+ if not name:
909
+ console.print("[red]Error: Collection name is required[/red]")
910
+ console.print(
911
+ "[dim]Usage: claude-mpm skills collection-disable NAME[/dim]"
912
+ )
913
+ return CommandResult(success=False, exit_code=1)
914
+
915
+ result = self.skills_deployer.disable_collection(name)
916
+
917
+ console.print(f"\n[green]✓ {result['message']}[/green]\n")
918
+
919
+ return CommandResult(success=True, exit_code=0)
920
+
921
+ except ValueError as e:
922
+ console.print(f"[red]Error: {e}[/red]")
923
+ return CommandResult(success=False, message=str(e), exit_code=1)
924
+ except Exception as e:
925
+ console.print(f"[red]Unexpected error: {e}[/red]")
926
+ return CommandResult(success=False, message=str(e), exit_code=1)
927
+
928
+ def _collection_set_default(self, args) -> CommandResult:
929
+ """Set the default collection."""
930
+ try:
931
+ name = getattr(args, "collection_name", None)
932
+
933
+ if not name:
934
+ console.print("[red]Error: Collection name is required[/red]")
935
+ console.print(
936
+ "[dim]Usage: claude-mpm skills collection-set-default NAME[/dim]"
937
+ )
938
+ return CommandResult(success=False, exit_code=1)
939
+
940
+ result = self.skills_deployer.set_default_collection(name)
941
+
942
+ console.print(f"\n[green]✓ {result['message']}[/green]")
943
+ if result.get("previous_default"):
944
+ console.print(f" [dim]Previous: {result['previous_default']}[/dim]")
945
+ console.print()
946
+
947
+ return CommandResult(success=True, exit_code=0)
948
+
949
+ except ValueError as e:
950
+ console.print(f"[red]Error: {e}[/red]")
951
+ return CommandResult(success=False, message=str(e), exit_code=1)
952
+ except Exception as e:
953
+ console.print(f"[red]Unexpected error: {e}[/red]")
954
+
955
+ def _configure_skills(self, args) -> CommandResult:
956
+ """Interactive skills configuration with checkbox selection.
957
+
958
+ Provides checkbox-based selection interface matching agents configure UX:
959
+ - Status column showing Installed/Available
960
+ - Pre-selection for installed skills
961
+ - Apply/Adjust/Cancel menu
962
+ - While loop for adjustment
963
+ - Simplified labels (checkbox state only)
964
+
965
+ This is Option 3 (Hybrid approach): Separate command for interactive mode
966
+ while keeping deploy-github for CLI automation.
967
+ """
968
+ try:
969
+ import questionary
970
+ from questionary import Choice, Style
971
+ from rich.prompt import Prompt
972
+
973
+ # Questionary style (matching agents configure)
974
+ QUESTIONARY_STYLE = Style(
975
+ [
976
+ (
977
+ "selected",
978
+ "fg:#e0e0e0 bold",
979
+ ), # Light gray - excellent readability
980
+ (
981
+ "pointer",
982
+ "fg:#ffd700 bold",
983
+ ), # Gold/yellow - highly visible pointer
984
+ ("highlighted", "fg:#e0e0e0"), # Light gray - clear hover state
985
+ (
986
+ "question",
987
+ "fg:#e0e0e0 bold",
988
+ ), # Light gray bold - prominent questions
989
+ ("checkbox", "fg:#00ff00"), # Green - for checked boxes
990
+ (
991
+ "checkbox-selected",
992
+ "fg:#00ff00 bold",
993
+ ), # Green bold - for checked selected boxes
994
+ ]
995
+ )
996
+
997
+ console.print("\n[bold cyan]Interactive Skills Configuration[/bold cyan]\n")
998
+ console.print(
999
+ "[dim]Select skills to install/uninstall using checkboxes[/dim]"
1000
+ )
1001
+ console.print("[dim]● = Installed, ○ = Available[/dim]\n")
1002
+
1003
+ # Get deployed skills for status detection
1004
+ deployed_result = self.skills_deployer.check_deployed_skills()
1005
+ deployed_skills = {
1006
+ skill["name"] for skill in deployed_result.get("skills", [])
1007
+ }
1008
+
1009
+ # Get available skills from GitHub
1010
+ console.print("[dim]Fetching available skills from GitHub...[/dim]\n")
1011
+ available_result = self.skills_deployer.list_available_skills()
1012
+
1013
+ if available_result.get("error"):
1014
+ console.print(f"[red]Error: {available_result['error']}[/red]")
1015
+ return CommandResult(
1016
+ success=False, message=available_result["error"], exit_code=1
1017
+ )
1018
+
1019
+ # Flatten skills by category
1020
+ all_skills = []
1021
+ for category, skills in available_result.get("by_category", {}).items():
1022
+ for skill in skills:
1023
+ skill_info = {
1024
+ "name": skill.get("name", "unknown"),
1025
+ "category": category,
1026
+ "is_deployed": skill.get("name", "unknown") in deployed_skills,
1027
+ }
1028
+ all_skills.append(skill_info)
1029
+
1030
+ # Sort by deployed status (deployed first), then by name
1031
+ all_skills.sort(key=lambda s: (not s["is_deployed"], s["name"]))
1032
+
1033
+ # Build checkbox choices with pre-selection
1034
+ # Loop to allow adjusting selection
1035
+ while True:
1036
+ skill_choices = []
1037
+ skill_map = {} # For lookup after selection
1038
+
1039
+ for skill in all_skills:
1040
+ skill_name = skill["name"]
1041
+ category = skill["category"]
1042
+ is_deployed = skill["is_deployed"]
1043
+
1044
+ # Simple format: "skill-name (category)"
1045
+ # Checkbox state (checked/unchecked) indicates installed status
1046
+ choice_text = f"{skill_name} ({category})"
1047
+
1048
+ # Pre-select if deployed
1049
+ choice = Choice(
1050
+ title=choice_text, value=skill_name, checked=is_deployed
1051
+ )
1052
+
1053
+ skill_choices.append(choice)
1054
+ skill_map[skill_name] = skill
1055
+
1056
+ # Display checkbox selection
1057
+ selected_skills = questionary.checkbox(
1058
+ "Select skills (Space to toggle, Enter to confirm):",
1059
+ choices=skill_choices,
1060
+ style=QUESTIONARY_STYLE,
1061
+ ).ask()
1062
+
1063
+ if selected_skills is None:
1064
+ # User cancelled (Ctrl+C)
1065
+ console.print("[yellow]Skills configuration cancelled[/yellow]")
1066
+ return CommandResult(success=True, exit_code=0)
1067
+
1068
+ # Determine changes
1069
+ to_install = []
1070
+ to_remove = []
1071
+
1072
+ for skill in all_skills:
1073
+ skill_name = skill["name"]
1074
+ is_deployed = skill["is_deployed"]
1075
+ is_selected = skill_name in selected_skills
1076
+
1077
+ if is_selected and not is_deployed:
1078
+ to_install.append(skill_name)
1079
+ elif not is_selected and is_deployed:
1080
+ to_remove.append(skill_name)
1081
+
1082
+ # Show summary of changes
1083
+ console.print("\n[bold]Changes to apply:[/bold]")
1084
+ if to_install:
1085
+ console.print(
1086
+ f"\n[green]✓ Install ({len(to_install)} skills):[/green]"
1087
+ )
1088
+ for skill in to_install:
1089
+ console.print(f" • {skill}")
1090
+
1091
+ if to_remove:
1092
+ console.print(
1093
+ f"\n[yellow]✗ Remove ({len(to_remove)} skills):[/yellow]"
1094
+ )
1095
+ for skill in to_remove:
1096
+ console.print(f" • {skill}")
1097
+
1098
+ if not to_install and not to_remove:
1099
+ console.print(
1100
+ "\n[dim]No changes (selection matches current deployment)[/dim]"
1101
+ )
1102
+
1103
+ console.print()
1104
+
1105
+ # Ask user to confirm, adjust, or cancel
1106
+ action = questionary.select(
1107
+ "\nWhat would you like to do?",
1108
+ choices=[
1109
+ Choice("Apply these changes", value="apply"),
1110
+ Choice("Adjust selection", value="adjust"),
1111
+ Choice("Cancel", value="cancel"),
1112
+ ],
1113
+ default="apply",
1114
+ style=QUESTIONARY_STYLE,
1115
+ ).ask()
1116
+
1117
+ if action == "cancel":
1118
+ console.print("[yellow]Changes cancelled[/yellow]")
1119
+ Prompt.ask("\nPress Enter to continue")
1120
+ return CommandResult(success=True, exit_code=0)
1121
+ if action == "adjust":
1122
+ # Loop back to skill selection
1123
+ console.print("\n[dim]Adjusting selection...[/dim]\n")
1124
+ continue
1125
+
1126
+ # Apply changes
1127
+ success = True
1128
+ errors = []
1129
+
1130
+ # Install skills
1131
+ if to_install:
1132
+ console.print("\n[bold cyan]Installing skills...[/bold cyan]\n")
1133
+ for skill_name in to_install:
1134
+ try:
1135
+ # Deploy single skill
1136
+ result = self.skills_deployer.deploy_skills(
1137
+ skill_names=[skill_name], force=False
1138
+ )
1139
+
1140
+ if result.get("errors"):
1141
+ errors.extend(result["errors"])
1142
+ success = False
1143
+ else:
1144
+ console.print(
1145
+ f"[green]✓ Installed: {skill_name}[/green]"
1146
+ )
1147
+ except Exception as e:
1148
+ errors.append(f"Failed to install {skill_name}: {e}")
1149
+ success = False
1150
+
1151
+ # Remove skills
1152
+ if to_remove:
1153
+ console.print("\n[bold yellow]Removing skills...[/bold yellow]\n")
1154
+ for skill_name in to_remove:
1155
+ try:
1156
+ # Remove single skill
1157
+ result = self.skills_deployer.remove_skills(
1158
+ skill_names=[skill_name]
1159
+ )
1160
+
1161
+ if result.get("errors"):
1162
+ errors.extend(result["errors"])
1163
+ success = False
1164
+ else:
1165
+ console.print(
1166
+ f"[yellow]✗ Removed: {skill_name}[/yellow]"
1167
+ )
1168
+ except Exception as e:
1169
+ errors.append(f"Failed to remove {skill_name}: {e}")
1170
+ success = False
1171
+
1172
+ # Show errors if any
1173
+ if errors:
1174
+ console.print(f"\n[red]✗ {len(errors)} error(s):[/red]")
1175
+ for error in errors:
1176
+ console.print(f" • {error}")
1177
+
1178
+ # Show restart instructions
1179
+ if success and (to_install or to_remove):
1180
+ console.print(
1181
+ "\n[bold green]✓ Changes applied successfully![/bold green]"
1182
+ )
1183
+ console.print("\n[yellow]⚠️ Important:[/yellow]")
1184
+ console.print(" Restart Claude Code for changes to take effect")
1185
+
1186
+ console.print()
1187
+ Prompt.ask("\nPress Enter to continue")
1188
+
1189
+ # Exit the loop after successful execution
1190
+ break
1191
+
1192
+ exit_code = 0 if success else 1
1193
+ return CommandResult(success=success, exit_code=exit_code)
1194
+
1195
+ except Exception as e:
1196
+ console.print(f"[red]Error in skills configuration: {e}[/red]")
1197
+ import traceback
1198
+
1199
+ console.print(f"[dim]{traceback.format_exc()}[/dim]")
1200
+ return CommandResult(success=False, message=str(e), exit_code=1)
1201
+
1202
+ return CommandResult(success=False, message=str(e), exit_code=1)
1203
+
467
1204
 
468
1205
  def manage_skills(args) -> int:
469
1206
  """