claude-mpm 5.4.55__py3-none-any.whl → 5.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (401) 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 +111 -686
  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 +46 -0
  13. claude_mpm/cli/commands/configure.py +620 -21
  14. claude_mpm/cli/commands/hook_errors.py +60 -60
  15. claude_mpm/cli/commands/monitor.py +2 -2
  16. claude_mpm/cli/commands/mpm_init/core.py +2 -2
  17. claude_mpm/cli/commands/run.py +35 -3
  18. claude_mpm/cli/commands/skills.py +166 -14
  19. claude_mpm/cli/executor.py +120 -16
  20. claude_mpm/cli/interactive/__init__.py +10 -0
  21. claude_mpm/cli/interactive/agent_wizard.py +30 -50
  22. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  23. claude_mpm/cli/interactive/skill_selector.py +481 -0
  24. claude_mpm/cli/parsers/base_parser.py +76 -1
  25. claude_mpm/cli/parsers/commander_parser.py +83 -0
  26. claude_mpm/cli/parsers/run_parser.py +10 -0
  27. claude_mpm/cli/startup.py +276 -403
  28. claude_mpm/cli/startup_display.py +72 -5
  29. claude_mpm/cli/startup_logging.py +2 -2
  30. claude_mpm/cli/utils.py +7 -3
  31. claude_mpm/commander/__init__.py +72 -0
  32. claude_mpm/commander/adapters/__init__.py +31 -0
  33. claude_mpm/commander/adapters/base.py +191 -0
  34. claude_mpm/commander/adapters/claude_code.py +361 -0
  35. claude_mpm/commander/adapters/communication.py +366 -0
  36. claude_mpm/commander/api/__init__.py +16 -0
  37. claude_mpm/commander/api/app.py +105 -0
  38. claude_mpm/commander/api/errors.py +112 -0
  39. claude_mpm/commander/api/routes/__init__.py +8 -0
  40. claude_mpm/commander/api/routes/events.py +184 -0
  41. claude_mpm/commander/api/routes/inbox.py +171 -0
  42. claude_mpm/commander/api/routes/messages.py +148 -0
  43. claude_mpm/commander/api/routes/projects.py +271 -0
  44. claude_mpm/commander/api/routes/sessions.py +215 -0
  45. claude_mpm/commander/api/routes/work.py +260 -0
  46. claude_mpm/commander/api/schemas.py +182 -0
  47. claude_mpm/commander/chat/__init__.py +7 -0
  48. claude_mpm/commander/chat/cli.py +107 -0
  49. claude_mpm/commander/chat/commands.py +96 -0
  50. claude_mpm/commander/chat/repl.py +310 -0
  51. claude_mpm/commander/config.py +49 -0
  52. claude_mpm/commander/config_loader.py +115 -0
  53. claude_mpm/commander/daemon.py +398 -0
  54. claude_mpm/commander/events/__init__.py +26 -0
  55. claude_mpm/commander/events/manager.py +332 -0
  56. claude_mpm/commander/frameworks/__init__.py +12 -0
  57. claude_mpm/commander/frameworks/base.py +143 -0
  58. claude_mpm/commander/frameworks/claude_code.py +58 -0
  59. claude_mpm/commander/frameworks/mpm.py +62 -0
  60. claude_mpm/commander/inbox/__init__.py +16 -0
  61. claude_mpm/commander/inbox/dedup.py +128 -0
  62. claude_mpm/commander/inbox/inbox.py +224 -0
  63. claude_mpm/commander/inbox/models.py +70 -0
  64. claude_mpm/commander/instance_manager.py +337 -0
  65. claude_mpm/commander/llm/__init__.py +6 -0
  66. claude_mpm/commander/llm/openrouter_client.py +167 -0
  67. claude_mpm/commander/llm/summarizer.py +70 -0
  68. claude_mpm/commander/models/__init__.py +18 -0
  69. claude_mpm/commander/models/events.py +121 -0
  70. claude_mpm/commander/models/project.py +162 -0
  71. claude_mpm/commander/models/work.py +214 -0
  72. claude_mpm/commander/parsing/__init__.py +20 -0
  73. claude_mpm/commander/parsing/extractor.py +132 -0
  74. claude_mpm/commander/parsing/output_parser.py +270 -0
  75. claude_mpm/commander/parsing/patterns.py +100 -0
  76. claude_mpm/commander/persistence/__init__.py +11 -0
  77. claude_mpm/commander/persistence/event_store.py +274 -0
  78. claude_mpm/commander/persistence/state_store.py +309 -0
  79. claude_mpm/commander/persistence/work_store.py +164 -0
  80. claude_mpm/commander/polling/__init__.py +13 -0
  81. claude_mpm/commander/polling/event_detector.py +104 -0
  82. claude_mpm/commander/polling/output_buffer.py +49 -0
  83. claude_mpm/commander/polling/output_poller.py +153 -0
  84. claude_mpm/commander/project_session.py +268 -0
  85. claude_mpm/commander/proxy/__init__.py +12 -0
  86. claude_mpm/commander/proxy/formatter.py +89 -0
  87. claude_mpm/commander/proxy/output_handler.py +191 -0
  88. claude_mpm/commander/proxy/relay.py +155 -0
  89. claude_mpm/commander/registry.py +404 -0
  90. claude_mpm/commander/runtime/__init__.py +10 -0
  91. claude_mpm/commander/runtime/executor.py +191 -0
  92. claude_mpm/commander/runtime/monitor.py +316 -0
  93. claude_mpm/commander/session/__init__.py +6 -0
  94. claude_mpm/commander/session/context.py +81 -0
  95. claude_mpm/commander/session/manager.py +59 -0
  96. claude_mpm/commander/tmux_orchestrator.py +361 -0
  97. claude_mpm/commander/web/__init__.py +1 -0
  98. claude_mpm/commander/work/__init__.py +30 -0
  99. claude_mpm/commander/work/executor.py +189 -0
  100. claude_mpm/commander/work/queue.py +405 -0
  101. claude_mpm/commander/workflow/__init__.py +27 -0
  102. claude_mpm/commander/workflow/event_handler.py +219 -0
  103. claude_mpm/commander/workflow/notifier.py +146 -0
  104. claude_mpm/commands/mpm-config.md +8 -0
  105. claude_mpm/commands/mpm-doctor.md +8 -0
  106. claude_mpm/commands/mpm-help.md +8 -0
  107. claude_mpm/commands/mpm-init.md +8 -0
  108. claude_mpm/commands/mpm-monitor.md +8 -0
  109. claude_mpm/commands/mpm-organize.md +8 -0
  110. claude_mpm/commands/mpm-postmortem.md +8 -0
  111. claude_mpm/commands/mpm-session-resume.md +9 -1
  112. claude_mpm/commands/mpm-status.md +8 -0
  113. claude_mpm/commands/mpm-ticket-view.md +8 -0
  114. claude_mpm/commands/mpm-version.md +8 -0
  115. claude_mpm/commands/mpm.md +8 -0
  116. claude_mpm/config/agent_presets.py +8 -7
  117. claude_mpm/constants.py +1 -0
  118. claude_mpm/core/claude_runner.py +2 -2
  119. claude_mpm/core/config.py +5 -0
  120. claude_mpm/core/hook_manager.py +51 -3
  121. claude_mpm/core/interactive_session.py +7 -7
  122. claude_mpm/core/logger.py +10 -7
  123. claude_mpm/core/logging_utils.py +4 -2
  124. claude_mpm/core/output_style_manager.py +31 -13
  125. claude_mpm/core/unified_config.py +54 -8
  126. claude_mpm/core/unified_paths.py +30 -13
  127. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  128. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  129. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cs_tUR18.js → 1WZnGYqX.js} +1 -1
  130. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CDuw-vjf.js → 67pF3qNn.js} +1 -1
  131. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bTOqqlTd.js → 6RxdMKe4.js} +1 -1
  132. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DwBR2MJi.js → 8cZrfX0h.js} +1 -1
  133. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{ZGh7QtNv.js → 9a6T2nm-.js} +1 -1
  134. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D9lljYKQ.js → B443AUzu.js} +1 -1
  135. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{RJiighC3.js → B8AwtY2H.js} +1 -1
  136. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uuIeMWc-.js → BF15LAsF.js} +1 -1
  137. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D3k0OPJN.js → BRcwIQNr.js} +1 -1
  138. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CyWMqx4W.js → BV6nKitt.js} +1 -1
  139. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CiIAseT4.js → BViJ8lZt.js} +5 -5
  140. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CBBdVcY8.js → BcQ-Q0FE.js} +1 -1
  141. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BovzEFCE.js → Bpyvgze_.js} +1 -1
  142. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  143. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  144. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{eNVUfhuA.js → C3rbW_a-.js} +1 -1
  145. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{GYwsonyD.js → C8WYN38h.js} +1 -1
  146. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BIF9m_hv.js → C9I8FlXH.js} +1 -1
  147. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B0uc0UOD.js → CIQcWgO2.js} +3 -3
  148. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Be7GpZd6.js → CIctN7YN.js} +1 -1
  149. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Bh0LDWpI.js → CKrS_JZW.js} +2 -2
  150. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DUrLdbGD.js → CR6P9C4A.js} +1 -1
  151. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7xVLGWV.js → CRRR9MD_.js} +1 -1
  152. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  153. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dhb8PKl3.js → CSXtMOf0.js} +1 -1
  154. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BPYeabCQ.js → CT-sbxSk.js} +1 -1
  155. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{sQeU3Y1z.js → CWm6DJsp.js} +1 -1
  156. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CnA0NrzZ.js → CpqQ1Kzn.js} +1 -1
  157. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4B-KCzX.js → D2nGpDRe.js} +1 -1
  158. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DGkLK5U1.js → D9iCMida.js} +1 -1
  159. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BofRWZRR.js → D9ykgMoY.js} +1 -1
  160. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DmxopI1J.js → DL2Ldur1.js} +1 -1
  161. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C30mlcqg.js → DPfltzjH.js} +1 -1
  162. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Vzk33B_K.js → DR8nis88.js} +2 -2
  163. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DI7hHRFL.js → DUliQN2b.js} +1 -1
  164. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4JcI4KD.js → DXlhR01x.js} +1 -1
  165. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bT1r9zLR.js → D_lyTybS.js} +1 -1
  166. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DZX00Y4g.js → DngoTTgh.js} +1 -1
  167. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzZX-COe.js → DqkmHtDC.js} +1 -1
  168. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7RN905-.js → DsDh8EYs.js} +1 -1
  169. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DLVjFsZ3.js → DypDmXgd.js} +1 -1
  170. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{iEWssX7S.js → IPYC-LnN.js} +1 -1
  171. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  172. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DaimHw_p.js → JpevfAFt.js} +1 -1
  173. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DY1XQ8fi.js → R8CEIRAd.js} +1 -1
  174. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dle-35c7.js → Zxy7qc-l.js} +2 -2
  175. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  176. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C_Usid8X.js → qtd3IeO4.js} +2 -2
  177. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzeYkLYB.js → ulBFON_C.js} +2 -2
  178. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cfqx1Qun.js → wQVh1CoA.js} +1 -1
  179. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/{app.D6-I5TpK.js → app.Dr7t0z2J.js} +2 -2
  180. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  181. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.m1gL8KXf.js → 0.RgBboRvH.js} +1 -1
  182. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{1.CgNOuw-d.js → 1.DG-KkbDf.js} +1 -1
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  184. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
  185. claude_mpm/dashboard/static/svelte-build/index.html +9 -9
  186. claude_mpm/experimental/cli_enhancements.py +2 -1
  187. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  188. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  189. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +486 -0
  190. claude_mpm/hooks/claude_hooks/event_handlers.py +250 -11
  191. claude_mpm/hooks/claude_hooks/hook_handler.py +106 -89
  192. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  193. claude_mpm/hooks/claude_hooks/installer.py +69 -5
  194. claude_mpm/hooks/claude_hooks/response_tracking.py +3 -1
  195. claude_mpm/hooks/claude_hooks/services/connection_manager.py +20 -0
  196. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +14 -77
  197. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +30 -6
  198. claude_mpm/hooks/session_resume_hook.py +85 -1
  199. claude_mpm/init.py +1 -1
  200. claude_mpm/scripts/claude-hook-handler.sh +36 -10
  201. claude_mpm/scripts/start_activity_logging.py +0 -0
  202. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  203. claude_mpm/services/agents/cache_git_manager.py +1 -1
  204. claude_mpm/services/agents/deployment/agent_template_builder.py +8 -0
  205. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  206. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +3 -0
  207. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  208. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  209. claude_mpm/services/agents/sources/git_source_sync_service.py +7 -4
  210. claude_mpm/services/agents/startup_sync.py +5 -2
  211. claude_mpm/services/cli/__init__.py +3 -0
  212. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  213. claude_mpm/services/cli/session_resume_helper.py +10 -2
  214. claude_mpm/services/delegation_detector.py +175 -0
  215. claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
  216. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  217. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  218. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  219. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  220. claude_mpm/services/diagnostics/models.py +14 -1
  221. claude_mpm/services/event_log.py +325 -0
  222. claude_mpm/services/infrastructure/__init__.py +4 -0
  223. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  224. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  225. claude_mpm/services/monitor/daemon_manager.py +15 -4
  226. claude_mpm/services/monitor/management/lifecycle.py +8 -2
  227. claude_mpm/services/monitor/server.py +106 -16
  228. claude_mpm/services/pm_skills_deployer.py +261 -85
  229. claude_mpm/services/skills/git_skill_source_manager.py +75 -10
  230. claude_mpm/services/skills/selective_skill_deployer.py +177 -80
  231. claude_mpm/services/skills/skill_discovery_service.py +57 -3
  232. claude_mpm/services/socketio/handlers/hook.py +14 -7
  233. claude_mpm/services/socketio/server/main.py +12 -4
  234. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  235. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  236. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  237. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  238. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  239. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  240. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  241. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  242. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  243. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  244. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  245. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  246. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  247. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  248. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  249. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  250. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  251. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  252. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  253. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  254. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  255. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  256. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  257. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  258. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  259. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  260. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  261. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  262. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  263. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  264. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  265. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  266. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  267. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  268. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  269. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  270. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  271. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  272. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  273. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  274. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  275. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  276. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  277. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  278. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  279. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  280. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  281. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  282. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  283. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  284. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  285. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  286. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  287. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  288. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  289. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  290. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  291. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  292. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  293. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  294. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  295. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  296. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  297. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  298. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  299. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  300. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  301. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  302. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  303. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  304. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  305. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  306. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  307. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  308. claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
  309. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  310. claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
  311. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  312. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  313. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  314. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  315. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  316. claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
  317. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  318. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  319. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  320. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  321. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  322. claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
  323. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  324. claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
  325. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  326. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  327. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  328. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  329. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  330. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  331. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  332. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  333. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  334. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  335. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  336. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  337. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  338. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  339. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  340. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  341. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  342. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  343. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  344. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  345. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  346. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  347. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  348. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  349. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  350. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  351. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  352. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  353. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  354. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  355. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  356. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  357. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  358. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  359. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  360. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  361. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  362. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  363. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  364. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  365. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  366. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  367. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  368. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  369. claude_mpm/skills/skill_manager.py +4 -4
  370. claude_mpm/utils/agent_dependency_loader.py +103 -4
  371. claude_mpm/utils/robust_installer.py +45 -24
  372. claude_mpm-5.6.1.dist-info/METADATA +391 -0
  373. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/RECORD +377 -166
  374. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +0 -1
  375. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +0 -1
  376. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +0 -1
  377. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +0 -24
  378. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +0 -1
  379. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +0 -1
  380. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +0 -323
  381. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +0 -1
  382. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +0 -1
  383. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  384. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  385. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  386. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  387. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  388. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  389. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  390. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  391. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  392. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  393. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  394. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  395. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  396. claude_mpm-5.4.55.dist-info/METADATA +0 -999
  397. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/WHEEL +0 -0
  398. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/entry_points.txt +0 -0
  399. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/licenses/LICENSE +0 -0
  400. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  401. {claude_mpm-5.4.55.dist-info → claude_mpm-5.6.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,310 @@
1
+ """Commander chat REPL interface."""
2
+
3
+ import asyncio
4
+ from pathlib import Path
5
+ from typing import Optional
6
+
7
+ from prompt_toolkit import PromptSession
8
+ from prompt_toolkit.history import FileHistory
9
+
10
+ from claude_mpm.commander.instance_manager import InstanceManager
11
+ from claude_mpm.commander.llm.openrouter_client import OpenRouterClient
12
+ from claude_mpm.commander.proxy.relay import OutputRelay
13
+ from claude_mpm.commander.session.manager import SessionManager
14
+
15
+ from .commands import Command, CommandParser, CommandType
16
+
17
+
18
+ class CommanderREPL:
19
+ """Interactive REPL for Commander mode."""
20
+
21
+ def __init__(
22
+ self,
23
+ instance_manager: InstanceManager,
24
+ session_manager: SessionManager,
25
+ output_relay: Optional[OutputRelay] = None,
26
+ llm_client: Optional[OpenRouterClient] = None,
27
+ ):
28
+ """Initialize REPL.
29
+
30
+ Args:
31
+ instance_manager: Manages Claude instances.
32
+ session_manager: Manages chat session state.
33
+ output_relay: Optional relay for instance output.
34
+ llm_client: Optional OpenRouter client for chat.
35
+ """
36
+ self.instances = instance_manager
37
+ self.session = session_manager
38
+ self.relay = output_relay
39
+ self.llm = llm_client
40
+ self.parser = CommandParser()
41
+ self._running = False
42
+
43
+ async def run(self) -> None:
44
+ """Start the REPL loop."""
45
+ self._running = True
46
+ self._print_welcome()
47
+
48
+ # Setup history file
49
+ history_path = Path.home() / ".claude-mpm" / "commander_history"
50
+ history_path.parent.mkdir(parents=True, exist_ok=True)
51
+
52
+ prompt = PromptSession(history=FileHistory(str(history_path)))
53
+
54
+ while self._running:
55
+ try:
56
+ user_input = await asyncio.to_thread(prompt.prompt, self._get_prompt())
57
+ await self._handle_input(user_input.strip())
58
+ except KeyboardInterrupt:
59
+ continue
60
+ except EOFError:
61
+ break
62
+
63
+ self._print("\nGoodbye!")
64
+
65
+ async def _handle_input(self, input_text: str) -> None:
66
+ """Handle user input - command or natural language.
67
+
68
+ Args:
69
+ input_text: User input string.
70
+ """
71
+ if not input_text:
72
+ return
73
+
74
+ # Check if it's a built-in command
75
+ command = self.parser.parse(input_text)
76
+ if command:
77
+ await self._execute_command(command)
78
+ else:
79
+ # Natural language - send to connected instance
80
+ await self._send_to_instance(input_text)
81
+
82
+ async def _execute_command(self, cmd: Command) -> None:
83
+ """Execute a built-in command.
84
+
85
+ Args:
86
+ cmd: Parsed command.
87
+ """
88
+ handlers = {
89
+ CommandType.LIST: self._cmd_list,
90
+ CommandType.START: self._cmd_start,
91
+ CommandType.STOP: self._cmd_stop,
92
+ CommandType.CONNECT: self._cmd_connect,
93
+ CommandType.DISCONNECT: self._cmd_disconnect,
94
+ CommandType.STATUS: self._cmd_status,
95
+ CommandType.HELP: self._cmd_help,
96
+ CommandType.EXIT: self._cmd_exit,
97
+ }
98
+ handler = handlers.get(cmd.type)
99
+ if handler:
100
+ await handler(cmd.args)
101
+
102
+ async def _cmd_list(self, args: list[str]) -> None:
103
+ """List active instances."""
104
+ instances = self.instances.list_instances()
105
+ if not instances:
106
+ self._print("No active instances.")
107
+ else:
108
+ self._print("Active instances:")
109
+ for inst in instances:
110
+ status = (
111
+ "→" if inst.name == self.session.context.connected_instance else " "
112
+ )
113
+ git_info = f" [{inst.git_branch}]" if inst.git_branch else ""
114
+ self._print(
115
+ f" {status} {inst.name} ({inst.framework}){git_info} - {inst.project_path}"
116
+ )
117
+
118
+ async def _cmd_start(self, args: list[str]) -> None:
119
+ """Start a new instance: start <path> [--framework cc|mpm] [--name name]."""
120
+ if not args:
121
+ self._print("Usage: start <path> [--framework cc|mpm] [--name name]")
122
+ return
123
+
124
+ # Parse arguments
125
+ project_path = Path(args[0]).expanduser().resolve()
126
+ framework = "cc" # default
127
+ name = project_path.name # default
128
+
129
+ # Parse optional flags
130
+ i = 1
131
+ while i < len(args):
132
+ if args[i] == "--framework" and i + 1 < len(args):
133
+ framework = args[i + 1]
134
+ i += 2
135
+ elif args[i] == "--name" and i + 1 < len(args):
136
+ name = args[i + 1]
137
+ i += 2
138
+ else:
139
+ i += 1
140
+
141
+ # Validate path
142
+ if not project_path.exists():
143
+ self._print(f"Error: Path does not exist: {project_path}")
144
+ return
145
+
146
+ if not project_path.is_dir():
147
+ self._print(f"Error: Path is not a directory: {project_path}")
148
+ return
149
+
150
+ # Start instance
151
+ try:
152
+ instance = await self.instances.start_instance(
153
+ name, project_path, framework
154
+ )
155
+ self._print(f"Started instance '{name}' ({framework}) at {project_path}")
156
+ self._print(f"Tmux: {instance.tmux_session}:{instance.pane_target}")
157
+ except Exception as e:
158
+ self._print(f"Error starting instance: {e}")
159
+
160
+ async def _cmd_stop(self, args: list[str]) -> None:
161
+ """Stop an instance: stop <name>."""
162
+ if not args:
163
+ self._print("Usage: stop <instance-name>")
164
+ return
165
+
166
+ name = args[0]
167
+
168
+ try:
169
+ await self.instances.stop_instance(name)
170
+ self._print(f"Stopped instance '{name}'")
171
+
172
+ # Disconnect if we were connected
173
+ if self.session.context.connected_instance == name:
174
+ self.session.disconnect()
175
+ except Exception as e:
176
+ self._print(f"Error stopping instance: {e}")
177
+
178
+ async def _cmd_connect(self, args: list[str]) -> None:
179
+ """Connect to an instance: connect <name>."""
180
+ if not args:
181
+ self._print("Usage: connect <instance-name>")
182
+ return
183
+
184
+ name = args[0]
185
+ inst = self.instances.get_instance(name)
186
+ if not inst:
187
+ self._print(f"Instance '{name}' not found")
188
+ return
189
+
190
+ self.session.connect_to(name)
191
+ self._print(f"Connected to {name}")
192
+
193
+ async def _cmd_disconnect(self, args: list[str]) -> None:
194
+ """Disconnect from current instance."""
195
+ if not self.session.context.is_connected:
196
+ self._print("Not connected to any instance")
197
+ return
198
+
199
+ name = self.session.context.connected_instance
200
+ self.session.disconnect()
201
+ self._print(f"Disconnected from {name}")
202
+
203
+ async def _cmd_status(self, args: list[str]) -> None:
204
+ """Show status of current session."""
205
+ if self.session.context.is_connected:
206
+ name = self.session.context.connected_instance
207
+ inst = self.instances.get_instance(name)
208
+ if inst:
209
+ self._print(f"Connected to: {name}")
210
+ self._print(f" Framework: {inst.framework}")
211
+ self._print(f" Project: {inst.project_path}")
212
+ if inst.git_branch:
213
+ self._print(f" Git: {inst.git_branch} ({inst.git_status})")
214
+ self._print(f" Tmux: {inst.tmux_session}:{inst.pane_target}")
215
+ else:
216
+ self._print(f"Connected to: {name} (instance no longer exists)")
217
+ else:
218
+ self._print("Not connected to any instance")
219
+
220
+ self._print(f"Messages in history: {len(self.session.context.messages)}")
221
+
222
+ async def _cmd_help(self, args: list[str]) -> None:
223
+ """Show help message."""
224
+ help_text = """
225
+ Commander Commands:
226
+ list, ls, instances List active instances
227
+ start <path> Start new instance at path
228
+ --framework <cc|mpm> Specify framework (default: cc)
229
+ --name <name> Specify instance name (default: dir name)
230
+ stop <name> Stop an instance
231
+ connect <name> Connect to an instance
232
+ disconnect Disconnect from current instance
233
+ status Show current session status
234
+ help Show this help message
235
+ exit, quit, q Exit Commander
236
+
237
+ Natural Language:
238
+ When connected to an instance, any input that is not a built-in
239
+ command will be sent to the connected instance as a message.
240
+
241
+ Examples:
242
+ start ~/myproject --framework cc --name myapp
243
+ connect myapp
244
+ Fix the authentication bug in login.py
245
+ disconnect
246
+ exit
247
+ """
248
+ self._print(help_text)
249
+
250
+ async def _cmd_exit(self, args: list[str]) -> None:
251
+ """Exit the REPL."""
252
+ self._running = False
253
+
254
+ async def _send_to_instance(self, message: str) -> None:
255
+ """Send natural language to connected instance.
256
+
257
+ Args:
258
+ message: User message to send.
259
+ """
260
+ if not self.session.context.is_connected:
261
+ self._print("Not connected to any instance. Use 'connect <name>' first.")
262
+ return
263
+
264
+ name = self.session.context.connected_instance
265
+ inst = self.instances.get_instance(name)
266
+ if not inst:
267
+ self._print(f"Instance '{name}' no longer exists")
268
+ self.session.disconnect()
269
+ return
270
+
271
+ self._print(f"[Sending to {name}...]")
272
+ await self.instances.send_to_instance(name, message)
273
+ self.session.add_user_message(message)
274
+
275
+ # Wait for and display response
276
+ if self.relay:
277
+ try:
278
+ output = await self.relay.get_latest_output(
279
+ name, inst.pane_target, context=message
280
+ )
281
+ self._print(f"\n[Response from {name}]:\n{output}")
282
+ self.session.add_assistant_message(output)
283
+ except Exception as e:
284
+ self._print(f"\n[Error getting response: {e}]")
285
+
286
+ def _get_prompt(self) -> str:
287
+ """Get prompt string based on connection state.
288
+
289
+ Returns:
290
+ Prompt string for input.
291
+ """
292
+ if self.session.context.is_connected:
293
+ return f"Commander ({self.session.context.connected_instance})> "
294
+ return "Commander> "
295
+
296
+ def _print(self, msg: str) -> None:
297
+ """Print message to console.
298
+
299
+ Args:
300
+ msg: Message to print.
301
+ """
302
+ print(msg)
303
+
304
+ def _print_welcome(self) -> None:
305
+ """Print welcome message."""
306
+ print("╔══════════════════════════════════════════╗")
307
+ print("║ MPM Commander - Interactive Mode ║")
308
+ print("╚══════════════════════════════════════════╝")
309
+ print("Type 'help' for commands, or natural language to chat.")
310
+ print()
@@ -0,0 +1,49 @@
1
+ """Daemon configuration for MPM Commander.
2
+
3
+ This module defines configuration structures for the Commander daemon,
4
+ including server settings, resource limits, and persistence options.
5
+ """
6
+
7
+ from dataclasses import dataclass
8
+ from pathlib import Path
9
+
10
+
11
+ @dataclass
12
+ class DaemonConfig:
13
+ """Configuration for Commander daemon.
14
+
15
+ Attributes:
16
+ host: API server bind address
17
+ port: API server port
18
+ log_level: Logging level (DEBUG, INFO, WARNING, ERROR)
19
+ state_dir: Directory for state persistence
20
+ max_projects: Maximum concurrent projects
21
+ healthcheck_interval: Healthcheck interval in seconds
22
+ save_interval: State persistence interval in seconds
23
+ poll_interval: Event polling interval in seconds
24
+
25
+ Example:
26
+ >>> config = DaemonConfig(port=8765, log_level="DEBUG")
27
+ >>> config.state_dir
28
+ PosixPath('/Users/user/.claude-mpm/commander')
29
+ """
30
+
31
+ host: str = "127.0.0.1"
32
+ port: int = 8765
33
+ log_level: str = "INFO"
34
+ state_dir: Path = Path.home() / ".claude-mpm" / "commander"
35
+ max_projects: int = 10
36
+ healthcheck_interval: int = 30
37
+ save_interval: int = 30
38
+ poll_interval: float = 2.0
39
+
40
+ def __post_init__(self):
41
+ """Ensure state_dir is a Path object and create if needed."""
42
+ if isinstance(self.state_dir, str):
43
+ self.state_dir = Path(self.state_dir)
44
+
45
+ # Expand user home directory
46
+ self.state_dir = self.state_dir.expanduser()
47
+
48
+ # Create state directory if it doesn't exist
49
+ self.state_dir.mkdir(parents=True, exist_ok=True)
@@ -0,0 +1,115 @@
1
+ """Project configuration loading for MPM Commander.
2
+
3
+ This module handles loading configuration from a project's .claude-mpm/
4
+ directory, including YAML config files and directory structure validation.
5
+ """
6
+
7
+ import logging
8
+ from pathlib import Path
9
+ from typing import Any, Dict, Optional
10
+
11
+ import yaml
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ def load_project_config(project_path: str) -> Optional[Dict[str, Any]]:
17
+ """Load configuration from project's .claude-mpm/ directory.
18
+
19
+ Looks for:
20
+ - .claude-mpm/configuration.yaml (main config file)
21
+ - .claude-mpm/agents/ (directory exists check)
22
+ - .claude-mpm/skills/ (directory exists check)
23
+ - .claude-mpm/memories/ (directory exists check)
24
+
25
+ Args:
26
+ project_path: Absolute path to project directory
27
+
28
+ Returns:
29
+ Dict with config data and directory flags, or None if no config found.
30
+ Example structure:
31
+ {
32
+ 'configuration': {...}, # Parsed YAML config
33
+ 'has_agents': True,
34
+ 'has_skills': False,
35
+ 'has_memories': True,
36
+ }
37
+
38
+ Raises:
39
+ yaml.YAMLError: If configuration.yaml is malformed
40
+
41
+ Example:
42
+ >>> config = load_project_config("/Users/masa/Projects/my-app")
43
+ >>> if config:
44
+ ... print(f"Agents dir: {config['has_agents']}")
45
+ ... print(f"Config: {config.get('configuration', {})}")
46
+ Agents dir: True
47
+ Config: {'default_adapter': 'linear', ...}
48
+ """
49
+ proj_path = Path(project_path)
50
+ config_dir = proj_path / ".claude-mpm"
51
+
52
+ # Check if .claude-mpm/ directory exists
53
+ if not config_dir.exists() or not config_dir.is_dir():
54
+ logger.debug("No .claude-mpm/ directory found in project: %s", project_path)
55
+ return None
56
+
57
+ logger.info("Loading configuration from %s", config_dir)
58
+
59
+ result: Dict[str, Any] = {
60
+ "configuration": {},
61
+ "has_agents": False,
62
+ "has_skills": False,
63
+ "has_memories": False,
64
+ }
65
+
66
+ # Load configuration.yaml if present
67
+ config_file = config_dir / "configuration.yaml"
68
+ if config_file.exists() and config_file.is_file():
69
+ try:
70
+ with open(config_file, encoding="utf-8") as f:
71
+ config_data = yaml.safe_load(f)
72
+ result["configuration"] = config_data or {}
73
+ logger.info(
74
+ "Loaded configuration.yaml with %d top-level keys",
75
+ len(result["configuration"]),
76
+ )
77
+ except yaml.YAMLError as e:
78
+ logger.error(
79
+ "Failed to parse configuration.yaml in %s: %s",
80
+ config_dir,
81
+ e,
82
+ )
83
+ raise
84
+ except Exception as e:
85
+ logger.warning(
86
+ "Failed to read configuration.yaml in %s: %s",
87
+ config_dir,
88
+ e,
89
+ )
90
+ # Continue with empty config
91
+
92
+ # Check for subdirectories
93
+ agents_dir = config_dir / "agents"
94
+ result["has_agents"] = agents_dir.exists() and agents_dir.is_dir()
95
+ if result["has_agents"]:
96
+ logger.debug("Found agents directory: %s", agents_dir)
97
+
98
+ skills_dir = config_dir / "skills"
99
+ result["has_skills"] = skills_dir.exists() and skills_dir.is_dir()
100
+ if result["has_skills"]:
101
+ logger.debug("Found skills directory: %s", skills_dir)
102
+
103
+ memories_dir = config_dir / "memories"
104
+ result["has_memories"] = memories_dir.exists() and memories_dir.is_dir()
105
+ if result["has_memories"]:
106
+ logger.debug("Found memories directory: %s", memories_dir)
107
+
108
+ logger.info(
109
+ "Project config loaded: agents=%s, skills=%s, memories=%s",
110
+ result["has_agents"],
111
+ result["has_skills"],
112
+ result["has_memories"],
113
+ )
114
+
115
+ return result