Skip to content

Commit d8966cd

Browse files
committed
feat: fix macOS permissions and improve CLI commands
- Fix macOS "operation not permitted" errors (Setsid → Setpgid) - Simplify 'loex list' output (remove service details from main view) - Add individual service start: 'loex start \[project\] \[service\]' - Move detect to subcommand: 'loex config detect \[project\]' - Enhance detect to skip existing services and show current configuration - Improve overall CLI usability and command structure
1 parent 6209729 commit d8966cd

7 files changed

Lines changed: 170 additions & 147 deletions

File tree

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ loex init myproject
4040
```bash
4141
# Option A: Auto-detect services in current directory
4242
cd /path/to/your/project
43-
loex detect myproject
43+
loex config detect myproject
4444

4545
# Option B: Interactive wizard
4646
loex config wizard myproject
@@ -96,7 +96,7 @@ loex rename [old-name] [new-name]
9696

9797
```bash
9898
# Auto-detect services in current directory
99-
loex detect [project-name]
99+
loex config detect [project-name]
100100

101101
# Interactive configuration wizard
102102
loex config wizard [project-name]
@@ -117,21 +117,27 @@ loex config myapp db "docker-compose up -d"
117117
loex start [project-name]
118118

119119
# Start specific service
120-
loex start [project-name] --service frontend
120+
loex start [project-name] [service-name]
121+
122+
# Examples:
123+
loex start myapp # Start all services
124+
loex start myapp frontend # Start only frontend
125+
loex start myapp backend # Start only backend
126+
loex start myapp db # Start only database
121127

122128
# Stop all services
123129
loex stop [project-name]
124130

125131
# Stop specific service
126-
loex stop [project-name] --service backend
132+
loex stop [project-name] [service-name]
127133

128134
# Check service status
129135
loex status [project-name]
130136
```
131137

132138
## 🔍 Auto-Detection
133139

134-
Loex automatically detects common project types and suggests appropriate commands when using the `detect` or `wizard` commands.
140+
Loex automatically detects common project types and suggests appropriate commands when using the `config detect` or `config wizard` commands.
135141

136142
**💡 Important**: Run the command from your project's root directory to enable auto-detection. Loex analyzes files in the current directory to suggest the best commands for each service type.
137143

@@ -180,7 +186,7 @@ loex start webapp
180186
```bash
181187
# Use auto-detection (run from project root directory)
182188
cd /path/to/your/project
183-
loex detect ecommerce
189+
loex config detect ecommerce
184190

185191
# Or use wizard for interactive setup
186192
loex config wizard ecommerce

cmd/config.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,9 +431,146 @@ var configWizardCmd = &cobra.Command{
431431
},
432432
}
433433

434+
var configDetectCmd = &cobra.Command{
435+
Use: "detect [project]",
436+
Short: "Auto-detect and configure services in current directory",
437+
Long: `Automatically detect services in the current directory and configure them for the project.`,
438+
Args: cobra.ExactArgs(1),
439+
Run: func(cmd *cobra.Command, args []string) {
440+
projectName := args[0]
441+
442+
configManager, err := config.NewManager()
443+
if err != nil {
444+
fmt.Printf("Error: %v\n", err)
445+
os.Exit(1)
446+
}
447+
448+
// Load or create project
449+
var project *models.Project
450+
if configManager.ProjectExists(projectName) {
451+
project, err = configManager.LoadProject(projectName)
452+
if err != nil {
453+
fmt.Printf("Failed to load project: %v\n", err)
454+
os.Exit(1)
455+
}
456+
fmt.Printf("Checking project '%s' for new services\n\n", projectName)
457+
} else {
458+
project = &models.Project{
459+
Name: projectName,
460+
Services: make(map[models.ServiceType]models.Service),
461+
Created: time.Now(),
462+
Updated: time.Now(),
463+
}
464+
fmt.Printf("Creating new project '%s'\n\n", projectName)
465+
}
466+
467+
// Get current directory
468+
cwd, _ := os.Getwd()
469+
fmt.Printf("Analyzing current directory: %s\n\n", cwd)
470+
471+
// Auto-detect services in current directory
472+
detector := detector.New()
473+
results, err := detector.DetectServices(cwd)
474+
if err != nil {
475+
fmt.Printf("Failed to detect services: %v\n", err)
476+
os.Exit(1)
477+
}
478+
479+
if len(results) == 0 {
480+
fmt.Printf("No services detected in current directory.\n")
481+
fmt.Printf("Make sure you're in a project directory (with package.json, go.mod, etc.)\n")
482+
return
483+
}
484+
485+
// Check for existing services and show them
486+
var existingServices []models.ServiceType
487+
var hasNewServices bool
488+
489+
for _, result := range results {
490+
if _, exists := project.Services[result.Service]; exists {
491+
existingServices = append(existingServices, result.Service)
492+
} else {
493+
hasNewServices = true
494+
}
495+
}
496+
497+
// Show existing services
498+
if len(existingServices) > 0 {
499+
fmt.Printf("Already configured services in this project:\n")
500+
for _, serviceType := range existingServices {
501+
service := project.Services[serviceType]
502+
fmt.Printf(" - %s: %s\n", serviceType, service.Command)
503+
}
504+
fmt.Println()
505+
}
506+
507+
// Check if there are new services to configure
508+
if !hasNewServices {
509+
fmt.Printf("No new services detected. All detected services are already configured.\n")
510+
return
511+
}
512+
513+
fmt.Printf("New services detected:\n")
514+
for _, result := range results {
515+
if _, exists := project.Services[result.Service]; !exists {
516+
fmt.Printf(" - %s: %s (%s)\n", result.Service, result.Command, result.DetectionReason)
517+
}
518+
}
519+
fmt.Println()
520+
521+
reader := bufio.NewReader(os.Stdin)
522+
523+
// Configure each new detected service
524+
for _, result := range results {
525+
if _, exists := project.Services[result.Service]; exists {
526+
continue // Skip already configured services
527+
}
528+
fmt.Printf("Configuring %s service:\n", result.Service)
529+
fmt.Printf("Auto-detected command: %s\n", result.Command)
530+
fmt.Printf("Reason: %s\n", result.DetectionReason)
531+
fmt.Print("Use this command? (Y/n): ")
532+
533+
response, _ := reader.ReadString('\n')
534+
response = strings.TrimSpace(strings.ToLower(response))
535+
536+
var command string
537+
if response == "" || response == "y" || response == "yes" {
538+
command = result.Command
539+
} else {
540+
fmt.Printf("Enter custom command for %s service: ", result.Service)
541+
cmdInput, _ := reader.ReadString('\n')
542+
command = strings.TrimSpace(cmdInput)
543+
544+
if command == "" {
545+
fmt.Printf("No command provided, skipping %s service\n\n", result.Service)
546+
continue
547+
}
548+
}
549+
550+
// Save service
551+
project.Services[result.Service] = models.Service{
552+
Type: result.Service,
553+
Command: command,
554+
Dir: cwd,
555+
}
556+
557+
fmt.Printf("%s service configured\n\n", result.Service)
558+
}
559+
560+
if err := configManager.SaveProject(project); err != nil {
561+
fmt.Printf("Failed to save project: %v\n", err)
562+
os.Exit(1)
563+
}
564+
565+
fmt.Printf("Project '%s' configured successfully with %d service(s)\n", projectName, len(project.Services))
566+
fmt.Printf("Use 'loex start %s' to start services\n", projectName)
567+
},
568+
}
569+
434570
func init() {
435571
configCmd.AddCommand(configSetCmd)
436572
configCmd.AddCommand(configWizardCmd)
573+
configCmd.AddCommand(configDetectCmd)
437574

438575
configSetCmd.Flags().StringVar(&dirFlag, "dir", "", "Directory path for the service")
439576
}

cmd/detect.go

Lines changed: 0 additions & 122 deletions
This file was deleted.

cmd/list.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,9 @@ var listCmd = &cobra.Command{
9292

9393
serviceCount := len(project.Services)
9494
fmt.Printf(" %s (%d service(s))\n", projectName, serviceCount)
95-
96-
if serviceCount > 0 {
97-
for serviceType := range project.Services {
98-
fmt.Printf(" - %s\n", serviceType)
99-
}
100-
}
101-
fmt.Println()
10295
}
10396

97+
fmt.Println()
10498
fmt.Printf("Use 'loex list [project]' to see detailed configuration\n")
10599
fmt.Printf("Use 'loex status [project]' to check service status\n")
106100
fmt.Printf("Use 'loex start [project]' to start services\n")

cmd/root.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ func init() {
6767
rootCmd.AddCommand(removeCmd)
6868
rootCmd.AddCommand(renameCmd)
6969
rootCmd.AddCommand(configCmd)
70-
rootCmd.AddCommand(detectCmd)
7170
rootCmd.AddCommand(versionCmd)
7271
rootCmd.AddCommand(updateCmd)
7372

0 commit comments

Comments
 (0)