package main import ( "encoding/json" "fmt" "os" "os/exec" "path/filepath" "runtime" "strings" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/log" "github.com/spf13/cobra" ) var ( // Version info - set by ldflags during build version = "dev" buildTime = "unknown" gitCommit = "unknown" // CLI flags projectName string phase string teamID int roleName string person string output string // Styles titleStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#7C3AED")) textStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#E5E7EB")) successStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#10B981")) errorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#EF4444")) warnStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#F59E0B")) infoStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#3B82F6")) ) func main() { rootCmd := &cobra.Command{ Use: "team", Short: "Team Manager CLI - Manage standardized team layouts", Long: `Team Manager CLI A command-line tool for managing standardized team structures across projects. Integrates with the team_manager.py backend to provide team initialization, role assignments, and status tracking.`, Version: fmt.Sprintf("%s (built: %s, commit: %s)", version, buildTime, gitCommit), } // Global flags rootCmd.PersistentFlags().StringVarP(&projectName, "project", "p", "", "Project name (required for most commands)") rootCmd.PersistentFlags().StringVarP(&output, "output", "o", "text", "Output format: text, json") // Add subcommands rootCmd.AddCommand(initCmd()) rootCmd.AddCommand(listCmd()) rootCmd.AddCommand(assignCmd()) rootCmd.AddCommand(unassignCmd()) rootCmd.AddCommand(startCmd()) rootCmd.AddCommand(completeCmd()) rootCmd.AddCommand(statusCmd()) rootCmd.AddCommand(validateCmd()) rootCmd.AddCommand(phaseGateCmd()) rootCmd.AddCommand(queryCmd()) rootCmd.AddCommand(reassignCmd()) rootCmd.AddCommand(exportCmd()) rootCmd.AddCommand(importCmd()) rootCmd.AddCommand(backupCmd()) rootCmd.AddCommand(restoreCmd()) rootCmd.AddCommand(deleteCmd()) rootCmd.AddCommand(auditCmd()) rootCmd.AddCommand(historyCmd()) rootCmd.AddCommand(templateCmd()) rootCmd.AddCommand(healthCmd()) if err := rootCmd.Execute(); err != nil { log.Error(err) os.Exit(1) } } // getTeamManagerPath returns the path to the team_manager.py script func getTeamManagerPath() string { // Check if TEAM_MANAGER_PATH env var is set if path := os.Getenv("TEAM_MANAGER_PATH"); path != "" { return path } // Try to find relative to executable exe, err := os.Executable() if err == nil { dir := filepath.Dir(exe) // Try multiple relative paths candidates := []string{ filepath.Join(dir, "..", "..", "..", "scripts", "team_manager.py"), filepath.Join(dir, "..", "..", "scripts", "team_manager.py"), filepath.Join(dir, "..", "scripts", "team_manager.py"), filepath.Join(dir, "scripts", "team_manager.py"), } for _, candidate := range candidates { if _, err := os.Stat(candidate); err == nil { return candidate } } } // Default path return "scripts/team_manager.py" } // runTeamManager executes the team_manager.py script with the given arguments // The Python script expects: --project PROJECT COMMAND [args...] func runTeamManager(project string, command string, args ...string) ([]byte, error) { scriptPath := getTeamManagerPath() // Check if Python is available pythonCmd := "python3" if _, err := exec.LookPath("python3"); err != nil { pythonCmd = "python" if _, err := exec.LookPath("python"); err != nil { return nil, fmt.Errorf("Python not found. Please install Python 3") } } // Build command: script --project PROJECT command [args...] cmdArgs := []string{scriptPath} // Always include --project since Python script requires it if project == "" { project = "_cli_health_check_" } cmdArgs = append(cmdArgs, "--project", project) cmdArgs = append(cmdArgs, command) cmdArgs = append(cmdArgs, args...) cmd := exec.Command(pythonCmd, cmdArgs...) cmd.Stderr = os.Stderr output, err := cmd.Output() if err != nil { if exitErr, ok := err.(*exec.ExitError); ok { return nil, fmt.Errorf("team_manager.py failed: %s", string(exitErr.Stderr)) } return nil, fmt.Errorf("failed to run team_manager.py: %w", err) } return output, nil } // initCmd creates the init command func initCmd() *cobra.Command { return &cobra.Command{ Use: "init [project-name]", Short: "Initialize a new project with team structure", Long: `Initialize a new project with the standardized 12-team structure.`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { project := args[0] if output == "json" { result, err := runTeamManager(project, "init", "--format", "json") if err != nil { return err } fmt.Println(string(result)) return nil } fmt.Println(titleStyle.Render("Initializing Team Structure")) fmt.Printf("Project: %s\n\n", textStyle.Render(project)) result, err := runTeamManager(project, "init") if err != nil { return fmt.Errorf("%s %v", errorStyle.Render("Failed to initialize project:"), err) } fmt.Println(string(result)) fmt.Println() fmt.Println(successStyle.Render("✓ Project initialized successfully")) fmt.Println(infoStyle.Render(fmt.Sprintf("Config: .teams/%s.json", project))) return nil }, } } // listCmd creates the list command func listCmd() *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "List all teams for a project", Long: `List all teams and their role assignments for a project.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } listExtraArgs := []string{} if phase != "" { listExtraArgs = append(listExtraArgs, "--phase", phase) } if output == "json" { listExtraArgs = append(listExtraArgs, "--format", "json") result, err := runTeamManager(projectName, "list", listExtraArgs...) if err != nil { return err } fmt.Println(string(result)) return nil } fmt.Println(titleStyle.Render("Team List")) fmt.Printf("Project: %s\n\n", textStyle.Render(projectName)) result, err := runTeamManager(projectName, "list", listExtraArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().StringVar(&phase, "phase", "", "Filter by phase (e.g., 'Phase 1')") return cmd } // assignCmd creates the assign command func assignCmd() *cobra.Command { cmd := &cobra.Command{ Use: "assign", Short: "Assign a person to a role", Long: `Assign a person to a specific role within a team.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } if teamID == 0 { return fmt.Errorf("--team flag is required") } if roleName == "" { return fmt.Errorf("--role flag is required") } if person == "" { return fmt.Errorf("--person flag is required") } assignArgs := []string{ "--team", fmt.Sprintf("%d", teamID), "--role", roleName, "--person", person, } if output == "json" { assignArgs = append(assignArgs, "--format", "json") result, err := runTeamManager(projectName, "assign", assignArgs...) if err != nil { return err } fmt.Println(string(result)) return nil } fmt.Println(titleStyle.Render("Assigning Role")) fmt.Printf("Project: %s\n", textStyle.Render(projectName)) fmt.Printf("Team: %s\n", textStyle.Render(fmt.Sprintf("Team %d", teamID))) fmt.Printf("Role: %s\n", textStyle.Render(roleName)) fmt.Printf("Person: %s\n\n", textStyle.Render(person)) result, err := runTeamManager(projectName, "assign", assignArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().IntVarP(&teamID, "team", "t", 0, "Team ID (1-12)") cmd.Flags().StringVarP(&roleName, "role", "r", "", "Role name to assign") cmd.Flags().StringVar(&person, "person", "", "Person to assign") cmd.MarkFlagRequired("team") cmd.MarkFlagRequired("role") cmd.MarkFlagRequired("person") return cmd } // unassignCmd creates the unassign command func unassignCmd() *cobra.Command { cmd := &cobra.Command{ Use: "unassign", Short: "Remove a person from a role", Long: `Remove a person from a specific role within a team.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } if teamID == 0 { return fmt.Errorf("--team flag is required") } if roleName == "" { return fmt.Errorf("--role flag is required") } unassignArgs := []string{ "--team", fmt.Sprintf("%d", teamID), "--role", roleName, } if output == "json" { unassignArgs = append(unassignArgs, "--format", "json") result, err := runTeamManager(projectName, "unassign", unassignArgs...) if err != nil { return err } fmt.Println(string(result)) return nil } fmt.Println(titleStyle.Render("Unassigning Role")) fmt.Printf("Project: %s\n", textStyle.Render(projectName)) fmt.Printf("Team: %s\n", textStyle.Render(fmt.Sprintf("Team %d", teamID))) fmt.Printf("Role: %s\n\n", textStyle.Render(roleName)) result, err := runTeamManager(projectName, "unassign", unassignArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().IntVarP(&teamID, "team", "t", 0, "Team ID (1-12)") cmd.Flags().StringVarP(&roleName, "role", "r", "", "Role name to unassign") cmd.MarkFlagRequired("team") cmd.MarkFlagRequired("role") return cmd } // startCmd creates the start command func startCmd() *cobra.Command { cmd := &cobra.Command{ Use: "start", Short: "Start a team", Long: `Mark a team as started/in-progress.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } if teamID == 0 { return fmt.Errorf("--team flag is required") } startArgs := []string{"--team", fmt.Sprintf("%d", teamID)} if output == "json" { startArgs = append(startArgs, "--format", "json") result, err := runTeamManager(projectName, "start", startArgs...) if err != nil { return err } fmt.Println(string(result)) return nil } fmt.Println(titleStyle.Render("Starting Team")) fmt.Printf("Project: %s\n", textStyle.Render(projectName)) fmt.Printf("Team: %s\n\n", textStyle.Render(fmt.Sprintf("Team %d", teamID))) result, err := runTeamManager(projectName, "start", startArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().IntVarP(&teamID, "team", "t", 0, "Team ID (1-12)") cmd.MarkFlagRequired("team") return cmd } // completeCmd creates the complete command func completeCmd() *cobra.Command { cmd := &cobra.Command{ Use: "complete", Short: "Complete a team", Long: `Mark a team as completed.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } if teamID == 0 { return fmt.Errorf("--team flag is required") } completeArgs := []string{"--team", fmt.Sprintf("%d", teamID)} if output == "json" { completeArgs = append(completeArgs, "--format", "json") result, err := runTeamManager(projectName, "complete", completeArgs...) if err != nil { return err } fmt.Println(string(result)) return nil } fmt.Println(titleStyle.Render("Completing Team")) fmt.Printf("Project: %s\n", textStyle.Render(projectName)) fmt.Printf("Team: %s\n\n", textStyle.Render(fmt.Sprintf("Team %d", teamID))) result, err := runTeamManager(projectName, "complete", completeArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().IntVarP(&teamID, "team", "t", 0, "Team ID (1-12)") cmd.MarkFlagRequired("team") return cmd } // statusCmd creates the status command func statusCmd() *cobra.Command { cmd := &cobra.Command{ Use: "status", Short: "Show project or phase status", Long: `Display the current status of teams in a project or phase.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } statusArgs := []string{} if phase != "" { statusArgs = append(statusArgs, "--phase", phase) } if output == "json" { statusArgs = append(statusArgs, "--format", "json") result, err := runTeamManager(projectName, "status", statusArgs...) if err != nil { return err } fmt.Println(string(result)) return nil } fmt.Println(titleStyle.Render("Project Status")) fmt.Printf("Project: %s\n\n", textStyle.Render(projectName)) result, err := runTeamManager(projectName, "status", statusArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().StringVar(&phase, "phase", "", "Show status for specific phase") return cmd } // validateCmd creates the validate command func validateCmd() *cobra.Command { return &cobra.Command{ Use: "validate", Short: "Validate team sizes meet requirements", Long: `Validate that all teams have 4-6 members as required by TEAM-007.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } if output == "json" { result, err := runTeamManager(projectName, "validate-size", "--format", "json") if err != nil { return err } fmt.Println(string(result)) return nil } fmt.Println(titleStyle.Render("Team Size Validation")) fmt.Printf("Project: %s\n\n", textStyle.Render(projectName)) result, err := runTeamManager(projectName, "validate-size") if err != nil { return err } fmt.Println(string(result)) return nil }, } } // phaseGateCmd creates the phase-gate command func phaseGateCmd() *cobra.Command { var fromPhase, toPhase int cmd := &cobra.Command{ Use: "phase-gate", Short: "Check phase gate requirements", Long: `Check if requirements are met for transitioning between phases.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } if fromPhase == 0 || toPhase == 0 { return fmt.Errorf("--from and --to flags are required") } phaseGateArgs := []string{ "--from", fmt.Sprintf("%d", fromPhase), "--to", fmt.Sprintf("%d", toPhase), } if output == "json" { phaseGateArgs = append(phaseGateArgs, "--format", "json") result, err := runTeamManager(projectName, "phase-gate-check", phaseGateArgs...) if err != nil { return err } fmt.Println(string(result)) return nil } fmt.Println(titleStyle.Render("Phase Gate Check")) fmt.Printf("Project: %s\n", textStyle.Render(projectName)) fmt.Printf("From: Phase %d → To: Phase %d\n\n", fromPhase, toPhase) result, err := runTeamManager(projectName, "phase-gate-check", phaseGateArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().IntVar(&fromPhase, "from", 0, "Source phase number (1-4)") cmd.Flags().IntVar(&toPhase, "to", 0, "Target phase number (2-5)") cmd.MarkFlagRequired("from") cmd.MarkFlagRequired("to") return cmd } // queryCmd creates the query command func queryCmd() *cobra.Command { var statusFilter, assigneeFilter, roleFilter string cmd := &cobra.Command{ Use: "query", Short: "Query teams with filters", Long: `Query teams with filters for status, assignee, or role.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } queryArgs := []string{} if statusFilter != "" { queryArgs = append(queryArgs, "--status", statusFilter) } if assigneeFilter != "" { queryArgs = append(queryArgs, "--assignee", assigneeFilter) } if roleFilter != "" { queryArgs = append(queryArgs, "--role", roleFilter) } if output == "json" { queryArgs = append(queryArgs, "--format", "json") } result, err := runTeamManager(projectName, "query", queryArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().StringVar(&statusFilter, "status", "", "Filter by status (not_started, active, completed, blocked)") cmd.Flags().StringVar(&assigneeFilter, "assignee", "", "Filter by assignee") cmd.Flags().StringVar(&roleFilter, "role", "", "Filter by role") return cmd } // reassignCmd creates the reassign command func reassignCmd() *cobra.Command { var fromTeam, toTeam int var fromRole, toRole, personName string cmd := &cobra.Command{ Use: "reassign", Short: "Reassign person from one role to another", Long: `Move a person from one role/team to another role/team.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } reassignArgs := []string{ "--from-team", fmt.Sprintf("%d", fromTeam), "--from-role", fromRole, "--to-team", fmt.Sprintf("%d", toTeam), "--to-role", toRole, "--person", personName, } if output == "json" { reassignArgs = append(reassignArgs, "--format", "json") } result, err := runTeamManager(projectName, "reassign", reassignArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().IntVar(&fromTeam, "from-team", 0, "Source team ID") cmd.Flags().StringVar(&fromRole, "from-role", "", "Source role") cmd.Flags().IntVar(&toTeam, "to-team", 0, "Target team ID") cmd.Flags().StringVar(&toRole, "to-role", "", "Target role") cmd.Flags().StringVar(&personName, "person", "", "Person to reassign") cmd.MarkFlagRequired("from-team") cmd.MarkFlagRequired("from-role") cmd.MarkFlagRequired("to-team") cmd.MarkFlagRequired("to-role") cmd.MarkFlagRequired("person") return cmd } // auditCmd creates the audit command func auditCmd() *cobra.Command { var limit int cmd := &cobra.Command{ Use: "audit", Short: "Query audit log", Long: `Query the audit log for project changes.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } auditArgs := []string{} if limit > 0 { auditArgs = append(auditArgs, "--limit", fmt.Sprintf("%d", limit)) } if output == "json" { auditArgs = append(auditArgs, "--format", "json") } result, err := runTeamManager(projectName, "audit", auditArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().IntVar(&limit, "limit", 50, "Number of entries to show") return cmd } // historyCmd creates the history command func historyCmd() *cobra.Command { var startDate, endDate string cmd := &cobra.Command{ Use: "history", Short: "Show team history", Long: `Show history for a specific team.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } if teamID == 0 { return fmt.Errorf("--team flag is required") } historyArgs := []string{ "--team", fmt.Sprintf("%d", teamID), } if startDate != "" { historyArgs = append(historyArgs, "--start-date", startDate) } if endDate != "" { historyArgs = append(historyArgs, "--end-date", endDate) } if output == "json" { historyArgs = append(historyArgs, "--format", "json") } result, err := runTeamManager(projectName, "team-history", historyArgs...) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().IntVarP(&teamID, "team", "t", 0, "Team ID") cmd.Flags().StringVar(&startDate, "start-date", "", "Start date (ISO format)") cmd.Flags().StringVar(&endDate, "end-date", "", "End date (ISO format)") cmd.MarkFlagRequired("team") return cmd } // templateCmd creates the template command func templateCmd() *cobra.Command { var format, outputFile string cmd := &cobra.Command{ Use: "template", Short: "Create template for bulk assignments", Long: `Create a CSV or JSON template for bulk role assignments.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } var cmdName string var fileFlag string switch format { case "csv": cmdName = "template-csv" fileFlag = "--file" case "json": cmdName = "template-json" fileFlag = "--file" default: return fmt.Errorf("unsupported format: %s (use csv or json)", format) } result, err := runTeamManager(projectName, cmdName, fileFlag, outputFile) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().StringVarP(&format, "format", "f", "csv", "Template format (csv or json)") cmd.Flags().StringVarP(&outputFile, "output", "o", "", "Output file path") return cmd } // healthCmd creates the health command func healthCmd() *cobra.Command { return &cobra.Command{ Use: "health", Short: "Check team manager health status", Long: `Check the health status of the team manager.`, RunE: func(cmd *cobra.Command, args []string) error { // Health check doesn't require a project result, err := runTeamManager("", "health") if err != nil { return err } fmt.Println(string(result)) return nil }, } } // exportCmd creates the export command func exportCmd() *cobra.Command { var format string cmd := &cobra.Command{ Use: "export", Short: "Export project data", Long: `Export team assignments and project data to a file.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } var result []byte var err error switch format { case "json": result, err = runTeamManager(projectName, "export-json") case "csv": result, err = runTeamManager(projectName, "export-csv") default: return fmt.Errorf("unsupported export format: %s", format) } if err != nil { return err } // Write to stdout or file fmt.Println(string(result)) return nil }, } cmd.Flags().StringVarP(&format, "format", "f", "json", "Export format (json, csv)") return cmd } // importCmd creates the import command func importCmd() *cobra.Command { var filePath string var format string cmd := &cobra.Command{ Use: "import", Short: "Import project data", Long: `Import team assignments from a file.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } if filePath == "" { return fmt.Errorf("--file flag is required") } var result []byte var err error switch format { case "json": result, err = runTeamManager(projectName, "import-json", "--file", filePath) case "csv": result, err = runTeamManager(projectName, "import-csv", "--file", filePath) default: return fmt.Errorf("unsupported import format: %s", format) } if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().StringVarP(&filePath, "file", "f", "", "Path to import file") cmd.Flags().StringVar(&format, "format", "json", "Import format (json, csv)") cmd.MarkFlagRequired("file") return cmd } // backupCmd creates the backup command func backupCmd() *cobra.Command { return &cobra.Command{ Use: "backup", Short: "List available backups", Long: `List all available backups for the project.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } if output == "json" { result, err := runTeamManager(projectName, "list-backups", "--format", "json") if err != nil { return err } fmt.Println(string(result)) return nil } fmt.Println(titleStyle.Render("Available Backups")) fmt.Printf("Project: %s\n\n", textStyle.Render(projectName)) result, err := runTeamManager(projectName, "list-backups") if err != nil { return err } fmt.Println(string(result)) return nil }, } } // restoreCmd creates the restore command func restoreCmd() *cobra.Command { var backupFile string cmd := &cobra.Command{ Use: "restore", Short: "Restore from backup", Long: `Restore project data from a backup file.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } if backupFile == "" { return fmt.Errorf("--backup flag is required") } fmt.Println(titleStyle.Render("Restoring from Backup")) fmt.Printf("Project: %s\n", textStyle.Render(projectName)) fmt.Printf("Backup: %s\n\n", textStyle.Render(backupFile)) result, err := runTeamManager(projectName, "restore", "--backup", backupFile) if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().StringVarP(&backupFile, "backup", "b", "", "Path to backup file") cmd.MarkFlagRequired("backup") return cmd } // deleteCmd creates the delete command func deleteCmd() *cobra.Command { var force bool cmd := &cobra.Command{ Use: "delete", Short: "Delete project or team", Long: `Delete a project or a specific team from the project.`, RunE: func(cmd *cobra.Command, args []string) error { if projectName == "" { return fmt.Errorf("--project flag is required") } var result []byte var err error if teamID > 0 { // Delete specific team if !force { fmt.Printf("Delete team %d from project '%s'? [y/N]: ", teamID, projectName) var response string fmt.Scanln(&response) if !strings.EqualFold(response, "y") { fmt.Println("Aborted.") return nil } } fmt.Println(titleStyle.Render("Deleting Team")) fmt.Printf("Project: %s\n", textStyle.Render(projectName)) fmt.Printf("Team: %d\n\n", teamID) result, err = runTeamManager(projectName, "delete-team", "--team", fmt.Sprintf("%d", teamID)) } else { // Delete entire project if !force { fmt.Printf("Delete entire project '%s'? This cannot be undone! [y/N]: ", projectName) var response string fmt.Scanln(&response) if !strings.EqualFold(response, "y") { fmt.Println("Aborted.") return nil } } fmt.Println(titleStyle.Render("Deleting Project")) fmt.Printf("Project: %s\n\n", textStyle.Render(projectName)) result, err = runTeamManager(projectName, "delete-project") } if err != nil { return err } fmt.Println(string(result)) return nil }, } cmd.Flags().IntVarP(&teamID, "team", "t", 0, "Team ID to delete (optional - if not specified, deletes entire project)") cmd.Flags().BoolVar(&force, "force", false, "Skip confirmation prompt") return cmd } // Helper function to pretty print JSON func prettyPrintJSON(data []byte) error { var v interface{} if err := json.Unmarshal(data, &v); err != nil { return err } pretty, err := json.MarshalIndent(v, "", " ") if err != nil { return err } fmt.Println(string(pretty)) return nil } // CheckPython returns an error if Python is not available func CheckPython() error { pythonCmd := "python3" if runtime.GOOS == "windows" { pythonCmd = "python" } _, err := exec.LookPath(pythonCmd) if err != nil { _, err = exec.LookPath("python") if err != nil { return fmt.Errorf("Python is required but not found. Please install Python 3") } } return nil }