grafana-helper

Complete Grafana operations via REST API - dashboards, Prometheus/Loki queries, alerting, annotations, Sift When user mentions Grafana, dashboards, Prometheus, Loki, metrics, logs, alerts, PromQL, LogQL

15 stars

Best use case

grafana-helper is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Complete Grafana operations via REST API - dashboards, Prometheus/Loki queries, alerting, annotations, Sift When user mentions Grafana, dashboards, Prometheus, Loki, metrics, logs, alerts, PromQL, LogQL

Teams using grafana-helper should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/grafana-helper/SKILL.md --create-dirs "https://raw.githubusercontent.com/shepherdjerred/monorepo/main/packages/dotfiles/dot_agents/skills/grafana-helper/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/grafana-helper/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How grafana-helper Compares

Feature / Agentgrafana-helperStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Complete Grafana operations via REST API - dashboards, Prometheus/Loki queries, alerting, annotations, Sift When user mentions Grafana, dashboards, Prometheus, Loki, metrics, logs, alerts, PromQL, LogQL

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Grafana Helper Agent

## Overview

Complete Grafana operations via REST API. This skill replaces Grafana MCP server functionality, providing API equivalents for all operations.

## MCP Tool Equivalents Reference

| MCP Tool                          | API Equivalent                                                                         |
| --------------------------------- | -------------------------------------------------------------------------------------- |
| `search_dashboards`               | `curl "$URL/api/search?query=..."`                                                     |
| `get_dashboard_by_uid`            | `curl "$URL/api/dashboards/uid/{uid}"`                                                 |
| `get_dashboard_summary`           | Parse dashboard JSON response                                                          |
| `get_dashboard_property`          | jq on dashboard JSON                                                                   |
| `get_dashboard_panel_queries`     | Extract from dashboard JSON                                                            |
| `update_dashboard`                | `curl -X POST "$URL/api/dashboards/db"`                                                |
| `list_datasources`                | `curl "$URL/api/datasources"`                                                          |
| `get_datasource_by_uid`           | `curl "$URL/api/datasources/uid/{uid}"`                                                |
| `get_datasource_by_name`          | `curl "$URL/api/datasources/name/{name}"`                                              |
| `query_prometheus`                | `curl "$URL/api/ds/query"`                                                             |
| `list_prometheus_metric_names`    | `curl "$URL/api/datasources/proxy/{id}/api/v1/label/__name__/values"`                  |
| `list_prometheus_label_names`     | `curl "$URL/api/datasources/proxy/{id}/api/v1/labels"`                                 |
| `list_prometheus_label_values`    | `curl "$URL/api/datasources/proxy/{id}/api/v1/label/{name}/values"`                    |
| `list_prometheus_metric_metadata` | `curl "$URL/api/datasources/proxy/{id}/api/v1/metadata"`                               |
| `query_loki_logs`                 | `curl "$URL/api/ds/query"`                                                             |
| `query_loki_stats`                | `curl "$URL/api/datasources/proxy/{id}/loki/api/v1/index/stats"`                       |
| `list_loki_label_names`           | `curl "$URL/api/datasources/proxy/{id}/loki/api/v1/labels"`                            |
| `list_loki_label_values`          | `curl "$URL/api/datasources/proxy/{id}/loki/api/v1/label/{name}/values"`               |
| `list_alert_rules`                | `curl "$URL/api/v1/provisioning/alert-rules"`                                          |
| `get_alert_rule_by_uid`           | `curl "$URL/api/v1/provisioning/alert-rules/{uid}"`                                    |
| `create_alert_rule`               | `curl -X POST "$URL/api/v1/provisioning/alert-rules"`                                  |
| `update_alert_rule`               | `curl -X PUT "$URL/api/v1/provisioning/alert-rules/{uid}"`                             |
| `delete_alert_rule`               | `curl -X DELETE "$URL/api/v1/provisioning/alert-rules/{uid}"`                          |
| `list_contact_points`             | `curl "$URL/api/v1/provisioning/contact-points"`                                       |
| `get_annotations`                 | `curl "$URL/api/annotations"`                                                          |
| `create_annotation`               | `curl -X POST "$URL/api/annotations"`                                                  |
| `update_annotation`               | `curl -X PUT "$URL/api/annotations/{id}"`                                              |
| `patch_annotation`                | `curl -X PATCH "$URL/api/annotations/{id}"`                                            |
| `create_graphite_annotation`      | `curl -X POST "$URL/api/annotations/graphite"`                                         |
| `get_annotation_tags`             | `curl "$URL/api/annotations/tags"`                                                     |
| `create_folder`                   | `curl -X POST "$URL/api/folders"`                                                      |
| `search_folders`                  | `curl "$URL/api/search?type=dash-folder"`                                              |
| `list_sift_investigations`        | `curl "$URL/api/plugins/grafana-sift-app/resources/investigations"`                    |
| `get_sift_investigation`          | `curl "$URL/api/plugins/grafana-sift-app/resources/investigations/{id}"`               |
| `get_sift_analysis`               | `curl "$URL/api/plugins/grafana-sift-app/resources/investigations/{id}/analyses/{id}"` |
| `find_error_pattern_logs`         | Via Sift plugin API                                                                    |
| `find_slow_requests`              | Via Sift plugin API                                                                    |
| `get_assertions`                  | Via Asserts plugin API                                                                 |

## Configuration

```bash
# Set environment variables
export GRAFANA_URL="https://your-grafana.com"
export GRAFANA_API_KEY="your-api-key"

# Service account tokens also use GRAFANA_API_KEY
# export GRAFANA_API_KEY="glsa_..."

# Auth header helper
AUTH="Authorization: Bearer $GRAFANA_API_KEY"

# Test connection
curl -H "$AUTH" "$GRAFANA_URL/api/health"
```

---

## Dashboard Operations

### Search Dashboards

```bash
# Search all dashboards
curl -H "$AUTH" "$GRAFANA_URL/api/search?type=dash-db"

# Search by query
curl -H "$AUTH" "$GRAFANA_URL/api/search?query=kubernetes"

# Search by tag
curl -H "$AUTH" "$GRAFANA_URL/api/search?tag=monitoring"

# Search in folder
curl -H "$AUTH" "$GRAFANA_URL/api/search?folderIds=1,2"

# Search starred dashboards
curl -H "$AUTH" "$GRAFANA_URL/api/search?starred=true"

# JSON output with jq
curl -H "$AUTH" "$GRAFANA_URL/api/search?query=api" | \
  jq '.[] | {uid, title, folderTitle}'
```

### Get Dashboard by UID

```bash
# Get full dashboard
curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}"

# Extract just the dashboard JSON
curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}" | jq '.dashboard'

# Get dashboard metadata
curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}" | jq '.meta'
```

### Get Dashboard Summary

```bash
# Get summary info (title, panel count, etc.)
curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}" | \
  jq '{
    title: .dashboard.title,
    uid: .dashboard.uid,
    panelCount: (.dashboard.panels | length),
    tags: .dashboard.tags,
    folder: .meta.folderTitle,
    url: .meta.url
  }'
```

### Get Dashboard Property (JSONPath)

```bash
# Get title
curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}" | jq '.dashboard.title'

# Get all panel titles
curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}" | jq '.dashboard.panels[].title'

# Get first panel
curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}" | jq '.dashboard.panels[0]'

# Get templating variables
curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}" | jq '.dashboard.templating.list'

# Get all queries from panels
curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}" | \
  jq '.dashboard.panels[].targets[]?.expr // empty'
```

### Get Dashboard Panel Queries

```bash
# Extract panel queries with datasource info
curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}" | \
  jq '.dashboard.panels[] | {
    title: .title,
    type: .type,
    datasource: .datasource,
    queries: [.targets[]? | {expr: .expr, refId: .refId}]
  }'
```

### Update/Create Dashboard

```bash
# Create/update dashboard
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/dashboards/db" \
  -d '{
    "dashboard": {
      "title": "My Dashboard",
      "tags": ["monitoring"],
      "panels": [],
      "schemaVersion": 36,
      "version": 0
    },
    "folderUid": "folder-uid",
    "message": "Initial version",
    "overwrite": false
  }'

# Update existing (with overwrite)
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/dashboards/db" \
  -d '{
    "dashboard": {...},
    "overwrite": true
  }'
```

### Delete Dashboard

```bash
curl -X DELETE -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/{uid}"
```

---

## Folder Operations

### Search Folders

