Skip to content

TUI: custom theme hot-reload no longer works — ThemeWatcher was unwired in the tab-view rewrite #3501

Description

@aheritier

Symptom

Docs (docs/features/tui/index.md, "Custom themes auto-reload when you save changes to the file — no restart needed") promise hot reload of ~/.cagent/themes/*.yaml, but editing a custom theme while the TUI runs does nothing until restart.

Root cause (confirmed via git history)

  • pkg/tui/styles/theme_watcher.go (NewThemeWatcher, fsnotify-based, debounced) and messages.ThemeFileChangedMsg still exist, and pkg/tui/tui.go still routes ThemeFileChangedMsghandleThemeFileChanged (hot-reload handler in pkg/tui/handlers.go).
  • But nothing constructs the watcher or emits the message anymore: the wiring (construct watcher with a callback emitting ThemeFileChangedMsg via program.Send, Watch(currentTheme.Ref) on startup and after every theme change, Stop() on exit) was introduced in ad380824b ("Support for TUI themes") and dropped in 0069cadf7 ("Parallel session support with a new tab view to switch between sessions"), which rewrote pkg/tui/tui.go and kept only the message handler. NewThemeWatcher currently has no non-test caller.

Fix sketch

  1. Re-wire in the current appModel lifecycle: create the watcher where the model gets its *tea.Program reference (SetProgram in cmd/root/new.go runTUIWrapped), callback → p.Send(messages.ThemeFileChangedMsg{ThemeRef: ref}).
  2. Watch(ref) initially and re-Watch after handleChangeTheme / handleThemeFileChanged / preview-commit (the watcher already no-ops for built-in-only refs); Stop() on TUI shutdown.
  3. Regression test: temp themes dir (paths.SetDataDir), start model via pkg/tui/tuitest, touch the theme file, assert a ThemeFileChangedMsg flows and styles.CurrentTheme() picks up the new color (the watcher has a 500 ms debounce — allow for it, or make the debounce injectable).
  4. If the fix is deferred instead: update docs/features/tui/index.md to drop the hot-reload claim until restored.

Acceptance criteria

  • Editing the active custom theme file updates the running TUI within ~1 s (debounce) without restart, incl. atomic-save editors (rename-based writes are already handled by the watcher).
  • Switching themes re-targets the watcher; exiting the TUI stops it (no goroutine/fd leak — watcher Close() called).
  • Covered by a regression test so the next TUI refactor can't silently drop the wiring again.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/docsDocumentation changesarea/tuiFor features/issues/fixes related to the TUIkind/fixPR fixes a bug (maps to fix:). Use on PRs only.

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions