cue-kind-definition — Claude Code skill: CUE kinds for grafana-app-sdk
Walks an agent through CUE kind definitions in grafana-app-sdk apps: spec and status schemas, versions, field constraints and codegen.
npx skills add grafana/skills --skill cue-kind-definition -a claude-codeWhat cue-kind-definition does
This skill keeps the agent on the right sequence when you add a resource type. First it scaffolds files with grafana-app-sdk project kind add MyKind --overwrite, then you fill in schema.spec and schema.status, and finally you run grafana-app-sdk generate. Adding a version to an existing kind gets its own walkthrough: copy the version file, rename the top-level object, register the version in kinds/manifest.cue.
Three references ship with it. One covers common kind metadata and app manifest fields, another lists schema field types with constraints such as regex, enums and ranges plus #-prefixed named types, the third explains custom routes and handler registration in app.go. Codegen config is covered too: the ts and go flags turn TypeScript and Go output on or off, and both are on when omitted.
There is one rule worth remembering. Breaking changes — dropped fields, changed types, new required fields — belong in a new version, never in a stable one like v1 or v2. Anything under pkg/generated/ is overwritten on every run, so edits there are wasted; keep your changes in the .cue sources. When generate fails, read the error first: CUE names the file, the line and the constraint that broke. Missing required fields, type mismatches and unresolved references between version files are the usual culprits.
What it helps with
- scaffold a new kind without forgetting the manifest
- add a version to an existing kind without touching the stable one
- constrain a field with regex, enum or a range
- factor a repeated struct into a
#-prefixed named type - read a CUE error from codegen and know what to fix
Example prompts for the agent
- Add a new kind MyKind to my grafana-app-sdk app and fill in the spec and status schema
- Create version v1 for the mykind kind by copying v1alpha1 and register it in kinds/manifest.cue
- Define count as an int with a >= 0 constraint and move the shared struct into a named type
How to install cue-kind-definition
1Skills CLI (Vercel)
npx skills add grafana/skills --skill cue-kind-definition -a claude-code2Manually: put the files in place
~/.claude/skills/cue-kind-definition/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/cue-kind-definition/
1Skills CLI (Vercel)
npx skills add grafana/skills --skill cue-kind-definition -a codex2Manually: put the files in place
.agents/skills/cue-kind-definition/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add grafana/skills --skill cue-kind-definition -a cursor2Manually: put the files in place
.cursor/skills/cue-kind-definition/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install grafana/skills cue-kind-definition2Manually: put the files in place
.github/skills/cue-kind-definition/SKILL.md1Skills CLI (Vercel)
npx skills add grafana/skills --skill cue-kind-definition -a gemini-cli2Platform CLI
gemini skills install https://github.com/grafana/skills --path skills/grafana-app-sdk/cue-kind-definitionManually: put the files in place
.devin/skills/cue-kind-definition/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add grafana/skills --skill cue-kind-definition -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 cue-kind-definition
How do I install cue-kind-definition in Claude?
Run npx skills add grafana/skills --skill cue-kind-definition -a claude-code. The skill lands at ~/.claude/skills/cue-kind-definition/SKILL.md.
What does cue-kind-definition do?
It guides the agent through writing CUE kind definitions: scaffolding with grafana-app-sdk project kind add, spec and status schemas with field constraints, version registration in the manifest, and grafana-app-sdk generate with error recovery.
Can I edit a stable kind version in place?
No. Breaking changes such as removed fields, changed types or new required fields go into a new version, while v1 and v2 stay untouched.
Source text
SKILL.md · Apache-2.0
---
name: cue-kind-definition
license: Apache-2.0
description: Author CUE kind definitions for grafana-app-sdk apps - schemas, versioning, field constraints, named type definitions, custom routes, and codegen configuration. Scaffolds kinds via `grafana-app-sdk project kind add`, writes spec/status schemas with type constraints (regex, enum, range), defines `#`-prefixed named types for reusable structs, registers versions in the app manifest, and runs `grafana-app-sdk generate` with explicit error recovery. Use when working with CUE kinds, adding a new resource type, adding a version to an existing kind, writing schema field constraints, defining `#Definition` types, adding custom routes, editing files under `kinds/`, or when the user asks to "model a resource", "add a CUE schema", or "write a kind" — even without saying "CUE" explicitly.
---
# CUE Kind Definition
## Common Workflows
### Adding a new kind
```bash
# 1. Scaffold the kind files
grafana-app-sdk project kind add MyKind --overwrite
# Produces kinds/mykind.cue + kinds/mykind_v1alpha1.cue + updates kinds/manifest.cue.
# 2. Edit the generated .cue files — fill in schema.spec / schema.status fields
# 3. Generate types and clients
grafana-app-sdk generate
# 4. Verify the generated artifacts exist
ls pkg/generated/ # should contain new types for MyKind
```
If `generate` fails with CUE errors:
- Read the error — CUE prints the offending file + line + which constraint failed
- Common causes: missing required field, type mismatch (e.g. `string` field assigned an `int`), unresolved reference between version files
- Fix the `.cue` source, re-run `grafana-app-sdk generate`. Never edit files under `pkg/generated/` — they're overwritten on every run.
### Adding a new version to an existing kind
```bash
# 1. Copy the existing version file
cp kinds/mykind_v1alpha1.cue kinds/mykind_v1.cue
# 2. Edit kinds/mykind_v1.cue — rename the top-level object (e.g. myKindv1) and adjust the schema
# 3. Register the new version in kinds/manifest.cue
# Add a versions["v1"]: { schema: myKindv1 } entry
# 4. Re-generate
grafana-app-sdk generate
# 5. Verify both versions were generated — per-version Go types live under pkg/generated/<group>/<version>/
ls pkg/generated/ # should list both version directories (e.g. v1alpha1/ v1/)
# Optionally inspect the CRD spec under definitions/ to confirm both versions appear in `spec.versions[]`
```
**Breaking changes** (removing fields, changing types, adding required fields) must go into a new version — never modify a stable version (`v1`, `v2`) in place.
## Kind file structure
The CLI produces a flat layout under `kinds/`:
```
kinds/
├── manifest.cue # App manifest + version list declarations
├── mykind.cue # Common (cross-version) kind metadata
└── mykind_v1alpha1.cue # v1alpha1 schema + codegen config
```
For multi-version kinds, additional version files sit alongside (`mykind_v1.cue`, etc.). For very large kind sets (10+ kinds), consider the per-kind subdirectory layout — full kind anatomy reference in [references/kind-layout.md](references/kind-layout.md).
## CUE Kind Anatomy
Three layers per kind:
### 1. Common kind metadata
```cue
// kinds/mykind.cue
package kinds
myKind: {
kind: "MyKind" // Required: PascalCase kind name
// other cross-version fields (scope, pluralName, validation, mutation, conversion, …)
// Full field reference in references/kind-layout.md.
}
```
### 2. Per-version schema
```cue
// kinds/mykind_v1alpha1.cue
package kinds
myKindv1alpha1: myKind & {
schema: {
spec: { // desired state — user-set
title: string
description: string | *""
count: int & >=0
enabled: bool | *true
}
status: { // observed state — operator-set
lastObservedGeneration: int | *0
state: string | *""
message: string | *""
}
}
codegen: {
ts: { enabled: true }
go: { enabled: true }
}
}
```
### 3. App manifest
```cue
// kinds/manifest.cue
package kinds
App: {
appName: "my-app"
versions: {
"v1alpha1": { schema: myKindv1alpha1 }
}
}
```
## Codegen configuration
Control what gets generated per kind per version:
```cue
codegen: {
ts: { enabled: true | false } // TypeScript types
go: { enabled: true | false } // Go types + client
}
```
Disabling `go` for frontend-only apps avoids unused Go code. Disabling `ts` for backend-only resources reduces bundle size. Both default to `true` when omitted.
## References
- [`references/kind-layout.md`](references/kind-layout.md) — full common-metadata field reference + app manifest fields + per-kind subdirectory layout
- [`references/schema-types.md`](references/schema-types.md) — CUE schema field types (basic types, constraints, regex, enums, maps, lists) + `#`-prefixed named type definitions
- [`references/custom-routes.md`](references/custom-routes.md) — kind-level + version-level custom routes + handler registration in `app.go`
## External resources
- [grafana-app-sdk GitHub](https://github.com/grafana/grafana-app-sdk)
- [CUE Language Reference](https://cuelang.org/docs/)
- [Example kinds layout](https://github.com/grafana/grafana/tree/main/apps/example/kinds)
© grafana · Apache-2.0 · grafana/skills