```bash
# List all folders
curl -H "$AUTH" "$GRAFANA_URL/api/search?type=dash-folder"

# Get folder by UID
curl -H "$AUTH" "$GRAFANA_URL/api/folders/{uid}"

# List folders
curl -H "$AUTH" "$GRAFANA_URL/api/folders"
```

### Create Folder

```bash
# Create folder
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/folders" \
  -d '{
    "title": "My Folder"
  }'

# Create with custom UID
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/folders" \
  -d '{
    "uid": "my-folder-uid",
    "title": "My Folder"
  }'

# Create nested folder (under parent)
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/folders" \
  -d '{
    "title": "Child Folder",
    "parentUid": "parent-folder-uid"
  }'
```

---

## Datasource Operations

### List Datasources

```bash
# List all datasources
curl -H "$AUTH" "$GRAFANA_URL/api/datasources"

# List with details
curl -H "$AUTH" "$GRAFANA_URL/api/datasources" | \
  jq '.[] | {id, uid, name, type, url, isDefault}'

# Filter by type
curl -H "$AUTH" "$GRAFANA_URL/api/datasources" | \
  jq '.[] | select(.type == "prometheus")'
```

### Get Datasource by UID

```bash
curl -H "$AUTH" "$GRAFANA_URL/api/datasources/uid/{uid}"
```

### Get Datasource by Name

```bash
curl -H "$AUTH" "$GRAFANA_URL/api/datasources/name/{name}"
```

### Get Datasource by ID

```bash
curl -H "$AUTH" "$GRAFANA_URL/api/datasources/{id}"
```

---

## Prometheus Queries

### Query Prometheus

```bash
# Using unified query API (recommended)
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/ds/query" \
  -d '{
    "queries": [{
      "refId": "A",
      "datasource": {"type": "prometheus", "uid": "datasource-uid"},
      "expr": "up",
      "instant": false,
      "range": true,
      "intervalMs": 15000,
      "maxDataPoints": 1000
    }],
    "from": "now-1h",
    "to": "now"
  }'

# Instant query
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/ds/query" \
  -d '{
    "queries": [{
      "refId": "A",
      "datasource": {"type": "prometheus", "uid": "datasource-uid"},
      "expr": "up",
      "instant": true
    }],
    "from": "now",
    "to": "now"
  }'

# Via datasource proxy
DATASOURCE_ID=1
curl -G -H "$AUTH" \
  --data-urlencode "query=up" \
  --data-urlencode "start=$(date -d '1 hour ago' +%s)" \
  --data-urlencode "end=$(date +%s)" \
  --data-urlencode "step=60" \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/query_range"
```

### List Prometheus Metric Names

```bash
# Get all metric names
curl -H "$AUTH" \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/label/__name__/values"

# Filter by regex (use match[] param)
curl -G -H "$AUTH" \
  --data-urlencode 'match[]={__name__=~"http.*"}' \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/label/__name__/values"
```

### List Prometheus Label Names

```bash
# All label names
curl -H "$AUTH" \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/labels"

# Labels for specific metric
curl -G -H "$AUTH" \
  --data-urlencode 'match[]={__name__="http_requests_total"}' \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/labels"
```

### List Prometheus Label Values

```bash
# Values for specific label
curl -H "$AUTH" \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/label/job/values"

# Values with filter
curl -G -H "$AUTH" \
  --data-urlencode 'match[]={__name__="http_requests_total"}' \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/label/status/values"
```

### List Prometheus Metric Metadata

```bash
# All metadata
curl -H "$AUTH" \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/metadata"

# Specific metric
curl -G -H "$AUTH" \
  --data-urlencode "metric=http_requests_total" \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/metadata"
```

---

## Loki Queries

### Query Loki Logs

```bash
# Using unified query API
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/ds/query" \
  -d '{
    "queries": [{
      "refId": "A",
      "datasource": {"type": "loki", "uid": "loki-uid"},
      "expr": "{job=\"app\"} |= \"error\"",
      "queryType": "range",
      "maxLines": 100
    }],
    "from": "now-1h",
    "to": "now"
  }'

# Via datasource proxy
LOKI_ID=2
curl -G -H "$AUTH" \
  --data-urlencode 'query={job="app"} |= "error"' \
  --data-urlencode "start=$(date -d '1 hour ago' +%s)000000000" \
  --data-urlencode "end=$(date +%s)000000000" \
  --data-urlencode "limit=100" \
  "$GRAFANA_URL/api/datasources/proxy/$LOKI_ID/loki/api/v1/query_range"
```

