wlog

module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 22, 2026 License: MIT

README

wlog

wlog

See what your Claude Code session is actually doing — tokens, cost, and tool decisions — without standing up Grafana.

Single static binary · reads ~/.claude/projects · zero-config · local-only · embedded web UI

Latest release CI Go reference MIT license Platforms


wlog reads the transcript files Claude Code already writes, normalizes everything locally, and serves an embedded web UI. No Docker, no daemon, no external database, no SaaS. Run wlog and your past sessions — cost, tokens, and command history — are there immediately, with zero configuration. Turn on OpenTelemetry (OTLP) when you also want live updates and tool-decision data.

Your Claude Code already writes its history to disk and already speaks OTel. You just need something to read it — without docker-compose.

Daily usage — a GitHub-style "잔디" heatmap of your tokens (or cost) per day.


Highlights

  • 🟢 Zero-config — reads ~/.claude/projects transcripts; your past sessions appear the moment you run it
  • 📊 Six screens — Now (live), Sessions, Cost & Tokens, Daily usage heatmap, Tools, Timeline
  • 🟩 Daily "잔디" — a GitHub-style contribution grid of tokens (or cost) per day
  • 🔍 Filters everywhere — shared period (7d · 30d · 90d · 1y · All); per-model & hour/day on Cost
  • 🖥️ Desktop app — a native Tauri app that bundles wlog as a sidecar: one window, no terminal
  • 🔒 Local-only — no Docker, no SaaS, no external DB; prompt collection is opt-in
  • 📡 Optional OTLP — add live updates and tool-decision data when you want them
  • 📦 Single static binary — pure-Go (incl. SQLite), ~26 MB, copy-and-run

Why wlog

The usual ways to look at Claude Code telemetry are heavy:

  • SaaS backends (SigNoz Cloud, Datadog, Honeycomb) — your token, cost, and tool-decision data leaves your machine, and the onboarding/pricing is overkill for one developer.
  • Self-hosted stacks — almost every guide is Collector → Prometheus + Loki → Grafana: four containers, four ports, and a "don't forget to start it every morning" footnote.

wlog sells simplicity as a feature. It is local-only, runs only when you run it, and goes from install to a live dashboard in about five minutes.

Two data sources, one local store

Source Setup What it gives you
Transcript JSONL (~/.claude/projects/**/*.jsonl) None — on by default Past sessions immediately: cost, tokens, model, cache hits, bash/MCP runs, repo & branch. Zero-config.
OTLP One env block (opt-in) Live updates as a session runs, plus tool_decision data (accept/reject and the source: config / hook / user).

Start with just the JSONL source to see everything you've already done. Add OTLP when you want the live tail and the tool-decision drill-downs. The two sources are de-duplicated against each other, so running both never double-counts cost.


Screens

Every view shares a period filter (7d · 30d · 90d · 1y · All) that scopes the whole dashboard, and the design is deliberately text- and whitespace-forward: monospace numbers, a single accent color, minimal motion, no AI-slop ornamentation.

Now — your live session

Current session cost (max emphasis), input/output tokens, active time, the in-progress tool call, and a live event tail (SSE). Calm 2-second tick — no spinners, no count-up.

Daily — usage heatmap

One square per calendar day, shaded by how much you spent. Toggle between tokens and cost, scope it with the period filter, hover any day for the exact figure. Folded to your local calendar day (no UTC drift).

Daily heatmap with tokens/cost toggle and period filter

Cost & Tokens

Cumulative-spend step line, a cache_hit_ratio card with estimated savings, an input/output token series, and a per-model table. Filter by period, hour/day bucket, and model.

Sessions

One row per session: start time, cost, duration, tool accept rate, total tokens, model, and a source badge (events / metrics / mixed). Search by id/date, sort by time/cost/tokens, click a row to open its Timeline.

Tools — decisions

"Auto-approved: N" headline, accept/reject counts and reject rate, a per-source table (config / hook / user_*), and the top rejection hotspots.

Timeline — per-session lifecycle

A vertical lifecycle for one session: prompt → api_request → tool calls → decisions → results, with tool nodes indented under the request that triggered them. Click a node to expand it inline.

Screenshots use synthetic demo data (tools/replay), not real usage.


Desktop app

wlog also ships as a native desktop app (built with Tauri). It bundles the wlog binary as a sidecar: launching the app starts the local server and opens the UI in one window, and closing the window shuts the server down cleanly — no orphaned processes, no terminal needed.

cd desktop
npm install
npm run build      # produces an installer under src-tauri/target/release/bundle/

The installer (.msi / -setup.exe on Windows) is a normal per-user install. Requirements: a Rust toolchain, and on Windows the WebView2 runtime (preinstalled on Windows 11). The desktop app reads the same local store as the CLI, so your past sessions show up the moment it opens.


Install

go install

go install github.com/openwong2kim/wlog/cmd/wlog@latest

GitHub Releases

Download a prebuilt static binary for your OS/arch from the Releases page, unpack it, and put wlog on your PATH. Builds are published for linux, macOS, and Windows on amd64 and arm64, with checksums and an SBOM.

A Homebrew tap and Scoop bucket are planned.


Start in 5 minutes

Stage 1 — zero-config: see your past sessions now

wlog

wlog scans ~/.claude/projects for the transcript files Claude Code already wrote, the web UI starts, and the browser opens. If you've used Claude Code before, your past sessions are already there — no env vars, no restart. The startup line tells you the ports:

wlog v0.1.0  otlp=grpc://127.0.0.1:4317,http://127.0.0.1:4318  ui=http://127.0.0.1:7890

Cost, tokens, models, cache-hit ratios, and bash/MCP command history are populated from the transcripts on disk.

Prefer the terminal? wlog last prints a one-shot summary of your most recent session without opening anything — see wlog last.

Stage 2 — optional: add live updates + tool decisions

The transcript files don't include Claude Code's permission decisions (accept/reject and the source), and they're only written as a session progresses. Turn on OTLP to get live updates and the tool-decision data that powers the Tools screen.

The fastest way is one command — it merges the OTel env block, the status line, and a SessionEnd summary hook into ~/.claude/settings.json (preserving your other settings, with a .bak backup):

wlog setup              # then restart Claude Code
wlog setup --status     # verify it took effect (read-only)
wlog setup --uninstall  # undo anytime

Prefer to do it by hand? wlog --print-claude-setup prints the exact JSON env block (and a bash form) to paste into ~/.claude/settings.json.

Then run Claude Code, make a request, and switch back to the Now tab — the first api_request reaches wlog within a few seconds.

Want prompt text and detailed tool arguments too? Those are opt-in on the Claude Code side (OTEL_LOG_USER_PROMPTS=1). See Privacy before enabling — they get stored in your local DB.

Tip: keep a live status line in Claude Code itself with wlog statusline, so you see your running cost without switching to the browser.


CLI

wlog                              run the receiver + UI, auto-open the browser
wlog last [--session id] [--n N]  print a one-shot summary of the latest session
wlog statusline [--install]       emit one status line for Claude Code's status bar
wlog setup [--status|--uninstall] auto-configure Claude Code (OTel + statusline + hook)
wlog tail [--session id]          stream live events to the terminal (no UI)
wlog export --session <id> [...]  export a session to a file or stdout
wlog version                      print version information
wlog --print-claude-setup         print the Claude Code OTel env snippet and exit

Flags

Flag Default Description
--otlp-grpc-port 4317 OTLP/gRPC listener port.
--otlp-http-port 4318 OTLP/HTTP listener port.
--ui-port 0 (auto) Web UI port; 0 picks a free port automatically.
--listen 127.0.0.1 Bind address.
--unsafe false Allow a non-loopback bind without auth.
--auth-token (none) Auth token required for non-loopback access.
--db platform data dir SQLite database path.
--memory false Use an in-memory database (nothing persisted).
--retention 90d Data retention window (e.g. 90d, 72h).
--max-sessions 1000 Max retained sessions (oldest pruned first).
--max-recv-bytes 16MB Max size of a single OTLP message.
--no-open false Do not auto-open the browser.
--no-store-prompts false Do not persist prompts / tool arguments.
--no-jsonl false Disable zero-config Claude Code transcript (JSONL) ingestion.
--claude-dir ~/.claude/projects Directory of Claude Code transcripts to scan.
--print-claude-setup false Print the Claude Code OTel env snippet and exit.

Every flag has a WLOG_* environment-variable equivalent (e.g. WLOG_OTLP_GRPC_PORT, WLOG_UI_PORT, WLOG_LISTEN, WLOG_DB, WLOG_RETENTION, WLOG_NO_STORE_PROMPTS, WLOG_NO_JSONL, WLOG_CLAUDE_DIR). Explicit flags always win over the environment.

wlog last

