claude-mpm 4.7.3__py3-none-any.whl → 4.7.5__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.
@@ -19,7 +19,6 @@ from rich.console import Console
19
19
  from rich.panel import Panel
20
20
  from rich.progress import Progress, SpinnerColumn, TextColumn
21
21
  from rich.prompt import Prompt
22
- from rich.table import Table
23
22
 
24
23
  from claude_mpm.core.logging_utils import get_logger
25
24
 
@@ -28,6 +27,7 @@ from claude_mpm.services.project.archive_manager import ArchiveManager
28
27
  from claude_mpm.services.project.documentation_manager import DocumentationManager
29
28
  from claude_mpm.services.project.enhanced_analyzer import EnhancedProjectAnalyzer
30
29
  from claude_mpm.services.project.project_organizer import ProjectOrganizer
30
+ from claude_mpm.utils.display_helper import DisplayHelper
31
31
 
32
32
  logger = get_logger(__name__)
33
33
  console = Console()
@@ -46,6 +46,7 @@ class MPMInitCommand:
46
46
  self.organizer = ProjectOrganizer(self.project_path)
47
47
  self.archive_manager = ArchiveManager(self.project_path)
48
48
  self.analyzer = EnhancedProjectAnalyzer(self.project_path)
49
+ self.display = DisplayHelper(console)
49
50
 
50
51
  def initialize_project(
51
52
  self,
@@ -61,6 +62,10 @@ class MPMInitCommand:
61
62
  preserve_custom: bool = True,
62
63
  skip_archive: bool = False,
63
64
  dry_run: bool = False,
65
+ quick_update: bool = False,
66
+ non_interactive: bool = False,
67
+ days: int = 30,
68
+ export: Optional[str] = None,
64
69
  ) -> Dict:
65
70
  """
66
71
  Initialize project with Agentic Coder Optimizer standards.
@@ -78,6 +83,10 @@ class MPMInitCommand:
78
83
  preserve_custom: Preserve custom sections when updating
79
84
  skip_archive: Skip archiving existing files
80
85
  dry_run: Show what would be done without making changes
86
+ quick_update: Perform lightweight update based on recent git activity
87
+ non_interactive: Non-interactive mode - display report only without prompting
88
+ days: Number of days for git history analysis (7, 14, 30, 60, or 90)
89
+ export: Export report to file (path or "auto" for default location)
81
90
 
82
91
  Returns:
83
92
  Dict containing initialization results
@@ -90,6 +99,13 @@ class MPMInitCommand:
90
99
  if review_only:
91
100
  return self._run_review_mode()
92
101
 
102
+ if quick_update:
103
+ return self._run_quick_update_mode(
104
+ days=days,
105
+ non_interactive=non_interactive,
106
+ export=export,
107
+ )
108
+
93
109
  if has_existing and not force and not update_mode:
94
110
  # Auto-select update mode if organize_files or dry_run is specified
95
111
  if organize_files or dry_run:
@@ -411,34 +427,7 @@ The final CLAUDE.md should be a comprehensive, well-organized guide that any AI
411
427
 
412
428
  def _display_documentation_status(self, analysis: Dict) -> None:
413
429
  """Display current documentation status."""
414
- table = Table(title="Current CLAUDE.md Status", show_header=True)
415
- table.add_column("Property", style="cyan")
416
- table.add_column("Value", style="white")
417
-
418
- table.add_row("Size", f"{analysis.get('size', 0):,} characters")
419
- table.add_row("Lines", str(analysis.get("lines", 0)))
420
- table.add_row("Sections", str(len(analysis.get("sections", []))))
421
- table.add_row(
422
- "Has Priority Index", "✓" if analysis.get("has_priority_index") else "✗"
423
- )
424
- table.add_row(
425
- "Has Priority Markers", "✓" if analysis.get("has_priority_markers") else "✗"
426
- )
427
-
428
- if analysis.get("last_modified"):
429
- table.add_row("Last Modified", analysis["last_modified"])
430
-
431
- console.print(table)
432
-
433
- if analysis.get("outdated_patterns"):
434
- console.print("\n[yellow]⚠️ Outdated patterns detected:[/yellow]")
435
- for pattern in analysis["outdated_patterns"]:
436
- console.print(f" • {pattern}")
437
-
438
- if analysis.get("custom_sections"):
439
- console.print("\n[blue][INFO]️ Custom sections found:[/blue]")
440
- for section in analysis["custom_sections"][:5]:
441
- console.print(f" • {section}")
430
+ self.display.display_documentation_status(analysis)
442
431
 
443
432
  def _prompt_update_action(self) -> str:
444
433
  """Prompt user for update action."""
@@ -511,29 +500,26 @@ The final CLAUDE.md should be a comprehensive, well-organized guide that any AI
511
500
  self, structure: Dict, docs: Dict, git: Optional[Dict], state: Dict
512
501
  ) -> None:
513
502
  """Display comprehensive review report."""
514
- console.print("\n" + "=" * 60)
515
- console.print("[bold]PROJECT REVIEW REPORT[/bold]")
516
- console.print("=" * 60 + "\n")
503
+ self.display.display_header("PROJECT REVIEW REPORT")
517
504
 
518
505
  # Project State
519
- console.print("[bold cyan]📊 Project State[/bold cyan]")
520
- console.print(f" Phase: {state.get('phase', 'unknown')}")
506
+ state_data = {"Phase": state.get("phase", "unknown")}
521
507
  if state.get("indicators"):
522
- console.print(" Indicators:")
523
- for indicator in state["indicators"][:5]:
524
- console.print(f" • {indicator}")
508
+ state_data["Indicators"] = state["indicators"][:5]
509
+ self.display.display_report_section("📊 Project State", state_data)
525
510
 
526
511
  # Structure Report
527
- console.print("\n[bold cyan]📁 Project Structure[/bold cyan]")
528
- console.print(f" Existing directories: {len(structure.get('exists', []))}")
529
- console.print(f" Missing directories: {len(structure.get('missing', []))}")
512
+ structure_data = {
513
+ "Existing directories": len(structure.get("exists", [])),
514
+ "Missing directories": len(structure.get("missing", [])),
515
+ }
530
516
  if structure.get("issues"):
531
- console.print(f" Issues found: {len(structure['issues'])}")
532
- for issue in structure["issues"][:3]:
533
- console.print(f" ⚠️ {issue['description']}")
517
+ structure_data["Issues found"] = len(structure["issues"])
518
+ structure_data["Issues"] = structure["issues"][:3]
519
+ self.display.display_report_section("📁 Project Structure", structure_data)
534
520
 
535
521
  # Documentation Report
536
- console.print("\n[bold cyan]📚 Documentation Status[/bold cyan]")
522
+ self.display.display_section_title("📚 Documentation Status")
537
523
  if docs.get("exists"):
538
524
  console.print(f" CLAUDE.md: Found ({docs.get('size', 0):,} chars)")
539
525
  console.print(f" Sections: {len(docs.get('sections', []))}")
@@ -545,32 +531,426 @@ The final CLAUDE.md should be a comprehensive, well-organized guide that any AI
545
531
 
546
532
  # Git Analysis
547
533
  if git and git.get("git_available"):
548
- console.print("\n[bold cyan]📈 Recent Activity (30 days)[/bold cyan]")
549
- console.print(f" Commits: {len(git.get('recent_commits', []))}")
534
+ git_metrics = {
535
+ "Commits": len(git.get("recent_commits", [])),
536
+ "Authors": git.get("authors", {}).get("total_authors", 0),
537
+ "Changed files": git.get("changed_files", {}).get("total_files", 0),
538
+ }
539
+
540
+ if git.get("branch_info"):
541
+ branch_info = git["branch_info"]
542
+ git_metrics["Current branch"] = branch_info.get(
543
+ "current_branch", "unknown"
544
+ )
545
+
546
+ self.display.display_metrics_section(
547
+ "📈 Recent Activity (30 days)", git_metrics
548
+ )
549
+
550
+ if git.get("branch_info", {}).get("has_uncommitted_changes"):
551
+ self.display.display_metric_row(
552
+ "⚠️ Uncommitted changes",
553
+ f"{git['branch_info'].get('uncommitted_files', 0)} files",
554
+ warning=True,
555
+ )
556
+
557
+ # Recommendations
558
+ if state.get("recommendations"):
559
+ self.display.display_recommendations(state["recommendations"])
560
+
561
+ self.display.display_separator()
562
+
563
+ def _run_quick_update_mode(
564
+ self,
565
+ days: int = 30,
566
+ non_interactive: bool = False,
567
+ export: Optional[str] = None,
568
+ ) -> Dict:
569
+ """Run quick update mode - lightweight update based on recent git activity."""
570
+ console.print("\n[bold cyan]⚡ Quick Update Mode[/bold cyan]\n")
571
+ console.print(
572
+ f"[dim]Analyzing recent git activity ({days} days) for lightweight documentation update...[/dim]\n"
573
+ )
574
+
575
+ if not self.analyzer.is_git_repo:
550
576
  console.print(
551
- f" Authors: {git.get('authors', {}).get('total_authors', 0)}"
577
+ "[yellow]⚠️ Not a git repository. Quick update requires git.[/yellow]"
552
578
  )
553
579
  console.print(
554
- f" Changed files: {git.get('changed_files', {}).get('total_files', 0)}"
580
+ "[dim]Tip: Use `/mpm-init --review` for non-git projects.[/dim]\n"
555
581
  )
582
+ return {
583
+ "status": "error",
584
+ "message": "Quick update requires a git repository",
585
+ }
556
586
 
557
- if git.get("branch_info"):
558
- branch_info = git["branch_info"]
559
- console.print(
560
- f" Current branch: {branch_info.get('current_branch', 'unknown')}"
587
+ claude_md = self.project_path / "CLAUDE.md"
588
+ if not claude_md.exists():
589
+ console.print(
590
+ "[yellow]⚠️ CLAUDE.md not found. Quick update requires existing documentation.[/yellow]"
591
+ )
592
+ console.print(
593
+ "[dim]Tip: Use `/mpm-init` to create initial documentation.[/dim]\n"
594
+ )
595
+ return {
596
+ "status": "error",
597
+ "message": "Quick update requires existing CLAUDE.md",
598
+ }
599
+
600
+ with Progress(
601
+ SpinnerColumn(),
602
+ TextColumn("[progress.description]{task.description}"),
603
+ console=console,
604
+ ) as progress:
605
+ # Analyze git history
606
+ task = progress.add_task(
607
+ f"[cyan]Analyzing git history ({days} days)...", total=None
608
+ )
609
+ git_analysis = self.analyzer.analyze_git_history(days_back=days)
610
+ progress.update(task, description="[green]✓ Git analysis complete")
611
+
612
+ # Analyze current documentation
613
+ task = progress.add_task(
614
+ "[cyan]Checking documentation status...", total=None
615
+ )
616
+ doc_analysis = self.doc_manager.analyze_existing_content()
617
+ progress.update(task, description="[green]✓ Documentation analyzed")
618
+
619
+ # Generate activity report
620
+ activity_report = self._generate_activity_report(
621
+ git_analysis, doc_analysis, days
622
+ )
623
+
624
+ # Display the report
625
+ self._display_activity_report(activity_report)
626
+
627
+ # Export report if requested
628
+ if export:
629
+ export_path = self._export_activity_report(activity_report, export)
630
+ console.print(f"\n[green]✅ Report exported to: {export_path}[/green]")
631
+
632
+ # Handle non-interactive mode
633
+ if non_interactive:
634
+ console.print(
635
+ "\n[cyan]ℹ️ Non-interactive mode: Report displayed, no changes made.[/cyan]"
636
+ )
637
+ return {
638
+ "status": "success",
639
+ "mode": "quick_update",
640
+ "activity_report": activity_report,
641
+ "changes_made": False,
642
+ "non_interactive": True,
643
+ }
644
+
645
+ # Offer to append activity notes to CLAUDE.md
646
+ console.print("\n[bold]Update Options:[/bold]")
647
+ console.print(" [1] Append activity summary to CLAUDE.md")
648
+ console.print(" [2] Display report only (no changes)")
649
+ console.print(" [3] Cancel")
650
+
651
+ from rich.prompt import Prompt
652
+
653
+ choice = Prompt.ask("\nSelect option", choices=["1", "2", "3"], default="2")
654
+
655
+ if choice == "1":
656
+ # Append activity notes
657
+ self._append_activity_notes(claude_md, activity_report)
658
+ console.print("\n[green]✅ Activity notes appended to CLAUDE.md[/green]")
659
+
660
+ # Archive the update
661
+ self.archive_manager.auto_archive_before_update(
662
+ claude_md, update_reason="Quick update - recent activity summary"
663
+ )
664
+
665
+ return {
666
+ "status": "success",
667
+ "mode": "quick_update",
668
+ "activity_report": activity_report,
669
+ "changes_made": True,
670
+ }
671
+ if choice == "2":
672
+ console.print("\n[cyan]Report generated - no changes made[/cyan]")
673
+ return {
674
+ "status": "success",
675
+ "mode": "quick_update",
676
+ "activity_report": activity_report,
677
+ "changes_made": False,
678
+ }
679
+ console.print("\n[yellow]Quick update cancelled[/yellow]")
680
+ return {"status": "cancelled", "message": "Quick update cancelled"}
681
+
682
+ def _generate_activity_report(
683
+ self, git_analysis: Dict, doc_analysis: Dict, days: int = 30
684
+ ) -> Dict:
685
+ """Generate activity report from git analysis and documentation status."""
686
+ from datetime import datetime, timezone
687
+
688
+ report = {
689
+ "period": f"Last {days} days",
690
+ "generated_at": datetime.now(timezone.utc).isoformat(),
691
+ "summary": {},
692
+ "recommendations": [],
693
+ }
694
+
695
+ # Git activity summary
696
+ if git_analysis.get("git_available"):
697
+ recent_commits = git_analysis.get("recent_commits", [])
698
+ changed_files = git_analysis.get("changed_files", {})
699
+ authors = git_analysis.get("authors", {})
700
+ branch_info = git_analysis.get("branch_info", {})
701
+
702
+ report["summary"] = {
703
+ "total_commits": len(recent_commits),
704
+ "total_authors": authors.get("total_authors", 0),
705
+ "files_changed": changed_files.get("total_files", 0),
706
+ "current_branch": branch_info.get("current_branch", "unknown"),
707
+ "has_uncommitted": branch_info.get("has_uncommitted_changes", False),
708
+ "uncommitted_count": branch_info.get("uncommitted_files", 0),
709
+ }
710
+
711
+ # Recent commits (last 10)
712
+ report["recent_commits"] = recent_commits[:10]
713
+
714
+ # Most changed files
715
+ most_changed = changed_files.get("most_changed", {})
716
+ report["hot_files"] = list(most_changed.items())[:10]
717
+
718
+ # Active branches
719
+ branches = branch_info.get("branches", [])
720
+ report["active_branches"] = [
721
+ b for b in branches if not b.startswith("remotes/")
722
+ ][:5]
723
+
724
+ # Generate recommendations
725
+ if len(recent_commits) > 20:
726
+ report["recommendations"].append(
727
+ "High activity detected - consider updating architecture docs"
561
728
  )
562
- if branch_info.get("has_uncommitted_changes"):
563
- console.print(
564
- f" ⚠️ Uncommitted changes: {branch_info.get('uncommitted_files', 0)} files"
565
- )
729
+
730
+ if changed_files.get("total_files", 0) > 50:
731
+ report["recommendations"].append(
732
+ "Many files changed - review CLAUDE.md for accuracy"
733
+ )
734
+
735
+ if branch_info.get("has_uncommitted_changes"):
736
+ report["recommendations"].append(
737
+ "Uncommitted changes detected - commit before updating docs"
738
+ )
739
+
740
+ # Check for documentation changes
741
+ doc_changes = git_analysis.get("documentation_changes", {})
742
+ if not doc_changes.get("has_recent_doc_changes"):
743
+ report["recommendations"].append(
744
+ "No recent doc updates - CLAUDE.md may be outdated"
745
+ )
746
+
747
+ # Documentation freshness
748
+ if doc_analysis.get("exists"):
749
+ report["doc_status"] = {
750
+ "size": doc_analysis.get("size", 0),
751
+ "lines": doc_analysis.get("lines", 0),
752
+ "has_priority_index": doc_analysis.get("has_priority_index", False),
753
+ "has_priority_markers": doc_analysis.get("has_priority_markers", False),
754
+ "last_modified": doc_analysis.get("last_modified", "unknown"),
755
+ }
756
+
757
+ if not doc_analysis.get("has_priority_markers"):
758
+ report["recommendations"].append(
759
+ "Add priority markers (🔴🟡🟢⚪) to CLAUDE.md"
760
+ )
761
+
762
+ return report
763
+
764
+ def _export_activity_report(self, report: Dict, export_path: str) -> Path:
765
+ """Export activity report to a markdown file."""
766
+ from datetime import datetime, timezone
767
+ from pathlib import Path
768
+
769
+ # Determine export path
770
+ if export_path == "auto":
771
+ # Generate default path with timestamp
772
+ timestamp = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
773
+ reports_dir = self.project_path / "docs" / "reports"
774
+ reports_dir.mkdir(parents=True, exist_ok=True)
775
+ file_path = reports_dir / f"activity-report-{timestamp}.md"
776
+ else:
777
+ # Use provided path
778
+ file_path = Path(export_path)
779
+ if not file_path.is_absolute():
780
+ file_path = self.project_path / file_path
781
+ # Create parent directory if needed
782
+ file_path.parent.mkdir(parents=True, exist_ok=True)
783
+
784
+ # Generate markdown content
785
+ summary = report.get("summary", {})
786
+ timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
787
+
788
+ content = f"""# Activity Report
789
+
790
+ **Generated**: {timestamp}
791
+ **Analysis Period**: {report.get('period', 'Last 30 days')}
792
+
793
+ ## Summary
794
+
795
+ - **Total Commits**: {summary.get('total_commits', 0)}
796
+ - **Active Contributors**: {summary.get('total_authors', 0)}
797
+ - **Files Modified**: {summary.get('files_changed', 0)}
798
+ - **Current Branch**: {summary.get('current_branch', 'unknown')}
799
+ """
800
+
801
+ if summary.get("has_uncommitted"):
802
+ content += f"- **⚠️ Uncommitted Changes**: {summary.get('uncommitted_count', 0)} files\n"
803
+
804
+ # Recent commits
805
+ recent_commits = report.get("recent_commits", [])
806
+ if recent_commits:
807
+ content += "\n## Recent Commits\n\n"
808
+ for commit in recent_commits[:10]:
809
+ content += (
810
+ f"- `{commit['hash']}` {commit['message']} - {commit['author']}\n"
811
+ )
812
+
813
+ # Hot files
814
+ hot_files = report.get("hot_files", [])
815
+ if hot_files:
816
+ content += "\n## Most Changed Files\n\n"
817
+ for hot_file_path, changes in hot_files[:10]:
818
+ content += f"- `{hot_file_path}`: {changes} changes\n"
819
+
820
+ # Active branches
821
+ branches = report.get("active_branches", [])
822
+ if branches:
823
+ content += "\n## Active Branches\n\n"
824
+ for branch in branches:
825
+ marker = "→" if branch == summary.get("current_branch") else " "
826
+ content += f"{marker} {branch}\n"
827
+
828
+ # Documentation status
829
+ doc_status = report.get("doc_status", {})
830
+ if doc_status:
831
+ content += "\n## CLAUDE.md Status\n\n"
832
+ content += f"- **Size**: {doc_status.get('size', 0):,} characters\n"
833
+ content += f"- **Lines**: {doc_status.get('lines', 0)}\n"
834
+ content += f"- **Priority Markers**: {'✓' if doc_status.get('has_priority_markers') else '✗'}\n"
835
+ content += (
836
+ f"- **Last Modified**: {doc_status.get('last_modified', 'unknown')}\n"
837
+ )
566
838
 
567
839
  # Recommendations
568
- if state.get("recommendations"):
569
- console.print("\n[bold cyan]💡 Recommendations[/bold cyan]")
570
- for rec in state["recommendations"][:5]:
571
- console.print(f" → {rec}")
840
+ recommendations = report.get("recommendations", [])
841
+ if recommendations:
842
+ content += "\n## Recommendations\n\n"
843
+ for rec in recommendations:
844
+ content += f"- {rec}\n"
845
+
846
+ content += (
847
+ "\n---\n\n*Generated by Claude MPM `/mpm-init --quick-update --export`*\n"
848
+ )
849
+
850
+ # Write to file
851
+ file_path.write_text(content, encoding="utf-8")
852
+
853
+ return file_path
854
+
855
+ def _display_activity_report(self, report: Dict) -> None:
856
+ """Display the activity report in a formatted manner."""
857
+ self.display.display_header("RECENT ACTIVITY SUMMARY")
858
+
859
+ summary = report.get("summary", {})
860
+ period = report.get("period", "Last 30 days")
861
+
862
+ # Summary statistics
863
+ self.display.display_activity_summary(summary, period)
864
+
865
+ # Recent commits
866
+ recent_commits = report.get("recent_commits", [])
867
+ if recent_commits:
868
+ self.display.display_commit_list(recent_commits)
869
+
870
+ # Hot files
871
+ hot_files = report.get("hot_files", [])
872
+ if hot_files:
873
+ self.display.display_file_change_list(hot_files)
874
+
875
+ # Active branches
876
+ branches = report.get("active_branches", [])
877
+ current_branch = summary.get("current_branch", "unknown")
878
+ if branches:
879
+ self.display.display_branch_list(branches, current_branch)
880
+
881
+ # Documentation status
882
+ doc_status = report.get("doc_status", {})
883
+ if doc_status:
884
+ doc_metrics = {
885
+ "Size": f"{doc_status.get('size', 0):,} characters",
886
+ "Lines": doc_status.get("lines", 0),
887
+ "Priority markers": (
888
+ "✓" if doc_status.get("has_priority_markers") else "✗"
889
+ ),
890
+ "Last modified": doc_status.get("last_modified", "unknown"),
891
+ }
892
+ self.display.display_metrics_section("📚 CLAUDE.md Status", doc_metrics)
893
+
894
+ # Recommendations
895
+ recommendations = report.get("recommendations", [])
896
+ if recommendations:
897
+ self.display.display_recommendations(recommendations)
898
+
899
+ self.display.display_separator()
900
+
901
+ def _append_activity_notes(self, claude_md_path: Path, report: Dict) -> None:
902
+ """Append activity notes to CLAUDE.md."""
903
+ from datetime import datetime, timezone
904
+
905
+ # Generate activity summary section
906
+ summary = report.get("summary", {})
907
+ timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
908
+
909
+ activity_section = f"""
910
+
911
+ ---
912
+
913
+ ## 📈 Recent Activity Summary
914
+
915
+ **Last Updated**: {timestamp}
916
+ **Analysis Period**: {report.get('period', 'Last 30 days')}
917
+
918
+ ### Activity Metrics
919
+ - **Commits**: {summary.get('total_commits', 0)}
920
+ - **Contributors**: {summary.get('total_authors', 0)}
921
+ - **Files Changed**: {summary.get('files_changed', 0)}
922
+ - **Current Branch**: {summary.get('current_branch', 'unknown')}
923
+ """
924
+
925
+ if summary.get("has_uncommitted"):
926
+ activity_section += f"- **⚠️ Uncommitted Changes**: {summary.get('uncommitted_count', 0)} files\n"
927
+
928
+ # Add recent commits
929
+ recent_commits = report.get("recent_commits", [])
930
+ if recent_commits:
931
+ activity_section += "\n### Recent Commits\n"
932
+ for commit in recent_commits[:5]:
933
+ activity_section += f"- `{commit['hash']}` {commit['message'][:60]} ({commit['author']})\n"
934
+
935
+ # Add hot files
936
+ hot_files = report.get("hot_files", [])
937
+ if hot_files:
938
+ activity_section += "\n### Most Active Files\n"
939
+ for file_path, changes in hot_files[:5]:
940
+ activity_section += f"- `{file_path}`: {changes} changes\n"
572
941
 
573
- console.print("\n" + "=" * 60 + "\n")
942
+ # Add recommendations
943
+ recommendations = report.get("recommendations", [])
944
+ if recommendations:
945
+ activity_section += "\n### 💡 Recommendations\n"
946
+ for rec in recommendations:
947
+ activity_section += f"- {rec}\n"
948
+
949
+ activity_section += "\n---\n"
950
+
951
+ # Append to file
952
+ with open(claude_md_path, "a", encoding="utf-8") as f:
953
+ f.write(activity_section)
574
954
 
575
955
  def _run_dry_run_mode(self, organize_files: bool, has_existing: bool) -> Dict:
576
956
  """Run dry-run mode to show what would be done without making changes."""
@@ -991,39 +1371,35 @@ preserving valuable project-specific information while refreshing standard secti
991
1371
  if result["status"] == "success":
992
1372
  console.print("\n[green]✅ Project Initialization Complete![/green]\n")
993
1373
 
1374
+ # Display files created
994
1375
  if result.get("files_created"):
995
- console.print("[bold]Files Created:[/bold]")
996
- for file in result["files_created"]:
997
- console.print(f" • {file}")
998
- console.print()
1376
+ self.display.display_files_list(
1377
+ "Files Created:", result["files_created"]
1378
+ )
999
1379
 
1380
+ # Display files updated
1000
1381
  if result.get("files_updated"):
1001
- console.print("[bold]Files Updated:[/bold]")
1002
- for file in result["files_updated"]:
1003
- console.print(f" • {file}")
1004
- console.print()
1382
+ self.display.display_files_list(
1383
+ "Files Updated:", result["files_updated"]
1384
+ )
1005
1385
 
1386
+ # Display next steps
1006
1387
  if result.get("next_steps"):
1007
- console.print("[bold]Next Steps:[/bold]")
1008
- for step in result["next_steps"]:
1009
- console.print(f" → {step}")
1010
- console.print()
1011
-
1012
- console.print(
1013
- Panel(
1014
- "[green]Your project is now optimized for Claude Code and Claude MPM![/green]\n\n"
1015
- "Key files:\n"
1016
- "• [cyan]CLAUDE.md[/cyan] - Main documentation for AI agents\n"
1017
- " - Organized with priority rankings (🔴🟡🟢⚪)\n"
1018
- " - Instructions ranked by importance for AI understanding\n"
1019
- " - Holistic documentation review completed\n"
1020
- "• [cyan].claude-mpm/[/cyan] - Configuration and memories\n"
1021
- "• [cyan]CODE_STRUCTURE.md[/cyan] - AST-derived architecture documentation (if enabled)\n\n"
1022
- "[dim]Run 'claude-mpm run' to start using the optimized setup[/dim]",
1023
- title="Success",
1024
- border_style="green",
1025
- )
1388
+ self.display.display_next_steps(result["next_steps"])
1389
+
1390
+ # Display success panel
1391
+ success_content = (
1392
+ "[green]Your project is now optimized for Claude Code and Claude MPM![/green]\n\n"
1393
+ "Key files:\n"
1394
+ "• [cyan]CLAUDE.md[/cyan] - Main documentation for AI agents\n"
1395
+ " - Organized with priority rankings (🔴🟡🟢⚪)\n"
1396
+ " - Instructions ranked by importance for AI understanding\n"
1397
+ " - Holistic documentation review completed\n"
1398
+ "• [cyan].claude-mpm/[/cyan] - Configuration and memories\n"
1399
+ " [cyan]CODE_STRUCTURE.md[/cyan] - AST-derived architecture documentation (if enabled)\n\n"
1400
+ "[dim]Run 'claude-mpm run' to start using the optimized setup[/dim]"
1026
1401
  )
1402
+ self.display.display_success_panel("Success", success_content)
1027
1403
 
1028
1404
 
1029
1405
  @click.command(name="mpm-init")
@@ -1082,6 +1458,28 @@ preserving valuable project-specific information while refreshing standard secti
1082
1458
  default=True,
1083
1459
  help="Enable/disable AST analysis for enhanced documentation (default: enabled)",
1084
1460
  )
1461
+ @click.option(
1462
+ "--quick-update",
1463
+ is_flag=True,
1464
+ help="Perform lightweight update based on recent git activity (default: 30 days)",
1465
+ )
1466
+ @click.option(
1467
+ "--non-interactive",
1468
+ is_flag=True,
1469
+ help="Non-interactive mode - display report only without prompting (use with --quick-update)",
1470
+ )
1471
+ @click.option(
1472
+ "--days",
1473
+ type=int,
1474
+ default=30,
1475
+ help="Number of days for git history analysis in quick update mode (default: 30)",
1476
+ )
1477
+ @click.option(
1478
+ "--export",
1479
+ type=str,
1480
+ default=None,
1481
+ help="Export activity report to file (default: docs/reports/activity-report-{timestamp}.md)",
1482
+ )
1085
1483
  @click.argument(
1086
1484
  "project_path",
1087
1485
  type=click.Path(exists=True, file_okay=False, dir_okay=True),
@@ -1100,6 +1498,10 @@ def mpm_init(
1100
1498
  skip_archive,
1101
1499
  verbose,
1102
1500
  ast_analysis,
1501
+ quick_update,
1502
+ non_interactive,
1503
+ days,
1504
+ export,
1103
1505
  project_path,
1104
1506
  ):
1105
1507
  """
@@ -1141,6 +1543,10 @@ def mpm_init(
1141
1543
  organize_files=organize,
1142
1544
  preserve_custom=preserve_custom,
1143
1545
  skip_archive=skip_archive,
1546
+ quick_update=quick_update,
1547
+ non_interactive=non_interactive,
1548
+ days=days,
1549
+ export=export,
1144
1550
  )
1145
1551
 
1146
1552
  # Exit with appropriate code