A terminal-based structured log viewer with real-time filtering, highlighting, and live tailing.
- Live tailing - Follow logs in real-time from files or stdin
- Multiple formats - JSON and logfmt with automatic detection
- CEL filtering - Filter logs using Common Expression Language expressions
- Field highlighting - Highlight specific fields or CEL-matched values
- Multi-line selection - Select multiple lines and copy to clipboard
- Syntax highlighting - Color-coded keys, levels, and IDs for readability
- Humanized display - Readable timestamps and shortened trace IDs
- Disk-backed - Efficiently handles large log files with LRU caching (file mode only; stdin streams to memory)
- File watching - Automatically picks up new content as files grow
Homebrew:
brew tap joealcorn/tap
brew install cutlGo:
go install github.com/joealcorn/cutl/cmd/cutl@latestBinary:
Download from releases.
# View a JSON log file (default)
cutl app.log
# Pipe from another command
kubectl logs -f my-pod | cutl
# Specify format explicitly
cutl -f logfmt app.log
cutl -f json app.log
# Plain output (no interactive TUI)
cat app.log | cutl -p| Flag | Description |
|---|---|
-f |
Log format: json (default), logfmt, guess |
-p |
Plain output mode (no interactive TUI) |
--filter |
CEL filter expression (plain mode only) |
# Filter errors in plain mode (use line.field syntax)
cutl -p --filter 'line.level == "error"' app.log
# Filter by severity
cutl -p --filter 'line.level.gte("warn")' app.logNote: In plain mode, use
line.fieldsyntax to access fields (e.g.,line.level,line.msg). The interactive TUI mode supports direct field names.
{"level":"info","msg":"Server started","time":"2024-01-15T10:30:00Z","port":8080}
{"level":"error","msg":"Connection failed","time":"2024-01-15T10:30:01Z","error":"timeout"}level=info msg="Server started" time=2024-01-15T10:30:00Z port=8080
level=error msg="Connection failed" time=2024-01-15T10:30:01Z error=timeout
Non-parseable lines are displayed as-is.
| Key | Action |
|---|---|
j / ↓ |
Move down |
k / ↑ |
Move up |
J / Shift+↓ |
Extend selection down |
K / Shift+↑ |
Extend selection up |
Ctrl+d / PgDn |
Page down |
Ctrl+u / PgUp |
Page up |
Shift+PgDn |
Extend selection page down |
Shift+PgUp |
Extend selection page up |
g / End |
Go to tail (newest) |
G / Home |
Go to head (oldest) |
c |
Copy selected line(s) to clipboard |
f |
Open filter prompt |
m |
Cycle display mode (human/normal/raw) |
h |
Open highlight manager |
q / Ctrl+c |
Quit |
Press f to enter filter mode. Filters use CEL (Common Expression Language) syntax.
- A field picker appears - select a field to start your expression
- The field is inserted and you can continue typing
- Press Tab to auto-complete field names as you type
# Filter by level
level == "error"
# Filter by level severity (gte, gt, lte, lt)
level.gte("warn") # warn, error, fatal
level.gt("info") # warn, error, fatal
level.lte("info") # trace, debug, info
level.lt("warn") # trace, debug, info
# Filter by message content
message.contains("timeout")
# Combine conditions
level == "error" && message.contains("database")
# Filter by trace ID
trace_id == "abc123"
# Check if a field exists
has(line.status_code)
# Access any field via line map
line.custom_field == "value"
All field names from your logs are automatically available as top-level variables. For example, if your logs contain request_id, user_id, and status_code, you can use them directly:
request_id == "abc123"
status_code >= 400
user_id.contains("admin")
The line map is also available for accessing any field: line.field_name.
Press h to open the highlight manager. From there:
- Enter: Toggle a highlight on/off
- e: Edit a CEL expression (when selected)
- /: Add a new CEL highlight
- Esc: Close
Select a field from the current log line and press Enter to highlight all values of that field.
Press / to add a CEL expression highlight using CEL syntax:
level == "error" # Highlights "error" values in level field
status_code >= 400 # Highlights matching status codes
msg.contains("timeout") # Highlights matching messages
Multiple highlights can be active with different colors.
Press m to cycle through display modes:
- Timestamps are converted to local 24-hour time:
2024/01/15 15:04:05 - Trace IDs are shortened to 4-character hashes for visual correlation
- Keys and values are styled with colors
- Timestamps shown as-is
- IDs shown in full with colored styling
- Keys styled with colors
- Original log line shown exactly as it appears in the file
[LIVE] Lines 1-50 of 1000 | f:filter(2) | m:human | h:highlight(3) | c:copy | g:follow | q:quit
[LIVE]- Following tail (green)[PAUSED]- Scrolled away from tail (orange)[EOF]- Input stream ended (gray)123/s- Lines per second (when streaming)f:filter(N)- Number of active filtersm:human/normal/raw- Current display modeh:highlight(N)- Number of active highlightsc:copy- Copy selected lines
MIT
