// Command transcript-tail is a minimal terminal client for transcriptor-ai's // live SSE transcript endpoint — connects, parses each `data: {...}` event, // and prints just the text, instead of raw JSON (`curl -N` works too, but // isn't pleasant to read live). See CLAUDE.md for the SSE message format. package main import ( "bufio" "encoding/json" "flag" "fmt" "net/http" "os" "strings" "github.com/stephanetailland/transcriptor-ai/internal/transcript" ) func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, "transcript-tail:", err) os.Exit(1) } } func run() error { url := flag.String("url", "http://localhost:8420/events", "transcriptor-ai SSE endpoint to follow") flag.Parse() resp, err := http.Get(*url) if err != nil { return fmt.Errorf("connect: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return fmt.Errorf("unexpected status: %s", resp.Status) } scanner := bufio.NewScanner(resp.Body) for scanner.Scan() { data, ok := strings.CutPrefix(scanner.Text(), "data: ") if !ok { continue // SSE keep-alive/blank lines, comments, etc. } var msg transcript.Message if err := json.Unmarshal([]byte(data), &msg); err != nil { continue } printMessage(msg) } // The connection ending here — whether cleanly or as a network-level // error — almost always just means the transcriptor-ai server stopped. // We can't reliably tell that apart from a real connection problem, so // don't be alarmist about it: this isn't a failure of transcript-tail // itself, the way a startup connection error (above) is. fmt.Fprintln(os.Stderr, "transcript-tail: stream ended (server stopped?)") return nil } func printMessage(msg transcript.Message) { marker := " " if !msg.IsFinal { marker = "…" // still a partial hypothesis, may be revised } fmt.Printf("[%s%s] %s\n", msg.Track, marker, msg.Text) }