### Query Loki Stats

```bash
# Get stream stats
curl -G -H "$AUTH" \
  --data-urlencode 'query={job="app"}' \
  --data-urlencode "start=$(date -d '1 hour ago' +%s)000000000" \
  --data-urlencode "end=$(date +%s)000000000" \
  "$GRAFANA_URL/api/datasources/proxy/$LOKI_ID/loki/api/v1/index/stats"
```

### List Loki Label Names

```bash
curl -H "$AUTH" \
  "$GRAFANA_URL/api/datasources/proxy/$LOKI_ID/loki/api/v1/labels"

# With time range
curl -G -H "$AUTH" \
  --data-urlencode "start=$(date -d '1 hour ago' +%s)000000000" \
  --data-urlencode "end=$(date +%s)000000000" \
  "$GRAFANA_URL/api/datasources/proxy/$LOKI_ID/loki/api/v1/labels"
```

### List Loki Label Values

```bash
# Values for label
curl -H "$AUTH" \
  "$GRAFANA_URL/api/datasources/proxy/$LOKI_ID/loki/api/v1/label/job/values"

# With time range
curl -G -H "$AUTH" \
  --data-urlencode "start=$(date -d '1 hour ago' +%s)000000000" \
  --data-urlencode "end=$(date +%s)000000000" \
  "$GRAFANA_URL/api/datasources/proxy/$LOKI_ID/loki/api/v1/label/job/values"
```

---

## Alerting

### List Alert Rules

```bash
# All alert rules
curl -H "$AUTH" "$GRAFANA_URL/api/v1/provisioning/alert-rules"

# Legacy alerting API
curl -H "$AUTH" "$GRAFANA_URL/api/ruler/grafana/api/v1/rules"

# By folder
curl -H "$AUTH" "$GRAFANA_URL/api/ruler/grafana/api/v1/rules/{folderName}"
```

### Get Alert Rule by UID

```bash
curl -H "$AUTH" "$GRAFANA_URL/api/v1/provisioning/alert-rules/{uid}"
```

### Create Alert Rule

```bash
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/v1/provisioning/alert-rules" \
  -d '{
    "title": "High CPU Usage",
    "ruleGroup": "my-group",
    "folderUID": "folder-uid",
    "condition": "A",
    "data": [{
      "refId": "A",
      "datasourceUid": "prometheus-uid",
      "model": {
        "expr": "avg(rate(node_cpu_seconds_total{mode!=\"idle\"}[5m])) > 0.8",
        "instant": true
      }
    }],
    "noDataState": "NoData",
    "execErrState": "Error",
    "for": "5m",
    "labels": {"severity": "warning"},
    "annotations": {"summary": "CPU usage above 80%"}
  }'
```

### Update Alert Rule

```bash
curl -X PUT -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/v1/provisioning/alert-rules/{uid}" \
  -d '{...}'
```

### Delete Alert Rule

```bash
curl -X DELETE -H "$AUTH" "$GRAFANA_URL/api/v1/provisioning/alert-rules/{uid}"
```

### List Contact Points

```bash
curl -H "$AUTH" "$GRAFANA_URL/api/v1/provisioning/contact-points"

# Filter by name
curl -H "$AUTH" "$GRAFANA_URL/api/v1/provisioning/contact-points?name=slack"
```

---

## Annotations

### Get Annotations

```bash
# All annotations
curl -H "$AUTH" "$GRAFANA_URL/api/annotations"

# With filters
curl -G -H "$AUTH" \
  --data-urlencode "dashboardUID=dashboard-uid" \
  --data-urlencode "from=$(date -d '24 hours ago' +%s)000" \
  --data-urlencode "to=$(date +%s)000" \
  "$GRAFANA_URL/api/annotations"

# By tags
curl -G -H "$AUTH" \
  --data-urlencode "tags=deployment" \
  "$GRAFANA_URL/api/annotations"

# Limit results
curl -H "$AUTH" "$GRAFANA_URL/api/annotations?limit=100"
```

### Create Annotation

