Authoring & Improving Grafana Skills
How to write, review, and improve SKILL.md files so they pass the repo's CI gate and score well against the Anthropic-aligned rubric Tessl uses.
Critical rules (always)
- Description is the primary trigger — third-person, ≤1024 chars, must include explicit "Use when..." phrasing AND list concrete trigger terms users naturally say. See references/descriptions.md for the pushy-description pattern that combats undertriggering.
- Body under 500 lines — split into
references/*.md if approaching the limit. SKILL.md is the routing layer, not the entire knowledge base.
- One level of nesting for references — link from SKILL.md directly, never
SKILL.md → a.md → b.md. Claude may use head -100 previews on nested chains and miss content.
- Imperative voice — "Run X" not "You should run X" not "It is important to run X". Explain why over heavy-handed
MUST markers.
- Concrete examples beat prose — copy-paste-ready commands, real config snippets. Tessl's
actionability dimension scores this directly.
- No reserved words in
name — anthropic and claude are forbidden in skill names.
- No time-sensitive language in the body — "after August 2025…" rots. Use an
<details> "Old patterns" section for legacy info instead.
- Validate before committing —
./scripts/lint-skills.sh skills/<plugin>/<your-skill> clean + Tessl score ≥75 (run tessl skill review --json <dir>).
The rubric
CI fails any PR where a touched SKILL.md scores below 75 on four 0-3 dimensions: conciseness, actionability, workflow clarity, progressive disclosure. Full per-dimension scoring + Anthropic-doc mapping in references/rubric.md.
Score variance
The judge is an LLM and swings 7-10 points run-to-run. Local 94 commonly lands at CI 85. Ship only on three consecutive local 100s.
Decision tree for a new skill
What product / domain does this skill belong to?
Pick the right plugin folder: grafana-core/, grafana-cloud/, grafana-lgtm/, grafana-app-sdk/, grafana-k6/, grafana-plugins/. If none fits cleanly, ask the user before creating a new plugin group (a new group requires updating three marketplace.json files).
Estimate body length.
- <200 lines of substance → single
SKILL.md, no bundle
- 200-500 lines →
SKILL.md + references/<topic>.md for the long-form material
500 lines → mandatory bundle split; see references/anatomy.md § Splitting strategies
Write a "pushy" description first.
The description is the only thing always loaded into context. If agents don't trigger the skill, nothing else matters. See references/descriptions.md for the pattern.
Draft body with the four-dimension rubric in mind.
- Cut every sentence Claude already knows (Conciseness)
- Replace prose explanations with code blocks (Actionability)
- Number every multi-step procedure + add a validation step at the end (Workflow clarity)
- If you reach for
<details>, consider whether that content belongs in references/ instead (Progressive disclosure)
Register in marketplace manifests.
Add the skill path to the skills array in all three:
.claude-plugin/marketplace.json
.cursor-plugin/marketplace.json
.agents-plugin/marketplace.json
Validate locally.
# 1. Lint clean (0 errors)
./scripts/lint-skills.sh skills/<plugin>/<your-skill>
# 2. Tessl reviewScore ≥75 (the CI gate)
tessl skill review --json skills/<plugin>/<your-skill> | jq '.review.reviewScore'
# 3. If below 75 or you want ≥85: run --optimize (requires auth)
tessl skill review --optimize --yes --max-iterations 3 skills/<plugin>/<your-skill>
If the run fails: read the lint error / Tessl suggestion, fix, re-run. Don't open the PR until both checks pass cleanly. The feedback-loop pattern beats one-shot writing.
Fixing a low-scoring existing skill
Read the judge's verbatim Suggestions text (non-JSON output):
tessl skill review skills/<plugin>/<name>
The Suggestions: block under each dimension names the exact sentences/sections to cut. Copy the suggestion — don't guess. Then verify the lowest dimension matches your read.
Apply the fix pattern from references/rubric.md:
- Conciseness 1-2 → cut intros, definitions, multi-line tables that mostly point to refs
- Actionability 1-2 → replace prose with code blocks and CLI commands
- Workflow clarity 1-2 → add numbered steps + validation checkpoints
- Progressive disclosure 1-2 → split into
references/*.md
If the skill is intentionally a routing document (like grafana-k6/k6-docs), don't let --optimize inline the bundle back into SKILL.md. Hand-craft a minimal copy-paste "validation loop" inline so SKILL.md is independently actionable, while preserving the bundle.
Re-score five times locally. Don't stop until all five runs hit 100 — see "Score variance" above for why.
Anti-patterns
See references/anti-patterns.md.
References
1---2name: skill-authoring3description: Author, audit, and improve Grafana SKILL.md files against Anthropic's published Agent Skills guidance and the four-dimension rubric the grafana/skills CI gate uses (conciseness, actionability, workflow clarity, progressive disclosure). Applies the canonical SKILL.md structure (YAML frontmatter + body + references/ + scripts/ + assets/), the "pushy description" trigger pattern, the three-level progressive-disclosure model, and the validate-fix-rerun feedback loop. Use when creating a new skill in this repo, when reviewing a skill PR, when a skill's Tessl review score is below 75 (the merge gate), when a skill's description isn't getting picked up by agents, when restructuring a long SKILL.md into a bundle, or when the user asks how to write, improve, optimize, audit, or fix a skill - even if they don't say "skill" explicitly (e.g. "this isn't triggering", "Tessl scored this 72", "split this doc").4license: Apache-2.05---6
7# Authoring & Improving Grafana Skills
8
9How to write, review, and improve SKILL.md files so they pass the repo's CI gate and score well against the Anthropic-aligned rubric Tessl uses.
10
11## Critical rules (always)
12
131. **Description is the primary trigger** — third-person, ≤1024 chars, must include explicit "Use when..." phrasing AND list concrete trigger terms users naturally say. See [references/descriptions.md](references/descriptions.md) for the pushy-description pattern that combats undertriggering.
142. **Body under 500 lines** — split into `references/*.md` if approaching the limit. SKILL.md is the routing layer, not the entire knowledge base.
153. **One level of nesting for references** — link from SKILL.md directly, never `SKILL.md → a.md → b.md`. Claude may use `head -100` previews on nested chains and miss content.
164. **Imperative voice** — "Run X" not "You should run X" not "It is important to run X". Explain *why* over heavy-handed `MUST` markers.
175. **Concrete examples beat prose** — copy-paste-ready commands, real config snippets. Tessl's `actionability` dimension scores this directly.
186. **No reserved words in `name`** — `anthropic` and `claude` are forbidden in skill names.
197. **No time-sensitive language in the body** — "after August 2025…" rots. Use an `<details>` "Old patterns" section for legacy info instead.
208. **Validate before committing** — `./scripts/lint-skills.sh skills/<plugin>/<your-skill>` clean + Tessl score ≥75 (run `tessl skill review --json <dir>`).
21
22## The rubric
23
24CI fails any PR where a touched SKILL.md scores below **75** on four 0-3 dimensions: **conciseness**, **actionability**, **workflow clarity**, **progressive disclosure**. Full per-dimension scoring + Anthropic-doc mapping in [references/rubric.md](references/rubric.md).
25
26## Score variance
27
28The judge is an LLM and swings 7-10 points run-to-run. Local 94 commonly lands at CI 85. **Ship only on three consecutive local 100s.**
29
30## Decision tree for a new skill
31
321. **What product / domain does this skill belong to?**
33 Pick the right plugin folder: `grafana-core/`, `grafana-cloud/`, `grafana-lgtm/`, `grafana-app-sdk/`, `grafana-k6/`, `grafana-plugins/`. If none fits cleanly, ask the user before creating a new plugin group (a new group requires updating three `marketplace.json` files).
34
352. **Estimate body length.**
36 - <200 lines of substance → single `SKILL.md`, no bundle
37 - 200-500 lines → `SKILL.md` + `references/<topic>.md` for the long-form material
38 - >500 lines → mandatory bundle split; see [references/anatomy.md § Splitting strategies](references/anatomy.md#splitting-strategies)
39
403. **Write a "pushy" description first.**
41 The description is the only thing always loaded into context. If agents don't trigger the skill, nothing else matters. See [references/descriptions.md](references/descriptions.md) for the pattern.
42
434. **Draft body with the four-dimension rubric in mind.**
44 - Cut every sentence Claude already knows (Conciseness)
45 - Replace prose explanations with code blocks (Actionability)
46 - Number every multi-step procedure + add a validation step at the end (Workflow clarity)
47 - If you reach for `<details>`, consider whether that content belongs in `references/` instead (Progressive disclosure)
48
495. **Register in marketplace manifests.**
50 Add the skill path to the `skills` array in all three:
51 - `.claude-plugin/marketplace.json`
52 - `.cursor-plugin/marketplace.json`
53 - `.agents-plugin/marketplace.json`
54
556. **Validate locally.**
56 ```bash
57 # 1. Lint clean (0 errors)
58 ./scripts/lint-skills.sh skills/<plugin>/<your-skill>
59
60 # 2. Tessl reviewScore ≥75 (the CI gate)
61 tessl skill review --json skills/<plugin>/<your-skill> | jq '.review.reviewScore'
62
63 # 3. If below 75 or you want ≥85: run --optimize (requires auth)
64 tessl skill review --optimize --yes --max-iterations 3 skills/<plugin>/<your-skill>
65 ```
66
67 If the run fails: read the lint error / Tessl suggestion, fix, re-run. Don't open the PR until both checks pass cleanly. The feedback-loop pattern beats one-shot writing.
68
69## Fixing a low-scoring existing skill
70
711. Read the judge's verbatim Suggestions text (non-JSON output):
72 ```bash
73 tessl skill review skills/<plugin>/<name>
74 ```
75 The `Suggestions:` block under each dimension names the exact sentences/sections to cut. **Copy the suggestion** — don't guess. Then verify the lowest dimension matches your read.
76
772. Apply the fix pattern from [references/rubric.md](references/rubric.md):
78 - **Conciseness 1-2** → cut intros, definitions, multi-line tables that mostly point to refs
79 - **Actionability 1-2** → replace prose with code blocks and CLI commands
80 - **Workflow clarity 1-2** → add numbered steps + validation checkpoints
81 - **Progressive disclosure 1-2** → split into `references/*.md`
82
833. If the skill is **intentionally a routing document** (like `grafana-k6/k6-docs`), don't let `--optimize` inline the bundle back into SKILL.md. Hand-craft a minimal copy-paste "validation loop" inline so SKILL.md is independently actionable, while preserving the bundle.
84
854. Re-score five times locally. **Don't stop until all five runs hit 100** — see "Score variance" above for why.
86
87## Anti-patterns
88
89See [references/anti-patterns.md](references/anti-patterns.md).
90
91## References
92
93- [`references/descriptions.md`](references/descriptions.md) — the pushy-description pattern + trigger-term checklist
94- [`references/rubric.md`](references/rubric.md) — per-dimension scoring with Anthropic-doc citations and concrete fix patterns
95- [`references/anatomy.md`](references/anatomy.md) — three-level progressive disclosure, bundle layout, splitting strategies
96- [`references/anti-patterns.md`](references/anti-patterns.md) — what NOT to do, with examples
97- [Anthropic — Agent Skills best practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices)
98- [anthropics/skills — skill-creator SKILL.md](https://github.com/anthropics/skills/blob/main/skills/skill-creator/SKILL.md)
99- [The Complete Guide to Building Skills for Claude (PDF)](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf)