Files
terdut-tui/CLAUDE.md
T
Niklas Ye 4740687b96
Release / test (push) Failing after 6s
Release / build (amd64, darwin) (push) Has been skipped
Release / build (amd64, linux) (push) Has been skipped
Release / build (arm64, darwin) (push) Has been skipped
Release / build (arm64, linux) (push) Has been skipped
Release / release (push) Has been skipped
feat!: stats as a section instead of an overlay
Stats was the one full-screen view reached by a key of its own rather
than by tab, and the interface was less coherent for it. It is now a
section sitting third, after Alerts, and behaves like every other one:
tab in, tab out, r to refresh.

Three things fall out of the move. It auto-refreshes for the first time
— the tick handler skips every non-dashboard mode, which is why the
overlay never updated while it was open. Its error path no longer forces
the queue back into view on a failed fetch, an assumption that only made
sense while stats floated above the dashboard. And first-visit loading
keys off a statsLoaded flag rather than slice emptiness, because the
three empty slices a quiet server returns are a real answer, not a
missing one; the loading placeholder is likewise suppressed once
something has been drawn, so a background refresh cannot blank the page
out from under whoever is reading it.

The S key is gone, and with it the ability to peek at statistics from an
open incident and land back on it. That round-trip was the only thing
statsReturnMode bought, and it was the whole reason stats needed a mode.
2026-08-06 12:46:38 +02:00

4.0 KiB

terdut-tui

TUI client for terdut-server, a Prometheus Alertmanager receiver and incident manager. Requires server v0.4.0+.

Domain model

The server splits alerts from incidents, and this client mirrors it:

  • Alert — Alertmanager's record. Firing or resolved, read-only, no workflow state.
  • Incident — the work item: triggered → acknowledged → resolved, with an assignee, snooze, notes and an append-only timeline. Many alerts to one incident, correlated by Alertmanager's groupKey.

All user actions target incidents. Two server behaviours the UI has to respect: manual resolve is terminal (hence the confirmation prompt), and snooze is the non-destructive "not now" alternative.

Tech stack

  • Go 1.25+
  • Bubbletea — TUI framework (strict Elm architecture)
  • Lipgloss — styles (all in internal/tui/styles.go, never inline)
  • Bubbles — table, textinput, help components

Project layout

main.go                      CLI entry point: flags, config load, health check, start TUI
internal/api/client.go       REST API client — one method per endpoint
internal/config/config.go    Config loader (~/.config/terdut-tui/config.yaml)
internal/tui/                Bubbletea UI
  model.go                   Model struct, mode/section constants, Init(), tea.Cmd constructors
  update.go                  Update() — dispatch only, no API calls inline
  view.go                    View() — pure rendering
  keys.go                    keyMap (bubbles/key pattern)
  styles.go                  All lipgloss styles
internal/updater/updater.go  Self-update via GitHub Releases

Architecture rules

  1. Never call API inside Update() — return tea.Cmd instead; the runtime runs it async.
  2. View() is pure — no side effects, no state mutations.
  3. All state in Model — no globals.
  4. All styles in styles.go — never use lipgloss inline in view.go.

Config

Location: ~/.config/terdut-tui/config.yaml

server_url: https://terdut.example.com
api_key: <64-char hex key>
refresh_interval: 30  # seconds, optional, default 30

The API key is a one-time secret generated by terdut-server (POST /api/users/{id}/api-keys).

Running

go run .
go run . --version
go run . --self-update

Building

go build -ldflags="-X main.version=v0.1.0" -o terdut-tui .

Sections

Incidents (the queue, and the default) · Alerts (raw read-only feed) · Stats (MTTA/MTTR and alert frequency charts) · Archived (archived incidents) · Schedule · Users

Development stages

Stage Feature
1 Scaffold, config, health check, placeholder TUI
2 Alert dashboard with auto-refresh and stats
3 Alert detail: acknowledge, comment, statistics charts
4 On-call schedule calendar view
5 User management and API key lifecycle
6 Incidents: queue, timeline, ack/assign/snooze/resolve, MTTA/MTTR

Memory (GrayMatter)

This project has persistent agent memory via the graymatter MCP tools:

  • memory_search (agent_id, query) — call at the start of a task when prior context might matter.
  • memory_add (agent_id, text) — call whenever you learn something durable: user preferences, decisions, conventions, gotchas.
  • memory_reflect (action, agent, text/target) — update or forget stale facts. ⚠ takes agent, not agent_id.
  • checkpoint_save / checkpoint_resume (agent_id) — snapshot/restore session state before major refactors or across restarts.

Use a stable agent_id of the form <project>-<role> (e.g. myapp-backend). Store conclusions, not conversation logs. Err on the side of remembering.