Skip to content

Kelora

Turn messy logs into structured data.

Kelora is a scriptable log processor for the command line. Parse structured or semi-structured logs (one format per file/stream), filter with complex logic, and analyze streams using embedded Rhai scripting—all in a single binary. It can also extract logfmt/JSON blobs embedded inside a single event.

cargo install kelora

Or download pre-built binaries for Windows, macOS, and Linux from GitHub Releases.

Development Status

Pre-1.0 tool generated entirely by AI agents. Validated by a large test suite and Rust security tools; see Development Approach and the Security Policy before relying on it in production. APIs might change without notice before v1.0.

When to Use Kelora

Kelora trades speed for programmability. It's slower than grep, awk, and jq, but adds stateful scripting for complex multi-stage transformations.

Reach for Kelora when:

  • Your logs are messy - One format per file/stream, with embedded JSON/logfmt fields you want to pull out
  • You're chaining tools - Replacing grep | awk | jq | custom-script.py with one command
  • You need stateful logic - Counting errors per service, windowed metrics, lookup tables
  • You want embedded scripting - Complex transformations without leaving your shell

Use specialized tools for:

  • Fast search: grep/rg (50-100× faster) - Finding text patterns in logs
  • Simple splitting: awk (faster, ubiquitous) - Field extraction and simple statistics
  • JSON queries: jq (faster, everywhere) - Querying structured JSON documents
  • Interactive exploration: lnav (TUI with SQL) - Browsing logs with a visual interface

Kelora reads from files or stdin and outputs JSON, CSV, or Logfmt. Combine it with lnav, jq, qsv, and other tools for visualization, analytics, and storage.


Live Examples

1. Filter & Convert (The Basics)

Scenario: Filter a Logfmt file for slow requests and output clean JSON.

kelora -f logfmt examples/traffic_logfmt.log \
  --filter 'e.status.to_int() >= 500 || e.latency_ms.to_int() > 1000' \
  -F json
{"ts":"2024-07-17T12:00:04Z","level":"INFO","method":"POST","path":"/checkout","status":200,"latency_ms":1450}
{"ts":"2024-07-17T12:00:05Z","level":"ERROR","method":"POST","path":"/checkout","status":502,"latency_ms":2100}
ts=2024-07-17T11:59:40Z level=INFO method=GET path=/docs status=200 latency_ms=280
ts=2024-07-17T11:59:55Z level=INFO method=POST path=/checkout status=200 latency_ms=950
ts=2024-07-17T12:00:01Z level=INFO method=GET path=/docs status=200 latency_ms=320
ts=2024-07-17T12:00:04Z level=INFO method=POST path=/checkout status=200 latency_ms=1450
ts=2024-07-17T12:00:05Z level=ERROR method=POST path=/checkout status=502 latency_ms=2100
ts=2024-07-17T12:00:07Z level=WARN method=GET path=/billing status=200 latency_ms=900

2. Modify & Anonymize (Scripting)

Scenario: Mask user emails for privacy and convert milliseconds to seconds before printing.

kelora -j examples/audit.jsonl \
  --exec 'e.email = "***"; e.duration_sec = e.ms / 1000.0;' \
  --keys timestamp,user_id,email,duration_sec
timestamp='2024-01-15T10:00:00Z' user_id='usr_123' email='***' duration_sec=1.25
timestamp='2024-01-15T10:05:00Z' user_id='usr_456' email='***' duration_sec=0.34
timestamp='2024-01-15T10:10:00Z' user_id='usr_789' email='***' duration_sec=2.1
timestamp='2024-01-15T10:15:00Z' user_id='usr_234' email='***' duration_sec=0.89
{"timestamp":"2024-01-15T10:00:00Z","user_id":"usr_123","email":"alice@example.com","action":"login","ms":1250}
{"timestamp":"2024-01-15T10:05:00Z","user_id":"usr_456","email":"bob@company.org","action":"view_document","ms":340}
{"timestamp":"2024-01-15T10:10:00Z","user_id":"usr_789","email":"charlie@domain.net","action":"update_profile","ms":2100}
{"timestamp":"2024-01-15T10:15:00Z","user_id":"usr_234","email":"diana@email.com","action":"download_report","ms":890}

3. Contextual Analysis (Pipeline Order)

Scenario: An error occurred. We want to see the error, but enrich it with context from the previous log line (even if that line wasn't an error).

Sequential Pipeline

Kelora processes flags in order. We run --exec before --filter so the sliding window can see the normal events before they are discarded.

kelora -j examples/api_errors.jsonl \
  --window 2 \
  --exec 'if e.level == "ERROR" && window.len() > 1 {
      e.prev_ctx = window[1].endpoint;
  }' \
  --filter 'e.level == "ERROR"' \
  -F logfmt
timestamp=2024-07-17T12:00:05Z level=ERROR endpoint=/api/data status=500 error="database timeout" prev_ctx=/health
timestamp=2024-07-17T12:00:12Z level=ERROR endpoint=/api/admin status=401 request_id=req-abc123 user=alice token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGljZSIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcwMDAwMDAwMH0.sig1 error="token expired" prev_ctx=/api/users
timestamp=2024-07-17T12:00:18Z level=ERROR endpoint=/api/billing status=401 request_id=req-def456 user=bob token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJib2IiLCJyb2xlIjoidXNlciIsImV4cCI6MTcwNTAwMDAwMH0.sig2 error="token expired" prev_ctx=/api/posts
timestamp=2024-07-17T12:00:20Z level=ERROR endpoint=/api/export status=503 error="service unavailable" prev_ctx=/api/billing
{"timestamp":"2024-07-17T12:00:00Z","level":"INFO","endpoint":"/health","status":200}
{"timestamp":"2024-07-17T12:00:05Z","level":"ERROR","endpoint":"/api/data","status":500,"error":"database timeout"}
{"timestamp":"2024-07-17T12:00:10Z","level":"INFO","endpoint":"/api/users","status":200}
{"timestamp":"2024-07-17T12:00:12Z","level":"ERROR","endpoint":"/api/admin","status":401,"request_id":"req-abc123","user":"alice","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGljZSIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcwMDAwMDAwMH0.sig1","error":"token expired"}
{"timestamp":"2024-07-17T12:00:15Z","level":"INFO","endpoint":"/api/posts","status":200}
{"timestamp":"2024-07-17T12:00:18Z","level":"ERROR","endpoint":"/api/billing","status":401,"request_id":"req-def456","user":"bob","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJib2IiLCJyb2xlIjoidXNlciIsImV4cCI6MTcwNTAwMDAwMH0.sig2","error":"token expired"}
{"timestamp":"2024-07-17T12:00:20Z","level":"ERROR","endpoint":"/api/export","status":503,"error":"service unavailable"}
{"timestamp":"2024-07-17T12:00:25Z","level":"INFO","endpoint":"/health","status":200}

Advanced Features

Beyond basic filtering and conversion, Kelora includes specialized functions that solve problems you'd otherwise need multiple tools or custom scripts for:

See Power-User Techniques for real-world examples. For performance characteristics and when to use specialized tools instead, see Performance Comparisons.


Get Started

→ Quickstart (5 minutes) - Install and run your first commands

→ Tutorial: Basics (30 minutes) - Learn input formats, filtering, and output

→ How-To Guides - Solve specific problems (including debugging)

For deeper understanding, see Concepts. For complete reference, see Glossary, Functions, Formats, and CLI options.


License

Kelora is open source software licensed under the MIT License.

Development Approach

Kelora is an experiment in agentic AI development. Claude Code (Sonnet 4.5) and Codex CLI (gpt-5-codex) generate all implementation and tests; I steer requirements but do not write or review code. Validation relies on the automated test suite plus cargo audit and cargo deny, so please inspect the code yourself before relying on it in production and expect the API to evolve until 1.0. This is a spare-time, single-developer project, so support and updates are best-effort.