DevTUI is a pure display layer built on Bubbletea that organizes messages from business logic into a clean terminal interface.
DevTUI follows consumer-driven interface design: your application defines the UI interface, and DevTUI implements it. This ensures:
- Zero Coupling: Business logic never imports
devtui. - High Testability: Easily mock UI dependencies.
- Pluggability: Swap UI implementations without changing core logic.
Define this in your application to use DevTUI:
type TuiInterface interface {
NewTabSection(title, description string) any
AddHandler(handler any, timeout time.Duration, color string, tabSection any)
RemoveTabSection(section any) // Dynamic removal
Start(args ...any) // Optional *sync.WaitGroup support
RefreshUI()
ReturnFocus() error
}func main() {
tui := devtui.NewTUI(&devtui.TuiConfig{AppName: "Demo", ExitChan: make(chan bool)})
// 1. Create a section
ops := tui.NewTabSection("Operations", "System Tasks")
// 2. Add handlers (DevTUI detects implemented interfaces automatically)
tui.AddHandler(&MyHandler{}, 5*time.Second, "#10b981", ops)
// 3. Optional: Remove section dynamically
// tui.RemoveTabSection(ops)
tui.Start()
}DevTUI detects 5 specialized interfaces to determine how to display and interact with your handlers:
| Interface | Purpose | Key Methods |
|---|---|---|
| Display | Read-only info | Name(), Content() |
| Edit | Interactive input | Label(), Value(), Change(newVal) |
| Execution | Action buttons | Label(), Execute() |
| Interactive | Rich interaction | WaitingForUser(), Value(), Change() |
| Loggable | Auto-logging | SetLog(func(...any)) |
Handlers implementing Loggable receive a logger. DevTUI only displays the most recent message per handler to keep the view focused. Full history is preserved for debugging.
For long-running operations, you can use the LogOpen and LogClose prefixes as the first argument to the logger. This triggers an auto-animated spinner and groups messages under the same line.
// Start animation (use "[..." literal or devtui.LogOpen)
handler.log("[...", "Deploying to production")
// ... long operation ...
// Stop animation and show final result (use "...]" literal or devtui.LogClose)
handler.log("...]", "Deployment complete")- Tab / Shift+Tab: Switch tabs
- Arrows: Navigate fields / Scroll view
- Enter / Esc: Execute (Edit) / Cancel
- Global Shortcuts: Handlers can implement
Shortcuts() []map[string]stringto register keys (e.g., 't' for test) that work from any tab.
Contributing | Built with Bubbletea