Coverage for src/moai_adk/cli/commands/backup.py: 30.77%
26 statements
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-20 15:28 +0900
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-20 15:28 +0900
1"""Backup command
3Create a backup of the current project including:
4- .claude/ (entire directory)
5- .moai/ (excluding specs and reports)
6- CLAUDE.md
8Backup location: .moai-backups/YYYYMMDD-HHMMSS/
10## Skill Invocation Guide (English-Only)
12### Related Skills
13- **moai-foundation-git**: For Git workflow and backup management
14 - Trigger: Before creating critical backups, review Git state
15 - Invocation: `Skill("moai-foundation-git")` for backup naming conventions
17### When to Invoke Skills in Related Workflows
181. **Before backup creation**:
19 - Run `Skill("moai-foundation-git")` to document current Git branch state
20 - Tag backup with feature branch name for easier recovery
222. **After restoration from backup**:
23 - Run `Skill("moai-foundation-trust")` to validate toolchain
24"""
26from pathlib import Path
28import click
29from rich.console import Console
31from moai_adk.core.template.processor import TemplateProcessor
33console = Console()
36@click.command()
37@click.option(
38 "--path",
39 type=click.Path(exists=True),
40 default=".",
41 help="Project path (default: current directory)",
42)
43def backup(path: str) -> None:
44 """Create a backup of the current project.
46 Includes:
47 - .claude/ (entire directory)
48 - .moai/ (excluding specs and reports)
49 - CLAUDE.md
51 Backup location: .moai-backup/YYYYMMDD-HHMMSS/
52 """
53 try:
54 project_path = Path(path).resolve()
56 # Verify the project has been initialized
57 if not (project_path / ".moai").exists():
58 console.print("[yellow]⚠ Project not initialized[/yellow]")
59 raise click.Abort()
61 # Create the backup
62 console.print("[cyan]💾 Creating backup...[/cyan]")
63 processor = TemplateProcessor(project_path)
64 backup_path = processor.create_backup()
66 # Success message
67 console.print(
68 f"[green]✓ Backup completed: {backup_path.relative_to(project_path)}[/green]"
69 )
71 # Show backup contents
72 backup_items = list(backup_path.iterdir())
73 for item in backup_items:
74 if item.is_dir():
75 file_count = len(list(item.rglob("*")))
76 console.print(f" ├─ {item.name}/ ({file_count} files)")
77 else:
78 console.print(f" └─ {item.name}")
80 except Exception as e:
81 console.print(f"[red]✗ Backup failed: {e}[/red]")
82 raise click.ClickException(str(e)) from e