diff --git a/packages/tui/cmd/opencode/main.go b/packages/tui/cmd/opencode/main.go index a9283525..ccb30d03 100644 --- a/packages/tui/cmd/opencode/main.go +++ b/packages/tui/cmd/opencode/main.go @@ -3,6 +3,7 @@ package main import ( "context" "encoding/json" + "io" "log/slog" "os" "path/filepath" @@ -56,11 +57,6 @@ func main() { option.WithBaseURL(url), ) - if err != nil { - slog.Error("Failed to create client", "error", err) - os.Exit(1) - } - // Create main context for the application ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -70,8 +66,25 @@ func main() { panic(err) } + stat, err := os.Stdin.Stat() + if err != nil { + slog.Error("Failed to stat stdin", "error", err) + os.Exit(1) + } + + // Check if there's data piped to stdin + var stdinContent string + if (stat.Mode() & os.ModeCharDevice) == 0 { + stdin, err := io.ReadAll(os.Stdin) + if err != nil { + slog.Error("Failed to read stdin", "error", err) + os.Exit(1) + } + stdinContent = strings.TrimSpace(string(stdin)) + } + program := tea.NewProgram( - tui.NewModel(app_), + tui.NewModel(app_, stdinContent), tea.WithAltScreen(), tea.WithKeyboardEnhancements(), tea.WithMouseCellMotion(), diff --git a/packages/tui/internal/components/status/status.go b/packages/tui/internal/components/status/status.go index 791267e0..e2293af1 100644 --- a/packages/tui/internal/components/status/status.go +++ b/packages/tui/internal/components/status/status.go @@ -95,7 +95,7 @@ func (m statusComponent) View() string { Render(m.app.Info.Path.Cwd) sessionInfo := "" - if m.app.Session.ID != "" { + if m.app.Session.ID != "" && m.app.Model != nil { tokens := float64(0) cost := float64(0) contextWindow := m.app.Model.Limit.Context diff --git a/packages/tui/internal/tui/tui.go b/packages/tui/internal/tui/tui.go index 150a1b26..6c0bd6ae 100644 --- a/packages/tui/internal/tui/tui.go +++ b/packages/tui/internal/tui/tui.go @@ -66,6 +66,7 @@ type appModel struct { fileViewerStart int fileViewerEnd int fileViewerHit bool + stdinContent string } func (a appModel) Init() tea.Cmd { @@ -89,6 +90,16 @@ func (a appModel) Init() tea.Cmd { return dialog.ShowInitDialogMsg{Show: shouldShow} }) + // If we have stdin content, send it as the first message + if a.stdinContent != "" { + cmds = append(cmds, func() tea.Msg { + return app.SendMsg{ + Text: a.stdinContent, + Attachments: []opencode.FilePartParam{}, + } + }) + } + return tea.Batch(cmds...) } @@ -974,7 +985,7 @@ func (a appModel) executeCommand(command commands.Command) (tea.Model, tea.Cmd) return a, tea.Batch(cmds...) } -func NewModel(app *app.App) tea.Model { +func NewModel(app *app.App, stdinContent string) tea.Model { commandProvider := completions.NewCommandCompletionProvider(app) fileProvider := completions.NewFileAndFolderContextGroup(app) @@ -1004,6 +1015,7 @@ func NewModel(app *app.App) tea.Model { interruptKeyState: InterruptKeyIdle, fileViewer: fileviewer.New(app), messagesRight: app.State.MessagesRight, + stdinContent: stdinContent, } return model