Skip to main content
skill CX Codex

loki — skill for Claude Code, Codex and Cursor

Grafana's loki skill gives your coding agent a LogQL reference and Loki setup notes. It covers stream selectors, parsers, metric queries, ingestion through Alloy, Promtail and Fluent Bit.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add grafana/skills --skill loki -a claude-code
Open on GitHub

What loki does

Loki indexes labels, not log content. Queries stay cheap, but you have to be precise: a stream selector first, then line filters. The skill keeps that order in front of the agent.

Inside is a LogQL reference — stream selectors, line filters, the json, logfmt, pattern, regexp and unpack parsers, label filters, line_format, label_format, drop and keep. A separate section covers metric queries: rate, count_over_time, bytes_rate, absent_over_time, aggregations with sum by and topk, numeric values pulled out with unwrap, and offset for comparing against an earlier window.

Worked examples are included: an error-rate alert, slow request lookup, nginx 5xx breakdown, credential leak detection. Ingestion configs too — loki.source.file and loki.process in Alloy, a Kubernetes DaemonSet, the HTTP push API with curl.

Architecture gets a short treatment: the write path from Distributor to object storage, the read path through Query Frontend and Querier, plus the roles of Ingester and Compactor. Enough that the agent won't mix up components when a pipeline breaks.

Worth installing if you already run Loki, or if you're still deciding where logs should live. The agent stops guessing at LogQL syntax and reads it from the reference instead.

What it helps with

  • write a LogQL query with a selector, parser and label filter
  • compute error rate per service and turn it into an alert
  • set up log shipping to Loki with Alloy or Promtail
  • debug why logs never reach the store
  • extract numeric values from logs and build a metric from them

