claude-mpm 5.4.48__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 (467) 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 +119 -689
  6. claude_mpm/agents/WORKFLOW.md +2 -0
  7. claude_mpm/agents/templates/circuit-breakers.md +26 -17
  8. claude_mpm/cli/__init__.py +5 -1
  9. claude_mpm/cli/commands/agents.py +2 -4
  10. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  11. claude_mpm/cli/commands/autotodos.py +566 -0
  12. claude_mpm/cli/commands/commander.py +216 -0
  13. claude_mpm/cli/commands/configure.py +620 -21
  14. claude_mpm/cli/commands/configure_agent_display.py +3 -1
  15. claude_mpm/cli/commands/hook_errors.py +60 -60
  16. claude_mpm/cli/commands/monitor.py +2 -2
  17. claude_mpm/cli/commands/mpm_init/core.py +15 -8
  18. claude_mpm/cli/commands/profile.py +9 -10
  19. claude_mpm/cli/commands/run.py +35 -3
  20. claude_mpm/cli/commands/skill_source.py +51 -2
  21. claude_mpm/cli/commands/skills.py +171 -17
  22. claude_mpm/cli/executor.py +120 -16
  23. claude_mpm/cli/interactive/__init__.py +10 -0
  24. claude_mpm/cli/interactive/agent_wizard.py +30 -50
  25. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  26. claude_mpm/cli/interactive/skill_selector.py +481 -0
  27. claude_mpm/cli/parsers/base_parser.py +76 -1
  28. claude_mpm/cli/parsers/commander_parser.py +116 -0
  29. claude_mpm/cli/parsers/profile_parser.py +0 -1
  30. claude_mpm/cli/parsers/run_parser.py +10 -0
  31. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  32. claude_mpm/cli/parsers/skills_parser.py +5 -0
  33. claude_mpm/cli/startup.py +544 -511
  34. claude_mpm/cli/startup_display.py +74 -6
  35. claude_mpm/cli/startup_logging.py +2 -2
  36. claude_mpm/cli/utils.py +7 -3
  37. claude_mpm/commander/__init__.py +78 -0
  38. claude_mpm/commander/adapters/__init__.py +60 -0
  39. claude_mpm/commander/adapters/auggie.py +260 -0
  40. claude_mpm/commander/adapters/base.py +288 -0
  41. claude_mpm/commander/adapters/claude_code.py +392 -0
  42. claude_mpm/commander/adapters/codex.py +237 -0
  43. claude_mpm/commander/adapters/communication.py +366 -0
  44. claude_mpm/commander/adapters/example_usage.py +310 -0
  45. claude_mpm/commander/adapters/mpm.py +389 -0
  46. claude_mpm/commander/adapters/registry.py +204 -0
  47. claude_mpm/commander/api/__init__.py +16 -0
  48. claude_mpm/commander/api/app.py +121 -0
  49. claude_mpm/commander/api/errors.py +133 -0
  50. claude_mpm/commander/api/routes/__init__.py +8 -0
  51. claude_mpm/commander/api/routes/events.py +184 -0
  52. claude_mpm/commander/api/routes/inbox.py +171 -0
  53. claude_mpm/commander/api/routes/messages.py +148 -0
  54. claude_mpm/commander/api/routes/projects.py +271 -0
  55. claude_mpm/commander/api/routes/sessions.py +226 -0
  56. claude_mpm/commander/api/routes/work.py +296 -0
  57. claude_mpm/commander/api/schemas.py +186 -0
  58. claude_mpm/commander/chat/__init__.py +7 -0
  59. claude_mpm/commander/chat/cli.py +146 -0
  60. claude_mpm/commander/chat/commands.py +96 -0
  61. claude_mpm/commander/chat/repl.py +310 -0
  62. claude_mpm/commander/config.py +51 -0
  63. claude_mpm/commander/config_loader.py +115 -0
  64. claude_mpm/commander/core/__init__.py +10 -0
  65. claude_mpm/commander/core/block_manager.py +325 -0
  66. claude_mpm/commander/core/response_manager.py +323 -0
  67. claude_mpm/commander/daemon.py +603 -0
  68. claude_mpm/commander/env_loader.py +59 -0
  69. claude_mpm/commander/events/__init__.py +26 -0
  70. claude_mpm/commander/events/manager.py +332 -0
  71. claude_mpm/commander/frameworks/__init__.py +12 -0
  72. claude_mpm/commander/frameworks/base.py +146 -0
  73. claude_mpm/commander/frameworks/claude_code.py +58 -0
  74. claude_mpm/commander/frameworks/mpm.py +62 -0
  75. claude_mpm/commander/inbox/__init__.py +16 -0
  76. claude_mpm/commander/inbox/dedup.py +128 -0
  77. claude_mpm/commander/inbox/inbox.py +224 -0
  78. claude_mpm/commander/inbox/models.py +70 -0
  79. claude_mpm/commander/instance_manager.py +450 -0
  80. claude_mpm/commander/llm/__init__.py +6 -0
  81. claude_mpm/commander/llm/openrouter_client.py +167 -0
  82. claude_mpm/commander/llm/summarizer.py +70 -0
  83. claude_mpm/commander/memory/__init__.py +45 -0
  84. claude_mpm/commander/memory/compression.py +347 -0
  85. claude_mpm/commander/memory/embeddings.py +230 -0
  86. claude_mpm/commander/memory/entities.py +310 -0
  87. claude_mpm/commander/memory/example_usage.py +290 -0
  88. claude_mpm/commander/memory/integration.py +325 -0
  89. claude_mpm/commander/memory/search.py +381 -0
  90. claude_mpm/commander/memory/store.py +657 -0
  91. claude_mpm/commander/models/__init__.py +18 -0
  92. claude_mpm/commander/models/events.py +121 -0
  93. claude_mpm/commander/models/project.py +162 -0
  94. claude_mpm/commander/models/work.py +214 -0
  95. claude_mpm/commander/parsing/__init__.py +20 -0
  96. claude_mpm/commander/parsing/extractor.py +132 -0
  97. claude_mpm/commander/parsing/output_parser.py +270 -0
  98. claude_mpm/commander/parsing/patterns.py +100 -0
  99. claude_mpm/commander/persistence/__init__.py +11 -0
  100. claude_mpm/commander/persistence/event_store.py +274 -0
  101. claude_mpm/commander/persistence/state_store.py +309 -0
  102. claude_mpm/commander/persistence/work_store.py +164 -0
  103. claude_mpm/commander/polling/__init__.py +13 -0
  104. claude_mpm/commander/polling/event_detector.py +104 -0
  105. claude_mpm/commander/polling/output_buffer.py +49 -0
  106. claude_mpm/commander/polling/output_poller.py +153 -0
  107. claude_mpm/commander/project_session.py +268 -0
  108. claude_mpm/commander/proxy/__init__.py +12 -0
  109. claude_mpm/commander/proxy/formatter.py +89 -0
  110. claude_mpm/commander/proxy/output_handler.py +191 -0
  111. claude_mpm/commander/proxy/relay.py +155 -0
  112. claude_mpm/commander/registry.py +410 -0
  113. claude_mpm/commander/runtime/__init__.py +10 -0
  114. claude_mpm/commander/runtime/executor.py +191 -0
  115. claude_mpm/commander/runtime/monitor.py +346 -0
  116. claude_mpm/commander/session/__init__.py +6 -0
  117. claude_mpm/commander/session/context.py +81 -0
  118. claude_mpm/commander/session/manager.py +59 -0
  119. claude_mpm/commander/tmux_orchestrator.py +361 -0
  120. claude_mpm/commander/web/__init__.py +1 -0
  121. claude_mpm/commander/work/__init__.py +30 -0
  122. claude_mpm/commander/work/executor.py +207 -0
  123. claude_mpm/commander/work/queue.py +405 -0
  124. claude_mpm/commander/workflow/__init__.py +27 -0
  125. claude_mpm/commander/workflow/event_handler.py +241 -0
  126. claude_mpm/commander/workflow/notifier.py +146 -0
  127. claude_mpm/commands/mpm-config.md +8 -0
  128. claude_mpm/commands/mpm-doctor.md +8 -0
  129. claude_mpm/commands/mpm-help.md +8 -0
  130. claude_mpm/commands/mpm-init.md +8 -0
  131. claude_mpm/commands/mpm-monitor.md +8 -0
  132. claude_mpm/commands/mpm-organize.md +8 -0
  133. claude_mpm/commands/mpm-postmortem.md +8 -0
  134. claude_mpm/commands/mpm-session-resume.md +9 -1
  135. claude_mpm/commands/mpm-status.md +8 -0
  136. claude_mpm/commands/mpm-ticket-view.md +8 -0
  137. claude_mpm/commands/mpm-version.md +8 -0
  138. claude_mpm/commands/mpm.md +8 -0
  139. claude_mpm/config/agent_presets.py +8 -7
  140. claude_mpm/config/skill_sources.py +16 -0
  141. claude_mpm/constants.py +1 -0
  142. claude_mpm/core/claude_runner.py +154 -2
  143. claude_mpm/core/config.py +35 -22
  144. claude_mpm/core/config_constants.py +74 -9
  145. claude_mpm/core/constants.py +56 -12
  146. claude_mpm/core/hook_manager.py +51 -3
  147. claude_mpm/core/interactive_session.py +12 -11
  148. claude_mpm/core/logger.py +26 -9
  149. claude_mpm/core/logging_utils.py +39 -13
  150. claude_mpm/core/network_config.py +148 -0
  151. claude_mpm/core/oneshot_session.py +7 -6
  152. claude_mpm/core/optimized_startup.py +3 -1
  153. claude_mpm/core/output_style_manager.py +66 -18
  154. claude_mpm/core/shared/config_loader.py +3 -1
  155. claude_mpm/core/socketio_pool.py +47 -15
  156. claude_mpm/core/unified_config.py +54 -8
  157. claude_mpm/core/unified_paths.py +95 -90
  158. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  159. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  160. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
  161. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
  162. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
  163. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
  164. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
  165. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
  166. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
  167. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
  168. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  169. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
  170. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
  171. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
  172. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
  173. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
  174. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
  175. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  176. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  177. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
  178. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
  179. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
  180. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
  181. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
  182. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
  184. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
  185. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  186. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
  187. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
  188. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
  189. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  190. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
  191. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  192. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
  193. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
  194. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
  195. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
  196. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
  197. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → DR8nis88.js} +2 -2
  198. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
  199. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  200. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
  201. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
  202. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
  203. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
  204. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
  205. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
  206. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  207. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
  208. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  209. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
  210. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
  211. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
  212. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
  213. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  214. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
  215. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
  216. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
  217. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
  218. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  219. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.RgBboRvH.js} +1 -1
  220. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
  221. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  222. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
  223. claude_mpm/dashboard/static/svelte-build/index.html +11 -11
  224. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  225. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  226. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  227. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  228. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  229. claude_mpm/experimental/cli_enhancements.py +2 -1
  230. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  231. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  232. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  233. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  234. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  235. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  236. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  237. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
  238. claude_mpm/hooks/claude_hooks/event_handlers.py +527 -136
  239. claude_mpm/hooks/claude_hooks/hook_handler.py +170 -104
  240. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  241. claude_mpm/hooks/claude_hooks/installer.py +206 -36
  242. claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
  243. claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
  244. claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
  245. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  246. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  247. claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
  248. claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
  249. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  250. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  251. claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
  252. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
  253. claude_mpm/hooks/claude_hooks/services/container.py +310 -0
  254. claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
  255. claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
  256. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
  257. claude_mpm/hooks/session_resume_hook.py +89 -1
  258. claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
  259. claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
  260. claude_mpm/init.py +215 -2
  261. claude_mpm/scripts/claude-hook-handler.sh +46 -19
  262. claude_mpm/scripts/start_activity_logging.py +0 -0
  263. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  264. claude_mpm/services/agents/agent_selection_service.py +2 -2
  265. claude_mpm/services/agents/cache_git_manager.py +1 -1
  266. claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -1
  267. claude_mpm/services/agents/deployment/agent_format_converter.py +8 -6
  268. claude_mpm/services/agents/deployment/agent_template_builder.py +14 -4
  269. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  270. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +4 -4
  271. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +4 -1
  272. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  273. claude_mpm/services/agents/git_source_manager.py +6 -2
  274. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  275. claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
  276. claude_mpm/services/agents/sources/git_source_sync_service.py +10 -5
  277. claude_mpm/services/agents/startup_sync.py +5 -2
  278. claude_mpm/services/cli/__init__.py +3 -0
  279. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  280. claude_mpm/services/cli/session_resume_helper.py +10 -2
  281. claude_mpm/services/command_deployment_service.py +44 -26
  282. claude_mpm/services/delegation_detector.py +175 -0
  283. claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
  284. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  285. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  286. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  287. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  288. claude_mpm/services/diagnostics/models.py +14 -1
  289. claude_mpm/services/event_log.py +325 -0
  290. claude_mpm/services/hook_installer_service.py +77 -8
  291. claude_mpm/services/infrastructure/__init__.py +4 -0
  292. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  293. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  294. claude_mpm/services/monitor/daemon_manager.py +15 -4
  295. claude_mpm/services/monitor/management/lifecycle.py +8 -3
  296. claude_mpm/services/monitor/server.py +106 -16
  297. claude_mpm/services/pm_skills_deployer.py +267 -94
  298. claude_mpm/services/profile_manager.py +10 -4
  299. claude_mpm/services/skills/git_skill_source_manager.py +192 -29
  300. claude_mpm/services/skills/selective_skill_deployer.py +211 -46
  301. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  302. claude_mpm/services/skills_deployer.py +188 -67
  303. claude_mpm/services/socketio/handlers/hook.py +14 -7
  304. claude_mpm/services/socketio/server/main.py +12 -4
  305. claude_mpm/skills/__init__.py +2 -1
  306. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  307. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  308. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  309. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  310. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  311. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  312. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  313. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  314. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  315. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  316. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  317. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  318. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  319. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  320. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  321. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  322. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  323. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  324. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  325. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  326. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  327. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  328. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  329. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  330. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  331. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  332. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  333. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  334. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  335. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  336. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  337. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  338. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  339. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  340. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  341. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  342. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  343. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  344. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  345. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  346. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  347. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  348. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  349. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  350. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  351. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  352. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  353. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  354. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  355. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  356. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  357. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  358. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  359. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  360. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  361. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  362. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  363. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  364. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  365. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  366. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  367. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  368. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  369. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  370. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  371. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  372. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  373. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  374. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  375. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  376. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  377. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  378. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  379. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  380. claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
  381. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  382. claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
  383. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  384. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  385. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  386. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  387. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  388. claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
  389. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  390. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  391. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  392. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  393. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  394. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  395. claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
  396. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  397. claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
  398. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  399. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  400. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  401. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  402. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  403. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  404. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  405. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  406. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  407. claude_mpm/skills/bundled/security-scanning.md +112 -0
  408. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  409. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  410. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  411. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  412. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  413. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  414. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  415. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  416. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  417. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  418. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  419. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  420. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  421. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  422. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  423. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  424. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  425. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  426. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  427. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  428. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  429. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  430. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  431. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  432. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  433. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  434. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  435. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  436. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  437. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  438. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  439. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  440. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  441. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  442. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  443. claude_mpm/skills/registry.py +295 -90
  444. claude_mpm/skills/skill_manager.py +29 -23
  445. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  446. claude_mpm/utils/agent_dependency_loader.py +103 -4
  447. claude_mpm/utils/robust_installer.py +45 -24
  448. claude_mpm-5.6.34.dist-info/METADATA +393 -0
  449. {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/RECORD +453 -151
  450. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
  451. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
  452. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
  453. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
  454. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +0 -1
  455. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
  456. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
  457. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
  458. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
  459. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
  460. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  461. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  462. claude_mpm-5.4.48.dist-info/METADATA +0 -999
  463. {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/WHEEL +0 -0
  464. {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/entry_points.txt +0 -0
  465. {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE +0 -0
  466. {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  467. {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.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,6 +340,53 @@ main "$@"
331
340
 
332
341
  return True
333
342
 
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
+
334
390
  def get_hook_script_path(self) -> Path:
335
391
  """Get the path to the hook handler script based on installation method.
336
392
 
@@ -485,6 +541,44 @@ main "$@"
485
541
  except Exception as e:
486
542
  self.logger.warning(f"Could not clean up old settings file: {e}")
487
543
 
544
+ def _fix_status_line(self, settings: Dict) -> None:
545
+ """Fix statusLine command to handle both output style schema formats.
546
+
547
+ The statusLine command receives input in different formats:
548
+ - Newer format: {"activeOutputStyle": "Claude MPM", ...}
549
+ - Older format: {"output_style": {"name": "Claude MPM"}, ...}
550
+
551
+ This method ensures the jq expression checks both locations.
552
+
553
+ Args:
554
+ settings: The settings dictionary to update
555
+ """
556
+ if "statusLine" not in settings:
557
+ return
558
+
559
+ status_line = settings.get("statusLine", {})
560
+ if "command" not in status_line:
561
+ return
562
+
563
+ command = status_line["command"]
564
+
565
+ # Pattern to match: '.output_style.name // "default"'
566
+ # We need to update it to: '.output_style.name // .activeOutputStyle // "default"'
567
+ old_pattern = r'\.output_style\.name\s*//\s*"default"'
568
+ new_pattern = '.output_style.name // .activeOutputStyle // "default"'
569
+
570
+ # Check if the command needs updating
571
+ if re.search(old_pattern, command) and ".activeOutputStyle" not in command:
572
+ updated_command = re.sub(old_pattern, new_pattern, command)
573
+ settings["statusLine"]["command"] = updated_command
574
+ self.logger.info(
575
+ "Fixed statusLine command to handle both output style schemas"
576
+ )
577
+ else:
578
+ self.logger.debug(
579
+ "StatusLine command already supports both schemas or not present"
580
+ )
581
+
488
582
  def _update_claude_settings(self, hook_script_path: Path) -> None:
489
583
  """Update Claude settings to use the installed hook."""
490
584
  self.logger.info("Updating Claude settings...")
@@ -511,40 +605,101 @@ main "$@"
511
605
  # Hook configuration for each event type
512
606
  hook_command = {"type": "command", "command": str(hook_script_path.absolute())}
513
607
 
608
+ def is_our_hook(cmd: dict) -> bool:
609
+ """Check if a hook command belongs to claude-mpm."""
610
+ if cmd.get("type") != "command":
611
+ return False
612
+ command = cmd.get("command", "")
613
+ return "claude-hook-handler.sh" in command or command.endswith(
614
+ "claude-mpm-hook.sh"
615
+ )
616
+
617
+ def merge_hooks_for_event(
618
+ existing_hooks: list, new_hook_command: dict, use_matcher: bool = True
619
+ ) -> list:
620
+ """Merge new hook command into existing hooks without duplication.
621
+
622
+ Args:
623
+ existing_hooks: Current hooks configuration for an event type
624
+ new_hook_command: The claude-mpm hook command to add
625
+ use_matcher: Whether to include matcher: "*" in the config
626
+
627
+ Returns:
628
+ Updated hooks list with our hook merged in
629
+ """
630
+ # Check if our hook already exists in any existing hook config
631
+ our_hook_exists = False
632
+
633
+ for hook_config in existing_hooks:
634
+ if "hooks" in hook_config and isinstance(hook_config["hooks"], list):
635
+ for hook in hook_config["hooks"]:
636
+ if is_our_hook(hook):
637
+ # Update existing hook command path (in case it changed)
638
+ hook["command"] = new_hook_command["command"]
639
+ our_hook_exists = True
640
+ break
641
+ if our_hook_exists:
642
+ break
643
+
644
+ if our_hook_exists:
645
+ # Our hook already exists, just return the updated list
646
+ return existing_hooks
647
+
648
+ # Our hook doesn't exist - need to add it
649
+ # Strategy: Add our hook to the first "*" matcher config, or create new config
650
+ added = False
651
+
652
+ for hook_config in existing_hooks:
653
+ # Check if this config has matcher: "*" (or no matcher for simple events)
654
+ matcher = hook_config.get("matcher")
655
+ if matcher == "*" or (not use_matcher and matcher is None):
656
+ # Add our hook to this config's hooks array
657
+ if "hooks" not in hook_config:
658
+ hook_config["hooks"] = []
659
+ hook_config["hooks"].append(new_hook_command)
660
+ added = True
661
+ break
662
+
663
+ if not added:
664
+ # No suitable config found, create a new one
665
+ if use_matcher:
666
+ new_config = {"matcher": "*", "hooks": [new_hook_command]}
667
+ else:
668
+ new_config = {"hooks": [new_hook_command]}
669
+ existing_hooks.append(new_config)
670
+
671
+ return existing_hooks
672
+
514
673
  # Tool-related events need a matcher string
515
674
  tool_events = ["PreToolUse", "PostToolUse"]
516
675
  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
- ]
676
+ existing = settings["hooks"].get(event_type, [])
677
+ settings["hooks"][event_type] = merge_hooks_for_event(
678
+ existing, hook_command, use_matcher=True
679
+ )
523
680
 
524
681
  # Simple events (no subtypes, no matcher needed)
525
682
  simple_events = ["Stop", "SubagentStop", "SubagentStart"]
526
683
  for event_type in simple_events:
527
- settings["hooks"][event_type] = [
528
- {
529
- "hooks": [hook_command],
530
- }
531
- ]
684
+ existing = settings["hooks"].get(event_type, [])
685
+ settings["hooks"][event_type] = merge_hooks_for_event(
686
+ existing, hook_command, use_matcher=False
687
+ )
532
688
 
533
689
  # SessionStart needs matcher for subtypes (startup, resume)
534
- settings["hooks"]["SessionStart"] = [
535
- {
536
- "matcher": "*", # Match all SessionStart subtypes
537
- "hooks": [hook_command],
538
- }
539
- ]
690
+ existing = settings["hooks"].get("SessionStart", [])
691
+ settings["hooks"]["SessionStart"] = merge_hooks_for_event(
692
+ existing, hook_command, use_matcher=True
693
+ )
540
694
 
541
695
  # UserPromptSubmit needs matcher for potential subtypes
542
- settings["hooks"]["UserPromptSubmit"] = [
543
- {
544
- "matcher": "*",
545
- "hooks": [hook_command],
546
- }
547
- ]
696
+ existing = settings["hooks"].get("UserPromptSubmit", [])
697
+ settings["hooks"]["UserPromptSubmit"] = merge_hooks_for_event(
698
+ existing, hook_command, use_matcher=True
699
+ )
700
+
701
+ # Fix statusLine command to handle both output style schemas
702
+ self._fix_status_line(settings)
548
703
 
549
704
  # Write settings to settings.json
550
705
  with self.settings_file.open("w") as f:
@@ -556,7 +711,22 @@ main "$@"
556
711
  self._cleanup_old_settings()
557
712
 
558
713
  def _install_commands(self) -> None:
559
- """Install custom commands for Claude Code."""
714
+ """Install custom commands for Claude Code.
715
+
716
+ For Claude Code >= 2.1.3, commands are deployed as skills via PMSkillsDeployerService.
717
+ This method provides backward compatibility for older versions.
718
+ """
719
+ # Check if skills-based commands are supported
720
+ if self.supports_user_invocable_skills():
721
+ self.logger.info(
722
+ "Claude Code >= 2.1.3 detected. Commands deployed as skills - "
723
+ "skipping legacy command installation."
724
+ )
725
+ return
726
+
727
+ # Legacy installation for older Claude Code versions
728
+ self.logger.info("Installing legacy commands for Claude Code < 2.1.3")
729
+
560
730
  # Find commands directory using proper resource resolution
561
731
  try:
562
732
  from ...core.unified_paths import get_package_resource_path
@@ -782,7 +952,7 @@ main "$@"
782
952
  if "hooks" in settings:
783
953
  status["configured_events"] = list(settings["hooks"].keys())
784
954
  configured_in_local = True
785
- except Exception:
955
+ except Exception: # nosec B110 - Intentional: ignore errors reading settings file
786
956
  pass
787
957
 
788
958
  # Also check old settings file
@@ -796,7 +966,7 @@ main "$@"
796
966
  status["warning"] = (
797
967
  "Hooks found in settings.local.json but Claude Code reads from settings.json"
798
968
  )
799
- except Exception:
969
+ except Exception: # nosec B110 - Intentional: ignore errors reading old settings file
800
970
  pass
801
971
 
802
972
  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