diff --git a/internal/cmd/crew.go b/internal/cmd/crew.go index 594d1eb7..17fdfb20 100644 --- a/internal/cmd/crew.go +++ b/internal/cmd/crew.go @@ -6,13 +6,14 @@ import ( // Crew command flags var ( - crewRig string - crewBranch bool - crewJSON bool - crewForce bool - crewNoTmux bool - crewMessage string - crewAccount string + crewRig string + crewBranch bool + crewJSON bool + crewForce bool + crewNoTmux bool + crewDetached bool + crewMessage string + crewAccount string ) var crewCmd = &cobra.Command{ @@ -79,6 +80,12 @@ var crewAtCmd = &cobra.Command{ Creates a new tmux session if none exists, or attaches to existing. Use --no-tmux to just print the directory path instead. +When run from inside tmux, the session is started but you stay in your +current pane. Use C-b s to switch to the new session. + +When run from outside tmux, you are attached to the session (unless +--detached is specified). + Role Discovery: If no name is provided, attempts to detect the crew workspace from the current directory. If you're in /crew//, it will attach to @@ -87,6 +94,7 @@ Role Discovery: Examples: gt crew at dave # Attach to dave's session gt crew at # Auto-detect from cwd + gt crew at dave --detached # Start session without attaching gt crew at dave --no-tmux # Just print path`, Args: cobra.MaximumNArgs(1), RunE: runCrewAt, @@ -198,6 +206,7 @@ func init() { crewAtCmd.Flags().StringVar(&crewRig, "rig", "", "Rig to use") crewAtCmd.Flags().BoolVar(&crewNoTmux, "no-tmux", false, "Just print directory path") + crewAtCmd.Flags().BoolVarP(&crewDetached, "detached", "d", false, "Start session without attaching") crewAtCmd.Flags().StringVar(&crewAccount, "account", "", "Claude Code account handle to use (overrides default)") crewRemoveCmd.Flags().StringVar(&crewRig, "rig", "", "Rig to use") diff --git a/internal/cmd/crew_at.go b/internal/cmd/crew_at.go index 3b85c666..4a491c45 100644 --- a/internal/cmd/crew_at.go +++ b/internal/cmd/crew_at.go @@ -160,6 +160,18 @@ func runCrewAt(cmd *cobra.Command, args []string) error { return execClaude("gt prime") } - // Attach to session using exec to properly forward TTY + // If inside tmux (but different session), don't switch - just inform user + if tmux.IsInsideTmux() { + fmt.Printf("Started %s/%s. Use C-b s to switch.\n", r.Name, name) + return nil + } + + // Outside tmux: attach unless --detached flag is set + if crewDetached { + fmt.Printf("Started %s/%s. Run 'gt crew at %s' to attach.\n", r.Name, name, name) + return nil + } + + // Attach to session return attachToTmuxSession(sessionID) } diff --git a/internal/cmd/crew_helpers.go b/internal/cmd/crew_helpers.go index 1e727401..d17aa7f7 100644 --- a/internal/cmd/crew_helpers.go +++ b/internal/cmd/crew_helpers.go @@ -12,7 +12,6 @@ import ( "github.com/steveyegge/gastown/internal/git" "github.com/steveyegge/gastown/internal/rig" "github.com/steveyegge/gastown/internal/style" - "github.com/steveyegge/gastown/internal/tmux" "github.com/steveyegge/gastown/internal/workspace" ) @@ -169,21 +168,9 @@ func isInTmuxSession(targetSession string) bool { return currentSession == targetSession } -// attachToTmuxSession attaches to a tmux session with smart behavior: -// - If already inside tmux: links the session as a new tab (use C-b n/p to switch) -// - If outside tmux: attaches normally (takes over terminal) +// attachToTmuxSession attaches to a tmux session. +// Should only be called from outside tmux. func attachToTmuxSession(sessionID string) error { - // If already inside tmux, link the window as a tab instead of switching sessions - if tmux.IsInsideTmux() { - t := tmux.NewTmux() - if err := t.LinkWindow(sessionID, 0); err != nil { - return fmt.Errorf("linking window: %w", err) - } - fmt.Printf("Linked %s as a new tab. Use C-b n to switch to it.\n", sessionID) - return nil - } - - // Outside tmux: attach normally tmuxPath, err := exec.LookPath("tmux") if err != nil { return fmt.Errorf("tmux not found: %w", err)