Blazing Fast
Written in Rust for minimal overhead and maximum performance when handling large log volumes.
The LogChef CLI is a powerful, high-performance terminal companion for LogChef. Built in Rust, it provides a fast and intuitive way to interact with your logs without leaving your terminal.
Blazing Fast
Written in Rust for minimal overhead and maximum performance when handling large log volumes.
Rich Highlighting
Beautiful syntax highlighting for log levels, dates, IPs, and custom keywords powered by tailspin.
Multi-Context
Manage multiple LogChef instances (dev/staging/prod) with kubectl-style context switching.
Secure Auth
Native support for OIDC PKCE flow, keeping your credentials secure while being easy to use.
# 1. Build the CLIcd logchef/cli && cargo build --release
# 2. Add to PATH (or copy to /usr/local/bin)export PATH="$PATH:$(pwd)/target/release"
# 3. Authenticate (auto-creates context from hostname)logchef auth --server https://logs.example.com
# 4. Rename context to something friendlylogchef config rename logs.example.com prod
# 5. Set defaults so you don't need --team/--source every timelogchef config set team "my-team"logchef config set source "nginx-logs"
# 6. Query logslogchef query "level:error" --since 1hDownload the latest CLI release for your platform from GitHub Releases.
| Platform | File |
|---|---|
| Linux x86_64 | logchef-cli_<version>_linux-x86_64-musl.tar.gz |
| Linux ARM64 | logchef-cli_<version>_linux-aarch64-musl.tar.gz |
| macOS Apple Silicon | logchef-cli_<version>_macos-aarch64.tar.gz |
| macOS Intel | logchef-cli_<version>_macos-x86_64.tar.gz |
| Windows x86_64 | logchef-cli_<version>_windows-x86_64.zip |
# Example: Download and install (replace VERSION with actual version)VERSION="0.1.2"
# Linux x86_64curl -LO "https://github.com/mr-karan/logchef/releases/download/cli-v${VERSION}/logchef-cli_${VERSION}_linux-x86_64-musl.tar.gz"tar xzf logchef-cli_${VERSION}_linux-x86_64-musl.tar.gzsudo mv logchef /usr/local/bin/
# macOS Apple Siliconcurl -LO "https://github.com/mr-karan/logchef/releases/download/cli-v${VERSION}/logchef-cli_${VERSION}_macos-aarch64.tar.gz"tar xzf logchef-cli_${VERSION}_macos-aarch64.tar.gzsudo mv logchef /usr/local/bin/If you prefer to build from source (requires Rust):
# Clone the repositorygit clone https://github.com/mr-karan/logchef.gitcd logchef/cli
# Build the release binarycargo build --release
# The binary is at cli/target/release/logchef# Copy to your PATH:sudo cp target/release/logchef /usr/local/bin/If you have just installed:
# Build release binaryjust build-cli
# Build debug binary (faster compilation for testing)just build-cli-debug
# Install to ~/.cargo/bin (must be in PATH)just install-clilogchef --versionlogchef --helpThe CLI supports two authentication methods: browser-based OIDC and API tokens.
To use browser-based auth, configure a public OIDC client for the CLI and set it in the server config:
[oidc]cli_client_id = "logchef-cli"Your OIDC provider must allow loopback redirects for the CLI:
http://127.0.0.1:19876/callback through http://127.0.0.1:19878/callback.
For interactive use, authenticate via your browser:
logchef authThis opens your browser to complete the OIDC login flow. The token is automatically saved to your config file.
# Check authentication statuslogchef auth --status
# Log out (clear stored token)logchef auth --logoutFor scripts and automation, use an API token directly:
# Set token via environment variableexport LOGCHEF_AUTH_TOKEN="logchef_1_abc123..."logchef query ""
# Or pass token as argumentlogchef --token "logchef_1_abc123..." query ""
# Or save to config filelogchef config set auth.token "logchef_1_abc123..."Generate API tokens from the LogChef web UI under your profile settings.
The query command allows you to execute LogChefQL queries directly from your terminal.
logchef query "level:error service:api" --since 1h| Option | Shorthand | Description | Default |
|---|---|---|---|
--team | -t | Team name (or ID) | (from config) |
--source | -S | Source name, database.table_name, or ID | (from config) |
--since | -s | Time range (e.g., “15m”, “1h”, “24h”) | “15m” |
--from | Absolute start time (ISO 8601) | ||
--to | Absolute end time (ISO 8601) | ||
--limit | -l | Maximum number of results | 100 |
--output | Output format (text, json, jsonl, table) | text | |
--no-highlight | Disable syntax highlighting | false | |
--no-timestamp | Hide timestamp from text output | false | |
--show-sql | Display the generated SQL query | false |
When you run logchef query without specifying team, source, or query, and you’re in a terminal, the CLI enters interactive mode:
# Launch interactive modelogchef query
# Prompts:# ? Select team: [production, staging, dev]# ? Select source: [nginx-logs, app-logs, api-logs]# ? LogChefQL query: level:errorThis is useful for quick exploration without remembering exact team/source names.
# Get all logs from the last 15 minuteslogchef query "" --team "production" --source "nginx-logs"
# Use database.table_name format (copy from UI)logchef query "" --team "production" --source "logs.nomad_apps"
# Filter by field valuelogchef query "status:500" --team "production" --source "nginx-logs"
# Multiple conditions (AND)logchef query "method:POST status:403" --team "production" --source "nginx-logs"
# Search within a time rangelogchef query "level:error" --since 1h --limit 50
# Hide timestamp from outputlogchef query "level:error" --no-timestamp
# Output as JSON (returns object with logs, stats, columns)logchef query "status:500" --output json | jq '.logs[] | .host'
# Output as JSON Lines (one JSON object per line, great for jq)logchef query "" --output jsonl | jq '.msg'
# JSON output is jq-friendly - stats are included in the objectlogchef query "" --output json | jq '{count: .count, time_ms: .stats.execution_time_ms}'
# Show the SQL that will be executedlogchef query "method:GET" --show-sql
# Use absolute time rangelogchef query "" --from "2026-01-14T00:00:00Z" --to "2026-01-14T12:00:00Z"The sql command lets you execute raw ClickHouse SQL directly. Unlike query, you have full control over the SQL—including time filters, aggregations, and joins.
logchef sql "SELECT * FROM logs.app WHERE level='error' LIMIT 10"| Option | Shorthand | Description | Default |
|---|---|---|---|
--team | -t | Team name (or ID) | (from config) |
--source | -S | Source name, database.table_name, or ID | (from config) |
--timeout | Query timeout in seconds | 30 | |
--output | Output format (text, json, jsonl, table) | text | |
--no-highlight | Disable syntax highlighting | false | |
--no-timestamp | Hide timestamp from text output | false |
Similar to query, the sql command supports interactive mode:
# Launch interactive modelogchef sql
# Prompts:# ? Select team: [production, staging, dev]# ? Select source: [nginx-logs, app-logs, api-logs]# ? SQL query: SELECT * FROM logs.app LIMIT 10# Simple query with time filterlogchef sql "SELECT * FROM logs.app WHERE _timestamp > now() - INTERVAL 1 HOUR LIMIT 100"
# Aggregation querylogchef sql "SELECT level, count() as cnt FROM logs.app WHERE _timestamp > now() - INTERVAL 1 DAY GROUP BY level"
# Read SQL from stdin (useful for complex queries)cat query.sql | logchef sql -
# Or use heredoclogchef sql - <<'EOF'SELECT toStartOfHour(_timestamp) as hour, count() as requests, countIf(status >= 500) as errorsFROM logs.nginxWHERE _timestamp > now() - INTERVAL 24 HOURGROUP BY hourORDER BY hourEOF
# Output as JSONlogchef sql "SELECT * FROM logs.app LIMIT 5" --output json
# Pipe to jq for processinglogchef sql "SELECT host, count() as cnt FROM logs.app GROUP BY host" --output jsonl | jq -s 'sort_by(.cnt) | reverse'When running a query, you’ll see highlighted output with colors:
2026-01-14T07:16:06.149Z host=172.100.86.236 method=PATCH status=410 bytes=451122026-01-14T07:16:06.049Z host=156.89.90.123 method=PATCH status=200 bytes=420922026-01-14T07:16:05.949Z host=217.33.68.177 method=POST status=403 bytes=10709The highlighting includes:
The collections command lets you list and run saved collections (saved queries) from the LogChef web UI.
# List all collections for a sourcelogchef collections --team "production" --source "nginx-logs"
# Run a collection by namelogchef collections "Error Dashboard" --team "production" --source "nginx-logs"| Option | Shorthand | Description | Default |
|---|---|---|---|
--team | -t | Team name (or ID) | (from config) |
--source | -S | Source name, database.table_name, or ID | (from config) |
--since | -s | Override time range (e.g., “15m”, “1h”, “24h”) | (from collection) |
--from | Override absolute start time (ISO 8601) | ||
--to | Override absolute end time (ISO 8601) | ||
--limit | -l | Override maximum number of results | (from collection) |
--var | Set variable value (format: name=value) | ||
--output | Output format (text, json, jsonl, table) | text | |
--no-highlight | Disable syntax highlighting | false | |
--no-timestamp | Hide timestamp from text output | false | |
--show-sql | Display the generated SQL query | false |
When run without arguments, enters interactive mode to select team, source, and collection:
# Launch interactive modelogchef collections
# Prompts:# ? Select team: [production, staging, dev]# ? Select source: [nginx-logs, app-logs, api-logs]# ? Select collection: [Error Dashboard, Slow Requests, Daily Summary]# List all collectionslogchef collections -t "production" -S "nginx-logs"# ID NAME TYPE DESCRIPTION# 1 Error Dashboard logchefql Track 5xx errors# 2 Slow Requests logchefql Requests > 1s
# Run a collection with default settingslogchef collections "Error Dashboard" -t "production" -S "nginx-logs"
# Override time rangelogchef collections "Error Dashboard" -t 1 -S 1 --since 1h
# Set variables defined in the collectionlogchef collections "Service Logs" --var service=api --var level=error
# Output as JSONlogchef collections "Error Dashboard" --output json | jq '.count'Manage your CLI settings using the config command.
# List all contextslogchef config list
# Switch to a different contextlogchef config use prod
# Show current context configurationlogchef config show
# Set configuration values for current contextlogchef config set team 2logchef config set source 2logchef config set limit 50logchef config set since "1h"
# Rename a contextlogchef config rename logs.example.com prod
# Delete a contextlogchef config delete old-serverThe CLI supports managing multiple LogChef instances (dev/staging/prod):
# Authenticate with prod (context auto-created from hostname)logchef auth --server https://logs.company.comlogchef config rename logs.company.com prod
# Authenticate with devlogchef auth --server http://localhost:8125logchef config rename localhost dev
# List contextslogchef config list# CONTEXT SERVER AUTH# * prod https://logs.company.com yes# dev http://localhost:8125 yes
# Switch contextslogchef config use devlogchef query "level:debug"
# One-off query to different contextlogchef --context prod query "level:error"After authenticating, set your defaults to avoid typing --team and --source every time:
# Set defaults using team and source nameslogchef config set team "my-team"logchef config set source "nginx-logs"
# Now you can just run:logchef query "level:error"The configuration is stored at ~/.config/logchef/logchef.json:
{ "current_context": "prod", "contexts": { "prod": { "server_url": "https://logs.example.com", "timeout_secs": 30, "token": "logchef_1_...", "token_expires_at": "2026-02-14T00:00:00Z", "defaults": { "team": "production", "source": "nginx-logs", "limit": 100, "since": "15m" } }, "dev": { "server_url": "http://localhost:8125", "timeout_secs": 30, "token": "logchef_1_...", "defaults": {} } }, "highlights": { "custom_keywords": ["MYAPP", "CRITICAL"], "disable_builtin": false, "disabled_groups": [], "custom_regexes": [ { "pattern": "trace_id=[a-f0-9]+", "color": "cyan", "bold": false, "italic": false } ] }}| Section | Key | Description |
|---|---|---|
current_context | Active context | Name of the context to use by default |
contexts.<name>.server_url | Server URL | LogChef server address for this context |
contexts.<name>.timeout_secs | Timeout | HTTP request timeout in seconds |
contexts.<name>.defaults.team | Default team | Team name (or ID) to use when --team is omitted |
contexts.<name>.defaults.source | Default source | Source name (or ID) to use when --source is omitted |
contexts.<name>.defaults.limit | Default limit | Number of results when --limit is omitted |
contexts.<name>.defaults.since | Default time range | Time range when --since is omitted |
highlights.custom_keywords | Custom keywords | Words to highlight in magenta |
highlights.disable_builtin | Disable defaults | Turn off built-in log level highlighting |
highlights.disabled_groups | Disabled groups | List of highlighter groups to disable |
highlights.custom_regexes | Custom patterns | Regex patterns with custom colors |
LogChef CLI provides automatic syntax highlighting for common log patterns, powered by tailspin.
| Category | What’s Highlighted | Colors |
|---|---|---|
| Log Levels | ERROR, FATAL, CRITICAL | Red (bold) |
| WARN, WARNING | Yellow | |
| INFO | Green | |
| DEBUG, TRACE | Blue | |
| HTTP Methods | GET | Green (bold) |
| POST | Yellow (bold) | |
| PUT, PATCH | Magenta (bold) | |
| DELETE | Red (bold) | |
| Identifiers | IPs, UUIDs, URLs | Cyan/Blue |
| Temporal | Dates, timestamps | Magenta |
| Data | Numbers, key=value pairs | Cyan |
| Booleans | true, false, null | Cyan |
Highlight specific words on-the-fly without changing your config:
# Highlight words in specific colorslogchef query "" --highlight red:ERROR,FAIL --highlight green:SUCCESS,OK
# Available colors: red, green, yellow, blue, magenta, cyan, white, black# Also: bright_red, bright_green, bright_yellow, etc.Turn off specific highlighting groups for cleaner output:
# Disable date/time and number highlightinglogchef query "" --disable-highlight dates --disable-highlight numbers
# Available groups: dates, numbers, uuids, ips, urls, paths,# pointers, keyvalue, quotes, json, keywordsAdd custom regex patterns in your config file:
{ "highlights": { "custom_regexes": [ { "pattern": "user_id=(\\d+)", "color": "cyan", "bold": true }, { "pattern": "request_id=[a-f0-9-]+", "color": "magenta" } ] }}For piping to other tools or file output:
logchef query "" --no-highlight > logs.txtlogchef query "" --no-highlight | grep "ERROR"--output json)Returns a single JSON object containing logs, stats, and metadata:
{ "logs": [ { "_timestamp": "2026-01-20T10:30:00Z", "level": "error", "msg": "..." }, { "_timestamp": "2026-01-20T10:29:59Z", "level": "info", "msg": "..." } ], "count": 2, "stats": { "execution_time_ms": 45, "rows_read": 2, "bytes_read": 1024 }, "query_id": "abc123-...", "generated_sql": "SELECT * FROM ...", "columns": [ { "name": "_timestamp", "type": "DateTime64(3)" }, { "name": "level", "type": "String" } ]}--output jsonl)Each log entry is output as a separate JSON object on its own line:
{"_timestamp":"2026-01-20T10:30:00Z","level":"error","msg":"Connection failed"}{"_timestamp":"2026-01-20T10:29:59Z","level":"info","msg":"Request completed"}The CLI automatically detects if output is going to a terminal (TTY) or being piped:
3 logs | 45ms | 3 rows read)grep, jq, etc.# Stats shown (terminal)logchef query ""# Output: [logs...]# 3 logs | 45ms | 3 rows read
# Stats suppressed (piped)logchef query "" | grep "error"# Output: [matching lines only, no stats]The following options can be used with any command:
| Option | Environment Variable | Description |
|---|---|---|
--context / -c | LOGCHEF_CONTEXT | Use a specific context |
--server | LOGCHEF_SERVER_URL | Override server URL (ephemeral) |
--token | LOGCHEF_AUTH_TOKEN | Override API token |
--debug / -d | Enable detailed debug output |
For CI/CD pipelines and automation, you can configure the CLI entirely via environment variables:
# Option 1: Use a saved contextexport LOGCHEF_CONTEXT="prod"logchef query "level:error" --team "production" --source "app-logs"
# Option 2: Ephemeral mode (no saved context needed)export LOGCHEF_SERVER_URL="https://logs.example.com"export LOGCHEF_AUTH_TOKEN="logchef_1_abc123..."logchef query "level:error" --team "production" --source "app-logs"logchef query "status:500" --output jsonl > errors.jsonllogchef query "level:error" --output json | jq '.count'# Get all unique hosts from JSON outputlogchef query "status:500" --output json | jq -r '.logs[].host' | sort -u
# Get all unique hosts from JSONL outputlogchef query "status:500" --output jsonl | jq -r '.host' | sort -u
# Pretty print messageslogchef query "level:error" --output jsonl | jq '.msg'
# Get query statslogchef query "" --output json | jq '.stats'logchef query "" --no-highlight | grep -i "database"logchef query "level:error" --no-timestamp --no-highlight > errors.txtfor source in "nginx-logs" "app-logs" "api-logs"; do echo "=== Source: $source ===" logchef query "level:error" --source "$source" --limit 5done