crew at: don't link windows by default, add --detached flag

When running `gt crew at` from inside tmux:
- No longer auto-links the target session as a tab
- Just prints "Started X. Use C-b s to switch."
- User stays in their current pane

When running from outside tmux:
- Default: attach to the session (existing behavior)
- With -d/--detached: start session without attaching

This gives users more control over tmux session navigation and
reduces confusion for tmux newcomers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-24 15:22:12 -08:00
parent b930704b5f
commit e8dff71b37
3 changed files with 31 additions and 23 deletions

View File

@@ -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 <rig>/crew/<name>/, 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")

View File

@@ -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)
}

View File

@@ -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)