Hacker News

Show HN: Ctrlb-decompose: Strip the noise from logs before sending to LLMs

Compress raw log lines into structural patterns with statistics, anomalies, and correlations. Turn millions of noisy log lines into a handful of actionable patterns - with typed variables, quantile stats, anomaly flags, and severity scoring. Runs as a CLI, in the browser via WASM, or as a Rust library.

$ cat server.log | ctrlb-decompose
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ctrlb-decompose: 1,247,831 lines -> 43 patterns (99.9% reduction) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

#1 [ERROR] β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 18,402 (1.5%)
ERROR [ ] Connection to timed out after
   ip          IPv4 unique=12 top: 10.0.1.15 (34%), 10.0.1.22 (28%)
   duration    Duration p50=120ms p99=4.8s

#2 [INFO] β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 904,221 (72.5%)
INFO [ ] Request from completed in status=
   ip          IPv4 unique=1,847 top: 10.0.1.15 (12%), 10.0.1.22 (8%)
   duration    Duration p50=23ms p99=312ms
   status      Enum unique=3 values: 200 (91%), 404 (6%), 500 (3%)

Website coming soon.

ctrlb-decompose uses a two-stage normalization and clustering pipeline that processes logs in a single streaming pass with minimal memory footprint.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              ctrlb-decompose pipeline         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Raw Log Lines
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Strip & parse timestamps (ISO 8601, Apache,
β”‚   Timestamp  β”‚   syslog, Unix epoch, etc.) into normalized
β”‚  Extraction  β”‚   markers with DateTime values.
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Replace integers, floats, IPs, and strings
β”‚     CLP      β”‚   with compact placeholder bytes. Structurally
β”‚   Encoding   β”‚   identical lines now produce the same "logtype."
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Tree-based similarity clustering (Drain3) groups
β”‚   Drain3     β”‚   logtypes into patterns. Differing tokens become
β”‚  Clustering  β”‚   wildcards. Incremental - no second pass needed.
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Merge CLP-decoded values with Drain3 wildcard
β”‚   Variable   β”‚   positions. Classify each variable into semantic
β”‚  Extraction  β”‚   types: IPv4, UUID, Duration, Enum, Integer, etc.
β”‚  & Typing    β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   DDSketch quantiles (p50/p99), HyperLogLog
β”‚  Statistics  β”‚   cardinality estimation, top-k values, temporal
β”‚ Accumulation β”‚   bucketing, and reservoir-sampled example lines.
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Frequency spikes, error cascades, low-cardinality
β”‚   Anomaly    β”‚   flags, bimodal distributions, and clustered
β”‚  Detection   β”‚   numeric detection.
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   Keyword-based severity (ERROR > WARN > INFO > DEBUG),
β”‚   Scoring    β”‚   temporal co-occurrence, shared variable correlation,
β”‚ & Correlationβ”‚   and error cascade detection across patterns.
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    Output    │──── Human (ANSI terminal) / LLM (compact markdown) / JSON
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

CLP Encoding

CLP (Compressed Log Processor) encoding normalizes variable tokens into typed placeholders, so structurally identical lines produce identical logtypes regardless of the actual values:

Input:  "Request from 10.0.1.15 completed in 45ms status=200"
Logtype: "Request from  completed in  ms status=  "

Drain3 Clustering

The Drain algorithm builds a prefix tree over logtypes and groups them by token similarity (configurable threshold, default 0.4). Where tokens diverge, the template gains a wildcard. This runs incrementally - each line is processed once with no second pass.

Variable Typing

Extracted variables are classified into semantic types for richer analysis:

Type Example Detection
IPv4/IPv6 10.0.1.15 CIDR pattern match
UUID 550e8400-e29b-... 8-4-4-4-12 hex format
Duration 45ms, 3.2s Numeric + time unit suffix
HexID 0x1a2b3c 4+ hex digits
Integer 200 Parses as i64
Float 3.14 Contains ., parses as f64
Enum ERROR Low cardinality (< 20 or >= 80%)
Timestamp 2024-01-15T14:22:01Z RFC 3339 pattern
String anything else Fallback
  • Drain3 clusters: O(k) with LRU eviction (default 10k max)
  • Quantiles: DDSketch - fixed ~200 bytes per numeric slot, no raw value storage
  • Cardinality: HyperLogLog++ - ~200 bytes per high-cardinality variable
  • Examples: Reservoir sampling - bounded buffer per pattern

Installation

Homebrew

brew tap ctrlb-hq/tap
brew install ctrlb-decompose

Debian / Ubuntu

curl -LO https://github.com/ctrlb-hq/ctrlb-decompose/releases/download/v0.1.0/ctrlb-decompose_0.1.0-1_amd64.deb
sudo dpkg -i ctrlb-decompose_0.1.0-1_amd64.deb

Build from source

git clone https://github.com/ctrlb-hq/ctrlb-decompose.git
cd ctrlb-decompose
cargo build --release
# Binary at target/release/ctrlb-decompose

Usage Examples

Basic usage

# Pipe from stdin
cat /var/log/syslog | ctrlb-decompose

# Read from file
ctrlb-decompose server.log

Output formats

# LLM-optimized output (compact, token-efficient)
ctrlb-decompose --llm app.log

# JSON output
ctrlb-decompose --json app.log

# Top 10 patterns with 3 example lines each
ctrlb-decompose --top 10 --context 3 app.log

Command-line options

ctrlb-decompose [OPTIONS] [FILE]

Arguments:
  [FILE]  Log file path (reads stdin if omitted or "-")

Options:
      --human      Human-readable output with colors (default)
      --llm        LLM-optimized compact markdown
      --json       Structured JSON output
      --top        Show top N patterns (default: 20)
      --context    Example lines per pattern (default: 0)
      --no-color   Disable ANSI colors
      --no-banner  Suppress header/footer
  -q, --quiet      Suppress progress messages
  -h, --help       Show help
  -V, --version    Show version

Output format summary

Format Flag Best for
Human --human (default) Terminal investigation - colored, visual bars
LLM --llm Feeding into LLMs - compact, token-efficient markdown
JSON --json Programmatic consumption - structured, machine-readable

Claude Code Plugin

Use ctrlb-decompose directly from Claude Code - no CLI knowledge needed. The plugin installs ctrlb-decompose automatically and lets you analyze logs just by asking.

/plugin marketplace add ctrlb-hq/ctrlb-decompose
/plugin install ctrlb-decompose@ctrlb-hq

Just describe what you want in plain language:

  • "Analyze the errors in /var/log/app.log"
  • "What are the most common patterns in this log file?"
  • "Summarize these logs and highlight anomalies"

Claude will check if ctrlb-decompose is installed (and walk you through installation if not), run the analysis, and explain the results - surfacing errors first, calling out anomalies, and suggesting what to investigate next.

See plugin/README.md for full details.

Comments

No comments yet. Start the discussion.