GE

Provides TUI patterns and code templates for the Gentleman.Dots installer.

Install

mkdir -p .claude/skills/gentleman-bubbletea && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/5965" && unzip -o skill.zip -d .claude/skills/gentleman-bubbletea && rm skill.zip

Installs to .claude/skills/gentleman-bubbletea

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Bubbletea TUI patterns for Gentleman.Dots installer. Trigger: When editing Go files in installer/internal/tui/, working on TUI screens, or adding new UI features.
162 chars · catalog description✓ has a “when” trigger
Intermediate

Key capabilities

  • Define new TUI screens as constants
  • Manage application state within a single model struct
  • Handle keyboard input with a type switch in Update()
  • Create separate key handlers for each screen
  • Implement screen transitions and back navigation
  • Add scrollable content to TUI screens

How it works

This skill enforces specific patterns for Bubbletea TUI development, including defining screen constants, centralizing application state in a Model struct, and using a type switch for input handling.

Inputs & outputs

You give it
Go files in installer/internal/tui/ for TUI screens or new UI features.
You get back
Standardized Bubbletea TUI components, screen definitions, and input handling logic.

When to use gentleman-bubbletea

  • Adding new screens to the TUI installer
  • Implementing keyboard navigation logic
  • Creating new Lipgloss UI components
  • Refactoring screen state management

About this skill

When to Use

Use this skill when:

  • Adding new screens to the TUI installer
  • Handling keyboard input or navigation
  • Creating new UI components with Lipgloss
  • Working on screen transitions or state management

Critical Patterns

Pattern 1: Screen Constants in model.go

All screens MUST be defined as Screen constants in model.go:

type Screen int

const (
    ScreenWelcome Screen = iota
    ScreenMainMenu
    ScreenOSSelect
    // ... new screens go here
    ScreenNewFeature      // Add new screen
    ScreenNewFeatureCat   // Add category screen if needed
)

Pattern 2: Model Struct Holds All State

The Model struct in model.go holds ALL application state:

type Model struct {
    Screen      Screen
    PrevScreen  Screen      // For back navigation
    Width       int
    Height      int
    Cursor      int
    // Add new state here
    NewFeatureData    []SomeType
    NewFeatureScroll  int
}

Pattern 3: Update Pattern with Type Switch

All input handling goes through Update() with a type switch:

func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    switch msg := msg.(type) {
    case tea.KeyMsg:
        return m.handleKeyPress(msg)
    case tea.WindowSizeMsg:
        m.Width = msg.Width
        m.Height = msg.Height
        return m, nil
    case customMsg:
        // Handle custom messages
        return m, nil
    }
    return m, nil
}

Pattern 4: Key Handlers Return (Model, Cmd)

Separate handler per screen, always return (tea.Model, tea.Cmd):

func (m Model) handleNewFeatureKeys(key string) (tea.Model, tea.Cmd) {
    options := m.GetCurrentOptions()

    switch key {
    case "up", "k":
        if m.Cursor > 0 {
            m.Cursor--
            // Skip separator
            if strings.HasPrefix(options[m.Cursor], "───") && m.Cursor > 0 {
                m.Cursor--
            }
        }
    case "down", "j":
        if m.Cursor < len(options)-1 {
            m.Cursor++
            if strings.HasPrefix(options[m.Cursor], "───") && m.Cursor < len(options)-1 {
                m.Cursor++
            }
        }
    case "enter", " ":
        // Handle selection
        return m.handleNewFeatureSelection()
    case "esc":
        m.Screen = m.PrevScreen
        m.Cursor = 0
    }
    return m, nil
}

Decision Tree

Adding a new screen?
├── Define Screen constant in model.go
├── Add state fields to Model struct
├── Add handler in handleKeyPress switch
├── Create handle{Screen}Keys function in update.go
├── Add view case in view.go
└── Add title in GetScreenTitle()

Adding navigation to existing screen?
├── Use m.PrevScreen for back navigation
├── Reset m.Cursor = 0 on screen change
└── Save scroll position if scrollable

Adding scrollable content?
├── Add {Screen}Scroll int to Model
├── Calculate visibleItems from m.Height
├── Handle up/down for scroll position
└── Reset scroll on screen exit

Code Examples

Example 1: Adding Screen to handleKeyPress

// In handleKeyPress switch statement:
case ScreenNewFeature:
    return m.handleNewFeatureKeys(key)

case ScreenNewFeatureCat:
    return m.handleNewFeatureCatKeys(key)

