Skip to content

psandis/logclaw

Repository files navigation

logclaw

npm

A Node-native log investigator for the terminal. It eats messy, half-structured app output, the stuff console.log and framework loggers actually emit, and turns it into something readable: stack traces folded into single events, noisy repeats collapsed, levels colorized. Plus an AI digest of what went wrong.

What It Does

  • reads logs from a file or stdin
  • detects json, logfmt, common, and syslog formats automatically
  • normalizes raw framework-style logs through config-driven regex patterns
  • folds stack traces into single events instead of shredding them line by line
  • collapses consecutive duplicate entries into (×N) badges
  • renders readable terminal output with timestamps, levels, and extra fields
  • generates AI summaries of failures through --summarize when provider keys are configured

Why this exists

The terminal log space is crowded but lopsided. lnav (~10k stars, C++) owns interactive investigation. hl (~3k stars, Rust) owns fast JSON/logfmt reformatting. Both are excellent and you will not out-perform them on raw speed.

The gaps they leave:

  1. Unstructured app output. hl only speaks JSON and logfmt. The messy reality, raw stdout, ad-hoc logger lines, and multi-line Node/Java/Python stack traces, is unserved. That's logclaw's primary target.
  2. No AI, anywhere. None of the incumbents summarize or triage. logclaw's --summarize is the headline, not a bolt-on.
  3. No Node-native option. Every serious tool is Rust/C++/Go. "Runs in the runtime my app already uses, npm i -g, just works" is an open lane.

logclaw does not try to win on throughput against a multithreaded Rust tool. It wins on handling the mess and on the AI investigator.

Requirements

  • Node 22+

Install

npm install -g logclaw

Both logclaw and lclaw are available after install.

Quick Start

logclaw /var/log/app.log
lclaw /var/log/app.log --level warn

Read from stdin:

cat /var/log/nginx/access.log | logclaw
kubectl logs my-pod | logclaw --level error
docker logs my-container | logclaw --summarize

Live tail:

logclaw /var/log/app.log -f
logclaw /var/log/app.log -f --level warn

Compressed files:

logclaw /var/log/app.log.gz
logclaw archive/app-2026-05-21.log.gz --level error

Development

Clone and run from source:

git clone https://github.com/psandis/logclaw.git
cd logclaw
npm install
npm run dev -- samples/json.log
npm run dev -- samples/spring-boot.log
npm test
npm run build

Quick Commands

Command Purpose Result
lclaw app.log parse a log file readable terminal output with grouping and repeat collapsing
lclaw app.log --level warn filter by minimum level only warn, error, and fatal entries shown
lclaw app.log -f live tail a file new lines rendered as they arrive
lclaw app.log.gz read a compressed file transparent gzip decompression
cat app.log | lclaw read from stdin same render pipeline without a file path
kubectl logs my-pod | lclaw --level error triage pod logs errors only, stack traces grouped
lclaw app.log --summarize AI triage short plain-text root-cause summary
lclaw app.log --summarize --errors-only AI triage on failures only tighter digest focused on error events
lclaw app.log --ai-detect infer unknown format with AI pattern applied for the session
npm test run automated tests (dev) Vitest suite result
npm run typecheck verify TypeScript correctness (dev) compile check without emit

Sample Fixtures

Fixtures live in samples/. Use them to verify each supported format family:

File Format What it proves
json.log JSON structured parsing, repeat collapsing, stack-trace grouping
logfmt.log logfmt key/value parsing, extras rendering, repeat collapsing
apache.log Apache access + error common-log detection plus regex-driven raw parsing
nginx.log nginx access + error common-log detection plus regex-driven raw parsing
syslog.log RFC3164 syslog syslog detection plus regex-driven raw parsing
spring-boot.log Spring Boot regex-driven raw parsing and Java stack-trace grouping
laravel.log Laravel regex-driven raw parsing
python.log Python logging regex-driven raw parsing and traceback grouping
mixed.log mixed formats fallback behavior when one file mixes multiple styles

Run them from the cloned repo:

npm run dev -- samples/json.log
npm run dev -- samples/logfmt.log
npm run dev -- samples/apache.log
npm run dev -- samples/syslog.log

Development Scripts

Script What it does
npm run dev -- <file> run from source through tsx (no build needed)
npm run build compile TypeScript to dist/
npm test run the Vitest suite
npm run typecheck TypeScript compile check without emitting

Usage

logclaw [file] [options]
lclaw [file] [options]

  -l, --level <level>   minimum level to show (trace|debug|info|warn|error|fatal)
      --format <fmt>    force format instead of auto-detect (json|logfmt|common|syslog)
  -f, --follow          watch the file for new lines and render them as they arrive
      --no-color        disable ANSI colors
      --no-group        disable multiline / stack-trace grouping
      --no-collapse     disable consecutive-repeat collapsing
      --no-trace        hide grouped stack traces
      --summarize       print an AI digest of what went wrong
      --errors-only     with --summarize, only feed error/fatal entries
      --ai-detect       use AI to infer format when auto-detection returns unknown

Set LOGCLAW_DEBUG=1 to print the detected format + confidence to stderr.

Live tail

Watch a file and render new lines as they arrive:

lclaw /var/log/app.log -f
lclaw /var/log/app.log -f --level warn
kubectl logs -f my-pod > /tmp/pod.log && lclaw /tmp/pod.log -f

--follow requires a file path. Stack-trace grouping and repeat collapsing work the same as in batch mode, carrying state across watch callbacks.

Compressed input

Pass a .gz file directly — logclaw decompresses it transparently:

lclaw /var/log/nginx/access.log.gz
lclaw archive/app-2026-05-21.log.gz --level error
cat backup.log.gz | lclaw

Both file and stdin paths are supported. Detection is by .gz extension or gzip magic bytes.

AI format inference

When auto-detection returns unknown and you have a provider key configured, --ai-detect sends a sample of lines to the model and applies the inferred pattern for the session:

lclaw custom-app.log --ai-detect
LOGCLAW_DEBUG=1 lclaw custom-app.log --ai-detect
lclaw custom-app.log --ai-detect --summarize

Requires OPENAI_API_KEY or ANTHROPIC_API_KEY in your environment or .env file. The inferred pattern is session-only and does not modify data/defaults.jsonc.

Config

Default behavior is defined in data/defaults.jsonc.

It defines:

  • detection thresholds
  • structured field aliases
  • regex-driven raw log patterns
  • level normalization aliases
  • renderer defaults

The runtime loads this file once at startup and threads it through detection, parsing, level normalization, and rendering.

What the config file controls:

Section Purpose
detection sample size and confidence threshold for format detection
parsers.fieldMappings which keys count as level, message, and timestamp in structured logs
rawPatterns ordered regex profiles for raw framework and server log formats
levelAliases mapping from raw level words to canonical logclaw levels
render.timestampSlice which part of the timestamp string is shown in terminal output
render.levelColors per-level terminal color selection

Editing the config file changes behavior without touching parser or renderer code.

AI Setup

Create a local .env from .env.example to enable --summarize.

Supported variables:

Variable What it does
LOGCLAW_AI_PROVIDER optional override: openai or anthropic
OPENAI_API_KEY enables OpenAI-backed summaries
OPENAI_MODEL OpenAI model id, defaults to gpt-4.1-mini
ANTHROPIC_API_KEY enables Anthropic-backed summaries
CLAUDE_API_KEY alias for ANTHROPIC_API_KEY
ANTHROPIC_MODEL Anthropic model id, defaults to claude-sonnet-4-20250514
CLAUDE_MODEL alias for ANTHROPIC_MODEL

Example:

cp .env.example .env
node dist/index.js samples/spring-boot.log --summarize

AI usage examples:

lclaw samples/spring-boot.log --summarize
lclaw samples/spring-boot.log --summarize --errors-only
cat samples/json.log | lclaw --summarize
LOGCLAW_AI_PROVIDER=anthropic lclaw samples/laravel.log --summarize

