00 — Overview

v0.3.0 · Apache-2.0 · Windows · macOS · Linux

See what your agent actually did.

ThreadlineLM reads the audit logs your agent already writes — OpenAI-compatible, OpenTelemetry GenAI or LiteLLM — and rebuilds the run: every call, every tool call, every retry. Parsing happens on your machine.

Portable Windows build · 5.2 MB · no account, no telemetry

audit.log
ThreadlineLM chat view: a CI failure reconstructed as a conversation with an assistant tool call, a tool result, a reasoning block and the final answer.
p50 1,840 ms · p95 4,100 ms
5.2 MB portable Windows build
0 network calls at runtime
6 log formats, detected by content
Ctrl+1…5 one keystroke per view
01 — The file

The run is gone. The log is not.

An agent fails and leaves a file: requests, streamed chunks, tool calls, retries, one 429 at 14:02:31. Grep gives you lines. It doesn't tell you which session a line belongs to, which call edited the file, or where the loop started.

ThreadlineLM parses that file and reconstructs the run — the conversation the model saw, the tools it called, what each call cost. Same evidence, readable.

inputExample/audit.log · synthetic · 9 events evt_0009

        01
        {
      
        02
          "id": "evt_0009",
      
        03
          "ts": "2026-05-17T15:30:09.000Z",
      
        04
          "client": "eval-runner",
      
        05
          "model": "gemini/gemini-2.0-flash",
      
        06
          "status": 429,
      
        07
          "duration_ms": 95,
      
        08
          "upstream": { "status": 429 },
      
        09
          "req_body": {
      
        10
            "messages": [
      
        11
              {
      
        12
                "role": "user",
      
        13
                "content": "Translate to Spanish: good night."
      
        14
              }
      
        15
            ]
      
        16
          },
      
        17
          "resp_body": {
      
        18
            "error": {
      
        19
              "code": 429,
      
        20
              "status": "RESOURCE_EXHAUSTED"
      
        21
            }
      
        22
          }
      
        23
        }
      
429 · upstream rate limit · 95 ms
02 — Views

Four ways into the same file.

The timeline is the index. Everything else is one keystroke away: the same events, read four ways, with no re-import.

Every call, in order

01 Timeline

Every call, in order

Provider, model, status, latency and tokens in/out. A failed request keeps its HTTP code instead of disappearing into a stack trace.

8 sessions · newest first

Compare is the fifth tab: put a working call next to a broken one and diff request and response, field by field.

Ctrl+1…5
03 — Input

Six formats. Detected by content, not by extension.

Drop the file on the window. The parser is chosen from the first records, so .log, .jsonl and .json all work.

Format What it reads Example Events
OpenAI-compatible audit JSONL Tool calls, SSE streams, reasoning, Anthropic tool_use, 429 errors audit.log 9
Audit records as a JSON array The same records in a single array audit-array.json 3
OpenTelemetry GenAI spans One span per line; non-GenAI spans are skipped otel-genai-spans.jsonl 3
OTLP/JSON envelope resourceSpans with KeyValue attributes otel-genai-otlp.json 2
LiteLLM StandardLoggingPayload Streamed response, tool use, embedding, failure litellm.jsonl 5
Plain-text proxy log Audit JSON embedded in log lines proxy-raw.log 2

Every example is synthetic and ships in inputExample/. One record per line: pretty-printed multi-line JSON isn't detected yet.

Watch
Runs still being written

Re-reads the file every 500 ms while the agent works, so you can follow a run as it happens.

Compare
Working run vs broken run

Request and response of two calls, side by side, field by field.

Export
Markdown for the ticket

Fuzzy search across calls, then export a session to paste into the bug report.

04 — Boundary

Nothing leaves the machine.

No account, no telemetry, no cloud, no update pings. Parsing runs in Rust, in memory. The log is never uploaded, and nothing is written except the Markdown you ask for.

No network calls

The app opens no socket. The timeline builds with the network cable unplugged.

In memory

The file is read, parsed and dropped when the window closes. No cache, no copy on disk.

Auditable

Apache-2.0. The parsers and IPC commands are a few Rust files — read them, or build the binary yourself.

05 — Inside

From file to timeline.

Parsing and session grouping stay in the Rust backend; the interface receives typed results over Tauri IPC.

01 Detect

The first records pick the parser. Unknown lines are skipped, not fatal.

Rust
02 Parse

Requests, responses, tool calls, reasoning, usage and status.

4 parsers
03 Group

Calls become sessions by client and a 10-minute window.

session.rs
04 Rebuild

Chat order, tool results and graph edges for each session.

store.ts
05 Inspect

Virtualized lists, fuzzy search, Markdown export.

React · IPC
06 — Download

Take it for a run.

Drop inputExample/audit.log on the window: 9 calls in the timeline, the rebuilt chat, the graph and p50/p95 latency.

Builds aren't code-signed yet. On Windows, SmartScreen asks for More info → Run anyway. On macOS, clear the flag once: xattr -dr com.apple.quarantine /Applications/ThreadlineLM.app

Early: v0.3.0. Formats and views are stable enough for daily debugging; unusual log shapes can still trip a parser. An issue with a redacted sample is the most useful report.

Or build it

Node 20+, pnpm 10+, a stable Rust toolchain and the Tauri system dependencies.

$ git clone https://github.com/aralde/ThreadlineLM
$ cd ThreadlineLM && pnpm install
$ pnpm tauri dev