How the no-mistakes TUI Works: Architecture, User Interactions, and Keyboard Controls

The no-mistakes TUI is a Bubble Tea-based terminal interface that implements the Model-View-Update pattern to let users monitor pipeline runs, inspect code diffs, manage findings, and approve fixes through comprehensive keyboard-driven interactions.

The no-mistakes TUI (Terminal User Interface) provides an interactive dashboard for managing automated code review pipelines directly from the terminal. Built on the Bubble Tea framework and following the classic Model-View-Update architecture, this interface—implemented in the kunchenguid/no-mistakes repository—allows developers to track step progress, review diffs, and respond to findings without leaving their shell.

Architecture Overview

The no-mistakes TUI follows the Model-View-Update pattern standard to Elm and Bubble Tea applications, with clear separation between state management, event handling, and rendering.

Model State Management

The central Model struct in internal/tui/app.go (lines 11-55) maintains the complete UI state, including run information, step data, findings, diffs, cursor positions, and modal editor states.

// internal/tui/app.go – model definition
type Model struct {
    // Contains run info, steps, findings, diffs, 
    // cursor positions, and editor state
}

Update Loop and Event Handling

The Update method in internal/tui/app.go (lines 62-92) processes Bubble Tea messages, while the heavy lifting of key press handling resides in internal/tui/keys.go (lines 8-45). During Init, the model subscribes to the daemon's IPC event stream (subscribeCmd), wrapping incoming events in eventMsg structures.

View Rendering Pipeline

The View method in internal/tui/view.go (lines 11-59) composes the screen from several components: pipeline progress, findings/diff panels, log tail, help overlay, and a persistent footer with shortcuts. The layout adapts responsively to terminal width via shouldUseResponsiveLayout.

User Interactions and Keyboard Shortcuts

All user interactions are handled through the handleKey function in internal/tui/keys.go, which maps keystrokes to high-level actions.

Users navigate findings and diffs using Vim-style keybindings:

  • j / k or down / up: Move the findings cursor or scroll the diff view
  • n / p: Page-wise navigation inside the diff view
  • Space: Toggle selection of the highlighted finding
  • A / N: Select all or clear all findings for the current step
  • d: Toggle the diff panel for the awaiting step
  • ?: Toggle the help overlay

Step Actions and Responses

When a step awaits approval, users respond with single keystrokes:

  • a: Send an Approve response
  • f: Send a Fix response
  • s: Send a Skip response
  • y: Enable "yolo" mode to auto-approve every awaiting step
  • r: Request a rerun of the entire pipeline
  • o: Open the PR URL in a browser
  • x: Two-press abort sequence (first warns, second aborts)
  • q / Ctrl-C: Quit or detach from the TUI

The TUI provides full-screen editors for customizing findings:

Press e to open the instruction editor for the selected finding, allowing free-form guidance to be attached. Press + to open the add-finding editor, which prompts for a required description and optional fix instruction.

Both editors use the Bubbles textarea component and capture all keystrokes until the user saves with Ctrl-S or Ctrl-Enter, or cancels with Esc. The editor implementations live in internal/tui/editors.go (lines 13-84).

Implementation Deep Dive

Starting the TUI

The TUI launches via the Run function in internal/tui/app.go, which initializes the model and starts the Bubble Tea program with an alt-screen buffer:

func Run(socketPath string, client *ipc.Client, run *ipc.RunInfo, latestVersion string) error {
    model := NewModel(socketPath, client, run)
    p := tea.NewProgram(model, tea.WithAltScreen())
    _, err := p.Run()
    return err
}

Handling Key Presses

The handleKey function in internal/tui/keys.go routes keystrokes to commands. For example, approving a step:

// internal/tui/keys.go – pressing 'a' sends an approve command
case "a":
    return m, m.respondCmd(types.ActionApprove)

Adding Custom Findings

When the user presses +, the system creates an editor state:

case "+":
    if step := awaitingStep(m.steps); step != nil {
        m.editor = newAddFindingEditor(step.StepName)
    }
    return m, nil

Upon saving, saveAddFinding in internal/tui/editors.go validates the description and constructs a new types.Finding:

func (m *Model) saveAddFinding() error {
    if desc := strings.TrimSpace(m.editor.addDesc.Value()); desc == "" {
        return fmt.Errorf("description is required")
    }
    f := types.Finding{
        Severity:    "info",
        Description: desc,
        Action:      types.ActionAutoFix,
        Source:      types.FindingSourceUser,
        UserInstructions: strings.TrimSpace(m.editor.addInstr.Value()),
    }
    f.ID = m.nextUserFindingID(step)
    m.addedFindings[step] = append(m.addedFindings[step], f)
    // ...
}

Rendering the Interface

The view composes multiple panels. The findings box renders with cursor highlighting:

if _, ok := m.stepFindings[step.StepName]; ok || len(m.addedFindings[step.StepName]) > 0 {
    cursor := m.findingCursor[step.StepName]
    raw := m.combinedFindingsJSON(step.StepName)
    appendExtraSection(renderFindingsBoxForHeight(raw, rightWidth, cursor,
        m.findingSelections[step.StepName], boxHeight))
}

Typical User Session Flow

A standard interaction with the no-mistakes TUI follows this sequence:

  1. Launch: The TUI connects to the daemon via IPC and displays the pipeline view
  2. Monitoring: As steps progress, spinners update and the terminal title reflects the running step
  3. Review: When a step reaches StepStatusAwaitingApproval or StepStatusFixReview, findings appear in the action bar
  4. Selection: Use Space, A, or N to manage finding selections stored in m.findingSelections
  5. Inspection: Press d to view diffs, using j/k and n/p to navigate
  6. Customization: Press e to add instructions or + to create new findings
  7. Resolution: Press a, f, or s to respond, or y to enable auto-approve
  8. Completion: Press q to detach when finished

Summary

  • The no-mistakes TUI implements a Model-View-Update architecture using the Bubble Tea framework
  • State management lives in internal/tui/app.go, while key handling resides in internal/tui/keys.go
  • Users interact through Vim-style keybindings for navigation and single-keystroke commands for actions
  • Modal editors in internal/tui/editors.go provide multi-line text editing for custom findings and instructions
  • The interface supports responsive layouts, diff viewing, and real-time IPC communication with the daemon

Frequently Asked Questions

What framework does the no-mistakes TUI use?

The TUI is built on Bubble Tea, a Go framework based on The Elm Architecture. It uses the Bubbles library for textarea components in modal editors.

How does the TUI communicate with the backend daemon?

During initialization, the model subscribes to the daemon's IPC event stream via subscribeCmd. Incoming events are wrapped in eventMsg structures and applied to the model through the applyEvent method, allowing real-time updates of step progress and findings.

Can I customize findings during a review session?

Yes. Press + to open the add-finding editor, which creates a new finding with a description and optional instructions. Press e on an existing finding to attach custom instructions. These user-added findings are stored separately and merged into the findings list.

What happens when I press 'y' in the TUI?

Pressing y toggles "yolo" mode, which automatically approves every step that reaches the awaiting status. The UI issues maybeAutoApproveCmd commands behind the scenes, effectively automating the approval process for the remainder of the run.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →