Grafana Grizzly Dashboards as Code Prompt
Manage Grafana dashboards, folders, and alert rules as code with Grizzly (grr) using a kubectl-style apply/diff workflow.
- Target user
- Platform engineers who prefer a kubectl-style Grafana CLI
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT
The prompt
You are a senior platform engineer who manages Grafana resources with Grizzly (`grr`) — a kubectl-style tool that applies dashboards, folders, datasources, and alert rules from YAML/JSON/Jsonnet. I will provide: - The resources to manage and their source format (YAML, JSON, Jsonnet/Grafonnet) - The target Grafana URL/token - Whether you want live-edit watch or CI apply Your job: 1. **Config**: set the target via env (`GRAFANA_URL`, `GRAFANA_TOKEN`) or `grizzly.yaml` context; confirm connectivity with `grr config get`. 2. **Resource model**: express each object as a Grizzly resource with `apiVersion: grizzly.grafana.com/v1alpha1`, `kind` (Dashboard, DashboardFolder, AlertRuleGroup, Datasource), and a `metadata.name` matching the `uid`. 3. **Jsonnet/Grafonnet**: generate dashboards programmatically with Grafonnet libraries so panels are DRY; point `grr` at the `.jsonnet` entrypoint. 4. **Diff before apply**: always run `grr diff` to preview server changes; treat a non-empty diff in CI as a required review. 5. **Apply**: use `grr apply` to push; `grr pull` to snapshot live resources back into files for import. 6. **Live workflow**: use `grr watch` for local iteration and `grr serve` to preview without writing to the server. 7. **Folders + UIDs**: ensure `DashboardFolder` exists before dashboards; keep `uid` stable so links and alerts survive. 8. **CI**: run `grr diff` in PRs and `grr apply` on merge with a scoped token. Mark DESTRUCTIVE: `grr apply` overwriting UI-edited dashboards, deleting a folder that holds live dashboards, or applying to the wrong context/URL. --- Resources + format: [DESCRIBE] Grafana URL/token: [DESCRIBE] Watch vs CI apply: [DESCRIBE]
Why this prompt works
Grizzly gives Grafana a kubectl-like diff/apply/pull loop, which is powerful but easy to misfire — wrong context, clobbered UI edits, silent Jsonnet errors. This prompt enforces the diff-before-apply discipline, folder ordering, and stable UIDs, and shows the Grafonnet path for DRY dashboards.
How to use it
- Confirm the target context so you never apply to the wrong Grafana.
- Pick your source format (raw JSON vs Grafonnet) up front.
- Gate every apply behind
grr diffin CI. - Use
grr pullto onboard existing dashboards.
Useful commands
# Configure and verify context
export GRAFANA_URL=https://grafana.example.com
export GRAFANA_TOKEN=$GRAFANA_SA_TOKEN
grr config get
# Diff local resources against the live server
grr diff dashboards/
# Apply changes
grr apply dashboards/
# Pull live resources into files (import)
grr pull imported/
# Live-reload while editing locally
grr watch ./out dashboards/slo.jsonnet
# Preview via local server without writing to Grafana
grr serve dashboards/
Example config
Grizzly resource wrapping a dashboard (YAML), plus a Grafonnet entrypoint:
apiVersion: grizzly.grafana.com/v1alpha1
kind: DashboardFolder
metadata:
name: slo
spec:
title: SLO Dashboards
---
apiVersion: grizzly.grafana.com/v1alpha1
kind: Dashboard
metadata:
name: slo-overview
folder: slo
spec:
title: SLO Overview
schemaVersion: 39
panels:
- title: Error budget burn
type: timeseries
datasource: { type: prometheus, uid: prometheus-prod }
targets:
- expr: 'sum(rate(errors_total[5m])) / sum(rate(requests_total[5m]))'
// slo.jsonnet — DRY dashboards with Grafonnet
local g = import 'g.libsonnet';
g.dashboard.new('SLO Overview')
+ g.dashboard.withUid('slo-overview')
+ g.dashboard.withPanels([
g.panel.timeSeries.new('Availability')
+ g.panel.timeSeries.queryOptions.withTargets([
g.query.prometheus.new('prometheus-prod',
'1 - (sum(rate(errors_total[5m])) / sum(rate(requests_total[5m])))'),
]),
])
Common findings this catches
- Clobbered dashboards →
applywithout a revieweddiff. - Wrong environment → context/URL misconfigured.
- Missing folders → dashboards applied before their folder.
- Empty panels → Jsonnet build error not caught.
- Orphaned links →
uidrenamed. - Leaked tokens → credentials in
grizzly.yaml.
When to escalate
- Standing up a Grafonnet library and conventions — observability lead.
- Bulk migration from UI-authored dashboards — staged
pull/reconcile. - Multi-environment promotion pipelines — platform team.
Related prompts
-
Grafana Data Source Provisioning YAML Prompt
Provision Grafana data sources as code with provisioning YAML in /etc/grafana/provisioning/datasources for reproducible, secret-safe config.
-
Grafana Library Panels Reuse Prompt
Design reusable Grafana library panels shared across many dashboards so one edit propagates everywhere without copy-paste drift.
-
Grafana Terraform Provider Dashboards Prompt
Manage Grafana dashboards, folders, and alerts as code using the Terraform grafana provider with stable UIDs and state.