Print a one-shot summary of your latest session — cost, tokens, tool accept/reject counts, and recent command history — and exit. It is read-only: it does not start the receiver or the web UI, so it works whether or not a wlog server is running.

wlog last                      # summarize the latest session
wlog last --session 0a1b2c3d   # summarize a specific session
wlog last --n 20               # list the last 20 commands (default: 10)
session 0a1b2c3d  18:42–19:05 (23m)  cost=$0.42  in=128.4K out=12.1K  cache_hit=71%
tools  accept 34  reject 2  auto-approved 28
  ✕ reject  Bash (source=user_reject)
bash (last 10)
  18:43:07  ok   npm ci
  19:02:54  fail go build ./cmd/wlog

wlog statusline

Show your current session's cost, tokens, cache-hit ratio, rejections, and the running tool directly in Claude Code's status bar:

$0.42 · in 128.4K/out 12.1K · cache 71% · ⊘2 reject · Bash

Install it (idempotent; backs up settings.json first):

wlog statusline --install

It reads the store directly and needs no running wlog server — it works from the zero-config transcript data alone, and never fails the status bar (blank line + exit 0 on any error).


Privacy

wlog is local-only. Data never leaves your machine, and it makes no outbound connections.

  • Prompts and tool arguments are not collected by default. They reach wlog only if you opt in on the Claude Code side (OTEL_LOG_USER_PROMPTS=1). wlog stores only what it receives.
  • --no-store-prompts drops prompt/argument payloads even when Claude Code sends them.
  • The UI shows a three-stage privacy banner: detailed-logging-off (default), a one-time amber warning when logging is on, and a persistent red banner on a non-loopback bind.
  • The database file is created with 0600 permissions, and non-loopback binds require --unsafe or --auth-token (with a Host-header check to block DNS rebinding).

How it works

Claude Code ──OTLP gRPC :4317 / HTTP :4318──▶  receiver  ─┐
                                                          │
~/.claude/projects/**/*.jsonl ──scan + watch──▶ jsonl.Parse ─┤   wlog (single process)
                                                          │
                       otel.Parse ──▶ delta normalization ─┤
                                                          ▼
        single-writer (dedup) ──▶ SQLite (WAL) + series_state ──▶ live bus (SSE)
                                                          │
              embedded web UI (go:embed) ──▶ http://127.0.0.1:<auto>

Two ingest paths, one store. On startup wlog scans ~/.claude/projects for Claude Code's transcript JSONL and watches for new lines; in parallel OTLP arrives over gRPC/HTTP (all three signals) through a bounded, backpressuring queue, and counters are normalized from cumulative/delta temporality into per-interval deltas. When the same api_request arrives from both sources, a shared de-duplication key collapses it to one row, so cost is never double-counted. A single writer goroutine serializes all SQLite writes; reads use a separate WAL pool. The UI is compiled into the binary via go:embed.

Where your data lives:

Platform Default database path
Windows %LOCALAPPDATA%\wlog\wlog.db
macOS ~/Library/Application Support/wlog/wlog.db
Linux / other ${XDG_DATA_HOME:-~/.local/share}/wlog/wlog.db

Override with --db PATH, or use --memory to keep everything in RAM.


Build from source

Requirements: Go 1.26+, Node 22+, and always CGO_ENABLED=0 (the SQLite driver is pure Go).

# 1. Build the embedded UI
cd ui && npm ci && npm run build      # outputs into ../internal/web/dist

# 2. Build the static binary (from the repo root)
cd .. && CGO_ENABLED=0 go build \
  -ldflags "-s -w -X github.com/openwong2kim/wlog/internal/version.Version=0.1.0" \
  -o wlog ./cmd/wlog

The result is a single static binary (~26 MB) with the UI embedded — copy it anywhere and run it. A Taskfile.yml is included (task build, task run, task test, task cross).

