package cmd import ( "fmt" "os" "path/filepath" "github.com/spf13/cobra" ) var initCmd = &cobra.Command{ Use: "init [path]", Short: "Initialize Devour for a project", Long: `Initialize Devour configuration for a project. Creates a devour.yaml configuration file and the necessary directory structure for storing documents and indexes. Examples: devour init # Initialize in current directory devour init ./my-project # Initialize in specific directory devour init --remote # Initialize with remote mode config`, RunE: runInit, } var ( initRemote bool initForce bool ) func init() { initCmd.Flags().BoolVar(&initRemote, "remote", false, "configure for remote mode") initCmd.Flags().BoolVarP(&initForce, "force", "f", false, "overwrite existing config") } func runInit(cmd *cobra.Command, args []string) error { // Determine target directory targetDir := "." if len(args) > 0 { targetDir = args[0] } // Create directory if it doesn't exist if err := os.MkdirAll(targetDir, 0755); err != nil { return fmt.Errorf("failed to create directory: %w", err) } configPath := filepath.Join(targetDir, "devour.yaml") // Check if config already exists if _, err := os.Stat(configPath); err == nil && !initForce { return fmt.Errorf("config file already exists at %s (use --force to overwrite)", configPath) } // Create default config config := generateDefaultConfig(initRemote) if err := os.WriteFile(configPath, []byte(config), 0644); err != nil { return fmt.Errorf("failed to write config: %w", err) } // Create data directories dataDir := filepath.Join(targetDir, "devour_data") dirs := []string{ filepath.Join(dataDir, "docs"), filepath.Join(dataDir, "index"), filepath.Join(dataDir, "metadata"), filepath.Join(dataDir, "cache"), } for _, dir := range dirs { if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("failed to create directory %s: %w", dir, err) } } fmt.Printf("✓ Created config at %s\n", configPath) fmt.Printf("✓ Created data directories at %s\n", dataDir) fmt.Println("\nNext steps:") fmt.Println(" 1. Set OPENAI_API_KEY environment variable") fmt.Println(" 2. Add sources to devour.yaml") fmt.Println(" 3. Run 'devour scrape ' to index documentation") return nil } func generateDefaultConfig(remote bool) string { mode := "local" if remote { mode = "remote" } return fmt.Sprintf(`# Devour Configuration version: 1 # Storage paths storage: docs_dir: ./devour_data/docs index_dir: ./devour_data/index metadata_dir: ./devour_data/metadata # Embedding settings embeddings: provider: openai model: text-embedding-3-small dimensions: 1536 api_key: ${OPENAI_API_KEY} batch_size: 100 # Vector database vector_db: type: chromem persist: true similarity_metric: cosine # Scraping settings scraper: user_agent: "Devour/1.0" timeout: 30s retry_count: 3 concurrency: 10 rate_limit: 500ms max_depth: 3 cache_dir: ./devour_data/cache # Scheduler scheduler: enabled: true interval: 72h check_method: hash # Server settings server: mode: %s port: 8080 host: localhost # Sources (add your own) sources: [] # - name: example-docs # type: url # url: https://docs.example.com # include: ["**/*.md", "**/*.html"] `, mode) }