From 560431d2f58bb24e4aa631a42c977a8117493b02 Mon Sep 17 00:00:00 2001 From: James Gifford Date: Wed, 21 Jan 2026 01:27:19 -0500 Subject: [PATCH] fix: ExpectedPaneCommands returns both node and claude for Claude Code (#740) Newer versions of Claude Code report the tmux pane command as "claude" instead of "node". This caused gt mayor attach (and similar commands) to incorrectly detect that the runtime had exited and restart the session. The fix adds "claude" to the expected pane commands alongside "node", matching the behavior of IsClaudeRunning() which already handles both. Co-authored-by: Claude Opus 4.5 --- internal/config/loader.go | 5 +++-- internal/config/loader_test.go | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/internal/config/loader.go b/internal/config/loader.go index 9a859fb2..2f56808d 100644 --- a/internal/config/loader.go +++ b/internal/config/loader.go @@ -1465,13 +1465,14 @@ func BuildCrewStartupCommandWithAgentOverride(rigName, crewName, rigPath, prompt } // ExpectedPaneCommands returns tmux pane command names that indicate the runtime is running. -// For example, Claude runs as "node", while most other runtimes report their executable name. +// Claude can report as "node" (older versions) or "claude" (newer versions). +// Other runtimes typically report their executable name. func ExpectedPaneCommands(rc *RuntimeConfig) []string { if rc == nil || rc.Command == "" { return nil } if filepath.Base(rc.Command) == "claude" { - return []string{"node"} + return []string{"node", "claude"} } return []string{filepath.Base(rc.Command)} } diff --git a/internal/config/loader_test.go b/internal/config/loader_test.go index 299eb687..b8b845ba 100644 --- a/internal/config/loader_test.go +++ b/internal/config/loader_test.go @@ -1437,10 +1437,11 @@ func TestGetRuntimeCommand_UsesRigAgentWhenRigPathProvided(t *testing.T) { func TestExpectedPaneCommands(t *testing.T) { t.Parallel() - t.Run("claude maps to node", func(t *testing.T) { + t.Run("claude maps to node and claude", func(t *testing.T) { got := ExpectedPaneCommands(&RuntimeConfig{Command: "claude"}) - if len(got) != 1 || got[0] != "node" { - t.Fatalf("ExpectedPaneCommands(claude) = %v, want %v", got, []string{"node"}) + want := []string{"node", "claude"} + if len(got) != 2 || got[0] != "node" || got[1] != "claude" { + t.Fatalf("ExpectedPaneCommands(claude) = %v, want %v", got, want) } })