```bash
# Dashboard annotation
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/annotations" \
  -d '{
    "dashboardUID": "dashboard-uid",
    "panelId": 1,
    "time": 1234567890000,
    "timeEnd": 1234567900000,
    "text": "Deployment started",
    "tags": ["deployment", "v1.2.0"]
  }'

# Global annotation (no dashboard)
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/annotations" \
  -d '{
    "time": '$(date +%s)000',
    "text": "System maintenance",
    "tags": ["maintenance"]
  }'
```

### Update Annotation

```bash
curl -X PUT -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/annotations/{id}" \
  -d '{
    "text": "Updated annotation text",
    "tags": ["updated", "tag"]
  }'
```

### Patch Annotation

```bash
curl -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/annotations/{id}" \
  -d '{
    "text": "Partially updated text"
  }'
```

### Create Graphite Annotation

```bash
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/annotations/graphite" \
  -d '{
    "what": "Deployment",
    "tags": ["deploy", "production"],
    "when": 1234567890,
    "data": "v1.2.0"
  }'
```

### Get Annotation Tags

```bash
curl -H "$AUTH" "$GRAFANA_URL/api/annotations/tags"

# Filter by tag prefix
curl -H "$AUTH" "$GRAFANA_URL/api/annotations/tags?tag=deploy"
```

### Delete Annotation

```bash
curl -X DELETE -H "$AUTH" "$GRAFANA_URL/api/annotations/{id}"
```

---

## Sift Investigations (Grafana Cloud)

### List Sift Investigations

```bash
curl -H "$AUTH" \
  "$GRAFANA_URL/api/plugins/grafana-sift-app/resources/investigations"

# With limit
curl -H "$AUTH" \
  "$GRAFANA_URL/api/plugins/grafana-sift-app/resources/investigations?limit=10"
```

### Get Sift Investigation

```bash
curl -H "$AUTH" \
  "$GRAFANA_URL/api/plugins/grafana-sift-app/resources/investigations/{id}"
```

### Get Sift Analysis

```bash
curl -H "$AUTH" \
  "$GRAFANA_URL/api/plugins/grafana-sift-app/resources/investigations/{investigationId}/analyses/{analysisId}"
```

### Find Error Pattern Logs

```bash
# Create investigation for error patterns
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/plugins/grafana-sift-app/resources/investigations" \
  -d '{
    "name": "Error Pattern Analysis",
    "type": "error-patterns",
    "labels": {"app": "my-app", "env": "production"},
    "start": "2024-01-01T00:00:00Z",
    "end": "2024-01-01T01:00:00Z"
  }'
```

### Find Slow Requests

```bash
# Create investigation for slow requests
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/plugins/grafana-sift-app/resources/investigations" \
  -d '{
    "name": "Slow Request Analysis",
    "type": "slow-requests",
    "labels": {"service": "api-gateway"},
    "start": "2024-01-01T00:00:00Z",
    "end": "2024-01-01T01:00:00Z"
  }'
```

---

## Asserts (Grafana Cloud)

### Get Assertions

```bash
curl -G -H "$AUTH" \
  --data-urlencode "entityType=Service" \
  --data-urlencode "entityName=my-service" \
  --data-urlencode "startTime=2024-01-01T00:00:00Z" \
  --data-urlencode "endTime=2024-01-01T01:00:00Z" \
  "$GRAFANA_URL/api/plugins/grafana-asserts-app/resources/assertions"
```

---

## Common Workflows

### Dashboard Backup Script

```bash
#!/bin/bash
mkdir -p dashboards-backup

curl -H "$AUTH" "$GRAFANA_URL/api/search?type=dash-db" | \
  jq -r '.[] | .uid' | \
  while read uid; do
    echo "Backing up: $uid"
    curl -H "$AUTH" "$GRAFANA_URL/api/dashboards/uid/$uid" | \
      jq '.dashboard' > "dashboards-backup/${uid}.json"
  done
```

### Metrics Health Check

```bash
#!/bin/bash
echo "=== System Health ==="

# CPU usage
curl -sG -H "$AUTH" \
  --data-urlencode 'query=100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)' \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/query" | \
  jq -r '.data.result[0].value[1] | "CPU: \(.)%"'

# Memory usage
curl -sG -H "$AUTH" \
  --data-urlencode 'query=100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)' \
  "$GRAFANA_URL/api/datasources/proxy/$DATASOURCE_ID/api/v1/query" | \
  jq -r '.data.result[0].value[1] | "Memory: \(.)%"'
```

