feat: add watch mode to gt status (#8) (#11) (#231)

* feat: add watch mode to gt status

- Add --watch/-w flag for continuous status refresh
- Add --interval/-n flag to set refresh interval (default 2s)
- Clears screen and shows timestamp on each refresh
- Graceful Ctrl+C handling to stop watch mode
- Works with existing --fast and --json flags

* fix(status): validate watch interval to prevent panic on zero/negative values

* fix(status): harden watch mode with signal cleanup, TTY detection, and tests

- Add defer signal.Stop() to prevent signal handler leak
- Reject --json + --watch combination (produces invalid output)
- Add TTY detection for ANSI escapes (safe when piped)
- Use style.Dim for header when in TTY mode
- Fix duplicate '(default 2)' in flag help
- Add tests for interval validation and flag conflicts
This commit is contained in:
Subhrajit Makur
2026-01-07 08:40:43 +05:30
committed by GitHub
parent c2451b85e7
commit 93b19a7e72
2 changed files with 125 additions and 1 deletions

View File

@@ -95,3 +95,66 @@ func TestRenderAgentDetails_UsesRigPrefix(t *testing.T) {
t.Fatalf("output %q does not contain rig-prefixed bead ID", output)
}
}
func TestRunStatusWatch_RejectsZeroInterval(t *testing.T) {
oldInterval := statusInterval
oldWatch := statusWatch
defer func() {
statusInterval = oldInterval
statusWatch = oldWatch
}()
statusInterval = 0
statusWatch = true
err := runStatusWatch(nil, nil)
if err == nil {
t.Fatal("expected error for zero interval, got nil")
}
if !strings.Contains(err.Error(), "positive") {
t.Errorf("error %q should mention 'positive'", err.Error())
}
}
func TestRunStatusWatch_RejectsNegativeInterval(t *testing.T) {
oldInterval := statusInterval
oldWatch := statusWatch
defer func() {
statusInterval = oldInterval
statusWatch = oldWatch
}()
statusInterval = -5
statusWatch = true
err := runStatusWatch(nil, nil)
if err == nil {
t.Fatal("expected error for negative interval, got nil")
}
if !strings.Contains(err.Error(), "positive") {
t.Errorf("error %q should mention 'positive'", err.Error())
}
}
func TestRunStatusWatch_RejectsJSONCombo(t *testing.T) {
oldJSON := statusJSON
oldWatch := statusWatch
oldInterval := statusInterval
defer func() {
statusJSON = oldJSON
statusWatch = oldWatch
statusInterval = oldInterval
}()
statusJSON = true
statusWatch = true
statusInterval = 2
err := runStatusWatch(nil, nil)
if err == nil {
t.Fatal("expected error for --json + --watch, got nil")
}
if !strings.Contains(err.Error(), "cannot be used together") {
t.Errorf("error %q should mention 'cannot be used together'", err.Error())
}
}