claude-mpm 5.4.22__py3-none-any.whl → 5.6.34__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 (487) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_AGENT.md +164 -0
  3. claude_mpm/agents/BASE_ENGINEER.md +658 -0
  4. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
  5. claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
  6. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
  7. claude_mpm/agents/MEMORY.md +1 -1
  8. claude_mpm/agents/PM_INSTRUCTIONS.md +374 -1257
  9. claude_mpm/agents/WORKFLOW.md +6 -253
  10. claude_mpm/agents/agent_loader.py +1 -1
  11. claude_mpm/agents/base_agent.json +31 -0
  12. claude_mpm/agents/frontmatter_validator.py +2 -2
  13. claude_mpm/agents/templates/circuit-breakers.md +26 -17
  14. claude_mpm/cli/__init__.py +5 -1
  15. claude_mpm/cli/commands/agent_state_manager.py +10 -10
  16. claude_mpm/cli/commands/agents.py +11 -13
  17. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  18. claude_mpm/cli/commands/auto_configure.py +4 -4
  19. claude_mpm/cli/commands/autotodos.py +566 -0
  20. claude_mpm/cli/commands/commander.py +216 -0
  21. claude_mpm/cli/commands/configure.py +621 -22
  22. claude_mpm/cli/commands/configure_agent_display.py +12 -0
  23. claude_mpm/cli/commands/hook_errors.py +60 -60
  24. claude_mpm/cli/commands/monitor.py +2 -2
  25. claude_mpm/cli/commands/mpm_init/core.py +72 -0
  26. claude_mpm/cli/commands/postmortem.py +1 -1
  27. claude_mpm/cli/commands/profile.py +276 -0
  28. claude_mpm/cli/commands/run.py +35 -3
  29. claude_mpm/cli/commands/skill_source.py +51 -2
  30. claude_mpm/cli/commands/skills.py +182 -32
  31. claude_mpm/cli/executor.py +130 -16
  32. claude_mpm/cli/interactive/__init__.py +10 -0
  33. claude_mpm/cli/interactive/agent_wizard.py +32 -52
  34. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  35. claude_mpm/cli/interactive/skill_selector.py +481 -0
  36. claude_mpm/cli/parsers/base_parser.py +83 -1
  37. claude_mpm/cli/parsers/commander_parser.py +116 -0
  38. claude_mpm/cli/parsers/profile_parser.py +147 -0
  39. claude_mpm/cli/parsers/run_parser.py +10 -0
  40. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  41. claude_mpm/cli/parsers/skills_parser.py +2 -3
  42. claude_mpm/cli/startup.py +690 -386
  43. claude_mpm/cli/startup_display.py +74 -6
  44. claude_mpm/cli/startup_logging.py +2 -2
  45. claude_mpm/cli/utils.py +7 -3
  46. claude_mpm/commander/__init__.py +78 -0
  47. claude_mpm/commander/adapters/__init__.py +60 -0
  48. claude_mpm/commander/adapters/auggie.py +260 -0
  49. claude_mpm/commander/adapters/base.py +288 -0
  50. claude_mpm/commander/adapters/claude_code.py +392 -0
  51. claude_mpm/commander/adapters/codex.py +237 -0
  52. claude_mpm/commander/adapters/communication.py +366 -0
  53. claude_mpm/commander/adapters/example_usage.py +310 -0
  54. claude_mpm/commander/adapters/mpm.py +389 -0
  55. claude_mpm/commander/adapters/registry.py +204 -0
  56. claude_mpm/commander/api/__init__.py +16 -0
  57. claude_mpm/commander/api/app.py +121 -0
  58. claude_mpm/commander/api/errors.py +133 -0
  59. claude_mpm/commander/api/routes/__init__.py +8 -0
  60. claude_mpm/commander/api/routes/events.py +184 -0
  61. claude_mpm/commander/api/routes/inbox.py +171 -0
  62. claude_mpm/commander/api/routes/messages.py +148 -0
  63. claude_mpm/commander/api/routes/projects.py +271 -0
  64. claude_mpm/commander/api/routes/sessions.py +226 -0
  65. claude_mpm/commander/api/routes/work.py +296 -0
  66. claude_mpm/commander/api/schemas.py +186 -0
  67. claude_mpm/commander/chat/__init__.py +7 -0
  68. claude_mpm/commander/chat/cli.py +146 -0
  69. claude_mpm/commander/chat/commands.py +96 -0
  70. claude_mpm/commander/chat/repl.py +310 -0
  71. claude_mpm/commander/config.py +51 -0
  72. claude_mpm/commander/config_loader.py +115 -0
  73. claude_mpm/commander/core/__init__.py +10 -0
  74. claude_mpm/commander/core/block_manager.py +325 -0
  75. claude_mpm/commander/core/response_manager.py +323 -0
  76. claude_mpm/commander/daemon.py +603 -0
  77. claude_mpm/commander/env_loader.py +59 -0
  78. claude_mpm/commander/events/__init__.py +26 -0
  79. claude_mpm/commander/events/manager.py +332 -0
  80. claude_mpm/commander/frameworks/__init__.py +12 -0
  81. claude_mpm/commander/frameworks/base.py +146 -0
  82. claude_mpm/commander/frameworks/claude_code.py +58 -0
  83. claude_mpm/commander/frameworks/mpm.py +62 -0
  84. claude_mpm/commander/inbox/__init__.py +16 -0
  85. claude_mpm/commander/inbox/dedup.py +128 -0
  86. claude_mpm/commander/inbox/inbox.py +224 -0
  87. claude_mpm/commander/inbox/models.py +70 -0
  88. claude_mpm/commander/instance_manager.py +450 -0
  89. claude_mpm/commander/llm/__init__.py +6 -0
  90. claude_mpm/commander/llm/openrouter_client.py +167 -0
  91. claude_mpm/commander/llm/summarizer.py +70 -0
  92. claude_mpm/commander/memory/__init__.py +45 -0
  93. claude_mpm/commander/memory/compression.py +347 -0
  94. claude_mpm/commander/memory/embeddings.py +230 -0
  95. claude_mpm/commander/memory/entities.py +310 -0
  96. claude_mpm/commander/memory/example_usage.py +290 -0
  97. claude_mpm/commander/memory/integration.py +325 -0
  98. claude_mpm/commander/memory/search.py +381 -0
  99. claude_mpm/commander/memory/store.py +657 -0
  100. claude_mpm/commander/models/__init__.py +18 -0
  101. claude_mpm/commander/models/events.py +121 -0
  102. claude_mpm/commander/models/project.py +162 -0
  103. claude_mpm/commander/models/work.py +214 -0
  104. claude_mpm/commander/parsing/__init__.py +20 -0
  105. claude_mpm/commander/parsing/extractor.py +132 -0
  106. claude_mpm/commander/parsing/output_parser.py +270 -0
  107. claude_mpm/commander/parsing/patterns.py +100 -0
  108. claude_mpm/commander/persistence/__init__.py +11 -0
  109. claude_mpm/commander/persistence/event_store.py +274 -0
  110. claude_mpm/commander/persistence/state_store.py +309 -0
  111. claude_mpm/commander/persistence/work_store.py +164 -0
  112. claude_mpm/commander/polling/__init__.py +13 -0
  113. claude_mpm/commander/polling/event_detector.py +104 -0
  114. claude_mpm/commander/polling/output_buffer.py +49 -0
  115. claude_mpm/commander/polling/output_poller.py +153 -0
  116. claude_mpm/commander/project_session.py +268 -0
  117. claude_mpm/commander/proxy/__init__.py +12 -0
  118. claude_mpm/commander/proxy/formatter.py +89 -0
  119. claude_mpm/commander/proxy/output_handler.py +191 -0
  120. claude_mpm/commander/proxy/relay.py +155 -0
  121. claude_mpm/commander/registry.py +410 -0
  122. claude_mpm/commander/runtime/__init__.py +10 -0
  123. claude_mpm/commander/runtime/executor.py +191 -0
  124. claude_mpm/commander/runtime/monitor.py +346 -0
  125. claude_mpm/commander/session/__init__.py +6 -0
  126. claude_mpm/commander/session/context.py +81 -0
  127. claude_mpm/commander/session/manager.py +59 -0
  128. claude_mpm/commander/tmux_orchestrator.py +361 -0
  129. claude_mpm/commander/web/__init__.py +1 -0
  130. claude_mpm/commander/work/__init__.py +30 -0
  131. claude_mpm/commander/work/executor.py +207 -0
  132. claude_mpm/commander/work/queue.py +405 -0
  133. claude_mpm/commander/workflow/__init__.py +27 -0
  134. claude_mpm/commander/workflow/event_handler.py +241 -0
  135. claude_mpm/commander/workflow/notifier.py +146 -0
  136. claude_mpm/commands/mpm-config.md +20 -249
  137. claude_mpm/commands/mpm-doctor.md +16 -21
  138. claude_mpm/commands/mpm-help.md +12 -205
  139. claude_mpm/commands/mpm-init.md +88 -506
  140. claude_mpm/commands/mpm-monitor.md +22 -401
  141. claude_mpm/commands/mpm-organize.md +70 -442
  142. claude_mpm/commands/mpm-postmortem.md +13 -107
  143. claude_mpm/commands/mpm-session-resume.md +20 -363
  144. claude_mpm/commands/mpm-status.md +13 -69
  145. claude_mpm/commands/mpm-ticket-view.md +60 -495
  146. claude_mpm/commands/mpm-version.md +13 -107
  147. claude_mpm/commands/mpm.md +8 -0
  148. claude_mpm/config/agent_presets.py +8 -7
  149. claude_mpm/config/skill_sources.py +16 -0
  150. claude_mpm/constants.py +1 -0
  151. claude_mpm/core/claude_runner.py +154 -2
  152. claude_mpm/core/config.py +37 -26
  153. claude_mpm/core/config_constants.py +74 -9
  154. claude_mpm/core/constants.py +56 -12
  155. claude_mpm/core/framework/loaders/agent_loader.py +1 -1
  156. claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
  157. claude_mpm/core/hook_manager.py +51 -3
  158. claude_mpm/core/interactive_session.py +12 -11
  159. claude_mpm/core/logger.py +26 -9
  160. claude_mpm/core/logging_utils.py +39 -13
  161. claude_mpm/core/network_config.py +148 -0
  162. claude_mpm/core/oneshot_session.py +7 -6
  163. claude_mpm/core/optimized_startup.py +61 -0
  164. claude_mpm/core/output_style_manager.py +66 -18
  165. claude_mpm/core/shared/config_loader.py +3 -1
  166. claude_mpm/core/socketio_pool.py +47 -15
  167. claude_mpm/core/unified_agent_registry.py +1 -1
  168. claude_mpm/core/unified_config.py +54 -8
  169. claude_mpm/core/unified_paths.py +95 -90
  170. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  171. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  172. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  173. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
  174. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
  175. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
  176. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
  177. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
  178. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
  179. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
  180. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
  181. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  182. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
  184. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
  185. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
  186. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
  187. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
  188. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  189. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  190. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
  191. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
  192. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
  193. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
  194. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
  195. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
  196. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
  197. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
  198. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  199. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
  200. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
  201. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
  202. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  203. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
  204. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  205. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
  206. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
  207. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
  208. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
  209. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
  210. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DR8nis88.js +2 -0
  211. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
  212. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  213. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
  214. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
  215. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
  216. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
  217. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
  218. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
  219. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  220. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
  221. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  222. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
  223. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
  224. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
  225. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
  226. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  227. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
  228. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
  229. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
  230. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
  231. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  232. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.RgBboRvH.js +1 -0
  233. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
  234. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  235. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  236. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  237. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  238. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  239. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  240. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  241. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  242. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  243. claude_mpm/experimental/cli_enhancements.py +2 -1
  244. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  245. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  246. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  247. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  248. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  249. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  250. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  251. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  252. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  253. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  254. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
  255. claude_mpm/hooks/claude_hooks/event_handlers.py +527 -136
  256. claude_mpm/hooks/claude_hooks/hook_handler.py +313 -99
  257. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  258. claude_mpm/hooks/claude_hooks/installer.py +206 -36
  259. claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
  260. claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
  261. claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
  262. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  263. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  264. claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
  265. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  266. claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
  267. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  268. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  269. claude_mpm/hooks/claude_hooks/services/connection_manager.py +67 -32
  270. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
  271. claude_mpm/hooks/claude_hooks/services/container.py +310 -0
  272. claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
  273. claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
  274. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
  275. claude_mpm/hooks/kuzu_memory_hook.py +5 -5
  276. claude_mpm/hooks/session_resume_hook.py +89 -1
  277. claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
  278. claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
  279. claude_mpm/init.py +276 -0
  280. claude_mpm/models/git_repository.py +3 -3
  281. claude_mpm/scripts/claude-hook-handler.sh +46 -19
  282. claude_mpm/services/agents/agent_builder.py +3 -3
  283. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  284. claude_mpm/services/agents/agent_selection_service.py +2 -2
  285. claude_mpm/services/agents/cache_git_manager.py +7 -7
  286. claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
  287. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -2
  288. claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
  289. claude_mpm/services/agents/deployment/agent_template_builder.py +39 -19
  290. claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
  291. claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
  292. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  293. claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
  294. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +169 -26
  295. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +101 -75
  296. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  297. claude_mpm/services/agents/git_source_manager.py +23 -4
  298. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  299. claude_mpm/services/agents/recommender.py +5 -3
  300. claude_mpm/services/agents/single_tier_deployment_service.py +6 -6
  301. claude_mpm/services/agents/sources/git_source_sync_service.py +121 -10
  302. claude_mpm/services/agents/startup_sync.py +27 -4
  303. claude_mpm/services/cli/__init__.py +3 -0
  304. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  305. claude_mpm/services/cli/session_resume_helper.py +10 -2
  306. claude_mpm/services/command_deployment_service.py +44 -26
  307. claude_mpm/services/delegation_detector.py +175 -0
  308. claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
  309. claude_mpm/services/diagnostics/checks/agent_sources_check.py +31 -1
  310. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  311. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  312. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  313. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  314. claude_mpm/services/diagnostics/models.py +14 -1
  315. claude_mpm/services/event_log.py +325 -0
  316. claude_mpm/services/git/git_operations_service.py +8 -8
  317. claude_mpm/services/hook_installer_service.py +77 -8
  318. claude_mpm/services/infrastructure/__init__.py +4 -0
  319. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  320. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  321. claude_mpm/services/monitor/daemon_manager.py +15 -4
  322. claude_mpm/services/monitor/management/lifecycle.py +15 -3
  323. claude_mpm/services/monitor/server.py +571 -11
  324. claude_mpm/services/pm_skills_deployer.py +884 -0
  325. claude_mpm/services/profile_manager.py +337 -0
  326. claude_mpm/services/skills/git_skill_source_manager.py +281 -20
  327. claude_mpm/services/skills/selective_skill_deployer.py +211 -46
  328. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  329. claude_mpm/services/skills_deployer.py +192 -70
  330. claude_mpm/services/socketio/dashboard_server.py +1 -0
  331. claude_mpm/services/socketio/event_normalizer.py +37 -6
  332. claude_mpm/services/socketio/handlers/hook.py +14 -7
  333. claude_mpm/services/socketio/server/core.py +262 -123
  334. claude_mpm/services/socketio/server/main.py +12 -4
  335. claude_mpm/skills/__init__.py +2 -1
  336. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  337. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  338. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  339. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  340. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  341. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  342. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  343. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  344. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  345. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  346. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  347. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  348. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  349. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  350. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  351. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  352. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  353. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  354. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  355. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  356. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  357. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  358. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  359. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  360. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  361. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  362. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  363. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  364. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  365. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  366. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  367. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  368. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  369. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  370. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  371. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  372. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  373. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  374. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  375. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  376. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  377. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  378. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  379. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  380. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  381. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  382. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  383. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  384. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  385. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  386. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  387. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  388. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  389. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  390. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  391. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  392. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  393. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  394. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  395. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  396. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  397. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  398. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  399. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  400. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  401. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  402. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  403. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  404. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  405. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  406. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  407. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  408. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  409. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  410. claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
  411. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  412. claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
  413. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  414. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  415. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  416. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  417. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  418. claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
  419. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  420. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  421. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  422. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  423. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  424. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  425. claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
  426. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  427. claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
  428. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  429. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  430. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  431. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  432. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  433. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  434. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  435. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  436. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  437. claude_mpm/skills/bundled/security-scanning.md +112 -0
  438. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  439. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  440. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  441. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  442. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  443. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  444. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  445. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  446. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  447. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  448. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  449. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  450. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  451. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  452. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  453. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  454. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  455. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  456. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  457. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  458. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  459. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  460. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  461. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  462. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  463. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  464. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  465. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  466. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  467. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  468. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  469. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  470. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  471. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  472. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  473. claude_mpm/skills/registry.py +295 -90
  474. claude_mpm/skills/skill_manager.py +98 -3
  475. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  476. claude_mpm/utils/agent_dependency_loader.py +115 -4
  477. claude_mpm/utils/agent_filters.py +1 -1
  478. claude_mpm/utils/migration.py +4 -4
  479. claude_mpm/utils/robust_installer.py +86 -21
  480. claude_mpm-5.6.34.dist-info/METADATA +393 -0
  481. {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/RECORD +486 -145
  482. claude_mpm-5.4.22.dist-info/METADATA +0 -996
  483. {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/WHEEL +0 -0
  484. {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/entry_points.txt +0 -0
  485. {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE +0 -0
  486. {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  487. {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/top_level.txt +0 -0
@@ -16,6 +16,7 @@ Trade-offs:
16
16
  - Flexibility: Easy to extend with skills-specific features
17
17
  """
18
18
 
19
+ import os
19
20
  from concurrent.futures import ThreadPoolExecutor, as_completed
20
21
  from datetime import datetime, timezone
21
22
  from pathlib import Path
@@ -32,6 +33,46 @@ from claude_mpm.services.skills.skill_discovery_service import SkillDiscoverySer
32
33
  logger = get_logger(__name__)
33
34
 
34
35
 
36
+ def _get_github_token(source: Optional[SkillSource] = None) -> Optional[str]:
37
+ """Get GitHub token with source-specific override support.
38
+
39
+ Priority: source.token > GITHUB_TOKEN > GH_TOKEN
40
+
41
+ Args:
42
+ source: Optional SkillSource to check for per-source token
43
+
44
+ Returns:
45
+ GitHub token if found, None otherwise
46
+
47
+ Token Resolution:
48
+ 1. If source has token starting with "$", resolve as env var
49
+ 2. If source has direct token, use it (not recommended for security)
50
+ 3. Fall back to GITHUB_TOKEN env var
51
+ 4. Fall back to GH_TOKEN env var
52
+ 5. Return None if no token found
53
+
54
+ Security Note:
55
+ Token is never logged or printed to avoid exposure.
56
+ Direct tokens in config are discouraged - use env var refs ($VAR_NAME).
57
+
58
+ Example:
59
+ >>> source = SkillSource(..., token="$PRIVATE_TOKEN")
60
+ >>> token = _get_github_token(source) # Resolves $PRIVATE_TOKEN from env
61
+ >>> token = _get_github_token() # Falls back to GITHUB_TOKEN
62
+ """
63
+ # Priority 1: Per-source token (env var reference or direct)
64
+ if source and source.token:
65
+ if source.token.startswith("$"):
66
+ # Env var reference: $VAR_NAME -> os.environ.get("VAR_NAME")
67
+ env_var_name = source.token[1:]
68
+ return os.environ.get(env_var_name)
69
+ # Direct token (not recommended but supported)
70
+ return source.token
71
+
72
+ # Priority 2-3: Global environment variables
73
+ return os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
74
+
75
+
35
76
  class GitSkillSourceManager:
36
77
  """Manages multiple Git-based skill sources with priority resolution.
37
78
 
@@ -217,9 +258,21 @@ class GitSkillSourceManager:
217
258
  )
218
259
 
219
260
  # Discover skills in cache
261
+ self.logger.debug(f"Scanning cache path for skills: {cache_path}")
220
262
  discovery_service = SkillDiscoveryService(cache_path)
221
263
  discovered_skills = discovery_service.discover_skills()
222
264
 
265
+ # Log discovery results
266
+ if len(discovered_skills) == 0:
267
+ self.logger.info(
268
+ f"No SKILL.md files found in {cache_path}. "
269
+ "Ensure your skill source has SKILL.md files with valid frontmatter."
270
+ )
271
+ else:
272
+ self.logger.debug(
273
+ f"Successfully parsed {len(discovered_skills)} skills from {cache_path}"
274
+ )
275
+
223
276
  # Build result
224
277
  result = {
225
278
  "synced": True,
@@ -469,7 +522,7 @@ class GitSkillSourceManager:
469
522
  # Step 1: Discover all files via GitHub Tree API (single request)
470
523
  # This discovers the COMPLETE repository structure (272 files for skills)
471
524
  all_files = self._discover_repository_files_via_tree_api(
472
- owner_repo, source.branch
525
+ owner_repo, source.branch, source
473
526
  )
474
527
 
475
528
  if not all_files:
@@ -504,7 +557,7 @@ class GitSkillSourceManager:
504
557
  raw_url = f"https://raw.githubusercontent.com/{owner_repo}/{source.branch}/{file_path}"
505
558
  cache_file = cache_path / file_path
506
559
  future = executor.submit(
507
- self._download_file_with_etag, raw_url, cache_file, force
560
+ self._download_file_with_etag, raw_url, cache_file, force, source
508
561
  )
509
562
  future_to_file[future] = file_path
510
563
 
@@ -533,7 +586,7 @@ class GitSkillSourceManager:
533
586
  return files_updated, files_cached
534
587
 
535
588
  def _discover_repository_files_via_tree_api(
536
- self, owner_repo: str, branch: str
589
+ self, owner_repo: str, branch: str, source: Optional[SkillSource] = None
537
590
  ) -> List[str]:
538
591
  """Discover all files in repository using GitHub Git Tree API.
539
592
 
@@ -596,9 +649,17 @@ class GitSkillSourceManager:
596
649
  )
597
650
  self.logger.debug(f"Fetching commit SHA from {refs_url}")
598
651
 
599
- refs_response = requests.get(
600
- refs_url, headers={"Accept": "application/vnd.github+json"}, timeout=30
601
- )
652
+ # Build headers with authentication if token available
653
+ headers = {"Accept": "application/vnd.github+json"}
654
+ token = _get_github_token(source)
655
+ if token:
656
+ headers["Authorization"] = f"token {token}"
657
+ if source and source.token:
658
+ self.logger.debug(f"Using source-specific token for {source.id}")
659
+ else:
660
+ self.logger.debug("Using GitHub token for authentication")
661
+
662
+ refs_response = requests.get(refs_url, headers=headers, timeout=30)
602
663
 
603
664
  # Check for rate limiting
604
665
  if refs_response.status_code == 403:
@@ -621,7 +682,7 @@ class GitSkillSourceManager:
621
682
  self.logger.debug(f"Fetching recursive tree from {tree_url}")
622
683
  tree_response = requests.get(
623
684
  tree_url,
624
- headers={"Accept": "application/vnd.github+json"},
685
+ headers=headers, # Reuse headers with auth from Step 1
625
686
  params=params,
626
687
  timeout=30,
627
688
  )
@@ -652,7 +713,11 @@ class GitSkillSourceManager:
652
713
  return all_files
653
714
 
654
715
  def _download_file_with_etag(
655
- self, url: str, local_path: Path, force: bool = False
716
+ self,
717
+ url: str,
718
+ local_path: Path,
719
+ force: bool = False,
720
+ source: Optional[SkillSource] = None,
656
721
  ) -> bool:
657
722
  """Download file from URL with ETag caching (thread-safe).
658
723
 
@@ -660,6 +725,7 @@ class GitSkillSourceManager:
660
725
  url: Raw GitHub URL
661
726
  local_path: Local file path to save to
662
727
  force: Force download even if cached
728
+ source: Optional SkillSource for token resolution
663
729
 
664
730
  Returns:
665
731
  True if file was updated, False if cached
@@ -682,7 +748,7 @@ class GitSkillSourceManager:
682
748
  try:
683
749
  with open(etag_cache_file, encoding="utf-8") as f:
684
750
  etag_cache = json.load(f)
685
- except Exception:
751
+ except Exception: # nosec B110 - intentional: proceed without cache on read failure
686
752
  pass
687
753
 
688
754
  cached_etag = etag_cache.get(str(local_path))
@@ -692,6 +758,11 @@ class GitSkillSourceManager:
692
758
  if cached_etag and not force:
693
759
  headers["If-None-Match"] = cached_etag
694
760
 
761
+ # Add GitHub authentication if token available
762
+ token = _get_github_token(source)
763
+ if token:
764
+ headers["Authorization"] = f"token {token}"
765
+
695
766
  try:
696
767
  response = requests.get(url, headers=headers, timeout=30)
697
768
 
@@ -991,12 +1062,17 @@ class GitSkillSourceManager:
991
1062
  progress_callback=None,
992
1063
  skill_filter: Optional[Set[str]] = None,
993
1064
  ) -> Dict[str, Any]:
994
- """Deploy skills from cache to target directory with flat structure.
1065
+ """Deploy skills from cache to target directory with flat structure and automatic cleanup.
995
1066
 
996
1067
  Flattens nested Git repository structure into Claude Code compatible
997
1068
  flat directory structure. Each skill directory is copied with a
998
1069
  hyphen-separated name derived from its path.
999
1070
 
1071
+ CRITICAL: When skill_filter is provided (agent-referenced skills), this function:
1072
+ 1. Deploys ONLY the filtered skills
1073
+ 2. REMOVES orphaned skills (deployed but not in filter)
1074
+ 3. Returns removed_count and removed_skills in result
1075
+
1000
1076
  Transformation Example:
1001
1077
  Cache: collaboration/dispatching-parallel-agents/SKILL.md
1002
1078
  Deploy: collaboration-dispatching-parallel-agents/SKILL.md
@@ -1006,8 +1082,8 @@ class GitSkillSourceManager:
1006
1082
  force: Overwrite existing skills
1007
1083
  progress_callback: Optional callback(increment: int) called for each skill deployed
1008
1084
  skill_filter: Optional set of skill names to deploy (selective deployment).
1009
- If None, deploys all skills. If provided, only deploys skills
1010
- whose name matches an entry in the filter set.
1085
+ If None, deploys ALL skills WITHOUT cleanup.
1086
+ If provided, deploys ONLY filtered skills AND removes orphans.
1011
1087
 
1012
1088
  Returns:
1013
1089
  Dict with deployment results:
@@ -1018,7 +1094,9 @@ class GitSkillSourceManager:
1018
1094
  "deployed_skills": List[str],
1019
1095
  "skipped_skills": List[str],
1020
1096
  "errors": List[str],
1021
- "filtered_count": int # Number of skills filtered out
1097
+ "filtered_count": int, # Number of skills filtered out
1098
+ "removed_count": int, # Number of orphaned skills removed
1099
+ "removed_skills": List[str] # Names of removed orphaned skills
1022
1100
  }
1023
1101
 
1024
1102
  Example:
@@ -1026,10 +1104,10 @@ class GitSkillSourceManager:
1026
1104
  >>> result = manager.deploy_skills()
1027
1105
  >>> print(f"Deployed {result['deployed_count']} skills")
1028
1106
 
1029
- # Selective deployment based on agent requirements:
1107
+ # Selective deployment based on agent requirements (with cleanup):
1030
1108
  >>> required = {"typescript-core", "react-patterns"}
1031
1109
  >>> result = manager.deploy_skills(skill_filter=required)
1032
- >>> print(f"Deployed {result['deployed_count']} of {len(required)} required skills")
1110
+ >>> print(f"Deployed {result['deployed_count']}, removed {result['removed_count']} orphans")
1033
1111
  """
1034
1112
  if target_dir is None:
1035
1113
  target_dir = Path.home() / ".claude" / "skills"
@@ -1040,6 +1118,7 @@ class GitSkillSourceManager:
1040
1118
  skipped = []
1041
1119
  errors = []
1042
1120
  filtered_count = 0
1121
+ removed_skills = [] # Track removed orphaned skills
1043
1122
 
1044
1123
  # Get all skills from all sources
1045
1124
  all_skills = self.get_all_skills()
@@ -1049,12 +1128,31 @@ class GitSkillSourceManager:
1049
1128
  original_count = len(all_skills)
1050
1129
  # Normalize filter to lowercase for case-insensitive matching
1051
1130
  normalized_filter = {s.lower() for s in skill_filter}
1052
- # Match against deployment_name (not display name) since skill_filter contains
1053
- # deployment-style names like "toolchains-python-frameworks-django"
1131
+
1132
+ def matches_filter(deployment_name: str) -> bool:
1133
+ """Match using same fuzzy logic as ProfileManager.is_skill_enabled()"""
1134
+ deployment_lower = deployment_name.lower()
1135
+
1136
+ # Exact match
1137
+ if deployment_lower in normalized_filter:
1138
+ return True
1139
+
1140
+ # Fuzzy match: check if deployment name ends with or contains short name
1141
+ # Example: "toolchains-python-frameworks-flask" matches "flask"
1142
+ for short_name in normalized_filter:
1143
+ if deployment_lower.endswith(f"-{short_name}"):
1144
+ return True
1145
+ # Check if short name is contained as a segment
1146
+ if f"-{short_name}-" in deployment_lower:
1147
+ return True
1148
+ if deployment_lower.startswith(f"{short_name}-"):
1149
+ return True
1150
+
1151
+ return False
1152
+
1153
+ # Match against deployment_name using fuzzy matching
1054
1154
  all_skills = [
1055
- s
1056
- for s in all_skills
1057
- if s.get("deployment_name", "").lower() in normalized_filter
1155
+ s for s in all_skills if matches_filter(s.get("deployment_name", ""))
1058
1156
  ]
1059
1157
  filtered_count = original_count - len(all_skills)
1060
1158
  self.logger.info(
@@ -1062,6 +1160,19 @@ class GitSkillSourceManager:
1062
1160
  f"match agent requirements ({filtered_count} filtered out)"
1063
1161
  )
1064
1162
 
1163
+ # Cleanup: Remove skills from target directory that aren't in the filtered set
1164
+ # This ensures only agent-referenced skills remain deployed
1165
+ removed_skills = self._cleanup_unfiltered_skills(target_dir, all_skills)
1166
+ if removed_skills:
1167
+ self.logger.info(
1168
+ f"Removed {len(removed_skills)} orphaned skills not referenced by agents: {removed_skills[:10]}"
1169
+ + (
1170
+ f" (and {len(removed_skills) - 10} more)"
1171
+ if len(removed_skills) > 10
1172
+ else ""
1173
+ )
1174
+ )
1175
+
1065
1176
  self.logger.info(
1066
1177
  f"Deploying {len(all_skills)} skills to {target_dir} (force={force})"
1067
1178
  )
@@ -1103,6 +1214,7 @@ class GitSkillSourceManager:
1103
1214
  self.logger.info(
1104
1215
  f"Deployment complete: {len(deployed)} deployed, "
1105
1216
  f"{len(skipped)} skipped, {len(errors)} errors"
1217
+ + (f", {len(removed_skills)} removed" if removed_skills else "")
1106
1218
  )
1107
1219
 
1108
1220
  return {
@@ -1113,8 +1225,157 @@ class GitSkillSourceManager:
1113
1225
  "skipped_skills": skipped,
1114
1226
  "errors": errors,
1115
1227
  "filtered_count": filtered_count,
1228
+ "removed_count": len(removed_skills),
1229
+ "removed_skills": removed_skills,
1230
+ }
1231
+
1232
+ def _cleanup_unfiltered_skills(
1233
+ self, target_dir: Path, filtered_skills: List[Dict[str, Any]]
1234
+ ) -> List[str]:
1235
+ """Remove skills from target directory that aren't in the filtered skill list.
1236
+
1237
+ CRITICAL: Only removes MPM-managed skills (those in our cache). Custom user skills
1238
+ are preserved. This prevents accidental deletion of user-created skills that were
1239
+ never part of MPM's skill repository.
1240
+
1241
+ Uses fuzzy matching to handle both exact deployment names and short skill names.
1242
+ For example:
1243
+ - "toolchains-python-frameworks-flask" (deployed dir) matches "flask" (filter)
1244
+ - "toolchains-elixir-frameworks-phoenix-liveview" matches "phoenix-liveview"
1245
+
1246
+ Args:
1247
+ target_dir: Target deployment directory
1248
+ filtered_skills: List of skills that should remain deployed
1249
+
1250
+ Returns:
1251
+ List of skill names that were removed
1252
+ """
1253
+ import shutil
1254
+
1255
+ removed_skills = []
1256
+
1257
+ # Build set of deployment names (exact matches)
1258
+ expected_deployments = {
1259
+ skill.get("deployment_name").lower()
1260
+ for skill in filtered_skills
1261
+ if skill.get("deployment_name")
1116
1262
  }
1117
1263
 
1264
+ # Build helper function for fuzzy matching (matches logic from deploy_skills)
1265
+ def should_keep_skill(deployed_dir_name: str) -> bool:
1266
+ """Check if deployed skill matches any expected deployment using fuzzy matching.
1267
+
1268
+ Matches the same logic as matches_filter() in deploy_skills() at line 1053.
1269
+ """
1270
+ deployed_lower = deployed_dir_name.lower()
1271
+
1272
+ # Exact match
1273
+ if deployed_lower in expected_deployments:
1274
+ return True
1275
+
1276
+ # Fuzzy match: check if deployment name matches any short name pattern
1277
+ # Example: "toolchains-elixir-frameworks-phoenix-liveview" matches "phoenix-liveview"
1278
+ for expected_name in expected_deployments:
1279
+ # Suffix match: deployment ends with "-shortname"
1280
+ if deployed_lower.endswith(f"-{expected_name}"):
1281
+ return True
1282
+ # Segment match: "-shortname-" appears in deployment
1283
+ if f"-{expected_name}-" in deployed_lower:
1284
+ return True
1285
+ # Prefix match: deployment starts with "shortname-"
1286
+ if deployed_lower.startswith(f"{expected_name}-"):
1287
+ return True
1288
+
1289
+ return False
1290
+
1291
+ def is_mpm_managed_skill(skill_dir_name: str) -> bool:
1292
+ """Check if skill is managed by MPM (exists in our cache).
1293
+
1294
+ Custom user skills (not in cache) are NEVER deleted, even if not in filter.
1295
+ Only MPM-managed skills (in cache but not in filter) are candidates for removal.
1296
+
1297
+ Args:
1298
+ skill_dir_name: Name of deployed skill directory
1299
+
1300
+ Returns:
1301
+ True if skill exists in MPM cache (MPM-managed), False if custom user skill
1302
+ """
1303
+ # Check all configured skill sources for this skill
1304
+ for source in self.config.get_enabled_sources():
1305
+ cache_path = self._get_source_cache_path(source)
1306
+ if not cache_path.exists():
1307
+ continue
1308
+
1309
+ # Check if this skill directory exists anywhere in the cache
1310
+ # Use glob to find matching directories recursively
1311
+ matches = list(cache_path.rglob(f"*{skill_dir_name}*"))
1312
+ if matches:
1313
+ # Found in cache - this is MPM-managed
1314
+ self.logger.debug(
1315
+ f"Skill '{skill_dir_name}' found in cache at {matches[0]} - MPM-managed"
1316
+ )
1317
+ return True
1318
+
1319
+ # Not found in any cache - this is a custom user skill
1320
+ self.logger.debug(
1321
+ f"Skill '{skill_dir_name}' not found in cache - custom user skill, preserving"
1322
+ )
1323
+ return False
1324
+
1325
+ # Check each directory in target_dir
1326
+ if not target_dir.exists():
1327
+ return removed_skills
1328
+
1329
+ try:
1330
+ for item in target_dir.iterdir():
1331
+ # Skip files, only process directories
1332
+ if not item.is_dir():
1333
+ continue
1334
+
1335
+ # Skip hidden directories
1336
+ if item.name.startswith("."):
1337
+ continue
1338
+
1339
+ # Check if this skill directory should be kept (fuzzy matching)
1340
+ if not should_keep_skill(item.name):
1341
+ # CRITICAL: Check if this is an MPM-managed skill before deletion
1342
+ if not is_mpm_managed_skill(item.name):
1343
+ # This is a custom user skill - NEVER delete
1344
+ self.logger.debug(
1345
+ f"Preserving custom user skill (not in MPM cache): {item.name}"
1346
+ )
1347
+ continue
1348
+
1349
+ # It's MPM-managed but not in filter - safe to remove
1350
+ try:
1351
+ # Security: Validate path is within target_dir
1352
+ if not self._validate_safe_path(target_dir, item):
1353
+ self.logger.error(
1354
+ f"Refusing to remove path outside target directory: {item}"
1355
+ )
1356
+ continue
1357
+
1358
+ # Remove the skill directory
1359
+ if item.is_symlink():
1360
+ item.unlink()
1361
+ else:
1362
+ shutil.rmtree(item)
1363
+
1364
+ removed_skills.append(item.name)
1365
+ self.logger.info(
1366
+ f"Removed orphaned MPM-managed skill: {item.name}"
1367
+ )
1368
+
1369
+ except Exception as e:
1370
+ self.logger.warning(
1371
+ f"Failed to remove skill directory {item.name}: {e}"
1372
+ )
1373
+
1374
+ except Exception as e:
1375
+ self.logger.error(f"Error during skill cleanup: {e}")
1376
+
1377
+ return removed_skills
1378
+
1118
1379
  def _deploy_single_skill(
1119
1380
  self, skill: Dict[str, Any], target_dir: Path, deployment_name: str, force: bool
1120
1381
  ) -> Dict[str, Any]: