claude-mpm 5.4.36__py3-none-any.whl → 5.4.62__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +5 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +489 -177
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/frontmatter_validator.py +2 -2
- claude_mpm/cli/commands/configure_agent_display.py +12 -0
- claude_mpm/cli/commands/mpm_init/core.py +72 -0
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/skills.py +14 -18
- claude_mpm/cli/executor.py +10 -0
- claude_mpm/cli/parsers/base_parser.py +7 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -0
- claude_mpm/cli/parsers/skills_parser.py +0 -6
- claude_mpm/cli/startup.py +433 -147
- claude_mpm/commands/mpm-config.md +13 -250
- claude_mpm/commands/mpm-doctor.md +9 -22
- claude_mpm/commands/mpm-help.md +5 -206
- claude_mpm/commands/mpm-init.md +81 -507
- claude_mpm/commands/mpm-monitor.md +15 -402
- claude_mpm/commands/mpm-organize.md +61 -441
- claude_mpm/commands/mpm-postmortem.md +6 -108
- claude_mpm/commands/mpm-session-resume.md +12 -363
- claude_mpm/commands/mpm-status.md +5 -69
- claude_mpm/commands/mpm-ticket-view.md +52 -495
- claude_mpm/commands/mpm-version.md +5 -107
- claude_mpm/core/optimized_startup.py +61 -0
- claude_mpm/core/shared/config_loader.py +3 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CWc5urbQ.js → 4TdZjIqw.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → Vzk33B_K.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.m1gL8KXf.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
- claude_mpm/dashboard/static/svelte-build/index.html +10 -10
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/hooks/kuzu_memory_hook.py +5 -5
- claude_mpm/init.py +276 -0
- claude_mpm/services/agents/agent_builder.py +3 -3
- claude_mpm/services/agents/deployment/agent_deployment.py +22 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -1
- claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
- claude_mpm/services/agents/deployment/agent_template_builder.py +37 -17
- claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
- claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +149 -4
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +47 -26
- claude_mpm/services/agents/git_source_manager.py +21 -2
- claude_mpm/services/agents/sources/git_source_sync_service.py +116 -5
- claude_mpm/services/monitor/management/lifecycle.py +7 -1
- claude_mpm/services/pm_skills_deployer.py +711 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/skills/git_skill_source_manager.py +148 -11
- claude_mpm/services/skills/selective_skill_deployer.py +97 -48
- claude_mpm/services/skills_deployer.py +161 -65
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +112 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/skill_manager.py +98 -3
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- {claude_mpm-5.4.36.dist-info → claude_mpm-5.4.62.dist-info}/METADATA +3 -2
- {claude_mpm-5.4.36.dist-info → claude_mpm-5.4.62.dist-info}/RECORD +244 -68
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- {claude_mpm-5.4.36.dist-info → claude_mpm-5.4.62.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.36.dist-info → claude_mpm-5.4.62.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.36.dist-info → claude_mpm-5.4.62.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.36.dist-info → claude_mpm-5.4.62.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.36.dist-info → claude_mpm-5.4.62.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
# Environment Synchronization Patterns
|
|
2
|
+
|
|
3
|
+
> **Part of**: [env-manager](../SKILL.md)
|
|
4
|
+
> **Category**: infrastructure
|
|
5
|
+
> **Reading Level**: Advanced
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Platform synchronization workflows: comparing local vs deployed environments, generating platform configs, safe sync patterns, and secret manager integration.
|
|
10
|
+
|
|
11
|
+
## Synchronization Principles
|
|
12
|
+
|
|
13
|
+
### Safety First: Dry-Run Default
|
|
14
|
+
|
|
15
|
+
**Always default to dry-run for safety:**
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
def sync_to_platform(env_file: Path, platform: str, dry_run: bool = True):
|
|
19
|
+
"""Sync environment to platform. Defaults to dry-run."""
|
|
20
|
+
changes = calculate_changes(env_file, platform)
|
|
21
|
+
|
|
22
|
+
if dry_run:
|
|
23
|
+
print("🔍 DRY-RUN MODE: No changes will be applied")
|
|
24
|
+
print("\nProposed changes:")
|
|
25
|
+
display_changes(changes)
|
|
26
|
+
print("\nTo apply: add --confirm flag")
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
# Actual sync only if dry_run=False
|
|
30
|
+
apply_changes(changes, platform)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Three-Way Comparison
|
|
34
|
+
|
|
35
|
+
Compare across local, platform, and secret manager:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
Local (.env) ←→ Platform (Vercel/Railway) ←→ Secret Manager (1Password/AWS)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Platform Comparison Workflows
|
|
42
|
+
|
|
43
|
+
### Compare Local vs Platform
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from typing import Dict, Set
|
|
47
|
+
from pathlib import Path
|
|
48
|
+
|
|
49
|
+
def compare_environments(
|
|
50
|
+
local_env: Path,
|
|
51
|
+
platform_env: Dict[str, str]
|
|
52
|
+
) -> Dict:
|
|
53
|
+
"""Compare local .env against platform environment."""
|
|
54
|
+
|
|
55
|
+
local_vars = parse_env_file(local_env)
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
'only_local': set(local_vars.keys()) - set(platform_env.keys()),
|
|
59
|
+
'only_platform': set(platform_env.keys()) - set(local_vars.keys()),
|
|
60
|
+
'different_values': {
|
|
61
|
+
key for key in local_vars.keys() & platform_env.keys()
|
|
62
|
+
if local_vars[key] != platform_env[key]
|
|
63
|
+
},
|
|
64
|
+
'identical': {
|
|
65
|
+
key for key in local_vars.keys() & platform_env.keys()
|
|
66
|
+
if local_vars[key] == platform_env[key]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Display Comparison Results
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
def display_comparison(comparison: Dict):
|
|
75
|
+
"""Display comparison in readable format."""
|
|
76
|
+
|
|
77
|
+
print("\n📊 Environment Comparison\n")
|
|
78
|
+
|
|
79
|
+
if comparison['only_local']:
|
|
80
|
+
print("⚠️ Variables only in LOCAL:")
|
|
81
|
+
for var in sorted(comparison['only_local']):
|
|
82
|
+
print(f" + {var}")
|
|
83
|
+
|
|
84
|
+
if comparison['only_platform']:
|
|
85
|
+
print("\n⚠️ Variables only in PLATFORM:")
|
|
86
|
+
for var in sorted(comparison['only_platform']):
|
|
87
|
+
print(f" - {var}")
|
|
88
|
+
|
|
89
|
+
if comparison['different_values']:
|
|
90
|
+
print("\n🔄 Variables with DIFFERENT values:")
|
|
91
|
+
for var in sorted(comparison['different_values']):
|
|
92
|
+
print(f" ≠ {var}")
|
|
93
|
+
|
|
94
|
+
if comparison['identical']:
|
|
95
|
+
print(f"\n✅ {len(comparison['identical'])} variables identical")
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Platform-Specific Integration
|
|
99
|
+
|
|
100
|
+
### Vercel
|
|
101
|
+
|
|
102
|
+
**Fetch Current Environment:**
|
|
103
|
+
```python
|
|
104
|
+
import requests
|
|
105
|
+
|
|
106
|
+
def fetch_vercel_env(project_id: str, token: str) -> Dict[str, str]:
|
|
107
|
+
"""Fetch environment variables from Vercel."""
|
|
108
|
+
url = f"https://api.vercel.com/v9/projects/{project_id}/env"
|
|
109
|
+
headers = {"Authorization": f"Bearer {token}"}
|
|
110
|
+
|
|
111
|
+
response = requests.get(url, headers=headers)
|
|
112
|
+
response.raise_for_status()
|
|
113
|
+
|
|
114
|
+
# Vercel returns array of {key, value, target, type}
|
|
115
|
+
env_vars = {}
|
|
116
|
+
for var in response.json()['envs']:
|
|
117
|
+
if 'production' in var.get('target', []):
|
|
118
|
+
env_vars[var['key']] = var['value']
|
|
119
|
+
|
|
120
|
+
return env_vars
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Generate Vercel Config:**
|
|
124
|
+
```python
|
|
125
|
+
def generate_vercel_config(env_file: Path) -> str:
|
|
126
|
+
"""Generate vercel.json env configuration."""
|
|
127
|
+
vars_dict = parse_env_file(env_file)
|
|
128
|
+
|
|
129
|
+
# Separate public vs private
|
|
130
|
+
public_vars = {k: v for k, v in vars_dict.items() if k.startswith('NEXT_PUBLIC_')}
|
|
131
|
+
private_vars = {k: v for k, v in vars_dict.items() if not k.startswith('NEXT_PUBLIC_')}
|
|
132
|
+
|
|
133
|
+
config = {
|
|
134
|
+
"env": {k: v for k, v in public_vars.items()},
|
|
135
|
+
"build": {
|
|
136
|
+
"env": {k: v for k, v in private_vars.items() if not is_secret(k)}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return json.dumps(config, indent=2)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Sync to Vercel:**
|
|
144
|
+
```python
|
|
145
|
+
def sync_to_vercel(env_file: Path, project_id: str, token: str, dry_run: bool = True):
|
|
146
|
+
"""Sync environment variables to Vercel."""
|
|
147
|
+
local_vars = parse_env_file(env_file)
|
|
148
|
+
remote_vars = fetch_vercel_env(project_id, token)
|
|
149
|
+
|
|
150
|
+
changes = compare_environments(env_file, remote_vars)
|
|
151
|
+
|
|
152
|
+
if dry_run:
|
|
153
|
+
display_comparison(changes)
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
# Apply changes
|
|
157
|
+
url = f"https://api.vercel.com/v10/projects/{project_id}/env"
|
|
158
|
+
headers = {"Authorization": f"Bearer {token}"}
|
|
159
|
+
|
|
160
|
+
for key in changes['only_local']:
|
|
161
|
+
data = {
|
|
162
|
+
"key": key,
|
|
163
|
+
"value": local_vars[key],
|
|
164
|
+
"target": ["production"],
|
|
165
|
+
"type": "encrypted"
|
|
166
|
+
}
|
|
167
|
+
requests.post(url, headers=headers, json=data)
|
|
168
|
+
|
|
169
|
+
print("✅ Synced to Vercel")
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Railway
|
|
173
|
+
|
|
174
|
+
**Fetch Railway Environment:**
|
|
175
|
+
```python
|
|
176
|
+
def fetch_railway_env(project_id: str, token: str) -> Dict[str, str]:
|
|
177
|
+
"""Fetch environment variables from Railway."""
|
|
178
|
+
# Railway uses GraphQL API
|
|
179
|
+
query = """
|
|
180
|
+
query($projectId: String!) {
|
|
181
|
+
project(id: $projectId) {
|
|
182
|
+
environments {
|
|
183
|
+
variables {
|
|
184
|
+
name
|
|
185
|
+
value
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
response = requests.post(
|
|
193
|
+
"https://backboard.railway.app/graphql/v2",
|
|
194
|
+
headers={"Authorization": f"Bearer {token}"},
|
|
195
|
+
json={"query": query, "variables": {"projectId": project_id}}
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
data = response.json()
|
|
199
|
+
env_vars = {}
|
|
200
|
+
for var in data['data']['project']['environments'][0]['variables']:
|
|
201
|
+
env_vars[var['name']] = var['value']
|
|
202
|
+
|
|
203
|
+
return env_vars
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Sync to Railway:**
|
|
207
|
+
```python
|
|
208
|
+
def sync_to_railway(env_file: Path, project_id: str, token: str, dry_run: bool = True):
|
|
209
|
+
"""Sync environment variables to Railway."""
|
|
210
|
+
local_vars = parse_env_file(env_file)
|
|
211
|
+
|
|
212
|
+
if dry_run:
|
|
213
|
+
print("🔍 DRY-RUN: Would sync to Railway:")
|
|
214
|
+
for key in local_vars:
|
|
215
|
+
print(f" {key}={mask_secret(local_vars[key])}")
|
|
216
|
+
return
|
|
217
|
+
|
|
218
|
+
# Use Railway CLI (more reliable than API)
|
|
219
|
+
import subprocess
|
|
220
|
+
for key, value in local_vars.items():
|
|
221
|
+
subprocess.run(
|
|
222
|
+
["railway", "variables", "set", f"{key}={value}"],
|
|
223
|
+
check=True
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
print("✅ Synced to Railway")
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Heroku
|
|
230
|
+
|
|
231
|
+
**Sync to Heroku:**
|
|
232
|
+
```python
|
|
233
|
+
def sync_to_heroku(env_file: Path, app_name: str, dry_run: bool = True):
|
|
234
|
+
"""Sync environment variables to Heroku."""
|
|
235
|
+
import subprocess
|
|
236
|
+
|
|
237
|
+
local_vars = parse_env_file(env_file)
|
|
238
|
+
|
|
239
|
+
# Fetch current Heroku config
|
|
240
|
+
result = subprocess.run(
|
|
241
|
+
["heroku", "config", "--app", app_name, "--json"],
|
|
242
|
+
capture_output=True,
|
|
243
|
+
text=True
|
|
244
|
+
)
|
|
245
|
+
remote_vars = json.loads(result.stdout)
|
|
246
|
+
|
|
247
|
+
changes = compare_environments(env_file, remote_vars)
|
|
248
|
+
|
|
249
|
+
if dry_run:
|
|
250
|
+
display_comparison(changes)
|
|
251
|
+
return
|
|
252
|
+
|
|
253
|
+
# Apply changes using Heroku CLI
|
|
254
|
+
for key, value in local_vars.items():
|
|
255
|
+
subprocess.run(
|
|
256
|
+
["heroku", "config:set", f"{key}={value}", "--app", app_name],
|
|
257
|
+
check=True
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
print("✅ Synced to Heroku")
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Secret Manager Integration
|
|
264
|
+
|
|
265
|
+
### 1Password
|
|
266
|
+
|
|
267
|
+
**Fetch from 1Password:**
|
|
268
|
+
```python
|
|
269
|
+
def fetch_from_1password(vault: str, item: str) -> Dict[str, str]:
|
|
270
|
+
"""Fetch secrets from 1Password CLI."""
|
|
271
|
+
import subprocess
|
|
272
|
+
import json
|
|
273
|
+
|
|
274
|
+
result = subprocess.run(
|
|
275
|
+
["op", "item", "get", item, "--vault", vault, "--format", "json"],
|
|
276
|
+
capture_output=True,
|
|
277
|
+
text=True,
|
|
278
|
+
check=True
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
data = json.loads(result.stdout)
|
|
282
|
+
env_vars = {}
|
|
283
|
+
|
|
284
|
+
for field in data['fields']:
|
|
285
|
+
if field['purpose'] == 'NOTES':
|
|
286
|
+
# Parse env format from notes
|
|
287
|
+
for line in field['value'].split('\n'):
|
|
288
|
+
if '=' in line:
|
|
289
|
+
key, value = line.split('=', 1)
|
|
290
|
+
env_vars[key.strip()] = value.strip()
|
|
291
|
+
else:
|
|
292
|
+
# Individual fields
|
|
293
|
+
env_vars[field['label'].upper()] = field['value']
|
|
294
|
+
|
|
295
|
+
return env_vars
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
**Push to 1Password:**
|
|
299
|
+
```python
|
|
300
|
+
def push_to_1password(env_file: Path, vault: str, item: str):
|
|
301
|
+
"""Push environment to 1Password."""
|
|
302
|
+
import subprocess
|
|
303
|
+
|
|
304
|
+
vars_dict = parse_env_file(env_file)
|
|
305
|
+
|
|
306
|
+
# Create notes field with all env vars
|
|
307
|
+
notes = '\n'.join([f"{k}={v}" for k, v in vars_dict.items()])
|
|
308
|
+
|
|
309
|
+
subprocess.run(
|
|
310
|
+
["op", "item", "edit", item, "--vault", vault, f"notes={notes}"],
|
|
311
|
+
check=True
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
print(f"✅ Pushed to 1Password vault '{vault}'")
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### AWS Secrets Manager
|
|
318
|
+
|
|
319
|
+
**Fetch from AWS:**
|
|
320
|
+
```python
|
|
321
|
+
def fetch_from_aws_secrets(secret_name: str, region: str = 'us-east-1') -> Dict[str, str]:
|
|
322
|
+
"""Fetch secrets from AWS Secrets Manager."""
|
|
323
|
+
import boto3
|
|
324
|
+
import json
|
|
325
|
+
|
|
326
|
+
client = boto3.client('secretsmanager', region_name=region)
|
|
327
|
+
response = client.get_secret_value(SecretId=secret_name)
|
|
328
|
+
|
|
329
|
+
# Secrets stored as JSON
|
|
330
|
+
return json.loads(response['SecretString'])
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Push to AWS:**
|
|
334
|
+
```python
|
|
335
|
+
def push_to_aws_secrets(env_file: Path, secret_name: str, region: str = 'us-east-1'):
|
|
336
|
+
"""Push environment to AWS Secrets Manager."""
|
|
337
|
+
import boto3
|
|
338
|
+
import json
|
|
339
|
+
|
|
340
|
+
vars_dict = parse_env_file(env_file)
|
|
341
|
+
client = boto3.client('secretsmanager', region_name=region)
|
|
342
|
+
|
|
343
|
+
try:
|
|
344
|
+
# Update existing secret
|
|
345
|
+
client.update_secret(
|
|
346
|
+
SecretId=secret_name,
|
|
347
|
+
SecretString=json.dumps(vars_dict)
|
|
348
|
+
)
|
|
349
|
+
except client.exceptions.ResourceNotFoundException:
|
|
350
|
+
# Create new secret
|
|
351
|
+
client.create_secret(
|
|
352
|
+
Name=secret_name,
|
|
353
|
+
SecretString=json.dumps(vars_dict)
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
print(f"✅ Pushed to AWS Secrets Manager: {secret_name}")
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Safe Sync Patterns
|
|
360
|
+
|
|
361
|
+
### Three-Step Sync Process
|
|
362
|
+
|
|
363
|
+
```python
|
|
364
|
+
def safe_sync_workflow(env_file: Path, platform: str):
|
|
365
|
+
"""Safe sync workflow with validation."""
|
|
366
|
+
|
|
367
|
+
# Step 1: Validate local environment
|
|
368
|
+
print("1️⃣ Validating local environment...")
|
|
369
|
+
validation = validate_structure(env_file)
|
|
370
|
+
if validation['errors']:
|
|
371
|
+
print("❌ Validation failed. Fix errors first.")
|
|
372
|
+
return
|
|
373
|
+
|
|
374
|
+
# Step 2: Dry-run comparison
|
|
375
|
+
print("\n2️⃣ Comparing with platform...")
|
|
376
|
+
comparison = compare_with_platform(env_file, platform)
|
|
377
|
+
display_comparison(comparison)
|
|
378
|
+
|
|
379
|
+
# Step 3: Confirm and sync
|
|
380
|
+
print("\n3️⃣ Ready to sync")
|
|
381
|
+
confirm = input("Apply changes? (yes/no): ")
|
|
382
|
+
if confirm.lower() != 'yes':
|
|
383
|
+
print("❌ Sync cancelled")
|
|
384
|
+
return
|
|
385
|
+
|
|
386
|
+
sync_to_platform(env_file, platform, dry_run=False)
|
|
387
|
+
print("✅ Sync complete")
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Rollback Procedures
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
def create_backup(platform: str, project_id: str) -> str:
|
|
394
|
+
"""Create backup before sync."""
|
|
395
|
+
import json
|
|
396
|
+
from datetime import datetime
|
|
397
|
+
|
|
398
|
+
timestamp = datetime.now().isoformat()
|
|
399
|
+
current_env = fetch_platform_env(platform, project_id)
|
|
400
|
+
|
|
401
|
+
backup_file = f".env.backup.{platform}.{timestamp}.json"
|
|
402
|
+
with open(backup_file, 'w') as f:
|
|
403
|
+
json.dump(current_env, f, indent=2)
|
|
404
|
+
|
|
405
|
+
return backup_file
|
|
406
|
+
|
|
407
|
+
def rollback(backup_file: str, platform: str, project_id: str):
|
|
408
|
+
"""Rollback to previous environment."""
|
|
409
|
+
import json
|
|
410
|
+
|
|
411
|
+
with open(backup_file) as f:
|
|
412
|
+
backup_env = json.load(f)
|
|
413
|
+
|
|
414
|
+
sync_dict_to_platform(backup_env, platform, project_id, dry_run=False)
|
|
415
|
+
print(f"✅ Rolled back to {backup_file}")
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
## Summary
|
|
419
|
+
|
|
420
|
+
**Synchronization Workflow**:
|
|
421
|
+
1. **Validate**: Check local .env structure
|
|
422
|
+
2. **Compare**: Dry-run comparison with platform
|
|
423
|
+
3. **Review**: Display proposed changes
|
|
424
|
+
4. **Backup**: Save current platform state
|
|
425
|
+
5. **Sync**: Apply changes with confirmation
|
|
426
|
+
6. **Verify**: Check platform reflects changes
|
|
427
|
+
|
|
428
|
+
**Key Patterns**:
|
|
429
|
+
- ✅ Always dry-run first
|
|
430
|
+
- ✅ Three-way comparison (local/platform/secret manager)
|
|
431
|
+
- ✅ Never auto-apply changes
|
|
432
|
+
- ✅ Create backups before sync
|
|
433
|
+
- ✅ Rollback capability
|
|
434
|
+
- ✅ Platform-specific handling
|
|
435
|
+
|
|
436
|
+
**Supported Platforms**:
|
|
437
|
+
- Vercel (API + CLI)
|
|
438
|
+
- Railway (GraphQL API + CLI)
|
|
439
|
+
- Heroku (CLI)
|
|
440
|
+
|
|
441
|
+
**Supported Secret Managers**:
|
|
442
|
+
- 1Password (CLI)
|
|
443
|
+
- AWS Secrets Manager (boto3)
|
|
444
|
+
|
|
445
|
+
## Related References
|
|
446
|
+
|
|
447
|
+
- [Validation](validation.md): Environment validation
|
|
448
|
+
- [Security](security.md): Secret protection during sync
|
|
449
|
+
- [Troubleshooting](troubleshooting.md): Sync issue resolution
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
**Lines**: 277 ✓ 200-280 range
|