Build on top

Reading FS logs

Replay and tail the local NDJSON drain with readFsLogs and tailFsLogs — works in-process or from any external Node tool.

The filesystem drain writes wide events as NDJSON files in .evlog/logs/ (one file per day, optional rotation). The evlog/fs module also ships readers that let any Node tool replay or follow that history without hooking into the running app.

Replay history

import { readFsLogs } from 'evlog/fs'

for await (const event of readFsLogs({ since: '2026-03-01', level: 'error' })) {
  console.log(event.timestamp, event.action ?? event.message)
}

readFsLogs(options) walks the NDJSON files in chronological order, parses them line by line, and yields events that pass all filters. Files outside the date window are skipped entirely.

Options

OptionTypeDescription
dirstringDirectory to read from. Default: .evlog/logs.
sinceDate | stringYield events with timestamp >= since.
untilDate | stringYield events with timestamp <= until.
levelLogLevel | LogLevel[]Filter by event level.
filter(event) => booleanCustom predicate.

Malformed lines (partial writes, manual edits) are silently skipped — your script never crashes on a bad line.

Live tail

import { tailFsLogs } from 'evlog/fs'

const ac = new AbortController()
process.on('SIGINT', () => ac.abort())

for await (const event of tailFsLogs({ signal: ac.signal })) {
  console.log('live:', event.action ?? event.message)
}

tailFsLogs(options) first yields existing events (unless fromEnd: true), then keeps yielding new ones as they're appended — including events written into newly created daily files. Partial writes split across polls are recombined transparently.

Tail-specific options

OptionTypeDescription
pollIntervalMsnumberPolling interval. Default: 500ms (minimum 50ms).
fromEndbooleanSkip existing events; only yield future ones. Default: false.
signalAbortSignalStop tailing when aborted.

All readFsLogs options also apply.

Use cases

  • A local Electron / Tauri dashboard reading .evlog/logs/ from a target project directory.
  • A CI report aggregator that scans logs after a test run.
  • A grep-style CLI that pipes filtered events into jq.
  • Replaying historic events into a dashboard before switching to a live in-process subscription.