feat(tmux): add per-rig color themes and dynamic status line (gt-vc1n)

Add tmux status bar theming for Gas Town sessions:

- Per-rig color themes auto-assigned via consistent hashing
- 10 curated dark themes (ocean, forest, rust, plum, etc.)
- Special gold/dark theme for Mayor
- Dynamic status line showing current issue and mail count
- Mayor status shows polecat/rig counts

New commands:
- gt theme --list: show available themes
- gt theme apply: apply to running sessions
- gt issue set/clear: agents update their current issue
- gt status-line: internal command for tmux refresh

Status bar format:
- Left: [rig/worker] role
- Right: <issue> | <mail> | HH:MM

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-19 14:16:34 -08:00
parent e859938545
commit 4d0492fdf6
15 changed files with 1428 additions and 170 deletions

View File

@@ -6,6 +6,8 @@ import (
"os/exec"
"strings"
"time"
"github.com/steveyegge/gastown/internal/tmux"
)
// BeadsMessage represents a message from beads mail.
@@ -177,13 +179,14 @@ func (d *Daemon) identityToSession(identity string) string {
func (d *Daemon) restartSession(sessionName, identity string) error {
// Determine working directory and startup command based on agent type
var workDir, startCmd string
var rigName string
if identity == "mayor" {
workDir = d.config.TownRoot
startCmd = "exec claude --dangerously-skip-permissions"
} else if strings.HasSuffix(identity, "-witness") {
// Extract rig name: <rig>-witness → <rig>
rigName := strings.TrimSuffix(identity, "-witness")
rigName = strings.TrimSuffix(identity, "-witness")
workDir = d.config.TownRoot + "/" + rigName
startCmd = "exec claude --dangerously-skip-permissions"
} else {
@@ -198,6 +201,15 @@ func (d *Daemon) restartSession(sessionName, identity string) error {
// Set environment
_ = d.tmux.SetEnvironment(sessionName, "GT_ROLE", identity)
// Apply theme
if identity == "mayor" {
theme := tmux.MayorTheme()
_ = d.tmux.ConfigureGasTownSession(sessionName, theme, "", "Mayor", "coordinator")
} else if rigName != "" {
theme := tmux.AssignTheme(rigName)
_ = d.tmux.ConfigureGasTownSession(sessionName, theme, rigName, "witness", "witness")
}
// Send startup command
if err := d.tmux.SendKeys(sessionName, startCmd); err != nil {
return fmt.Errorf("sending startup command: %w", err)