Example prompts for the agent

  • Write a LogQL query for the 5xx rate per service over the last 5 minutes
  • Build an Alloy config that tails /var/log/app/*.log and pushes to Loki
  • Figure out why logs from Kubernetes pods aren't showing up in Loki

How to install loki

1Skills CLI (Vercel)

npx skills add grafana/skills --skill loki -a claude-code

2Manually: put the files in place

~/.claude/skills/loki/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/loki/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about loki

How do I install loki in Claude?

Run npx skills add grafana/skills --skill loki -a claude-code. The skill lands in ~/.claude/skills/loki/SKILL.md.

What does the loki skill do?

It hands the agent a LogQL and Loki reference: selectors, parsers, metric queries, architecture, ingestion. Queries and configs come out with correct syntax.

Which platforms does loki support?

Claude, Codex, Cursor, GitHub Copilot, Gemini CLI and OpenCode. Each takes its own install flag, such as -a cursor or -a opencode.

Source text

SKILL.md · Apache-2.0
---
name: loki
license: Apache-2.0
description: >
  Grafana Loki log aggregation and LogQL query language. Covers LogQL syntax (log queries, metric queries,
  label matchers, line filters, parsers: json/logfmt/pattern/regexp/unpack, label filters, line_format),
  Loki architecture, log ingestion via Alloy/Promtail/Fluent Bit, structured metadata, and Logs Drilldown.
  Use when writing LogQL queries, configuring Loki, troubleshooting log pipelines, or analyzing logs.
---

# Grafana Loki - Log Aggregation

> **Docs**: https://grafana.com/docs/loki/latest/

Indexes only metadata (labels), not full log content — dramatically cheaper than full-text search systems.

## LogQL Quick Reference

### Log Stream Selector (required in every query)

```logql
{app="nginx"}                        # exact match
{app!="nginx"}                       # not equal
{app=~"nginx|apache"}               # regex match
{app!~"debug.*"}                     # regex not match
{app="nginx", env="prod"}           # AND (multiple labels)
```

### Line Filters (pipeline stage 1 - put first for performance)

```logql
{app="nginx"} |= "error"            # contains string
{app="nginx"} != "info"             # does not contain
{app="nginx"} |~ "error|warn"       # regex match
{app="nginx"} !~ "health.*check"    # regex not match
{app="nginx"} |= `"status":5`       # backtick avoids escaping
```

### Parsers

```logql
# JSON
{app="api"} | json
{app="api"} | json status="http_status", path="request.path"

# Logfmt
{app="api"} | logfmt
{app="api"} | logfmt --strict
{app="api"} | logfmt --keep-empty

# Pattern (positional, _ discards)
{app="nginx"} | pattern `<ip> - - <_> "<method> <uri> <_>" <status> <bytes>`

# Regexp (named capture groups)
{app="nginx"} | regexp `(?P<method>\w+) (?P<path>\S+) HTTP/(?P<version>\S+)`

# Unpack (unwrap Promtail packed labels)
{app="api"} | unpack
```

### Label Filters (after parsers)

```logql
{app="api"} | json | status >= 500
{app="api"} | json | status == 200 and method != "OPTIONS"
{app="api"} | logfmt | duration > 1s
{app="api"} | json | level =~ "error|warn"
{app="api"} | json | bytes > 20MB
{app="api"} | json | path != "/healthz"
```

### Line Format

```logql
{app="api"} | json | line_format "{{.method}} {{.path}} -> {{.status}} ({{.duration}})"
{app="api"} | logfmt | line_format `{{.level | upper}}: {{.msg}}`
```

### Label Format

```logql
{app="api"} | logfmt | label_format new_name=old_name
{app="api"} | logfmt | label_format severity=level, svc=app
{app="api"} | logfmt | label_format msg=`{{.level}}: {{.message}}`
```

### Drop/Keep Labels

```logql
{app="api"} | json | drop filename, level="debug"
{app="api"} | json | keep level, status, method
```

### Decolorize

```logql
{app="cli-tool"} | decolorize
```

## Metric Queries

### Log Range Aggregations

```logql
# Requests per second
rate({app="nginx"}[5m])

# Total log lines in window
count_over_time({app="nginx"}[1h])

# Bytes per second
bytes_rate({app="nginx"}[5m])

# Total bytes
bytes_over_time({app="nginx"}[1h])

# Returns 1 if no logs in range (for absence alerting)
absent_over_time({app="nginx"}[5m])
```

### Aggregation

```logql
# Error rate by service
sum(rate({env="prod"} |= "error" [5m])) by (app)

# Top 5 most active services
topk(5, sum(rate({env="prod"}[5m])) by (app))

# Total errors across all services
sum(count_over_time({env="prod"} |= "error" [5m]))
```

### Unwrapped Range Aggregations (numeric values from logs)

```logql
# Average request duration from logfmt
avg_over_time({app="api"} | logfmt | unwrap duration [5m])

# 95th percentile latency
quantile_over_time(0.95, {app="api"} | logfmt | unwrap duration [5m]) by (app)

# Sum of bytes from JSON logs
sum_over_time({app="api"} | json | unwrap bytes [5m])

# With conversion (duration string → seconds)
avg_over_time({app="api"} | logfmt | unwrap duration | duration_seconds [5m])
```

### Offset Modifier

```logql
# Compare current rate vs 1 hour ago
rate({app="nginx"}[5m]) / rate({app="nginx"}[5m] offset 1h)
```

## Practical Examples

### Error rate alert query
```logql
sum(rate({env="prod"} |= "error" [5m])) by (service)
/
sum(rate({env="prod"}[5m])) by (service)
> 0.05
```

### Slow requests
```logql
{app="api"} | logfmt | duration > 1s | line_format "SLOW: {{.method}} {{.path}} {{.duration}}"
```

### HTTP 5xx errors with details
```logql
{app="nginx"} | pattern `<ip> - - <_> "<method> <uri> <_>" <status> <bytes>` | status >= 500
```

### Credential leak detection
```logql
{namespace="prod"} |~ `https?://\w+:\w+@`
```

## Sending Logs to Loki

### Via Grafana Alloy

```alloy
loki.source.file "app" {
  targets    = [{__path__ = "/var/log/app/*.log", job = "app"}]
  forward_to = [loki.process.parse.receiver]
}

loki.process "parse" {
  forward_to = [loki.write.cloud.receiver]
  stage.json {
    expressions = { level = "level", msg = "message" }
  }
  stage.labels {
    values = { level = "" }
  }
  stage.drop {
    expression = ".*healthcheck.*"
  }
}

loki.write "cloud" {
  endpoint {
    url = "https://logs-xxx.grafana.net/loki/api/v1/push"
    basic_auth {
      username = sys.env("LOKI_USER")
      password = sys.env("GRAFANA_API_KEY")
    }
  }
  external_labels = { cluster = "prod" }
}
```

### Via Kubernetes (Alloy DaemonSet)

```alloy
discovery.kubernetes "pods" {
  role = "pod"
}

loki.source.kubernetes "pods" {
  targets    = discovery.kubernetes.pods.targets
  forward_to = [loki.write.cloud.receiver]
}
```

### Loki HTTP Push API

```bash
curl -X POST https://logs-xxx.grafana.net/loki/api/v1/push \
  -u "user:apikey" \
  -H 'Content-Type: application/json' \
  -d '{
    "streams": [{
      "stream": { "app": "myapp", "env": "prod" },
      "values": [
        ["1609459200000000000", "log line here"]
      ]
    }]
  }'
```

## Architecture

```
Push path:  Client → Distributor → Ingester (WAL) → Object Storage (chunks)
Read path:  Query → Query Frontend → Querier → Ingester + Store (chunks)
```

**Components:**
- **Distributor**: Validates and hashes incoming log streams
- **Ingester**: Buffers chunks in memory, flushes to object storage
- **Querier**: Executes LogQL queries
- **Query Frontend**: Caches, splits, and parallelizes queries
- **Compactor**: Manages retention and deduplication

## References

- [LogQL Reference](references/logql.md)
- [Configuration](references/configuration.md)
- [Sending Data](references/send-data.md)

© grafana · Apache-2.0 · grafana/skills

Similar skills

Everything for DevOps and infrastructure →

From the same set47

dashboarding This skill writes and edits Grafana dashboard JSON, then pushes it through the HTTP API. Useful when panels should live in code instead of being clicked together in the UI. CX Codex +1 8,500installs promql Writes and validates PromQL against Prometheus, Mimir and Grafana Cloud Metrics. Useful when a p95 looks wrong or a query drags. CX Codex +1 8,000installs loki-label-analyzer Walks through a Grafana Loki label schema: where cardinality grows, which labels slow queries down, and what to do with them. CX Codex +1 6,300installs opentelemetry A skill that walks you through instrumenting an app with OpenTelemetry and sending metrics, logs and traces to Grafana Cloud or self-hosted Mimir, Loki and Tempo. CX Codex +1 6,100installs grafana-oss A skill that walks your agent through provisioning Grafana OSS dashboards and data sources from YAML, writing panel JSON, and verifying each step over the API. CX Codex +1 5,600installs prometheus PromQL reference, Prometheus alerting rules, and Alertmanager routing patterns. Guides AI agents in writing metrics queries and recording rules. CX Codex +1 5,200installs alerting-irm Configures Grafana Alerting, IRM, and SLOs from rules and routing to on-call schedules. Useful for YAML or API-based alert setup and debugging. CX Codex +1 5,100installs assistant-mcp Connects AI coding agents to Grafana Cloud via the mcp-grafana server. Useful for running metric queries, listing dashboards, and checking alerts in chat. CX Codex +1 5,000installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor