From c2034ceea34500a2747e8a478353d1e0f92887e3 Mon Sep 17 00:00:00 2001 From: gastown/crew/george Date: Sun, 4 Jan 2026 12:30:47 -0800 Subject: [PATCH] fix(costs): auto-detect tmux session in Stop hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gt costs record now auto-detects the current tmux session when running inside tmux, so the Stop hook no longer requires --session flag or GT_SESSION env var. Detection order: 1. --session flag 2. GT_SESSION env var 3. GT_RIG/GT_ROLE derivation 4. Current tmux session (new) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- internal/cmd/costs.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/internal/cmd/costs.go b/internal/cmd/costs.go index 7179b177..5e72c684 100644 --- a/internal/cmd/costs.go +++ b/internal/cmd/costs.go @@ -525,6 +525,10 @@ func runCostsRecord(cmd *cobra.Command, args []string) error { // Derive session name from GT_* environment variables session = deriveSessionName() } + if session == "" { + // Try to detect current tmux session (works when running inside tmux) + session = detectCurrentTmuxSession() + } if session == "" { return fmt.Errorf("--session flag required (or set GT_SESSION env var, or GT_RIG/GT_ROLE)") } @@ -649,6 +653,28 @@ func deriveSessionName() string { return "" } +// detectCurrentTmuxSession returns the current tmux session name if running inside tmux. +// Uses `tmux display-message -p '#S'` which prints the session name. +func detectCurrentTmuxSession() string { + // Check if we're inside tmux + if os.Getenv("TMUX") == "" { + return "" + } + + cmd := exec.Command("tmux", "display-message", "-p", "#S") + output, err := cmd.Output() + if err != nil { + return "" + } + + session := strings.TrimSpace(string(output)) + // Only return if it looks like a Gas Town session + if strings.HasPrefix(session, constants.SessionPrefix) { + return session + } + return "" +} + // buildAgentPath builds the agent path from role, rig, and worker. // Examples: "mayor", "gastown/witness", "gastown/polecats/toast" func buildAgentPath(role, rig, worker string) string {