Skip to main content
ClaudeWave
Skill12k repo starsupdated 9d ago

kfl

KFL (Kubeshark Filter Language) is a CEL-based query language for filtering Kubernetes cluster traffic captured by Kubeshark. Use it to search and display network traffic based on protocol type, endpoints, request/response attributes, and custom expressions without affecting what gets captured. It functions as a display filter similar to SQL for databases or search syntax for the web.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/kubeshark/kubeshark /tmp/kfl && cp -r /tmp/kfl/skills/kfl ~/.claude/skills/kfl
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# KFL2 — Kubeshark Filter Language

You are a KFL2 expert. KFL2 is built on Google's CEL (Common Expression Language)
and is the query language for all Kubeshark traffic analysis. It operates as a
**display filter** — it doesn't affect what's captured, only what you see.

Think of KFL the way you think of SQL for databases or Google search syntax for
the web. Kubeshark captures and indexes all cluster traffic; KFL is how you
search it.

For the complete variable and field reference, see `references/kfl2-reference.md`.

## Core Syntax

KFL expressions are boolean CEL expressions. An empty filter matches everything.

### Operators

| Category | Operators |
|----------|-----------|
| Comparison | `==`, `!=`, `<`, `<=`, `>`, `>=` |
| Logical | `&&`, `\|\|`, `!` |
| Arithmetic | `+`, `-`, `*`, `/`, `%` |
| Membership | `in` |
| Ternary | `condition ? true_val : false_val` |

### String Functions

```
str.contains(substring)      // Substring search
str.startsWith(prefix)       // Prefix match
str.endsWith(suffix)         // Suffix match
str.matches(regex)           // Regex match
size(str)                    // String length
```

### Collection Functions

```
size(collection)             // List/map/string length
key in map                   // Key existence
map[key]                     // Value access
map_get(map, key, default)   // Safe access with default
value in list                // List membership
```

### Time Functions

```
timestamp("2026-03-14T22:00:00Z")   // Parse ISO timestamp
duration("5m")                        // Parse duration
now()                                 // Current time (snapshot at filter creation)
```

### Negation

```
!http                                // Everything that is NOT HTTP
http && status_code != 200           // HTTP responses that aren't 200
http && !path.contains("/health")    // Exclude health checks
!(src.pod.namespace == "kube-system")  // Exclude system namespace
```

## Protocol Detection

Boolean flags that indicate which protocol was detected. Use these as the first
filter term — they're fast and narrow the search space immediately.

| Flag | Protocol | Flag | Protocol |
|------|----------|------|----------|
| `http` | HTTP/1.1, HTTP/2 | `redis` | Redis |
| `dns` | DNS | `kafka` | Kafka |
| `tls` | eBPF TLS interception | `amqp` | AMQP |
| `tcp` | TCP | `ldap` | LDAP |
| `udp` | UDP | `ws` | WebSocket |
| `sctp` | SCTP | `gql` | GraphQL (v1+v2) |
| `icmp` | ICMP | `gqlv1` / `gqlv2` | GraphQL version-specific |
| `grpc` | gRPC (HTTP/2 sub-protocol) | `mongodb` | MongoDB |
| `mysql` | MySQL | `postgresql` | PostgreSQL |
| `radius` | RADIUS | | |
| `diameter` | Diameter | `conn` / `flow` | L4 connection/flow tracking |
| | | `tcp_conn` / `udp_conn` | Transport-specific connections |

## Kubernetes Context

The most common starting point. Filter by where traffic originates or terminates.

### Pod and Service Fields

```
src.pod.name == "orders-594487879c-7ddxf"
dst.pod.namespace == "production"
src.service.name == "api-gateway"
dst.service.namespace == "payments"
```

Pod fields fall back to service data when pod info is unavailable, so
`dst.pod.namespace` works even for service-level entries.

### Summary Name and Namespace

Convenience variables that pick the best available identity for a peer:

```
src.name == "api-gateway"                    // pod > service > dns > process
dst.name.contains("payment")                 // works across identity types
src.namespace == "production"                 // pod namespace, falls back to service
dst.namespace != "kube-system"               // exclude system namespace
```

### Aggregate Collections

Match against any direction (src or dst):

```
"production" in namespaces           // Any namespace match
"orders" in pods                     // Any pod name match
"api-gateway" in services            // Any service name match
```

### Labels and Annotations

```
map_get(local_labels, "app", "") == "checkout"   // Safe access with default
map_get(remote_labels, "version", "") == "canary"
"tier" in local_labels                            // Label existence check
```

Always use `map_get()` for labels and annotations — direct access like
`local_labels["app"]` errors if the key doesn't exist.

### Node and Process

```
node_name == "ip-10-0-25-170.ec2.internal"
local_process_name == "nginx"
remote_process_name.contains("postgres")
```

### DNS Resolution

```
src.dns == "api.example.com"
dst.dns.contains("redis")
```

## HTTP Filtering

HTTP is the most common protocol for API-level investigation.

### Fields

| Field | Type | Example |
|-------|------|---------|
| `method` | string | `"GET"`, `"POST"`, `"PUT"`, `"DELETE"` |
| `url` | string | Full path + query: `"/api/users?id=123"` |
| `path` | string | Path only: `"/api/users"` |
| `status_code` | int | `200`, `404`, `500` |
| `http_version` | string | `"HTTP/1.1"`, `"HTTP/2"` |
| `request.headers` | map | `request.headers["content-type"]` |
| `response.headers` | map | `response.headers["server"]` |
| `request.cookies` | map | `request.cookies["session"]` |
| `response.cookies` | map | `response.cookies["token"]` |
| `query_string` | map | `query_string["id"]` |
| `request_body_size` | int | Request body bytes |
| `response_body_size` | int | Response body bytes |
| `elapsed_time` | int | Duration in **microseconds** |

### Common Patterns

```
// Error investigation
http && status_code >= 500                           // Server errors
http && status_code == 429                           // Rate limiting
http && status_code >= 400 && status_code < 500      // Client errors

// Endpoint targeting
http && method == "POST" && path.contains("/orders")
http && url.matches(".*/api/v[0-9]+/users.*")

// Performance
http && elapsed_time > 5000000                       // > 5 seconds
http && response_body_size > 1000000                 // > 1MB responses

// Header inspection
http && "authorization" in request.headers
http && request.headers["content-type"] == "