Fix gt crew at to detect existing Claude sessions (gt-l90dq)
Before: gt crew at only looked for tmux sessions with the specific naming convention gt-<rig>-crew-<name>. If the user started Claude manually or via a different mechanism, it would create a duplicate session. After: Before creating a new session, check if any existing tmux session has Claude running in the crews directory. If found, attach to that session instead of creating a new one. Changes: - Add FindSessionByWorkDir() to internal/tmux/tmux.go to search sessions by working directory, optionally filtering for Claude (node) running - Update runCrewAt() to check for existing sessions before creating new 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -83,6 +83,37 @@ func runCrewAt(cmd *cobra.Command, args []string) error {
|
|||||||
return fmt.Errorf("checking session: %w", err)
|
return fmt.Errorf("checking session: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Before creating a new session, check if there's already a Claude session
|
||||||
|
// running in this crew's directory (might have been started manually or via
|
||||||
|
// a different mechanism)
|
||||||
|
if !hasSession {
|
||||||
|
existingSessions, err := t.FindSessionByWorkDir(worker.ClonePath, true)
|
||||||
|
if err == nil && len(existingSessions) > 0 {
|
||||||
|
// Found an existing session with Claude running in this directory
|
||||||
|
existingSession := existingSessions[0]
|
||||||
|
fmt.Printf("%s Found existing Claude session '%s' in crew directory\n",
|
||||||
|
style.Warning.Render("⚠"),
|
||||||
|
existingSession)
|
||||||
|
fmt.Printf(" Attaching to existing session instead of creating a new one\n")
|
||||||
|
|
||||||
|
// If inside tmux (but different session), inform user
|
||||||
|
if tmux.IsInsideTmux() {
|
||||||
|
fmt.Printf("Use C-b s to switch to '%s'\n", existingSession)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outside tmux: attach unless --detached flag is set
|
||||||
|
if crewDetached {
|
||||||
|
fmt.Printf("Existing session: '%s'. Run 'tmux attach -t %s' to attach.\n",
|
||||||
|
existingSession, existingSession)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach to existing session
|
||||||
|
return attachToTmuxSession(existingSession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !hasSession {
|
if !hasSession {
|
||||||
// Create new session
|
// Create new session
|
||||||
if err := t.NewSession(sessionID, worker.ClonePath); err != nil {
|
if err := t.NewSession(sessionID, worker.ClonePath); err != nil {
|
||||||
|
|||||||
@@ -292,6 +292,42 @@ func (t *Tmux) GetPaneWorkDir(session string) (string, error) {
|
|||||||
return strings.TrimSpace(out), nil
|
return strings.TrimSpace(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindSessionByWorkDir finds tmux sessions where the pane's current working directory
|
||||||
|
// matches or is under the target directory. Returns session names that match.
|
||||||
|
// If checkClaude is true, only returns sessions that have Claude (node) running.
|
||||||
|
func (t *Tmux) FindSessionByWorkDir(targetDir string, checkClaude bool) ([]string, error) {
|
||||||
|
sessions, err := t.ListSessions()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var matches []string
|
||||||
|
for _, session := range sessions {
|
||||||
|
if session == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
workDir, err := t.GetPaneWorkDir(session)
|
||||||
|
if err != nil {
|
||||||
|
continue // Skip sessions we can't query
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if workdir matches target (exact match or subdir)
|
||||||
|
if workDir == targetDir || strings.HasPrefix(workDir, targetDir+"/") {
|
||||||
|
if checkClaude {
|
||||||
|
// Only include if Claude is running
|
||||||
|
if t.IsClaudeRunning(session) {
|
||||||
|
matches = append(matches, session)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
matches = append(matches, session)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches, nil
|
||||||
|
}
|
||||||
|
|
||||||
// CapturePane captures the visible content of a pane.
|
// CapturePane captures the visible content of a pane.
|
||||||
func (t *Tmux) CapturePane(session string, lines int) (string, error) {
|
func (t *Tmux) CapturePane(session string, lines int) (string, error) {
|
||||||
return t.run("capture-pane", "-p", "-t", session, "-S", fmt.Sprintf("-%d", lines))
|
return t.run("capture-pane", "-p", "-t", session, "-S", fmt.Sprintf("-%d", lines))
|
||||||
|
|||||||
Reference in New Issue
Block a user