Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions internal/session/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -1923,7 +1923,7 @@ func (i *Instance) Start() error {
// Build tmux option overrides from config (e.g. allow-passthrough = "all").
// Sandbox sessions also get remain-on-exit for dead-pane detection.
i.tmuxSession.OptionOverrides = i.buildTmuxOptionOverrides()
i.tmuxSession.RunCommandAsInitialProcess = i.IsSandboxed()
i.tmuxSession.RunCommandAsInitialProcess = i.IsSandboxed() || i.Tool != "shell"

// Start the tmux session
if err := i.tmuxSession.Start(command); err != nil {
Expand Down Expand Up @@ -2039,7 +2039,7 @@ func (i *Instance) StartWithMessage(message string) error {
// Build tmux option overrides from config (e.g. allow-passthrough = "all").
// Sandbox sessions also get remain-on-exit for dead-pane detection.
i.tmuxSession.OptionOverrides = i.buildTmuxOptionOverrides()
i.tmuxSession.RunCommandAsInitialProcess = i.IsSandboxed()
i.tmuxSession.RunCommandAsInitialProcess = i.IsSandboxed() || i.Tool != "shell"

// Start the tmux session
if err := i.tmuxSession.Start(command); err != nil {
Expand Down Expand Up @@ -4042,7 +4042,7 @@ func (i *Instance) Restart() error {
// Build tmux option overrides from config (e.g. allow-passthrough = "all").
// Sandbox sessions also get remain-on-exit for dead-pane detection.
i.tmuxSession.OptionOverrides = i.buildTmuxOptionOverrides()
i.tmuxSession.RunCommandAsInitialProcess = i.IsSandboxed()
i.tmuxSession.RunCommandAsInitialProcess = i.IsSandboxed() || i.Tool != "shell"

mcpLog.Debug("restart_starting_new_session", slog.String("command", command))

Expand Down
15 changes: 10 additions & 5 deletions internal/tmux/tmux.go
Original file line number Diff line number Diff line change
Expand Up @@ -1181,13 +1181,18 @@ func (s *Session) Start(command string) error {
workDir = os.Getenv("HOME")
}

// Create new tmux session in detached mode.
// Sandbox sessions launch command as the pane process for dead-pane restart.
// Non-sandbox sessions keep the legacy shell+send flow.
// Create new tmux session in detached mode with the command as the initial
// process. This avoids the slow shell-wait-sendkeys path (~2s pane ready poll).
// Commands containing bash-specific syntax are wrapped for fish compatibility.
startWithInitialProcess := command != "" && s.RunCommandAsInitialProcess
args := []string{"new-session", "-d", "-s", s.Name, "-c", workDir}
if startWithInitialProcess {
args = append(args, command)
cmdToStart := command
if strings.Contains(command, "$(") || strings.Contains(command, "session_id=") {
escapedCmd := strings.ReplaceAll(command, "'", "'\"'\"'")
cmdToStart = fmt.Sprintf("bash -c '%s'", escapedCmd)
}
Comment on lines +1191 to +1194
args = append(args, cmdToStart)
Comment on lines +1190 to +1195
Comment on lines +1184 to +1195
}
cmd := exec.Command("tmux", args...)
output, err := cmd.CombinedOutput()
Expand Down Expand Up @@ -1288,7 +1293,7 @@ func (s *Session) Start(command string) error {
}
}

// Legacy behavior for non-sandbox sessions: start shell first, then send command.
// Fallback: if RunCommandAsInitialProcess is false, send command via send-keys.
if command != "" && !startWithInitialProcess {
cmdToSend := command
// Commands containing bash-specific syntax must be wrapped for fish users.
Expand Down
Loading