Skip to content
Merged
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
23 changes: 2 additions & 21 deletions internal/cli/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ package cli

import (
"fmt"
"os"
"os/exec"
"strings"
"syscall"

"github.com/spf13/cobra"

Expand Down Expand Up @@ -103,24 +100,8 @@ func runAttachCmd(cmd *cobra.Command, args []string) error {
fmt.Printf("✅ Session '%s' recreated successfully\n", sessionToAttach.Core.Name)
}

// Attach to tmux session
fmt.Printf("🔗 Attaching to session '%s' (tmux: %s)...\n",
sessionToAttach.Core.Name, sessionToAttach.Core.TmuxSession)

// Use exec to replace current process with tmux attach
tmuxPath, err := exec.LookPath("tmux")
if err != nil {
return fmt.Errorf("tmux not found in PATH: %w", err)
}

args = []string{"tmux", "attach-session", "-t", sessionToAttach.Core.TmuxSession}
err = syscall.Exec(tmuxPath, args, os.Environ())
if err != nil {
return fmt.Errorf("failed to exec tmux: %w", err)
}

// This point should never be reached if exec succeeds
return nil
// Attach to tmux session using shared operations function
return operations.AttachToTmuxSession(sessionToAttach.Core.Name, sessionToAttach.Core.TmuxSession)
}

func promptForAttachSelection(sessions []types.Session) (*types.Session, error) {
Expand Down
13 changes: 5 additions & 8 deletions internal/cli/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,11 @@ func runNewCmd(cmd *cobra.Command, args []string) error {
}

// Success message
fmt.Printf("✅ Session '%s' created successfully!\n\n", sessionName)
fmt.Printf("Next steps:\n")
fmt.Printf(" • View all sessions: cwt list\n")
fmt.Printf(" • Attach to session: cwt attach %s\n", sessionName)
fmt.Printf(" • Open TUI dashboard: cwt tui\n")
fmt.Printf(" • Work in isolated directory: cd %s/worktrees/%s\n", dataDir, sessionName)

return nil
fmt.Printf("✅ Session '%s' created successfully!\n", sessionName)

// Attach to the newly created session
tmuxSessionName := fmt.Sprintf("cwt-%s", sessionName)
return operations.AttachToTmuxSession(sessionName, tmuxSessionName)
}

func promptForSessionName() (string, error) {
Expand Down
45 changes: 45 additions & 0 deletions internal/operations/sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"os/exec"
"strings"
"syscall"

"github.com/jlaneve/cwt-cli/internal/state"
"github.com/jlaneve/cwt-cli/internal/types"
Expand Down Expand Up @@ -135,3 +136,47 @@ func isValidExecutablePath(path string) bool {
}
return true
}

// AttachToTmuxSession attaches to the specified tmux session using exec.
// This function replaces the current process with tmux attach-session,
// so no code after the syscall.Exec call will execute.
func AttachToTmuxSession(sessionName, tmuxSessionName string) error {
// Validate input
if tmuxSessionName == "" {
return fmt.Errorf("tmux session name cannot be empty")
}

// Find tmux in PATH
tmuxPath, err := exec.LookPath("tmux")
if err != nil {
return fmt.Errorf("tmux not found in PATH: %w", err)
}

// Verify session exists before attempting attach
if err := verifyTmuxSessionExists(tmuxSessionName); err != nil {
return fmt.Errorf("tmux session not found: %w", err)
}

// Display consistent user feedback
fmt.Printf("🔗 Attaching to session '%s' (tmux: %s)...\n", sessionName, tmuxSessionName)

// Use exec to replace current process with tmux attach
args := []string{"tmux", "attach-session", "-t", tmuxSessionName}
err = syscall.Exec(tmuxPath, args, os.Environ())
if err != nil {
return fmt.Errorf("failed to exec tmux: %w", err)
}

// This point should never be reached if exec succeeds
// Using panic for consistency as this indicates a fundamental system issue
panic("syscall.Exec returned unexpectedly")
}

// verifyTmuxSessionExists checks if the specified tmux session exists
func verifyTmuxSessionExists(sessionName string) error {
cmd := exec.Command("tmux", "has-session", "-t", sessionName)
if err := cmd.Run(); err != nil {
return fmt.Errorf("session '%s' does not exist", sessionName)
}
return nil
}
Loading