### Deployment Annotation

```bash
#!/bin/bash
VERSION=$1
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
  "$GRAFANA_URL/api/annotations" \
  -d "{
    \"time\": $(date +%s)000,
    \"text\": \"Deployed version $VERSION\",
    \"tags\": [\"deployment\", \"$VERSION\"]
  }"
```

---

## PromQL Examples

```promql
# CPU usage
rate(node_cpu_seconds_total{mode!="idle"}[5m])

# Memory usage
node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes

# HTTP request rate
rate(http_requests_total[5m])

# Error rate percentage
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100

# Latency p95
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))

# Up/down status
up{job="my-service"}
```

## LogQL Examples

```logql
# Errors in last hour
{job="app"} |= "error"

# JSON parsing
{job="app"} | json | level="error"

# Regex match
{job="app"} |~ "failed.*connection"

# Count by service
sum by (service) (count_over_time({job="app"}[1h]))

# Rate of errors
rate({job="app"} |= "error" [5m])

# Label filtering
{namespace="production", app=~"api-.*"}
```

---

## When to Ask for Help

Ask the user for clarification when:

- Grafana URL or API key is not specified
- Datasource UID or ID is ambiguous
- Dashboard UID or folder location is unclear
- PromQL/LogQL query syntax needs validation
- Time range format or timezone considerations are uncertain
- Sift/Asserts features require Grafana Cloud

Related Skills

zellij-helper

15
from shepherdjerred/monorepo

Zellij terminal multiplexer for session management, layouts, and pane operations When user mentions Zellij, terminal multiplexer, zellij commands, sessions, panes, layouts, or tabs

vite-react-helper

15
from shepherdjerred/monorepo

Vite + React for fast modern web development - build config, HMR, hooks, state management, and performance patterns When user works with Vite, React, creates components, manages state, uses hooks, or configures Vite builds

typescript-helper

15
from shepherdjerred/monorepo

TypeScript development guidance for type systems and tooling When user works with .ts or .tsx files, mentions TypeScript, or encounters type errors

terraform-helper

15
from shepherdjerred/monorepo

Terraform and OpenTofu infrastructure as code - HCL, providers, modules, state management, and CLI operations When user works with .tf files, mentions Terraform, OpenTofu, tofu, HCL, infrastructure as code, or tf commands

talos-helper

15
from shepherdjerred/monorepo

Talos Linux cluster administration using talosctl When user mentions Talos, talosctl, or Talos cluster operations

tailscale-helper

15
from shepherdjerred/monorepo

Tailscale VPN and networking - CLI operations, MagicDNS, ACLs, SSH, funnel, serve, and network administration When user mentions Tailscale, tailscale commands, VPN, MagicDNS, tailnet, or Tailscale networking

sentry-helper

15
from shepherdjerred/monorepo

Complete Sentry operations via sentry-cli and REST API - issues, releases, source maps, traces, events When user mentions Sentry, errors, issues, releases, source maps, error tracking, stack traces

rust-helper

15
from shepherdjerred/monorepo

Rust development with cargo, clippy, rustfmt, testing, and common patterns When user works with .rs files, mentions Rust, cargo, clippy, rustfmt, or encounters Rust compiler errors

python-helper

15
from shepherdjerred/monorepo

Python development with modern patterns, type hints, testing, and tooling When user works with .py files, mentions Python, pip, pytest, ruff, uv, or encounters Python errors

prisma-helper

15
from shepherdjerred/monorepo

Prisma ORM for type-safe database access - schema design, migrations, queries, relations, and connection management When user works with Prisma, database schemas, migrations, Prisma Client queries, or mentions prisma commands

pinchtab-helper

15
from shepherdjerred/monorepo

PinchTab browser automation - profiles, instances, multi-instance routing, tabs, actions, and anti-detection When user mentions PinchTab, browser automation, pinchtab commands, headed/headless browser, or web scraping with Chrome

pagerduty-helper

15
from shepherdjerred/monorepo

Complete PagerDuty operations via REST API - incidents, schedules, oncall, services, orchestrations When user mentions PagerDuty, incidents, oncall, schedules, escalation, pages, alerts