What --summarize produces:

  • a short plain-text triage summary
  • the most likely root cause
  • which entries to inspect first
  • better signal when combined with --errors-only

Example AI summary output:

The checkout flow is failing because the application tries to read `total` from an undefined cart object during request handling. The primary failure is the `TypeError` in `computeCart`, which then surfaces as an unhandled rejection in `/checkout`. Start with the error event at 09:14:06.440 and the attached stack trace, especially `/app/src/cart.js:42` and `/app/src/routes/checkout.js:17`. The repeated healthcheck lines are unrelated noise.

Project Structure

logclaw/
├── data/
│   └── defaults.jsonc
├── .env.example
├── .gitignore
├── samples/
│   ├── apache.log
│   ├── json.log
│   ├── laravel.log
│   ├── logfmt.log
│   ├── mixed.log
│   ├── nginx.log
│   ├── python.log
│   ├── spring-boot.log
│   └── syslog.log
├── src/
│   ├── ai/
│   ├── parser/
│   ├── render/
│   ├── transform/
│   └── index.ts
├── tests/
│   ├── collapse.test.ts
│   ├── detect.test.ts
│   ├── fixtures.test.ts
│   ├── formats.test.ts
│   └── multiline.test.ts
├── package.json
├── tsconfig.json
└── vitest.config.ts

Related Projects

Other OpenClaw projects:

  • dustclaw - disk space analyzer and cleanup CLI
  • dietclaw - codebase health and dependency bloat monitor
  • feedclaw - RSS/Atom reader and AI digest builder
  • wirewatch - network traffic monitoring with AI-assisted anomaly detection
  • driftclaw - version drift inspection across environments
  • speak2text - speech-to-text CLI
  • text2speak - text-to-speech CLI
  • asciiclaw - image to ASCII art terminal converter
  • unasciiclaw - ASCII art to image converter
  • mymailclaw - email scanner, categorizer, and cleaner CLI

How It Works

source lines
   │
   ▼
detect format        src/parser/detect.ts   ← samples first ~50 lines, scores each format
   │
   ▼
parse per line       src/parser/formats.ts  ← json / logfmt / raw fallback
   │
   ▼
group multiline      src/transform/multiline.ts  ← folds stack traces into one entry
   │
   ▼
collapse repeats     src/transform/collapse.ts   ← "(×N)" instead of N identical lines
   │
   ▼
render / summarize   src/render/pretty.ts , src/ai/summarize.ts

json and logfmt have dedicated parsers. common, syslog, and framework-style raw logs are normalized through config-driven regex patterns plus multiline grouping.

Example Output

samples/json.log is the quick demo fixture used in the README flow:

09:14:01.221 INFO   server listening  port=3000
09:14:02.882 INFO   healthcheck ok (×3)
09:14:05.101 WARN   slow query  ms=812 query=SELECT * FROM orders
09:14:06.440 ERROR  unhandled rejection in /checkout
TypeError: Cannot read properties of undefined (reading 'total')
    at computeCart (/app/src/cart.js:42:18)
    at /app/src/routes/checkout.js:17:23
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
09:14:07.000 INFO   healthcheck ok

Roadmap

  • -f, --follow live tail mode.
  • Compressed input (.gz) — transparent decompression for files and stdin.
  • --ai-detect format inference when auto-detection returns unknown.
  • Optional: route src/ai/summarize.ts through psclawmcp instead of direct provider calls.
  • Dedicated common (Apache/nginx) and syslog parsers (detection exists, parsers fall back to raw for now).
  • Register logclaw as a tool in psclawmcp.

Notes

  • npm name to confirm. Backup naming if taken: logsclaw / clawlog.
  • ESM, "type": "module", NodeNext resolution, relative imports use .js.

License

See MIT

About

Node-native log investigator for messy app output. Groups stack traces, collapses repeats, and summarizes what went wrong with AI.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors