package cmd import ( "bufio" "fmt" "os" "strings" "github.com/fatih/color" "github.com/spf13/cobra" "gmgauthier.com/grokkit/config" "gmgauthier.com/grokkit/internal/grok" ) var scaffoldCmd = &cobra.Command{ Use: "scaffold [path]", Short: "Scaffold a new file with Grok (safe preview + confirmation)", Long: `Generate a new file from a description. Shows preview and requires explicit confirmation before writing.`, Run: runScaffold, } var scaffoldDescription string // set by agent mode when calling from chat --agent func init() { scaffoldCmd.Flags().String("description", "", "Scaffold description (used internally by agent mode)") rootCmd.AddCommand(scaffoldCmd) } func runScaffold(cmd *cobra.Command, args []string) { if len(args) == 0 { color.Red("Usage: grokkit scaffold ") return } path := args[0] // If agent mode passed a description, use it directly var description string if scaffoldDescription != "" { description = scaffoldDescription color.Cyan("Agent description: %s", description) } else { // Normal interactive mode color.Yellow("Enter description for %s: ", path) scanner := bufio.NewScanner(os.Stdin) if scanner.Scan() { description = strings.TrimSpace(scanner.Text()) } if description == "" { color.Yellow("No description provided.") return } } client := grok.NewClient() messages := buildScaffoldMessages(path, description) color.Yellow("Asking Grok to scaffold %s...", path) scaffolded := client.Stream(messages, config.GetModel("scaffold", "")) // Show preview color.Cyan("\n--- Proposed content for %s ---\n%s\n--------------------------------", path, scaffolded) var confirm string color.Yellow("Create %s with this content? (y/n): ", path) fmt.Scanln(&confirm) if confirm != "y" && confirm != "Y" { color.Yellow("Aborted.") return } if err := os.WriteFile(path, []byte(scaffolded), 0644); err != nil { color.Red("Failed to write file: %v", err) return } color.Green("✅ Successfully scaffolded %s", path) } // buildScaffoldMessages is kept unchanged from original func buildScaffoldMessages(path, description string) []map[string]string { return []map[string]string{ { "role": "system", "content": "You are an expert programmer. Generate a complete, well-structured file based on the user's description. Return ONLY the full file content. Do not include any explanations or markdown fences.", }, { "role": "user", "content": fmt.Sprintf("Path: %s\n\nDescription: %s", path, description), }, } }