claude-mpm 5.4.41__py3-none-any.whl → 5.6.72__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 (490) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
  3. claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
  4. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +161 -298
  6. claude_mpm/agents/WORKFLOW.md +2 -0
  7. claude_mpm/agents/templates/circuit-breakers.md +26 -17
  8. claude_mpm/auth/__init__.py +35 -0
  9. claude_mpm/auth/callback_server.py +328 -0
  10. claude_mpm/auth/models.py +104 -0
  11. claude_mpm/auth/oauth_manager.py +266 -0
  12. claude_mpm/auth/providers/__init__.py +12 -0
  13. claude_mpm/auth/providers/base.py +165 -0
  14. claude_mpm/auth/providers/google.py +261 -0
  15. claude_mpm/auth/token_storage.py +252 -0
  16. claude_mpm/cli/__init__.py +5 -1
  17. claude_mpm/cli/commands/agents.py +2 -4
  18. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  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 +620 -21
  22. claude_mpm/cli/commands/configure_agent_display.py +3 -1
  23. claude_mpm/cli/commands/hook_errors.py +60 -60
  24. claude_mpm/cli/commands/mcp.py +29 -17
  25. claude_mpm/cli/commands/mcp_command_router.py +39 -0
  26. claude_mpm/cli/commands/mcp_service_commands.py +304 -0
  27. claude_mpm/cli/commands/monitor.py +2 -2
  28. claude_mpm/cli/commands/mpm_init/core.py +15 -8
  29. claude_mpm/cli/commands/oauth.py +481 -0
  30. claude_mpm/cli/commands/profile.py +9 -10
  31. claude_mpm/cli/commands/run.py +35 -3
  32. claude_mpm/cli/commands/skill_source.py +51 -2
  33. claude_mpm/cli/commands/skills.py +182 -32
  34. claude_mpm/cli/executor.py +129 -16
  35. claude_mpm/cli/helpers.py +1 -1
  36. claude_mpm/cli/interactive/__init__.py +10 -0
  37. claude_mpm/cli/interactive/agent_wizard.py +30 -50
  38. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  39. claude_mpm/cli/interactive/skill_selector.py +481 -0
  40. claude_mpm/cli/parsers/base_parser.py +89 -1
  41. claude_mpm/cli/parsers/commander_parser.py +116 -0
  42. claude_mpm/cli/parsers/mcp_parser.py +79 -0
  43. claude_mpm/cli/parsers/oauth_parser.py +165 -0
  44. claude_mpm/cli/parsers/profile_parser.py +0 -1
  45. claude_mpm/cli/parsers/run_parser.py +10 -0
  46. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  47. claude_mpm/cli/parsers/skills_parser.py +2 -3
  48. claude_mpm/cli/startup.py +662 -524
  49. claude_mpm/cli/startup_display.py +76 -7
  50. claude_mpm/cli/startup_logging.py +2 -2
  51. claude_mpm/cli/utils.py +7 -3
  52. claude_mpm/commander/__init__.py +78 -0
  53. claude_mpm/commander/adapters/__init__.py +60 -0
  54. claude_mpm/commander/adapters/auggie.py +260 -0
  55. claude_mpm/commander/adapters/base.py +288 -0
  56. claude_mpm/commander/adapters/claude_code.py +392 -0
  57. claude_mpm/commander/adapters/codex.py +237 -0
  58. claude_mpm/commander/adapters/communication.py +366 -0
  59. claude_mpm/commander/adapters/example_usage.py +310 -0
  60. claude_mpm/commander/adapters/mpm.py +389 -0
  61. claude_mpm/commander/adapters/registry.py +204 -0
  62. claude_mpm/commander/api/__init__.py +16 -0
  63. claude_mpm/commander/api/app.py +121 -0
  64. claude_mpm/commander/api/errors.py +133 -0
  65. claude_mpm/commander/api/routes/__init__.py +8 -0
  66. claude_mpm/commander/api/routes/events.py +184 -0
  67. claude_mpm/commander/api/routes/inbox.py +171 -0
  68. claude_mpm/commander/api/routes/messages.py +148 -0
  69. claude_mpm/commander/api/routes/projects.py +271 -0
  70. claude_mpm/commander/api/routes/sessions.py +226 -0
  71. claude_mpm/commander/api/routes/work.py +296 -0
  72. claude_mpm/commander/api/schemas.py +186 -0
  73. claude_mpm/commander/chat/__init__.py +7 -0
  74. claude_mpm/commander/chat/cli.py +149 -0
  75. claude_mpm/commander/chat/commands.py +122 -0
  76. claude_mpm/commander/chat/repl.py +1821 -0
  77. claude_mpm/commander/config.py +51 -0
  78. claude_mpm/commander/config_loader.py +115 -0
  79. claude_mpm/commander/core/__init__.py +10 -0
  80. claude_mpm/commander/core/block_manager.py +325 -0
  81. claude_mpm/commander/core/response_manager.py +323 -0
  82. claude_mpm/commander/daemon.py +603 -0
  83. claude_mpm/commander/env_loader.py +59 -0
  84. claude_mpm/commander/events/__init__.py +26 -0
  85. claude_mpm/commander/events/manager.py +392 -0
  86. claude_mpm/commander/frameworks/__init__.py +12 -0
  87. claude_mpm/commander/frameworks/base.py +233 -0
  88. claude_mpm/commander/frameworks/claude_code.py +58 -0
  89. claude_mpm/commander/frameworks/mpm.py +57 -0
  90. claude_mpm/commander/git/__init__.py +5 -0
  91. claude_mpm/commander/git/worktree_manager.py +212 -0
  92. claude_mpm/commander/inbox/__init__.py +16 -0
  93. claude_mpm/commander/inbox/dedup.py +128 -0
  94. claude_mpm/commander/inbox/inbox.py +224 -0
  95. claude_mpm/commander/inbox/models.py +70 -0
  96. claude_mpm/commander/instance_manager.py +865 -0
  97. claude_mpm/commander/llm/__init__.py +6 -0
  98. claude_mpm/commander/llm/openrouter_client.py +167 -0
  99. claude_mpm/commander/llm/summarizer.py +70 -0
  100. claude_mpm/commander/memory/__init__.py +45 -0
  101. claude_mpm/commander/memory/compression.py +347 -0
  102. claude_mpm/commander/memory/embeddings.py +230 -0
  103. claude_mpm/commander/memory/entities.py +310 -0
  104. claude_mpm/commander/memory/example_usage.py +290 -0
  105. claude_mpm/commander/memory/integration.py +325 -0
  106. claude_mpm/commander/memory/search.py +381 -0
  107. claude_mpm/commander/memory/store.py +657 -0
  108. claude_mpm/commander/models/__init__.py +18 -0
  109. claude_mpm/commander/models/events.py +127 -0
  110. claude_mpm/commander/models/project.py +162 -0
  111. claude_mpm/commander/models/work.py +214 -0
  112. claude_mpm/commander/parsing/__init__.py +20 -0
  113. claude_mpm/commander/parsing/extractor.py +132 -0
  114. claude_mpm/commander/parsing/output_parser.py +270 -0
  115. claude_mpm/commander/parsing/patterns.py +100 -0
  116. claude_mpm/commander/persistence/__init__.py +11 -0
  117. claude_mpm/commander/persistence/event_store.py +274 -0
  118. claude_mpm/commander/persistence/state_store.py +403 -0
  119. claude_mpm/commander/persistence/work_store.py +164 -0
  120. claude_mpm/commander/polling/__init__.py +13 -0
  121. claude_mpm/commander/polling/event_detector.py +104 -0
  122. claude_mpm/commander/polling/output_buffer.py +49 -0
  123. claude_mpm/commander/polling/output_poller.py +153 -0
  124. claude_mpm/commander/project_session.py +268 -0
  125. claude_mpm/commander/proxy/__init__.py +12 -0
  126. claude_mpm/commander/proxy/formatter.py +89 -0
  127. claude_mpm/commander/proxy/output_handler.py +191 -0
  128. claude_mpm/commander/proxy/relay.py +155 -0
  129. claude_mpm/commander/registry.py +410 -0
  130. claude_mpm/commander/runtime/__init__.py +10 -0
  131. claude_mpm/commander/runtime/executor.py +191 -0
  132. claude_mpm/commander/runtime/monitor.py +346 -0
  133. claude_mpm/commander/session/__init__.py +6 -0
  134. claude_mpm/commander/session/context.py +81 -0
  135. claude_mpm/commander/session/manager.py +59 -0
  136. claude_mpm/commander/tmux_orchestrator.py +362 -0
  137. claude_mpm/commander/web/__init__.py +1 -0
  138. claude_mpm/commander/work/__init__.py +30 -0
  139. claude_mpm/commander/work/executor.py +207 -0
  140. claude_mpm/commander/work/queue.py +405 -0
  141. claude_mpm/commander/workflow/__init__.py +27 -0
  142. claude_mpm/commander/workflow/event_handler.py +241 -0
  143. claude_mpm/commander/workflow/notifier.py +146 -0
  144. claude_mpm/commands/mpm-config.md +8 -0
  145. claude_mpm/commands/mpm-doctor.md +8 -0
  146. claude_mpm/commands/mpm-help.md +8 -0
  147. claude_mpm/commands/mpm-init.md +8 -0
  148. claude_mpm/commands/mpm-monitor.md +8 -0
  149. claude_mpm/commands/mpm-organize.md +8 -0
  150. claude_mpm/commands/mpm-postmortem.md +8 -0
  151. claude_mpm/commands/mpm-session-resume.md +9 -1
  152. claude_mpm/commands/mpm-status.md +8 -0
  153. claude_mpm/commands/mpm-ticket-view.md +8 -0
  154. claude_mpm/commands/mpm-version.md +8 -0
  155. claude_mpm/commands/mpm.md +8 -0
  156. claude_mpm/config/agent_presets.py +8 -7
  157. claude_mpm/config/skill_sources.py +16 -0
  158. claude_mpm/constants.py +6 -0
  159. claude_mpm/core/claude_runner.py +154 -2
  160. claude_mpm/core/config.py +35 -22
  161. claude_mpm/core/config_constants.py +74 -9
  162. claude_mpm/core/constants.py +56 -12
  163. claude_mpm/core/hook_manager.py +53 -4
  164. claude_mpm/core/interactive_session.py +12 -11
  165. claude_mpm/core/logger.py +26 -9
  166. claude_mpm/core/logging_utils.py +39 -13
  167. claude_mpm/core/network_config.py +148 -0
  168. claude_mpm/core/oneshot_session.py +7 -6
  169. claude_mpm/core/optimized_startup.py +3 -1
  170. claude_mpm/core/output_style_manager.py +66 -18
  171. claude_mpm/core/shared/config_loader.py +3 -1
  172. claude_mpm/core/socketio_pool.py +47 -15
  173. claude_mpm/core/unified_config.py +54 -8
  174. claude_mpm/core/unified_paths.py +95 -90
  175. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  176. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  177. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
  178. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
  179. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
  180. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
  181. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
  182. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
  184. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
  185. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  186. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
  187. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
  188. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
  189. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
  190. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
  191. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
  192. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  193. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  194. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
  195. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
  196. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
  197. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
  198. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
  199. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
  200. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
  201. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
  202. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  203. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
  204. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
  205. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
  206. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  207. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
  208. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  209. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
  210. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
  211. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
  212. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
  213. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
  214. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → DR8nis88.js} +2 -2
  215. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
  216. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  217. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
  218. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
  219. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
  220. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
  221. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
  222. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
  223. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  224. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
  225. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  226. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
  227. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
  228. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
  229. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
  230. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  231. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
  232. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
  233. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
  234. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
  235. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  236. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.RgBboRvH.js} +1 -1
  237. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
  238. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  239. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
  240. claude_mpm/dashboard/static/svelte-build/index.html +11 -11
  241. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  242. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  243. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  244. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  245. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  246. claude_mpm/experimental/cli_enhancements.py +2 -1
  247. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  248. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  249. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  250. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  251. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  252. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  253. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.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 +466 -136
  256. claude_mpm/hooks/claude_hooks/hook_handler.py +204 -104
  257. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  258. claude_mpm/hooks/claude_hooks/installer.py +291 -59
  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__/protocols.cpython-311.pyc +0 -0
  266. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  267. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  268. claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
  269. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
  270. claude_mpm/hooks/claude_hooks/services/container.py +326 -0
  271. claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
  272. claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
  273. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
  274. claude_mpm/hooks/kuzu_memory_hook.py +5 -5
  275. claude_mpm/hooks/session_resume_hook.py +89 -1
  276. claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
  277. claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
  278. claude_mpm/init.py +224 -4
  279. claude_mpm/mcp/__init__.py +9 -0
  280. claude_mpm/mcp/google_workspace_server.py +610 -0
  281. claude_mpm/scripts/claude-hook-handler.sh +46 -19
  282. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  283. claude_mpm/services/agents/agent_selection_service.py +2 -2
  284. claude_mpm/services/agents/cache_git_manager.py +1 -1
  285. claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -1
  286. claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
  287. claude_mpm/services/agents/deployment/agent_template_builder.py +37 -17
  288. claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
  289. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  290. claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
  291. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +36 -8
  292. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +50 -26
  293. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  294. claude_mpm/services/agents/git_source_manager.py +21 -2
  295. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  296. claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
  297. claude_mpm/services/agents/sources/git_source_sync_service.py +116 -5
  298. claude_mpm/services/agents/startup_sync.py +5 -2
  299. claude_mpm/services/cli/__init__.py +3 -0
  300. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  301. claude_mpm/services/cli/session_resume_helper.py +10 -2
  302. claude_mpm/services/command_deployment_service.py +44 -26
  303. claude_mpm/services/delegation_detector.py +175 -0
  304. claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
  305. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  306. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  307. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  308. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  309. claude_mpm/services/diagnostics/models.py +14 -1
  310. claude_mpm/services/event_log.py +325 -0
  311. claude_mpm/services/hook_installer_service.py +77 -8
  312. claude_mpm/services/infrastructure/__init__.py +4 -0
  313. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  314. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  315. claude_mpm/services/mcp_config_manager.py +99 -19
  316. claude_mpm/services/mcp_service_registry.py +294 -0
  317. claude_mpm/services/monitor/daemon_manager.py +15 -4
  318. claude_mpm/services/monitor/management/lifecycle.py +8 -3
  319. claude_mpm/services/monitor/server.py +111 -16
  320. claude_mpm/services/pm_skills_deployer.py +302 -94
  321. claude_mpm/services/profile_manager.py +10 -4
  322. claude_mpm/services/skills/git_skill_source_manager.py +192 -29
  323. claude_mpm/services/skills/selective_skill_deployer.py +211 -46
  324. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  325. claude_mpm/services/skills_deployer.py +192 -70
  326. claude_mpm/services/socketio/handlers/hook.py +14 -7
  327. claude_mpm/services/socketio/server/main.py +12 -4
  328. claude_mpm/skills/__init__.py +2 -1
  329. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  330. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  331. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  332. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  333. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  334. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  335. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  336. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  337. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  338. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  339. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  340. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  341. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  342. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  343. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  344. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  345. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  346. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  347. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  348. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  349. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  350. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  351. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  352. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  353. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  354. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  355. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  356. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  357. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  358. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  359. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  360. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  361. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  362. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  363. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  364. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  365. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  366. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  367. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  368. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  369. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  370. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  371. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  372. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  373. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  374. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  375. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  376. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  377. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  378. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  379. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  380. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  381. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  382. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  383. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  384. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  385. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  386. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  387. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  388. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  389. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  390. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  391. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  392. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  393. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  394. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  395. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  396. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  397. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  398. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  399. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  400. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  401. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  402. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  403. claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
  404. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  405. claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
  406. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  407. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  408. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  409. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  410. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  411. claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
  412. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  413. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  414. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  415. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  416. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  417. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  418. claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
  419. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  420. claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
  421. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  422. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  423. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  424. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  425. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  426. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  427. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  428. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  429. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  430. claude_mpm/skills/bundled/security-scanning.md +112 -0
  431. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  432. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  433. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  434. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  435. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  436. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  437. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  438. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  439. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  440. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  441. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  442. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  443. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  444. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  445. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  446. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  447. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  448. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  449. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  450. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  451. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  452. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  453. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  454. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  455. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  456. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  457. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  458. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  459. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  460. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  461. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  462. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  463. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  464. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  465. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  466. claude_mpm/skills/registry.py +295 -90
  467. claude_mpm/skills/skill_manager.py +29 -23
  468. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  469. claude_mpm/utils/agent_dependency_loader.py +103 -4
  470. claude_mpm/utils/robust_installer.py +45 -24
  471. claude_mpm-5.6.72.dist-info/METADATA +416 -0
  472. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/RECORD +477 -159
  473. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/WHEEL +1 -1
  474. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/entry_points.txt +2 -0
  475. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
  476. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
  477. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
  478. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
  479. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +0 -1
  480. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
  481. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
  482. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
  483. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
  484. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
  485. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  486. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  487. claude_mpm-5.4.41.dist-info/METADATA +0 -998
  488. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE +0 -0
  489. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  490. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/top_level.txt +0 -0
