@@ -3,6 +3,7 @@ package tui
7 "github.com/charmbracelet/bubbles/key"
8 "github.com/charmbracelet/bubbles/key"
8 tea "github.com/charmbracelet/bubbletea"
9 tea "github.com/charmbracelet/bubbletea"
@@ -125,6 +126,9 @@ type appModel struct {
126 showThemeDialog bool
127 showThemeDialog bool
127 themeDialog dialog.ThemeDialog
128 themeDialog dialog.ThemeDialog
130+ showArgumentsDialog bool
131+ argumentsDialog dialog.ArgumentsDialogCmp
130func (a appModel) Init() tea.Cmd {
134func (a appModel) Init() tea.Cmd {
@@ -199,6 +203,13 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
199 cmds = append(cmds, filepickerCmd)
203 cmds = append(cmds, filepickerCmd)
201 a.initDialog.SetSize(msg.Width, msg.Height)
205 a.initDialog.SetSize(msg.Width, msg.Height)
207+ if a.showArgumentsDialog {
208+ a.argumentsDialog.SetSize(msg.Width, msg.Height)
209+ args, argsCmd := a.argumentsDialog.Update(msg)
210+ a.argumentsDialog = args.(dialog.ArgumentsDialogCmp)
211+ cmds = append(cmds, argsCmd, a.argumentsDialog.Init())
203 return a, tea.Batch(cmds...)
214 return a, tea.Batch(cmds...)
204 // Status
215 // Status
@@ -346,8 +357,37 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
346 return a, msg.Command.Handler(msg.Command)
357 return a, msg.Command.Handler(msg.Command)
348 return a, util.ReportInfo("Command selected: " + msg.Command.Title)
359 return a, util.ReportInfo("Command selected: " + msg.Command.Title)
361+ case dialog.ShowArgumentsDialogMsg:
362+ // Show arguments dialog
363+ a.argumentsDialog = dialog.NewArgumentsDialogCmp(msg.CommandID, msg.Content)
364+ a.showArgumentsDialog = true
365+ return a, a.argumentsDialog.Init()
367+ case dialog.CloseArgumentsDialogMsg:
368+ // Close arguments dialog
369+ a.showArgumentsDialog = false
371+ // If submitted, replace $ARGUMENTS and run the command
373+ // Replace $ARGUMENTS with the provided arguments
374+ content := strings.ReplaceAll(msg.Content, "$ARGUMENTS", msg.Arguments)
376+ // Execute the command with arguments
377+ return a, util.CmdHandler(dialog.CommandRunCustomMsg{
350 case tea.KeyMsg:
383 case tea.KeyMsg:
384+ // If arguments dialog is open, let it handle the key press first
385+ if a.showArgumentsDialog {
386+ args, cmd := a.argumentsDialog.Update(msg)
387+ a.argumentsDialog = args.(dialog.ArgumentsDialogCmp)
353 case key.Matches(msg, keys.Quit):
393 case key.Matches(msg, keys.Quit):
@@ -368,6 +408,9 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
368 if a.showModelDialog {
408 if a.showModelDialog {
369 a.showModelDialog = false
409 a.showModelDialog = false
411+ if a.showArgumentsDialog {
412+ a.showArgumentsDialog = false
371 return a, nil
414 return a, nil
372 case key.Matches(msg, keys.SwitchSession):
415 case key.Matches(msg, keys.SwitchSession):
373 if a.currentPage == page.ChatPage && !a.showQuit && !a.showPermissions && !a.showCommandDialog {
416 if a.currentPage == page.ChatPage && !a.showQuit && !a.showPermissions && !a.showCommandDialog {
@@ -746,6 +789,21 @@ func (a appModel) View() string {
793+ if a.showArgumentsDialog {
794+ overlay := a.argumentsDialog.View()
795+ row := lipgloss.Height(appView) / 2
796+ row -= lipgloss.Height(overlay) / 2
797+ col := lipgloss.Width(appView) / 2
798+ col -= lipgloss.Width(overlay) / 2
799+ appView = layout.PlaceOverlay(
750 return appView
808 return appView
@@ -792,5 +850,16 @@ If there are Cursor rules (in .cursor/rules/ or .cursorrules) or Copilot rules (
854+ // Load custom commands
855+ customCommands, err := dialog.LoadCustomCommands()
857+ logging.Warn("Failed to load custom commands", "error", err)
859+ for _, cmd := range customCommands {
860+ model.RegisterCommand(cmd)
795 return model
864 return model