CEL filters

Query bindings, operators, REST usage, and how agents should filter.

The UI filter bar and GET /api/logs?q= evaluate CEL against each log entry. Tight filters keep the stream readable and keep MCP search_logs results small (and cheap) for agents.

Empty q matches everything.

Natural language: the UI and POST /api/nl-cel compile phrases like errors from api last 15 minutes into CEL. MCP search_logs accepts the same via nl. Prefer CEL when you already know the expression.

Bindings

BindingMeaning
serviceStream service tag
levelFirst present of level / severity / lvl in data (string, lowercased for matching helpers)
sourceAttach source when present (browser, cursor, claude, …)
kindEvent kind (browser: console / network; agent hooks: lifecycle name)
cmdFull shell command when attach shell recorded it; also any JSON field named cmd
_mzp.*Receiver metadata (cwd, user, pid, exe)
fieldsTop-level keys from data (nested via ., e.g. user.id)

Property discovery for autocomplete and MCP: GET /api/properties / tool list_properties.

Examples

service == "api" && level == "error"
cmd.contains("npm test")
msg.contains("timeout") || error.contains("timeout")
has(user.id) && user.id == "42"
level in ["error", "warn"]
msg.matches("(?i)time.?out")
source == "browser" && kind == "network" && status >= 400

REST

curl -sS -G "http://127.0.0.1:3149/api/logs" \
  --data-urlencode 'q=level == "error"' \
  --data-urlencode 'service=api' \
  --data-urlencode 'limit=20'

curl -sS -G "http://127.0.0.1:3149/api/properties" \
  --data-urlencode 'q=redis'

Logs are newest-first. Paginate with cursor (return entries with id strictly less than the cursor).

For agents

Prefer specific CEL + small limits over broad dumps:

search_logs: q='level == "error"', service='api', limit=20
get_logs_around: id=<from result>, before=5, after=5

See MCP for tool parameters and hard caps.