From 630ff8c5dfeaabc96b8f05917d28455ad7e1075e Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Thu, 19 Mar 2026 11:06:13 -0300 Subject: [PATCH] feat: add support for `--session` and `--continue` for the tui (#2422) These flags were previously only available for `crush run`. --- internal/cmd/root.go | 23 ++++++++++++++++++++++- internal/ui/model/ui.go | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 060d94c13a3d1cb9b927ebfbddc473aa1593e9dc..39453f76a7dee055c17b3c220128a20242846c48 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -37,6 +37,9 @@ func init() { rootCmd.PersistentFlags().BoolP("debug", "d", false, "Debug") rootCmd.Flags().BoolP("help", "h", false, "Help") rootCmd.Flags().BoolP("yolo", "y", false, "Automatically accept all permissions (dangerous mode)") + rootCmd.Flags().StringP("session", "s", "", "Continue a previous session by ID") + rootCmd.Flags().BoolP("continue", "C", false, "Continue the most recent session") + rootCmd.MarkFlagsMutuallyExclusive("session", "continue") rootCmd.AddCommand( runCmd, @@ -73,21 +76,39 @@ crush --yolo # Run with custom data directory crush --data-dir /path/to/custom/.crush + +# Continue a previous session +crush --session {session-id} + +# Continue the most recent session +crush --continue `, RunE: func(cmd *cobra.Command, args []string) error { + sessionID, _ := cmd.Flags().GetString("session") + continueLast, _ := cmd.Flags().GetBool("continue") + app, err := setupAppWithProgressBar(cmd) if err != nil { return err } defer app.Shutdown() + // Resolve session ID if provided + if sessionID != "" { + sess, err := resolveSessionID(cmd.Context(), app.Sessions, sessionID) + if err != nil { + return err + } + sessionID = sess.ID + } + event.AppInitialized() // Set up the TUI. var env uv.Environ = os.Environ() com := common.DefaultCommon(app) - model := ui.New(com) + model := ui.New(com, sessionID, continueLast) program := tea.NewProgram( model, diff --git a/internal/ui/model/ui.go b/internal/ui/model/ui.go index ed0a7dd6851fbbe0b16540a4b72dc2486e96f438..f126020d32f2c3c974a0a9435bc69ae56380330d 100644 --- a/internal/ui/model/ui.go +++ b/internal/ui/model/ui.go @@ -139,6 +139,11 @@ type UI struct { // keeps track of read files while we don't have a session id sessionFileReads []string + // initialSessionID is set when loading a specific session on startup. + initialSessionID string + // continueLastSession is set to continue the most recent session on startup. + continueLastSession bool + lastUserMessageTime int64 // The width and height of the terminal in cells. @@ -242,7 +247,7 @@ type UI struct { } // New creates a new instance of the [UI] model. -func New(com *common.Common) *UI { +func New(com *common.Common, initialSessionID string, continueLast bool) *UI { // Editor components ta := textarea.New() ta.SetStyles(com.Styles.TextArea) @@ -298,6 +303,8 @@ func New(com *common.Common) *UI { mcpStates: make(map[string]mcp.ClientInfo), notifyBackend: notification.NoopBackend{}, notifyWindowFocused: true, + initialSessionID: initialSessionID, + continueLastSession: continueLast, } status := NewStatus(com, ui) @@ -346,9 +353,34 @@ func (m *UI) Init() tea.Cmd { cmds = append(cmds, m.loadCustomCommands()) // load prompt history async cmds = append(cmds, m.loadPromptHistory()) + // load initial session if specified + if cmd := m.loadInitialSession(); cmd != nil { + cmds = append(cmds, cmd) + } return tea.Batch(cmds...) } +// loadInitialSession loads the initial session if one was specified on startup. +func (m *UI) loadInitialSession() tea.Cmd { + switch { + case m.state != uiLanding: + // Only load if we're in landing state (i.e., fully configured) + return nil + case m.initialSessionID != "": + return m.loadSession(m.initialSessionID) + case m.continueLastSession: + return func() tea.Msg { + sess, err := m.com.App.Sessions.GetLast(context.Background()) + if err != nil { + return nil + } + return m.loadSession(sess.ID)() + } + default: + return nil + } +} + // sendNotification returns a command that sends a notification if allowed by policy. func (m *UI) sendNotification(n notification.Notification) tea.Cmd { if !m.shouldSendNotification() {