Example 2: Screen Options Pattern

func (m Model) GetCurrentOptions() []string {
    switch m.Screen {
    case ScreenNewFeature:
        categories := make([]string, len(m.NewFeatureData)+2)
        for i, item := range m.NewFeatureData {
            categories[i] = item.Name
        }
        categories[len(m.NewFeatureData)] = "─────────────"
        categories[len(m.NewFeatureData)+1] = "← Back"
        return categories
    // ...
    }
}

Example 3: Scrollable View Pattern

func (m Model) handleNewFeatureCatKeys(key string) (tea.Model, tea.Cmd) {
    data := m.NewFeatureData[m.SelectedNewFeature]

    visibleItems := m.Height - 9
    if visibleItems < 5 {
        visibleItems = 5
    }

    maxScroll := len(data.Items) - visibleItems
    if maxScroll < 0 {
        maxScroll = 0
    }

    switch key {
    case "up", "k":
        if m.NewFeatureScroll > 0 {
            m.NewFeatureScroll--
        }
    case "down", "j":
        if m.NewFeatureScroll < maxScroll {
            m.NewFeatureScroll++
        }
    case "esc", "q", "enter", " ":
        m.Screen = ScreenNewFeature
        m.NewFeatureScroll = 0
    }
    return m, nil
}

Example 4: Custom Message Pattern

// Define message type
type newFeatureLoadedMsg struct {
    data []SomeType
    err  error
}

// Send message from command
func loadNewFeatureCmd() tea.Cmd {
    return func() tea.Msg {
        data, err := loadData()
        return newFeatureLoadedMsg{data: data, err: err}
    }
}

// Handle in Update
case newFeatureLoadedMsg:
    if msg.err != nil {
        m.ErrorMsg = msg.err.Error()
        return m, nil
    }
    m.NewFeatureData = msg.data
    return m, nil

Commands

cd installer && go build ./cmd/gentleman-installer  # Build installer
cd installer && go test ./internal/tui/...          # Run TUI tests
cd installer && go test -run TestNewFeature         # Run specific test

Resources

  • Model: See installer/internal/tui/model.go for state management
  • Update: See installer/internal/tui/update.go for input handling
  • View: See installer/internal/tui/view.go for rendering
  • Styles: See installer/internal/tui/styles.go for Lipgloss styles

How it compares

This skill provides a structured framework for TUI development, ensuring consistency across screens and input handling, unlike ad-hoc UI component creation.

Compared to similar skills

gentleman-bubbletea side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
gentleman-bubbletea (this skill)27moReviewIntermediate
templ-htmx37moNo flagsIntermediate
shadmin-dev01moReviewAdvanced
bubbletea-designer05moNo flagsAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

templ-htmx

Xe

Build interactive hypermedia-driven applications with templ and HTMX. Use when creating dynamic UIs, real-time updates, AJAX interactions, mentions 'HTMX', 'dynamic content', or 'interactive templ app'.

314

shadmin-dev

ahaodev

Apply Shadmin feature-development standards (backend Go/Gin/Ent + frontend React/TS). Use when adding/modifying features, CRUD modules, API routes/controllers/usecases/repositories, Ent schemas, frontend pages/routes, React components, TanStack hooks, or any full-stack work in this project. Trigger

00

bubbletea-designer

slayer

Reference guide for Bubble Tea TUI design patterns, component selection, and architecture. Adapted for gcon's project-specific abstractions (custom View interface, CreateViewBase, TableClickDelegate, forms framework). Use when designing new views, planning component architecture, or needing design g

00

effective-go

openshift

Apply Go best practices, idioms, and conventions from golang.org/doc/effective_go. Use when writing, reviewing, or refactoring Go code to ensure idiomatic, clean, and efficient implementations.

323536

architecture-patterns

wshobson

Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use when architecting complex backend systems or refactoring existing applications for better maintainability.

55214

opencode-cli

SpillwaveSolutions

This skill should be used when configuring or using the OpenCode CLI for headless LLM automation. Use when the user asks to "configure opencode", "use opencode cli", "set up opencode", "opencode run command", "opencode model selection", "opencode providers", "opencode vertex ai", "opencode mcp servers", "opencode ollama", "opencode local models", "opencode deepseek", "opencode kimi", "opencode mistral", "fallback cli tool", or "headless llm cli". Covers command syntax, provider configuration, Vertex AI setup, MCP servers, local models, cloud providers, and subprocess integration patterns.

14174

Search skills

Search the agent skills registry