claude-mpm 5.1.9__py3-none-any.whl → 5.4.22__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 (176) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +4 -0
  3. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +1 -1
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +290 -34
  5. claude_mpm/agents/agent_loader.py +13 -44
  6. claude_mpm/agents/templates/circuit-breakers.md +138 -1
  7. claude_mpm/cli/__main__.py +4 -0
  8. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  9. claude_mpm/cli/commands/agent_state_manager.py +8 -17
  10. claude_mpm/cli/commands/agents.py +0 -31
  11. claude_mpm/cli/commands/auto_configure.py +210 -25
  12. claude_mpm/cli/commands/config.py +88 -2
  13. claude_mpm/cli/commands/configure.py +1097 -158
  14. claude_mpm/cli/commands/configure_agent_display.py +15 -6
  15. claude_mpm/cli/commands/mpm_init/core.py +160 -46
  16. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  17. claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
  18. claude_mpm/cli/commands/skills.py +214 -189
  19. claude_mpm/cli/commands/summarize.py +413 -0
  20. claude_mpm/cli/executor.py +11 -3
  21. claude_mpm/cli/parsers/agents_parser.py +0 -9
  22. claude_mpm/cli/parsers/auto_configure_parser.py +0 -138
  23. claude_mpm/cli/parsers/base_parser.py +5 -0
  24. claude_mpm/cli/parsers/config_parser.py +153 -83
  25. claude_mpm/cli/parsers/skills_parser.py +3 -2
  26. claude_mpm/cli/startup.py +550 -94
  27. claude_mpm/commands/mpm-config.md +265 -0
  28. claude_mpm/commands/mpm-help.md +14 -95
  29. claude_mpm/commands/mpm-organize.md +500 -0
  30. claude_mpm/config/agent_sources.py +27 -0
  31. claude_mpm/core/framework/formatters/content_formatter.py +3 -13
  32. claude_mpm/core/framework/loaders/agent_loader.py +8 -5
  33. claude_mpm/core/framework_loader.py +4 -2
  34. claude_mpm/core/logger.py +13 -0
  35. claude_mpm/core/socketio_pool.py +3 -3
  36. claude_mpm/core/unified_agent_registry.py +5 -15
  37. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  38. claude_mpm/hooks/claude_hooks/event_handlers.py +211 -78
  39. claude_mpm/hooks/claude_hooks/hook_handler.py +6 -0
  40. claude_mpm/hooks/claude_hooks/installer.py +33 -10
  41. claude_mpm/hooks/claude_hooks/memory_integration.py +26 -9
  42. claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
  43. claude_mpm/hooks/claude_hooks/services/connection_manager.py +4 -0
  44. claude_mpm/hooks/memory_integration_hook.py +46 -1
  45. claude_mpm/init.py +0 -19
  46. claude_mpm/scripts/claude-hook-handler.sh +58 -18
  47. claude_mpm/scripts/launch_monitor.py +93 -13
  48. claude_mpm/scripts/start_activity_logging.py +0 -0
  49. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  50. claude_mpm/services/agents/agent_review_service.py +280 -0
  51. claude_mpm/services/agents/deployment/agent_discovery_service.py +2 -3
  52. claude_mpm/services/agents/deployment/agent_template_builder.py +4 -2
  53. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +78 -9
  54. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +335 -53
  55. claude_mpm/services/agents/git_source_manager.py +34 -0
  56. claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
  57. claude_mpm/services/agents/sources/git_source_sync_service.py +8 -1
  58. claude_mpm/services/agents/toolchain_detector.py +10 -6
  59. claude_mpm/services/analysis/__init__.py +11 -1
  60. claude_mpm/services/analysis/clone_detector.py +1030 -0
  61. claude_mpm/services/command_deployment_service.py +81 -10
  62. claude_mpm/services/event_bus/config.py +3 -1
  63. claude_mpm/services/git/git_operations_service.py +93 -8
  64. claude_mpm/services/monitor/daemon.py +9 -2
  65. claude_mpm/services/monitor/daemon_manager.py +39 -3
  66. claude_mpm/services/monitor/server.py +225 -19
  67. claude_mpm/services/self_upgrade_service.py +120 -12
  68. claude_mpm/services/skills/__init__.py +3 -0
  69. claude_mpm/services/skills/git_skill_source_manager.py +32 -2
  70. claude_mpm/services/skills/selective_skill_deployer.py +704 -0
  71. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  72. claude_mpm/services/skills_deployer.py +126 -9
  73. claude_mpm/services/socketio/event_normalizer.py +15 -1
  74. claude_mpm/services/socketio/server/core.py +160 -21
  75. claude_mpm/services/version_control/git_operations.py +103 -0
  76. claude_mpm/utils/agent_filters.py +17 -44
  77. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.22.dist-info}/METADATA +47 -84
  78. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.22.dist-info}/RECORD +82 -161
  79. claude_mpm-5.4.22.dist-info/entry_points.txt +5 -0
  80. claude_mpm-5.4.22.dist-info/licenses/LICENSE +94 -0
  81. claude_mpm-5.4.22.dist-info/licenses/LICENSE-FAQ.md +153 -0
  82. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
  83. claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
  84. claude_mpm/agents/BASE_ENGINEER.md +0 -658
  85. claude_mpm/agents/BASE_OPS.md +0 -219
  86. claude_mpm/agents/BASE_PM.md +0 -480
  87. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
  88. claude_mpm/agents/BASE_QA.md +0 -167
  89. claude_mpm/agents/BASE_RESEARCH.md +0 -53
  90. claude_mpm/agents/base_agent.json +0 -31
  91. claude_mpm/agents/base_agent_loader.py +0 -601
  92. claude_mpm/cli/commands/agents_detect.py +0 -380
  93. claude_mpm/cli/commands/agents_recommend.py +0 -309
  94. claude_mpm/cli/ticket_cli.py +0 -35
  95. claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
  96. claude_mpm/commands/mpm-agents-detect.md +0 -177
  97. claude_mpm/commands/mpm-agents-list.md +0 -131
  98. claude_mpm/commands/mpm-agents-recommend.md +0 -223
  99. claude_mpm/commands/mpm-config-view.md +0 -150
  100. claude_mpm/commands/mpm-ticket-organize.md +0 -304
  101. claude_mpm/dashboard/analysis_runner.py +0 -455
  102. claude_mpm/dashboard/index.html +0 -13
  103. claude_mpm/dashboard/open_dashboard.py +0 -66
  104. claude_mpm/dashboard/static/css/activity.css +0 -1958
  105. claude_mpm/dashboard/static/css/connection-status.css +0 -370
  106. claude_mpm/dashboard/static/css/dashboard.css +0 -4701
  107. claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
  108. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
  109. claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
  110. claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
  111. claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
  112. claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
  113. claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
  114. claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
  115. claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
  116. claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
  117. claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
  118. claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
  119. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
  120. claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
  121. claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
  122. claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
  123. claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
  124. claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
  125. claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
  126. claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
  127. claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
  128. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
  129. claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
  130. claude_mpm/dashboard/static/js/connection-manager.js +0 -536
  131. claude_mpm/dashboard/static/js/dashboard.js +0 -1914
  132. claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
  133. claude_mpm/dashboard/static/js/socket-client.js +0 -1474
  134. claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
  135. claude_mpm/dashboard/static/socket.io.min.js +0 -7
  136. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
  137. claude_mpm/dashboard/templates/code_simple.html +0 -153
  138. claude_mpm/dashboard/templates/index.html +0 -606
  139. claude_mpm/dashboard/test_dashboard.html +0 -372
  140. claude_mpm/scripts/mcp_server.py +0 -75
  141. claude_mpm/scripts/mcp_wrapper.py +0 -39
  142. claude_mpm/services/mcp_gateway/__init__.py +0 -159
  143. claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
  144. claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
  145. claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
  146. claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
  147. claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
  148. claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
  149. claude_mpm/services/mcp_gateway/core/base.py +0 -312
  150. claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
  151. claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
  152. claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
  153. claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
  154. claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
  155. claude_mpm/services/mcp_gateway/main.py +0 -589
  156. claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
  157. claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
  158. claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
  159. claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
  160. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
  161. claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
  162. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
  163. claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
  164. claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
  165. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
  166. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
  167. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
  168. claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
  169. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
  170. claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
  171. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
  172. claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
  173. claude_mpm-5.1.9.dist-info/entry_points.txt +0 -10
  174. claude_mpm-5.1.9.dist-info/licenses/LICENSE +0 -21
  175. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.22.dist-info}/WHEEL +0 -0
  176. {claude_mpm-5.1.9.dist-info → claude_mpm-5.4.22.dist-info}/top_level.txt +0 -0
