Inspector
Local web UI for browsing, diffing, and replaying recorded runs.
starling-inspect opens a SQLite event log read-only and serves a
self-contained UI on loopback. No CDN, no JS build, never writes
back to the log.
go run github.com/jerkeyray/starling/cmd/starling-inspect runs.db--help lists every flag. For non-local access, see
Operations → Inspector auth and TLS.
Runs list
Per-run totals up top, status tabs and preset chips for narrowing,
substring search on run id (/ focuses). The runs list is paged on
the server: 50 rows by default, up to 200 with ?per_page=200.
Filters and search terms are preserved when paging. Totals reflect the
currently visible page, while the pager shows the full matching count.
Run detail
Timeline on the left (color-coded by event family, inline
cost/token chips). Detail pane on the right with a sticky meta
header - hash, prev hash, call id are click-to-copy - and a
syntax-highlighted JSON body that wraps long strings by default.
Press ? in the timeline header for the keyboard shortcuts.
Diff
/diff aligns two runs by sequence. Pick A and B from the latest 100
runs in the dropdowns, hit Compare. Older runs can still be compared by
opening /diff?a={runIDA}&b={runIDB} directly. Diverging rows get a red
left rail, a summary strip up top counts matches/diffs and points at
the first divergence.
Replaying a run
A Replay button shows up on the run page when the inspector is
built into a dual-mode binary that wires
starling.InspectCommand(factory). It opens a side-by-side
recorded-vs-reproduced timeline; divergence surfaces as a toast
plus a click-through dialog. The source log is never written to.
if len(os.Args) > 1 && os.Args[1] == "inspect" {
return starling.InspectCommand(myFactory).Run(os.Args[2:])
}Embedding the inspector
If you want to mount the inspector in a larger HTTP server, build it directly:
import "github.com/jerkeyray/starling/inspect"
srv, err := inspect.New(log,
inspect.WithAuth(inspect.BearerAuth(os.Getenv("STARLING_INSPECT_TOKEN"))),
inspect.WithReplayer(myFactory), // optional: enables Replay button
inspect.WithDBPath("/var/lib/runs.db"), // optional: shows the DB basename in the topbar context chip
)
if err != nil { return err }
http.Handle("/runs/", http.StripPrefix("/runs", srv))WithDBPath populates a small chip in the inspector topbar with
the database's basename (full path on hover) so operators can see
which log the UI is pointing at when several inspectors run side
by side. The standalone CLI passes it automatically.