feat(01-02): add CLI display and main.go for vmux list
- DisplaySessions: colored output with state, cwd, branch, preview - display_test.go: 5 tests covering color, noColor, empty, worktree, noBranch - main.go: full pipeline FindClaudeProcesses -> FindSession -> DetectState -> Display - Supports --no-color flag and NO_COLOR env var - resolveWorktree via git rev-parse --show-toplevel Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
95
main.go
95
main.go
@@ -1,5 +1,98 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Placeholder - will be implemented in Task 2
|
||||
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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user