package main import ( "flag" "fmt" "os" "os/exec" "path/filepath" "strings" "time" ) func main() { noColor := flag.Bool("no-color", false, "Disable colored output") flag.Parse() if os.Getenv("NO_COLOR") != "" { *noColor = true } args := flag.Args() // Also check for --no-color after subcommand (flag stops at first non-flag) var filteredArgs []string for _, arg := range args { if arg == "--no-color" { *noColor = true } else { filteredArgs = append(filteredArgs, arg) } } if len(filteredArgs) == 0 || filteredArgs[0] != "list" { fmt.Fprintf(os.Stderr, "Usage: vmux list [--no-color]\n") os.Exit(1) } processes, err := FindClaudeProcesses("/proc") if err != nil { fmt.Fprintf(os.Stderr, "Error scanning processes: %v\n", err) os.Exit(1) } claudeDir := filepath.Join(os.Getenv("HOME"), ".claude", "projects") now := time.Now() var sessions []Session for _, proc := range processes { jsonlPath, messages, err := FindSessionForProcess(claudeDir, proc) if err != nil { sessions = append(sessions, Session{ Process: proc, State: Unknown, CwdPath: proc.Cwd, }) continue } state := DetectState(messages, now) preview := ExtractPreview(messages) var sessionID, gitBranch string for _, msg := range messages { if msg.SessionID != "" { sessionID = msg.SessionID } if msg.GitBranch != "" { gitBranch = msg.GitBranch } } worktree := resolveWorktree(proc.Cwd) _ = jsonlPath sessions = append(sessions, Session{ Process: proc, SessionID: sessionID, GitBranch: gitBranch, State: state, Preview: preview, CwdPath: proc.Cwd, Worktree: worktree, }) } DisplaySessions(os.Stdout, sessions, *noColor) } // resolveWorktree uses git to find the worktree root. // Falls back to cwd if git fails (not a git repo). func resolveWorktree(cwd string) string { cmd := exec.Command("git", "-C", cwd, "rev-parse", "--show-toplevel") out, err := cmd.Output() if err != nil { return cwd } return strings.TrimSpace(string(out)) }