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

> Explore the no-mistakes TUI architecture and user interactions. Learn how this Bubble Tea-based interface simplifies pipeline monitoring, code inspection, and fix approvals with intuitive keyboard controls.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: architecture
- Published: 2026-06-25

---

**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`](https://github.com/kunchenguid/no-mistakes/blob/main/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.

```go
// 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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/tui/keys.go), which maps keystrokes to high-level actions.

### Navigation and Selection

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

### Modal Editors for Findings

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`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/tui/app.go), which initializes the model and starts the Bubble Tea program with an alt-screen buffer:

```go
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`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/tui/keys.go) routes keystrokes to commands. For example, approving a step:

```go
// 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:

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

```

Upon saving, `saveAddFinding` in [`internal/tui/editors.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/tui/editors.go) validates the description and constructs a new `types.Finding`:

```go
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:

```go
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`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/tui/app.go), while key handling resides in [`internal/tui/keys.go`](https://github.com/kunchenguid/no-mistakes/blob/main/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`](https://github.com/kunchenguid/no-mistakes/blob/main/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.