@@ -0,0 +1,53 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## What this is
|
||||
|
||||
A terminal dashboard (TUI) built with `github.com/grindlemire/go-tui`, showing simulated CPU/memory/disk gauges, network sparklines, and a scrolling event feed. Single binary, no external services.
|
||||
|
||||
## Commands
|
||||
|
||||
```sh
|
||||
# Regenerate dashboard_gsx.go from dashboard.gsx (required before build if the .go file is missing/stale)
|
||||
go run github.com/grindlemire/go-tui/cmd/tui generate ./...
|
||||
|
||||
# Build
|
||||
go build ./...
|
||||
|
||||
# Vet
|
||||
go vet ./...
|
||||
|
||||
# Run the app
|
||||
go run .
|
||||
```
|
||||
|
||||
There are no test files in this repo yet.
|
||||
|
||||
## Architecture
|
||||
|
||||
### The .gsx → .go code generation step
|
||||
|
||||
`dashboard.gsx` is the source of truth for the UI. It's written in `.gsx`, a JSX-like DSL (Tailwind-esque `class` strings, `{expr}` interpolation, `for`/`if` control flow, a `templ` method that compiles to `Render`) provided by the `go-tui` module. **`dashboard_gsx.go` is generated output — do not hand-edit it.** It's git-ignored and carries a `// Code generated by tui generate. DO NOT EDIT.` header.
|
||||
|
||||
To change the UI: edit `dashboard.gsx`, then run `go run github.com/grindlemire/go-tui/cmd/tui generate ./...` to regenerate `dashboard_gsx.go`. Non-templ Go code (helper funcs, the `dashboardApp` struct, `produceEvents`, etc.) also lives in `dashboard.gsx` — the whole file is the source, not just the template block.
|
||||
|
||||
The `tui` CLI is wired into `go.mod` as a Go 1.24+ `tool` dependency (`tool github.com/grindlemire/go-tui/cmd/tui`), which is why `go.sum` carries `golang.org/x/tools` etc. even though the app code doesn't import them directly. Don't `go mod tidy` this away — it strips the generator's transitive deps and breaks `go run .../cmd/tui generate`.
|
||||
|
||||
CI (`.gitea/workflows/build.yml`) regenerates `dashboard_gsx.go` from scratch on every run before building, so the generated file never needs to be committed or kept in sync manually.
|
||||
|
||||
### App structure (go-tui conventions)
|
||||
|
||||
- `main.go` wires up `tui.NewApp(tui.WithRootComponent(Dashboard(eventCh)), tui.WithMouse())` and runs it. A background goroutine (`produceEvents`) pushes random events onto `eventCh`.
|
||||
- `dashboardApp` (defined in `dashboard.gsx`) is the root component. It implements several go-tui interfaces, each independently optional and picked up via interface satisfaction (see the compile-time checks at the bottom of the generated file):
|
||||
- `KeyMap() tui.KeyMap` — key bindings (`q`/Esc to quit, `j`/`k`/arrows to scroll).
|
||||
- `HandleMouse(tui.MouseEvent) bool` — mouse wheel scroll support.
|
||||
- `Watchers() []tui.Watcher` — background subscriptions: a 500ms timer (`updateMetrics`, simulates metric drift) and a channel watch (`addEvent`, consumes `eventCh`).
|
||||
- `Render(*tui.App) *tui.Element` — the generated view tree (from the `templ` block).
|
||||
- `BindApp(*tui.App)` — generated; wires every `*tui.State[T]` field to the app so state changes trigger re-renders. If you override `BindApp` yourself, call the generated `bindAppFields` helper rather than re-listing fields.
|
||||
- All mutable UI state (`cpu`, `mem`, `sparkIn`, `events`, `scrollY`, ...) is `*tui.State[T]`, read via `.Get()` and mutated via `.Set()`. `eventsRef *tui.Ref` gives imperative access to the events panel element (used for `MaxScroll()`/auto-scroll-to-bottom in `addEvent`).
|
||||
- Adding a new stateful field to `dashboardApp` means: add the `tui.State`/`tui.Ref` field, initialize it in `Dashboard(...)`, use it in the `templ` block — the generator regenerates `bindAppFields` and the compile-time interface checks automatically.
|
||||
|
||||
### CI
|
||||
|
||||
`.gitea/workflows/build.yml` runs on push/PR to `main`: checkout → setup-go (version from `go.mod`) → `tui generate` → `go build` → `go vet`.
|
||||
Reference in New Issue
Block a user