@@ -59,12 +59,15 @@ class AgentDisplay:
59
59
  Shows:
60
60
  - Agent ID (for selection)
61
61
  - Name and description
62
- - Enable/disable status
62
+ - Installed/Available status
63
63
  - Model or tools information
64
64
 
65
65
  Args:
66
66
  agents: List of agent configurations to display
67
67
  """
68
+
69
+ from ...utils.agent_filters import get_deployed_agent_ids
70
+
68
71
  table = Table(
69
72
  title=f"Available Agents ({len(agents)} total)",
70
73
  box=ROUNDED,
@@ -77,12 +80,18 @@ class AgentDisplay:
77
80
  table.add_column("Description", style="bold", width=45)
78
81
  table.add_column("Model/Tools", style="dim", width=20)
79
82
 
83
+ # Get deployed agent IDs
84
+ deployed_ids = get_deployed_agent_ids()
85
+
80
86
  for idx, agent in enumerate(agents, 1):
81
- # Check if agent is enabled
82
- is_enabled = self.agent_manager.is_agent_enabled(agent.name)
83
- status = (
84
- "[green]✓ Enabled[/green]" if is_enabled else "[red]✗ Disabled[/red]"
85
- )
87
+ # Check if agent is deployed to .claude/agents/
88
+ # Use agent_id (technical ID) for comparison, not display name
89
+ agent_id = getattr(agent, "agent_id", agent.name)
90
+ agent_leaf_name = agent_id.split("/")[-1]
91
+ is_deployed = agent_leaf_name in deployed_ids
92
+
93
+ # Show "Installed" for deployed agents, "Available" otherwise
94
+ status = "[green]Installed[/green]" if is_deployed else "Available"
86
95
 
87
96
  # Format tools/dependencies - show first 2 tools
88
97
  tools_display = ""
@@ -24,6 +24,7 @@ from claude_mpm.utils.display_helper import DisplayHelper
24
24
 
25
25
  # Import from sibling modules in the mpm_init package
26
26
  from . import display, git_activity, modes, prompts
27
+ from .knowledge_extractor import ProjectKnowledgeExtractor
27
28
 
28
29
  logger = get_logger(__name__)
29
30
 
@@ -34,6 +35,7 @@ class MPMInitCommand:
34
35
  def __init__(self, project_path: Optional[Path] = None):
35
36
  """Initialize the MPM-Init command."""
36
37
  self.project_path = project_path or Path.cwd()
38
+ self.claude_mpm_dir = self.project_path / ".claude-mpm"
37
39
  self.claude_mpm_script = self._find_claude_mpm_script()
38
40
  self.console = Console()
39
41
 
@@ -155,9 +157,8 @@ class MPMInitCommand:
155
157
  if pre_check_result.get("status") == OperationResult.ERROR:
156
158
  return pre_check_result
157
159
 
158
- # Update .gitignore to exclude claude-mpm configuration directories
159
- if not review_only and not dry_run:
160
- self._update_gitignore()
160
+ # Note: .gitignore recommendations are now shown in 'mpm config' command
161
+ # instead of automatic updates during initialization
161
162
 
162
163
  # Build the delegation prompt
163
164
  if update_mode:
@@ -399,48 +400,6 @@ class MPMInitCommand:
399
400
  "warnings": warnings,
400
401
  }
401
402
 
402
- def _update_gitignore(self) -> None:
403
- """Update .gitignore to exclude claude-mpm configuration directories.
404
-
405
- Ensures that claude-mpm configuration directories are added to .gitignore
406
- to prevent them from being committed to version control.
407
-
408
- This is a non-destructive operation that:
409
- - Creates .gitignore if it doesn't exist
410
- - Appends missing entries only (never duplicates)
411
- - Preserves all existing content
412
-
413
- Standard entries added:
414
- - .claude-mpm/: Main configuration directory
415
- - .claude/agents/: Agent runtime files
416
- """
417
- from claude_mpm.utils.gitignore import ensure_claude_mpm_gitignore
418
-
419
- try:
420
- result = ensure_claude_mpm_gitignore(str(self.project_path))
421
-
422
- if result.get("status") == "success":
423
- if result.get("added"):
424
- self.console.print(
425
- f"[green]✓[/green] Updated .gitignore: {', '.join(result['added'])}"
426
- )
427
- logger.info(f"Added to .gitignore: {result['added']}")
428
- elif result.get("existing"):
429
- logger.debug(f".gitignore already contains: {result['existing']}")
430
- else:
431
- # Non-critical error - log but don't fail initialization
432
- logger.warning(
433
- f"Could not update .gitignore: {result.get('error', 'Unknown error')}"
434
- )
435
- self.console.print(
436
- f"[yellow]⚠️ Could not update .gitignore: {result.get('error')}[/yellow]"
437
- )
438
-
439
- except Exception as e:
440
- # Non-critical error - log but don't fail initialization
441
- logger.warning(f"Error updating .gitignore: {e}")
442
- self.console.print(f"[yellow]⚠️ Could not update .gitignore: {e}[/yellow]")
443
-
444
403
  def _build_initialization_prompt(
445
404
  self,
446
405
  project_type: Optional[str] = None,
@@ -452,6 +411,10 @@ class MPMInitCommand:
452
411
  self.project_path, project_type, framework, ast_analysis
453
412
  )
454
413
 
414
+ def _is_initialized(self) -> bool:
415
+ """Check if project is already initialized with .claude-mpm directory."""
416
+ return self.claude_mpm_dir.exists()
417
+
455
418
  def _build_update_prompt(
456
419
  self,
457
420
  project_type: Optional[str],
@@ -459,10 +422,65 @@ class MPMInitCommand:
459
422
  ast_analysis: bool,
460
423
  preserve_custom: bool,
461
424
  ) -> str:
462
- """Build prompt for update mode."""
425
+ """Build prompt for update mode with optional knowledge extraction."""
463
426
  # Get existing content analysis
464
427
  doc_analysis = self.doc_manager.analyze_existing_content()
465
428
 
429
+ # Check if project is initialized (.claude-mpm exists)
430
+ # If so, use enhanced update mode with knowledge extraction
431
+ if self._is_initialized():
432
+ self.console.print(
433
+ "[cyan]✓ Detected initialized project - activating enhanced update mode[/cyan]"
434
+ )
435
+
436
+ # Extract knowledge from all sources
437
+ extractor = ProjectKnowledgeExtractor(self.project_path)
438
+
439
+ self.console.print("[cyan]✓ Analyzing git history (last 90 days)...[/cyan]")
440
+ git_insights = extractor.extract_from_git(days=90)
441
+
442
+ if git_insights.get("available"):
443
+ arch_count = len(git_insights.get("architectural_decisions", []))
444
+ workflow_count = len(git_insights.get("workflow_patterns", []))
445
+ self.console.print(f" - Found {arch_count} architectural decisions")
446
+ self.console.print(f" - Detected {workflow_count} workflow patterns")
447
+
448
+ self.console.print("[cyan]✓ Analyzing session logs...[/cyan]")
449
+ log_insights = extractor.extract_from_logs()
450
+
451
+ if log_insights.get("available"):
452
+ learning_count = len(log_insights.get("learnings", []))
453
+ self.console.print(f" - Found {learning_count} learning entries")
454
+
455
+ self.console.print("[cyan]✓ Analyzing memory files...[/cyan]")
456
+ memory_insights = extractor.extract_from_memory()
457
+
458
+ if memory_insights.get("available"):
459
+ total_insights = (
460
+ len(memory_insights.get("architectural_knowledge", []))
461
+ + len(memory_insights.get("implementation_guidelines", []))
462
+ + len(memory_insights.get("common_mistakes", []))
463
+ + len(memory_insights.get("technical_context", []))
464
+ )
465
+ self.console.print(f" - Found {total_insights} accumulated insights")
466
+
467
+ self.console.print(
468
+ "[green]✓ Knowledge extraction complete - building enhanced prompt[/green]\n"
469
+ )
470
+
471
+ # Build enhanced prompt with extracted knowledge
472
+ return prompts.build_enhanced_update_prompt(
473
+ self.project_path,
474
+ doc_analysis,
475
+ git_insights,
476
+ log_insights,
477
+ memory_insights,
478
+ project_type,
479
+ framework,
480
+ ast_analysis,
481
+ preserve_custom,
482
+ )
483
+ # Standard update mode (no .claude-mpm directory)
466
484
  return prompts.build_update_prompt(
467
485
  self.project_path,
468
486
  doc_analysis,
@@ -548,6 +566,11 @@ class MPMInitCommand:
548
566
  self.archive_manager,
549
567
  )
550
568
 
569
+ # Optimize CLAUDE.md with prompt-engineer if it exists
570
+ claude_md = self.project_path / "CLAUDE.md"
571
+ if claude_md.exists():
572
+ self._optimize_claude_md_with_prompt_engineer()
573
+
551
574
  def _display_results(self, result: Dict, verbose: bool):
552
575
  """Display initialization results."""
553
576
  display.display_results(self.display, self.console, result, verbose)
@@ -569,5 +592,96 @@ class MPMInitCommand:
569
592
  """Build structured Research agent delegation prompt from git analysis."""
570
593
  return prompts.build_research_context_prompt(git_analysis, days)
571
594
 
595
+ def _optimize_claude_md_with_prompt_engineer(self) -> None:
596
+ """Optimize CLAUDE.md with prompt-engineer for conciseness and clarity."""
597
+ claude_md_path = self.project_path / "CLAUDE.md"
598
+ if not claude_md_path.exists():
599
+ return
600
+
601
+ try:
602
+ # Read current content
603
+ original_content = claude_md_path.read_text()
604
+ original_tokens = self._estimate_tokens(original_content)
605
+
606
+ # Create backup
607
+ backup_path = self.archive_manager.auto_archive_before_update(
608
+ claude_md_path, update_reason="Before prompt-engineer optimization"
609
+ )
610
+
611
+ if not backup_path:
612
+ logger.warning("Could not create backup before optimization")
613
+ self.console.print(
614
+ "[yellow]⚠️ Skipping optimization - backup failed[/yellow]"
615
+ )
616
+ return
617
+
618
+ self.console.print(
619
+ "\n[cyan]✓ Optimizing CLAUDE.md with prompt-engineer...[/cyan]"
620
+ )
621
+ self.console.print(f" - Original: {original_tokens:,} tokens (estimated)")
622
+ self.console.print(f" - Backup created: {backup_path}")
623
+
624
+ # Build optimization prompt
625
+ prompt = prompts.build_prompt_engineer_optimization_prompt(
626
+ original_content, original_tokens
627
+ )
628
+
629
+ # Run optimization through subprocess
630
+ with Progress(
631
+ SpinnerColumn(),
632
+ TextColumn("[progress.description]{task.description}"),
633
+ console=self.console,
634
+ ) as progress:
635
+ task = progress.add_task(
636
+ "[cyan]Running prompt-engineer optimization...", total=None
637
+ )
638
+
639
+ result = self._run_initialization(
640
+ prompt, verbose=False, update_mode=True
641
+ )
642
+
643
+ progress.update(task, description="[green]✓ Optimization complete")
644
+
645
+ # Check if optimization succeeded
646
+ if result.get("status") == OperationResult.SUCCESS:
647
+ # Read optimized content
648
+ optimized_content = claude_md_path.read_text()
649
+ optimized_tokens = self._estimate_tokens(optimized_content)
650
+
651
+ # Calculate reduction
652
+ token_reduction = original_tokens - optimized_tokens
653
+ reduction_percent = (
654
+ (token_reduction / original_tokens * 100)
655
+ if original_tokens > 0
656
+ else 0
657
+ )
658
+
659
+ self.console.print(
660
+ f" - Optimized: {optimized_tokens:,} tokens ({reduction_percent:.1f}% reduction)"
661
+ )
662
+ self.console.print("[green]✓ CLAUDE.md optimization complete[/green]\n")
663
+ # Restore from backup on failure
664
+ elif backup_path and backup_path.exists():
665
+ import shutil
666
+
667
+ shutil.copy2(backup_path, claude_md_path)
668
+ self.console.print(
669
+ "[yellow]⚠️ Optimization failed - restored from backup[/yellow]\n"
670
+ )
671
+
672
+ except Exception as e:
673
+ logger.error(f"Failed to optimize CLAUDE.md: {e}")
674
+ self.console.print(
675
+ f"[yellow]⚠️ Could not optimize CLAUDE.md: {e}[/yellow]\n"
676
+ )
677
+
678
+ def _estimate_tokens(self, text: str) -> int:
679
+ """Estimate token count for text (rough approximation).
680
+
681
+ Uses a simple heuristic: ~4 characters per token for English text.
682
+ This is a rough estimate but sufficient for displaying progress.
683
+ """
684
+ return len(text) // 4
685
+
572
686
 
573
687
  __all__ = ["MPMInitCommand"]