@@ -10,12 +10,10 @@ import os
10
10
  import re
11
11
  import shutil
12
12
  import stat
13
- import subprocess
13
+ import subprocess # nosec B404 - Safe: only uses hardcoded 'claude' CLI command, no user input
14
14
  from pathlib import Path
15
15
  from typing import Dict, List, Optional, Tuple
16
16
 
17
- from ...core.logger import get_logger
18
-
19
17
 
20
18
  class HookInstaller:
21
19
  """Manages installation and configuration of Claude MPM hooks."""
@@ -151,7 +149,7 @@ main() {
151
149
  if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
152
150
  echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Claude MPM not found, continuing..." >> /tmp/claude-mpm-hook.log
153
151
  fi
154
- echo '{"action": "continue"}'
152
+ echo '{"continue": true}'
155
153
  exit 0
156
154
  fi
157
155
 
@@ -178,7 +176,7 @@ main() {
178
176
  echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Hook handler failed, see /tmp/claude-mpm-hook-error.log" >> /tmp/claude-mpm-hook.log
179
177
  echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Error: $(cat /tmp/claude-mpm-hook-error.log 2>/dev/null | head -5)" >> /tmp/claude-mpm-hook.log
180
178
  fi
181
- echo '{"action": "continue"}'
179
+ echo '{"continue": true}'
182
180
  exit 0
183
181
  fi
184
182
 
@@ -194,14 +192,25 @@ main "$@"
194
192
  MIN_CLAUDE_VERSION = "1.0.92"
195
193
  # Minimum version for PreToolUse input modification support
196
194
  MIN_PRETOOL_MODIFY_VERSION = "2.0.30"
195
+ # Minimum version for user-invocable skills support
196
+ MIN_SKILLS_VERSION = "2.1.3"
197
197
 
198
198
  def __init__(self):
199
199
  """Initialize the hook installer."""
200
- self.logger = get_logger(__name__)
201
- self.claude_dir = Path.home() / ".claude"
200
+ # Use __name__ directly to avoid double prefix
201
+ # __name__ is already 'claude_mpm.hooks.claude_hooks.installer'
202
+ # get_logger() adds 'claude_mpm.' prefix, causing duplicate
203
+ import logging
204
+
205
+ self.logger = logging.getLogger(__name__)
206
+ # Use project-level paths, NEVER global ~/.claude/settings.json
207
+ # This ensures hooks are scoped to the current project only
208
+ self.project_root = Path.cwd()
209
+ self.claude_dir = self.project_root / ".claude"
202
210
  self.hooks_dir = self.claude_dir / "hooks" # Kept for backward compatibility
203
- # Use settings.json for hooks (Claude Code reads from this file)
204
- self.settings_file = self.claude_dir / "settings.json"
211
+ # Use settings.local.json for project-level hook settings
212
+ # Claude Code reads project-level settings from .claude/settings.local.json
213
+ self.settings_file = self.claude_dir / "settings.local.json"
205
214
  # There is no legacy settings file - this was a bug where both pointed to same file
206
215
  # Setting to None to disable cleanup that was deleting freshly installed hooks
207
216
  self.old_settings_file = None
@@ -220,7 +229,7 @@ main "$@"
220
229
 
221
230
  try:
222
231
  # Run claude --version command
223
- result = subprocess.run(
232
+ result = subprocess.run( # nosec B607 B603 - Safe: hardcoded command, no user input
224
233
  ["claude", "--version"],
225
234
  capture_output=True,
226
235
  text=True,
@@ -331,8 +340,82 @@ main "$@"
331
340
 
332
341
  return True
333
342
 
334
- def get_hook_script_path(self) -> Path:
335
- """Get the path to the hook handler script based on installation method.
343
+ def _version_meets_minimum(self, version: str, min_version: str) -> bool:
344
+ """Check if a version meets minimum requirements.
345
+
346
+ Args:
347
+ version: Current version string (e.g., "2.1.3")
348
+ min_version: Minimum required version string (e.g., "2.1.3")
349
+
350
+ Returns:
351
+ True if version meets or exceeds minimum, False otherwise
352
+ """
353
+
354
+ def parse_version(v: str) -> List[int]:
355
+ """Parse semantic version string to list of integers."""
356
+ try:
357
+ return [int(x) for x in v.split(".")]
358
+ except (ValueError, AttributeError):
359
+ return [0]
360
+
361
+ current = parse_version(version)
362
+ required = parse_version(min_version)
363
+
364
+ # Compare versions
365
+ for i in range(max(len(current), len(required))):
366
+ curr_part = current[i] if i < len(current) else 0
367
+ req_part = required[i] if i < len(required) else 0
368
+
369
+ if curr_part < req_part:
370
+ return False
371
+ if curr_part > req_part:
372
+ return True
373
+
374
+ return True
375
+
376
+ def supports_user_invocable_skills(self) -> bool:
377
+ """Check if Claude Code version supports user-invocable skills.
378
+
379
+ User-invocable skills were added in Claude Code v2.1.3.
380
+ This feature allows users to invoke skills via slash commands.
381
+
382
+ Returns:
383
+ True if version supports user-invocable skills, False otherwise
384
+ """
385
+ version = self.get_claude_version()
386
+ if not version:
387
+ return False
388
+ return self._version_meets_minimum(version, self.MIN_SKILLS_VERSION)
389
+
390
+ def get_hook_command(self) -> str:
391
+ """Get the hook command based on installation method.
392
+
393
+ Priority order:
394
+ 1. claude-hook entry point (uv tool install, pipx install, pip install)
395
+ 2. Fallback to bash script (development installs)
396
+
397
+ Returns:
398
+ Command string for the hook handler (either 'claude-hook' or path to bash script)
399
+
400
+ Raises:
401
+ FileNotFoundError: If no hook handler can be found
402
+ """
403
+ # Check if claude-hook entry point is available in PATH
404
+ claude_hook_path = shutil.which("claude-hook")
405
+ if claude_hook_path:
406
+ self.logger.info(f"Using claude-hook entry point: {claude_hook_path}")
407
+ return "claude-hook"
408
+
409
+ # Fallback to bash script for development installs
410
+ script_path = self._get_hook_script_path()
411
+ self.logger.info(f"Using fallback bash script: {script_path}")
412
+ return str(script_path.absolute())
413
+
414
+ def _get_hook_script_path(self) -> Path:
415
+ """Get the path to the fallback bash hook handler script.
416
+
417
+ This is used when the claude-hook entry point is not available
418
+ (e.g., development installs without uv tool install).
336
419
 
337
420
  Returns:
338
421
  Path to the claude-hook-handler.sh script
@@ -385,6 +468,19 @@ main "$@"
385
468
 
386
469
  raise FileNotFoundError(f"Hook handler script not found at {script_path}")
387
470
 
471
+ def get_hook_script_path(self) -> Path:
472
+ """Get the path to the hook handler script based on installation method.
473
+
474
+ DEPRECATED: Use get_hook_command() instead for proper entry point support.
475
+
476
+ Returns:
477
+ Path to the claude-hook-handler.sh script
478
+
479
+ Raises:
480
+ FileNotFoundError: If the script cannot be found
481
+ """
482
+ return self._get_hook_script_path()
483
+
388
484
  def install_hooks(self, force: bool = False) -> bool:
389
485
  """
390
486
  Install Claude MPM hooks.
@@ -417,18 +513,16 @@ main "$@"
417
513
  # Create Claude directory (hooks_dir no longer needed)
418
514
  self.claude_dir.mkdir(exist_ok=True)
419
515
 
420
- # Get the deployment-root hook script path
516
+ # Get the hook command (either claude-hook entry point or fallback bash script)
421
517
  try:
422
- hook_script_path = self.get_hook_script_path()
423
- self.logger.info(
424
- f"Using deployment-root hook script: {hook_script_path}"
425
- )
518
+ hook_command = self.get_hook_command()
519
+ self.logger.info(f"Using hook command: {hook_command}")
426
520
  except FileNotFoundError as e:
427
- self.logger.error(f"Failed to locate hook script: {e}")
521
+ self.logger.error(f"Failed to locate hook handler: {e}")
428
522
  return False
429
523
 
430
- # Update Claude settings to use deployment-root script
431
- self._update_claude_settings(hook_script_path)
524
+ # Update Claude settings to use the hook command
525
+ self._update_claude_settings(hook_command)
432
526
 
433
527
  # Install commands if available
434
528
  self._install_commands()
@@ -485,8 +579,50 @@ main "$@"
485
579
  except Exception as e:
486
580
  self.logger.warning(f"Could not clean up old settings file: {e}")
487
581
 
488
- def _update_claude_settings(self, hook_script_path: Path) -> None:
489
- """Update Claude settings to use the installed hook."""
582
+ def _fix_status_line(self, settings: Dict) -> None:
583
+ """Fix statusLine command to handle both output style schema formats.
584
+
585
+ The statusLine command receives input in different formats:
586
+ - Newer format: {"activeOutputStyle": "Claude MPM", ...}
587
+ - Older format: {"output_style": {"name": "Claude MPM"}, ...}
588
+
589
+ This method ensures the jq expression checks both locations.
590
+
591
+ Args:
592
+ settings: The settings dictionary to update
593
+ """
594
+ if "statusLine" not in settings:
595
+ return
596
+
597
+ status_line = settings.get("statusLine", {})
598
+ if "command" not in status_line:
599
+ return
600
+
601
+ command = status_line["command"]
602
+
603
+ # Pattern to match: '.output_style.name // "default"'
604
+ # We need to update it to: '.output_style.name // .activeOutputStyle // "default"'
605
+ old_pattern = r'\.output_style\.name\s*//\s*"default"'
606
+ new_pattern = '.output_style.name // .activeOutputStyle // "default"'
607
+
608
+ # Check if the command needs updating
609
+ if re.search(old_pattern, command) and ".activeOutputStyle" not in command:
610
+ updated_command = re.sub(old_pattern, new_pattern, command)
611
+ settings["statusLine"]["command"] = updated_command
612
+ self.logger.info(
613
+ "Fixed statusLine command to handle both output style schemas"
614
+ )
615
+ else:
616
+ self.logger.debug(
617
+ "StatusLine command already supports both schemas or not present"
618
+ )
619
+
620
+ def _update_claude_settings(self, hook_cmd: str) -> None:
621
+ """Update Claude settings to use the installed hook.
622
+
623
+ Args:
624
+ hook_cmd: The hook command to use (either 'claude-hook' or path to bash script)
625
+ """
490
626
  self.logger.info("Updating Claude settings...")
491
627
 
492
628
  # Load existing settings.json or create new
@@ -509,42 +645,107 @@ main "$@"
509
645
  settings["hooks"] = {}
510
646
 
511
647
  # Hook configuration for each event type
512
- hook_command = {"type": "command", "command": str(hook_script_path.absolute())}
648
+ hook_command = {"type": "command", "command": hook_cmd}
649
+
650
+ def is_our_hook(cmd: dict) -> bool:
651
+ """Check if a hook command belongs to claude-mpm."""
652
+ if cmd.get("type") != "command":
653
+ return False
654
+ command = cmd.get("command", "")
655
+ # Match claude-hook entry point or bash script fallback
656
+ return (
657
+ command == "claude-hook"
658
+ or "claude-hook-handler.sh" in command
659
+ or command.endswith("claude-mpm-hook.sh")
660
+ )
661
+
662
+ def merge_hooks_for_event(
663
+ existing_hooks: list, new_hook_command: dict, use_matcher: bool = True
664
+ ) -> list:
665
+ """Merge new hook command into existing hooks without duplication.
666
+
667
+ Args:
668
+ existing_hooks: Current hooks configuration for an event type
669
+ new_hook_command: The claude-mpm hook command to add
670
+ use_matcher: Whether to include matcher: "*" in the config
671
+
672
+ Returns:
673
+ Updated hooks list with our hook merged in
674
+ """
675
+ # Check if our hook already exists in any existing hook config
676
+ our_hook_exists = False
677
+
678
+ for hook_config in existing_hooks:
679
+ if "hooks" in hook_config and isinstance(hook_config["hooks"], list):
680
+ for hook in hook_config["hooks"]:
681
+ if is_our_hook(hook):
682
+ # Update existing hook command path (in case it changed)
683
+ hook["command"] = new_hook_command["command"]
684
+ our_hook_exists = True
685
+ break
686
+ if our_hook_exists:
687
+ break
688
+
689
+ if our_hook_exists:
690
+ # Our hook already exists, just return the updated list
691
+ return existing_hooks
692
+
693
+ # Our hook doesn't exist - need to add it
694
+ # Strategy: Add our hook to the first "*" matcher config, or create new config
695
+ added = False
696
+
697
+ for hook_config in existing_hooks:
698
+ # Check if this config has matcher: "*" (or no matcher for simple events)
699
+ matcher = hook_config.get("matcher")
700
+ if matcher == "*" or (not use_matcher and matcher is None):
701
+ # Add our hook to this config's hooks array
702
+ if "hooks" not in hook_config:
703
+ hook_config["hooks"] = []
704
+ hook_config["hooks"].append(new_hook_command)
705
+ added = True
706
+ break
707
+
708
+ if not added:
709
+ # No suitable config found, create a new one
710
+ if use_matcher:
711
+ new_config = {"matcher": "*", "hooks": [new_hook_command]}
712
+ else:
713
+ new_config = {"hooks": [new_hook_command]}
714
+ existing_hooks.append(new_config)
715
+
716
+ return existing_hooks
513
717
 
514
718
  # Tool-related events need a matcher string
515
719
  tool_events = ["PreToolUse", "PostToolUse"]
516
720
  for event_type in tool_events:
517
- settings["hooks"][event_type] = [
518
- {
519
- "matcher": "*", # String value to match all tools
520
- "hooks": [hook_command],
521
- }
522
- ]
721
+ existing = settings["hooks"].get(event_type, [])
722
+ settings["hooks"][event_type] = merge_hooks_for_event(
723
+ existing, hook_command, use_matcher=True
724
+ )
523
725
 
524
726
  # Simple events (no subtypes, no matcher needed)
525
- simple_events = ["Stop", "SubagentStop", "SubagentStart"]
727
+ # Note: SubagentStart is NOT a valid Claude Code event (only SubagentStop is)
728
+ simple_events = ["Stop", "SubagentStop"]
526
729
  for event_type in simple_events:
527
- settings["hooks"][event_type] = [
528
- {
529
- "hooks": [hook_command],
530
- }
531
- ]
730
+ existing = settings["hooks"].get(event_type, [])
731
+ settings["hooks"][event_type] = merge_hooks_for_event(
732
+ existing, hook_command, use_matcher=False
733
+ )
532
734
 
533
735
  # SessionStart needs matcher for subtypes (startup, resume)
534
- settings["hooks"]["SessionStart"] = [
535
- {
536
- "matcher": "*", # Match all SessionStart subtypes
537
- "hooks": [hook_command],
538
- }
539
- ]
736
+ existing = settings["hooks"].get("SessionStart", [])
737
+ settings["hooks"]["SessionStart"] = merge_hooks_for_event(
738
+ existing, hook_command, use_matcher=True
739
+ )
540
740
 
541
741
  # UserPromptSubmit needs matcher for potential subtypes
542
- settings["hooks"]["UserPromptSubmit"] = [
543
- {
544
- "matcher": "*",
545
- "hooks": [hook_command],
546
- }
547
- ]
742
+ existing = settings["hooks"].get("UserPromptSubmit", [])
743
+ settings["hooks"]["UserPromptSubmit"] = merge_hooks_for_event(
744
+ existing, hook_command, use_matcher=True
745
+ )
746
+
747
+ # Fix statusLine command to handle both output style schemas
748
+ self._fix_status_line(settings)
548
749
 
549
750
  # Write settings to settings.json
550
751
  with self.settings_file.open("w") as f:
@@ -556,7 +757,22 @@ main "$@"
556
757
  self._cleanup_old_settings()
557
758
 
558
759
  def _install_commands(self) -> None:
559
- """Install custom commands for Claude Code."""
760
+ """Install custom commands for Claude Code.
761
+
762
+ For Claude Code >= 2.1.3, commands are deployed as skills via PMSkillsDeployerService.
763
+ This method provides backward compatibility for older versions.
764
+ """
765
+ # Check if skills-based commands are supported
766
+ if self.supports_user_invocable_skills():
767
+ self.logger.info(
768
+ "Claude Code >= 2.1.3 detected. Commands deployed as skills - "
769
+ "skipping legacy command installation."
770
+ )
771
+ return
772
+
773
+ # Legacy installation for older Claude Code versions
774
+ self.logger.info("Installing legacy commands for Claude Code < 2.1.3")
775
+
560
776
  # Find commands directory using proper resource resolution
561
777
  try:
562
778
  from ...core.unified_paths import get_package_resource_path
@@ -628,10 +844,10 @@ main "$@"
628
844
  issues.append("No hooks configured in Claude settings")
629
845
  else:
630
846
  # Check for required event types
847
+ # Note: SubagentStart is NOT a valid Claude Code event
631
848
  required_events = [
632
849
  "Stop",
633
850
  "SubagentStop",
634
- "SubagentStart",
635
851
  "PreToolUse",
636
852
  "PostToolUse",
637
853
  ]
@@ -697,7 +913,8 @@ main "$@"
697
913
  ):
698
914
  cmd = hook_cmd.get("command", "")
699
915
  if (
700
- "claude-hook-handler.sh" in cmd
916
+ cmd == "claude-hook"
917
+ or "claude-hook-handler.sh" in cmd
701
918
  or cmd.endswith("claude-mpm-hook.sh")
702
919
  ):
703
920
  is_claude_mpm = True
@@ -742,27 +959,42 @@ main "$@"
742
959
 
743
960
  is_valid, issues = self.verify_hooks()
744
961
 
745
- # Try to get deployment-root script path
962
+ # Try to get hook command (entry point or fallback script)
963
+ hook_command = None
964
+ using_entry_point = False
746
965
  try:
747
- hook_script_path = self.get_hook_script_path()
966
+ hook_command = self.get_hook_command()
967
+ using_entry_point = hook_command == "claude-hook"
968
+ except FileNotFoundError:
969
+ hook_command = None
970
+
971
+ # For backward compatibility, also try to get the script path
972
+ hook_script_str = None
973
+ script_exists = False
974
+ try:
975
+ hook_script_path = self._get_hook_script_path()
748
976
  hook_script_str = str(hook_script_path)
749
977
  script_exists = hook_script_path.exists()
750
978
  except FileNotFoundError:
751
- hook_script_str = None
752
- script_exists = False
979
+ pass
753
980
 
754
981
  status = {
755
- "installed": script_exists and self.settings_file.exists(),
982
+ "installed": (hook_command is not None or script_exists)
983
+ and self.settings_file.exists(),
756
984
  "valid": is_valid,
757
985
  "issues": issues,
758
- "hook_script": hook_script_str,
986
+ "hook_command": hook_command,
987
+ "hook_script": hook_script_str, # Kept for backward compatibility
988
+ "using_entry_point": using_entry_point,
759
989
  "settings_file": (
760
990
  str(self.settings_file) if self.settings_file.exists() else None
761
991
  ),
762
992
  "claude_version": claude_version,
763
993
  "version_compatible": is_compatible,
764
994
  "version_message": version_message,
765
- "deployment_type": "deployment-root", # New field to indicate new architecture
995
+ "deployment_type": "entry-point"
996
+ if using_entry_point
997
+ else "deployment-root",
766
998
  "pretool_modify_supported": pretool_modify_supported, # v2.0.30+ feature
767
999
  "pretool_modify_message": (
768
1000
  f"PreToolUse input modification supported (v{claude_version})"
@@ -782,7 +1014,7 @@ main "$@"
782
1014
  if "hooks" in settings:
783
1015
  status["configured_events"] = list(settings["hooks"].keys())
784
1016
  configured_in_local = True
785
- except Exception:
1017
+ except Exception: # nosec B110 - Intentional: ignore errors reading settings file
786
1018
  pass
787
1019
 
788
1020
  # Also check old settings file
@@ -796,7 +1028,7 @@ main "$@"
796
1028
  status["warning"] = (
797
1029
  "Hooks found in settings.local.json but Claude Code reads from settings.json"
798
1030
  )
799
- except Exception:
1031
+ except Exception: # nosec B110 - Intentional: ignore errors reading old settings file
800
1032
  pass
801
1033
 
802
1034
  status["settings_location"] = (
@@ -7,39 +7,67 @@ including pre and post delegation hooks.
7
7
 
8
8
  import logging
9
9
  import os
10
- import sys
10
+ from pathlib import Path
11
+
12
+ # Try to import _log from hook_handler, fall back to no-op
13
+ try:
14
+ from claude_mpm.hooks.claude_hooks.hook_handler import _log
15
+ except ImportError:
16
+
17
+ def _log(msg: str) -> None:
18
+ pass # Silent fallback
19
+
11
20
 
12
21
  # Install-type-aware logging configuration BEFORE kuzu-memory imports
13
22
  # This overrides kuzu-memory's WARNING-level basicConfig (fixes 1M-445)
14
- # but respects production install silence
23
+ # but respects production install silence AND startup suppression
15
24
  try:
16
25
  from claude_mpm.core.unified_paths import DeploymentContext, PathContext
17
26
 
18
27
  context = PathContext.detect_deployment_context()
19
28
 
29
+ # CRITICAL: Check if root logger is already suppressed (CRITICAL+1 from startup.py)
30
+ # If so, don't call basicConfig as it will reset the level to INFO
31
+ root_logger = logging.getLogger()
32
+ is_suppressed = root_logger.level > logging.CRITICAL # CRITICAL+1 = 51
33
+
20
34
  # Only configure verbose logging for development/editable installs
21
- # Production installs remain silent by default
22
- if context in (DeploymentContext.DEVELOPMENT, DeploymentContext.EDITABLE_INSTALL):
35
+ # AND if logging isn't already suppressed by startup.py
36
+ if not is_suppressed and context in (
37
+ DeploymentContext.DEVELOPMENT,
38
+ DeploymentContext.EDITABLE_INSTALL,
39
+ ):
40
+ # Write logs to file instead of stderr to avoid hook errors
41
+ log_dir = Path.home() / ".claude-mpm"
42
+ log_dir.mkdir(parents=True, exist_ok=True)
43
+ log_file = log_dir / "hooks.log"
23
44
  logging.basicConfig(
24
45
  level=logging.INFO,
25
46
  format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
26
47
  force=True, # Python 3.8+ - reconfigures root logger
27
- stream=sys.stderr,
48
+ filename=str(log_file),
28
49
  )
29
50
  except ImportError:
30
- # Fallback: if unified_paths not available, configure logging
31
- # This maintains backward compatibility
32
- logging.basicConfig(
33
- level=logging.INFO,
34
- format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
35
- force=True,
36
- stream=sys.stderr,
37
- )
51
+ # Fallback: if unified_paths not available, check suppression before configuring
52
+ root_logger = logging.getLogger()
53
+ is_suppressed = root_logger.level > logging.CRITICAL
54
+
55
+ if not is_suppressed:
56
+ # Write logs to file instead of stderr to avoid hook errors
57
+ log_dir = Path.home() / ".claude-mpm"
58
+ log_dir.mkdir(parents=True, exist_ok=True)
59
+ log_file = log_dir / "hooks.log"
60
+ logging.basicConfig(
61
+ level=logging.INFO,
62
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
63
+ force=True,
64
+ filename=str(log_file),
65
+ )
38
66
  from datetime import datetime, timezone
39
67
  from typing import Optional
40
68
 
41
69
  # Debug mode
42
- DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "true").lower() != "false"
70
+ DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "false").lower() == "true"
43
71
 
44
72
  # Memory hooks integration
45
73
  MEMORY_HOOKS_AVAILABLE = False
@@ -60,7 +88,7 @@ try:
60
88
  except Exception as e:
61
89
  # Catch all exceptions to prevent any import errors from breaking the handler
62
90
  if DEBUG:
63
- print(f"Memory hooks not available: {e}", file=sys.stderr)
91
+ _log(f"Memory hooks not available: {e}")
64
92
  MEMORY_HOOKS_AVAILABLE = False
65
93
 
66
94
 
@@ -94,10 +122,7 @@ class MemoryHookManager:
94
122
  # Only initialize if memory system is enabled
95
123
  if not config.get("memory.enabled", True):
96
124
  if DEBUG:
97
- print(
98
- "Memory system disabled - skipping hook initialization",
99
- file=sys.stderr,
100
- )
125
+ _log("Memory system disabled - skipping hook initialization")
101
126
  return
102
127
 
103
128
  # Initialize pre-delegation hook for memory injection
@@ -115,14 +140,11 @@ class MemoryHookManager:
115
140
  hooks_info.append("pre-delegation")
116
141
  if self.post_delegation_hook:
117
142
  hooks_info.append("post-delegation")
118
- print(
119
- f"✅ Memory hooks initialized: {', '.join(hooks_info)}",
120
- file=sys.stderr,
121
- )
143
+ _log(f"✅ Memory hooks initialized: {', '.join(hooks_info)}")
122
144
 
123
145
  except Exception as e:
124
146
  if DEBUG:
125
- print(f"❌ Failed to initialize memory hooks: {e}", file=sys.stderr)
147
+ _log(f"❌ Failed to initialize memory hooks: {e}")
126
148
  # Don't fail the entire handler - memory system is optional
127
149
 
128
150
  def trigger_pre_delegation_hook(
@@ -171,14 +193,13 @@ class MemoryHookManager:
171
193
 
172
194
  if DEBUG:
173
195
  memory_size = len(memory_section.encode("utf-8"))
174
- print(
175
- f"✅ Injected {memory_size} bytes of memory for agent '{agent_type}'",
176
- file=sys.stderr,
196
+ _log(
197
+ f"✅ Injected {memory_size} bytes of memory for agent '{agent_type}'"
177
198
  )
178
199
 
179
200
  except Exception as e:
180
201
  if DEBUG:
181
- print(f"❌ Memory pre-delegation hook failed: {e}", file=sys.stderr)
202
+ _log(f"❌ Memory pre-delegation hook failed: {e}")
182
203
  # Don't fail the delegation - memory is optional
183
204
 
184
205
  def trigger_post_delegation_hook(
@@ -238,12 +259,11 @@ class MemoryHookManager:
238
259
  if result.success and result.metadata:
239
260
  learnings_extracted = result.metadata.get("learnings_extracted", 0)
240
261
  if learnings_extracted > 0 and DEBUG:
241
- print(
242
- f"✅ Extracted {learnings_extracted} learnings for agent '{agent_type}'",
243
- file=sys.stderr,
262
+ _log(
263
+ f"✅ Extracted {learnings_extracted} learnings for agent '{agent_type}'"
244
264
  )
245
265
 
246
266
  except Exception as e:
247
267
  if DEBUG:
248
- print(f"❌ Memory post-delegation hook failed: {e}", file=sys.stderr)
268
+ _log(f"❌ Memory post-delegation hook failed: {e}")
249
269
  # Don't fail the delegation result - memory is optional