To regenerate the demo screenshots: run a demo instance (wlog --db demo.db --no-jsonl --ui-port 8898 --otlp-grpc-port 14317 --otlp-http-port 14318), inject synthetic data (replay --endpoint grpc://127.0.0.1:14317 --spread-days 70), then capture each route.


License

MIT © 2026 openwong2kim

Directories

Path Synopsis
cmd
wlog command
Command wlog is the single-binary OTLP receiver + embedded web UI for Claude Code session telemetry.
Command wlog is the single-binary OTLP receiver + embedded web UI for Claude Code session telemetry.
internal
api
Package api is the UI-facing HTTP JSON API for wlog (PLAN §10 — frozen contract).
Package api is the UI-facing HTTP JSON API for wlog (PLAN §10 — frozen contract).
app
Package app wires together the wlog subsystems (receiver, ingest, store, api, web) and manages process lifecycle (start + graceful shutdown).
Package app wires together the wlog subsystems (receiver, ingest, store, api, web) and manages process lifecycle (start + graceful shutdown).
config
Package config holds runtime configuration for wlog: ports, bind policy, data path resolution (XDG / LOCALAPPDATA / macOS), retention, recv limits, and WLOG_* environment overrides.
Package config holds runtime configuration for wlog: ports, bind policy, data path resolution (XDG / LOCALAPPDATA / macOS), retention, recv limits, and WLOG_* environment overrides.
deps
Package deps pins the verified third-party dependencies that downstream batches (otel parser, store, receiver) will import, so that `go mod tidy` retains them in go.mod and teammates working in parallel worktrees do not hit module-graph conflicts.
Package deps pins the verified third-party dependencies that downstream batches (otel parser, store, receiver) will import, so that `go mod tidy` retains them in go.mod and teammates working in parallel worktrees do not hit module-graph conflicts.
ingest
Package ingest is the normalize-and-persist pipeline plus the live bus that feeds the SSE endpoint (PLAN §9, REVIEWS A·C, Eng F7 / Design D-02).
Package ingest is the normalize-and-persist pipeline plus the live bus that feeds the SSE endpoint (PLAN §9, REVIEWS A·C, Eng F7 / Design D-02).
jsonl
Package jsonl converts Claude Code transcript JSONL (the per-session ~/.claude/projects/<enc-cwd>/<session-uuid>.jsonl files) into the wlog domain model (internal/model).
Package jsonl converts Claude Code transcript JSONL (the per-session ~/.claude/projects/<enc-cwd>/<session-uuid>.jsonl files) into the wlog domain model (internal/model).
model
Package model defines the wlog domain types, the single-writer Batch unit, and the storage interfaces consumed by the ingest and otel packages.
Package model defines the wlog domain types, the single-writer Batch unit, and the storage interfaces consumed by the ingest and otel packages.
otel
Package otel converts OTLP export requests (metrics, logs, traces) into the wlog domain model (internal/model).
Package otel converts OTLP export requests (metrics, logs, traces) into the wlog domain model (internal/model).
pricing
Package pricing maps Claude model names to approximate per-token USD prices so the cost API can report dollar figures (cumulative spend, burn rate, cache savings) instead of raw token counts.
Package pricing maps Claude model names to approximate per-token USD prices so the cost API can report dollar figures (cumulative spend, burn rate, cache savings) instead of raw token counts.
receiver
Package receiver terminates OTLP over gRPC (:4317) and HTTP (:4318), applies wire-level limits and defenses, and hands each request to the ingest pipeline with retryable backpressure (PLAN §5, §17, REVIEWS B·D).
Package receiver terminates OTLP over gRPC (:4317) and HTTP (:4318), applies wire-level limits and defenses, and hands each request to the ingest pipeline with retryable backpressure (PLAN §5, §17, REVIEWS B·D).
store
Package store is the SQLite persistence layer for wlog (PLAN §8, §8a, §16).
Package store is the SQLite persistence layer for wlog (PLAN §8, §8a, §16).
version
Package version holds the build version metadata for the wlog binary.
Package version holds the build version metadata for the wlog binary.
web
Package web embeds the built static UI assets (ui/ -> dist) into the binary and serves them with SPA fallback.
Package web embeds the built static UI assets (ui/ -> dist) into the binary and serves them with SPA fallback.
tools
replay command
Command replay is the wlog dogfood harness CLI: it synthesizes realistic Claude Code OTLP telemetry (via the synth package) and replays it at a running wlog receiver over gRPC or HTTP (PLAN §2 dogfood, §19 T9).
Command replay is the wlog dogfood harness CLI: it synthesizes realistic Claude Code OTLP telemetry (via the synth package) and replays it at a running wlog receiver over gRPC or HTTP (PLAN §2 dogfood, §19 T9).
replay/synth
Package synth synthesizes realistic Claude Code OTLP telemetry (metrics + logs + traces for one or more sessions) for the wlog dogfood harness and the integration tests (PLAN §2 dogfood, §14 tests).
Package synth synthesizes realistic Claude Code OTLP telemetry (metrics + logs + traces for one or more sessions) for the wlog dogfood harness and the integration tests (PLAN §2 dogfood, §14 tests).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL