feat: read stdin (#101)

Carlos Alexandro Becker created

* feat: read stdin

Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>

* fix: mode pipe

---------

Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>

Change summary

cmd/root.go | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

Detailed changes

cmd/root.go 🔗

@@ -3,6 +3,7 @@ package cmd
 import (
 	"context"
 	"fmt"
+	"io"
 	"os"
 	"sync"
 	"time"
@@ -18,6 +19,7 @@ import (
 	"github.com/charmbracelet/crush/internal/tui"
 	"github.com/charmbracelet/crush/internal/version"
 	"github.com/charmbracelet/fang"
+	"github.com/charmbracelet/x/term"
 	"github.com/spf13/cobra"
 )
 
@@ -99,6 +101,12 @@ to assist developers in writing, debugging, and understanding code directly from
 		// Initialize MCP tools early for both modes
 		initMCPTools(ctx, app)
 
+		prompt, err = maybePrependStdin(prompt)
+		if err != nil {
+			logging.Error("Failed to read stdin: %v", err)
+			return err
+		}
+
 		// Non-interactive mode
 		if prompt != "" {
 			// Run non-interactive flow using the App method
@@ -301,3 +309,21 @@ func init() {
 		return format.SupportedFormats, cobra.ShellCompDirectiveNoFileComp
 	})
 }
+
+func maybePrependStdin(prompt string) (string, error) {
+	if term.IsTerminal(os.Stdin.Fd()) {
+		return prompt, nil
+	}
+	fi, err := os.Stdin.Stat()
+	if err != nil {
+		return prompt, err
+	}
+	if fi.Mode()&os.ModeNamedPipe == 0 {
+		return prompt, nil
+	}
+	bts, err := io.ReadAll(os.Stdin)
+	if err != nil {
+		return prompt, err
+	}
+	return string(bts) + "\n\n" + prompt, nil
+}