alloy — Claude Code skill: Grafana Alloy telemetry
Writes and validates Grafana Alloy configs: metrics, logs, traces and profiles in one pipeline.
npx skills add grafana/skills --skill alloy -a claude-codeWhat alloy does
The alloy skill from Grafana teaches your agent the Alloy config language and the usual pipeline shapes. It covers blocks, component references, sys.env, modules via import.file/git/http, clustering and Fleet Management remotecfg. Ready-made pairings are included: prometheus.scrape into remote_write, loki.source.file plus loki.process into loki.write, OTLP intake through otelcol.receiver.otlp and export to Tempo, and pyroscope.scrape for profiles.
Validation is a big part of it. The agent runs alloy fmt and alloy validate, then checks component health through the UI on port 12345 — a failing component shows up there with its reason. For deeper digging there are metrics like prometheus_remote_storage_samples_dropped_total and otelcol_receiver_refused_spans. Useful when the config exists but nothing arrives at the backend.
You need the alloy CLI installed and an endpoint to ship to: Grafana Cloud, Prometheus, Loki, Tempo or Pyroscope. Auth takes an API key and username, which the skill suggests keeping in environment variables such as GRAFANA_API_KEY. If alloy validate reports a missing component, your binary is too old — check alloy --version and upgrade.
What it helps with
- write a
config.alloythat scrapes metrics and logs - migrate from Grafana Agent or OTel Collector to Alloy
- scrape Kubernetes pods with relabeling
- debug why Alloy sends nothing
- receive OTLP traces and forward them to Tempo
Example prompts for the agent
- Write a
config.alloythat scrapes metrics from localhost:9090 and ships them to Grafana Cloud - Add log collection from
/var/log/app/*.logand send it to Loki - Alloy isn't sending anything — check which components are unhealthy on port 12345
How to install alloy
1Skills CLI (Vercel)
npx skills add grafana/skills --skill alloy -a claude-code2Manually: put the files in place
~/.claude/skills/alloy/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/alloy/
1Skills CLI (Vercel)
npx skills add grafana/skills --skill alloy -a codex2Manually: put the files in place
.agents/skills/alloy/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add grafana/skills --skill alloy -a cursor2Manually: put the files in place
.cursor/skills/alloy/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install grafana/skills alloy2Manually: put the files in place
.github/skills/alloy/SKILL.md1Skills CLI (Vercel)
npx skills add grafana/skills --skill alloy -a gemini-cli2Platform CLI
gemini skills install https://github.com/grafana/skills --path skills/grafana-core/alloyManually: put the files in place
.devin/skills/alloy/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add grafana/skills --skill alloy -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about alloy
How do I install alloy in Claude?
Run npx skills add grafana/skills --skill alloy -a claude-code. The skill lands in ~/.claude/skills/alloy/SKILL.md.
What does the alloy skill do?
It helps the agent write and validate Grafana Alloy configs for metrics, logs, traces and profiles, and troubleshoot failures through the UI and metrics.
What do I need before using it?
The alloy CLI and an endpoint to ship to. Auth needs an API key and username, which the skill suggests storing in environment variables.
Source text
SKILL.md · Apache-2.0
---
name: alloy
license: Apache-2.0
description: Build a unified telemetry pipeline with Grafana Alloy — one OpenTelemetry-compatible binary that collects metrics, logs, traces, and profiles and ships to Grafana Cloud / Prometheus / Loki / Tempo / Pyroscope. Covers the Alloy config language (blocks, `sys.env`, component refs), `prometheus.scrape` → `remote_write`, `loki.source.file` + `loki.process` → `loki.write`, `otelcol.receiver.otlp` → `otelcol.exporter.otlp`, `pyroscope.scrape`, K8s / Docker / EC2 discovery, relabeling, modules (`import.file/git/http`), clustering, Fleet Management `remotecfg`, the Alloy UI at `:12345`, and `alloy fmt` / `alloy validate`. Use when writing a `config.alloy`, replacing Grafana Agent / OTel Collector, scraping K8s pods, parsing logs, ingesting OTLP, or debugging "Alloy isn't sending anything" — even when the user says "set up the agent", "write me a scrape config", "drop these logs before sending", or "OTel collector config" without naming Alloy.
---
# Grafana Alloy
> **Docs**: https://grafana.com/docs/alloy/latest/
OpenTelemetry-compatible collector — one binary for metrics + logs + traces + profiles.
## Prerequisites
- `alloy` CLI installed (`brew install grafana/grafana/alloy`, `apt install alloy`, or `grafana/alloy` Docker image)
- An endpoint to ship to (Grafana Cloud, Prometheus, Loki, Tempo, Pyroscope)
- API key + username for that endpoint, exported as `GRAFANA_API_KEY` etc.
## Common Workflows
### 1. Write + validate a config locally
```alloy
// config.alloy — metrics → Grafana Cloud
prometheus.scrape "app" {
targets = [{"__address__" = "localhost:9090"}]
forward_to = [prometheus.remote_write.cloud.receiver]
scrape_interval = "30s"
}
prometheus.remote_write "cloud" {
endpoint {
url = sys.env("PROMETHEUS_URL")
basic_auth {
username = sys.env("PROM_USER")
password = sys.env("GRAFANA_API_KEY")
}
}
}
```
```bash
# 1. Format + syntax-check (catches typos before run)
alloy fmt config.alloy
alloy validate config.alloy
# 2. Run it
alloy run config.alloy
# or as a service: systemctl restart alloy
# 3. Verify all components are healthy via the UI on port 12345
curl -s http://localhost:12345/api/v0/web/components \
| jq '.[] | select(.health.state != "healthy") | {id, state:.health.state, msg:.health.message}'
# Expect: empty (nothing unhealthy). Otherwise the row shows the failing component + reason.
# 4. Verify samples are flowing
curl -s http://localhost:12345/metrics \
| grep -E '^prometheus_remote_storage_(samples_total|enqueue_retries_total)' | head
# samples_total should be > 0 and rising; retries should be 0.
```
### 2. Add log shipping (file → Loki)
```alloy
loki.source.file "app_logs" {
targets = [{ __path__ = "/var/log/app/*.log", job = "app" }]
forward_to = [loki.write.cloud.receiver]
}
loki.write "cloud" {
endpoint {
url = sys.env("LOKI_URL")
basic_auth {
username = sys.env("LOKI_USER")
password = sys.env("GRAFANA_API_KEY")
}
}
}
```
```bash
# Verify in Grafana → Explore → Loki:
# {job="app"}
# Expect lines streaming. If empty:
# - check /var/log/app/*.log actually exists + readable by the alloy user
# - http://localhost:12345 → loki.source.file.app_logs → "Targets" tab
```
### 3. Receive OTLP traces and ship to Tempo
```alloy
otelcol.receiver.otlp "default" {
grpc { endpoint = "0.0.0.0:4317" }
http { endpoint = "0.0.0.0:4318" }
output { traces = [otelcol.exporter.otlp.tempo.input] }
}
otelcol.exporter.otlp "tempo" {
client {
endpoint = "tempo-xxx.grafana.net/tempo:443"
auth = otelcol.auth.basic.grafana_cloud.handler
}
}
otelcol.auth.basic "grafana_cloud" {
username = sys.env("TEMPO_USER")
password = sys.env("GRAFANA_API_KEY")
}
```
```bash
# Verify in Grafana → Explore → Tempo → service.name = your-service
# At the Alloy level, watch the receiver:
curl -s http://localhost:12345/metrics | grep otelcol_receiver_accepted_spans
```
Full pattern set (Kubernetes discovery + relabel, complete Cloud pipeline for all 4 signals): [`references/collection-patterns.md`](references/collection-patterns.md).
## Reference
- [`references/config-syntax.md`](references/config-syntax.md) — block/attribute/expression grammar, `import.*`, `remotecfg`, clustering
- [`references/components.md`](references/components.md) — full component catalog with purpose + typical args
- [`references/collection-patterns.md`](references/collection-patterns.md) — end-to-end pipelines (K8s pods, OTLP, profiles, logs)
## Troubleshooting
- `alloy validate` → "component not found" → version too old; `alloy --version` and upgrade
- UI shows component `unhealthy` → click into it on http://localhost:12345 for the live error
- `prometheus_remote_storage_samples_dropped_total` rising → check `enqueue_retries_total` and the remote_write endpoint URL + creds
- No spans landing in Tempo → check `otelcol_receiver_refused_spans` and the exporter's `otelcol_exporter_sent_spans` / `otelcol_exporter_send_failed_spans`
## Resources
- [Alloy docs](https://grafana.com/docs/alloy/latest/)
- [Component reference](https://grafana.com/docs/alloy/latest/reference/components/)
- [Migrate from Grafana Agent](https://grafana.com/docs/alloy/latest/set-up/migrate/from-agent/)
© grafana · Apache-2.0 · grafana/skills