perses-cue-schema
Original:🇺🇸 English
Translated
CUE schema authoring for Perses plugins: define data models, write validation constraints, create JSON examples, implement Grafana migration schemas in migrate/migrate.cue. Educational skill that explains CUE patterns specific to Perses plugin development. Use for "perses cue schema", "perses model", "plugin schema", "cue validation perses". Do NOT use for dashboard CUE definitions (use perses-dac-pipeline).
13installs
Added on
NPX Install
npx skill4agent add notque/claude-code-toolkit perses-cue-schemaTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Perses CUE Schema Authoring
Write CUE schemas for Perses plugin data models, validation constraints, JSON examples, and Grafana migration logic.
Operator Context
This skill operates as a CUE schema author for Perses plugins. It produces validated schema files, matching JSON examples, and optional migration definitions that pass .
percli plugin test-schemasHardcoded Behaviors (Always Apply)
- Package model: All plugin CUE schemas MUST use — any other package name causes compilation failure
package model - Closed specs: Use for all spec definitions — open specs allow invalid fields through validation silently
close({...}) - JSON example required: Every schema MUST have a corresponding JSON example file at the same directory level
- Test after write: Run after creating or modifying any schema — never declare a schema complete without passing tests
percli plugin test-schemas - CUE v0.12.0+: Require CUE v0.12.0 or later; earlier versions have incompatible syntax for Perses schemas
- Migration package: Migration files MUST use , never
package migratepackage model
Default Behaviors (ON unless disabled)
- Educational mode: Explain CUE syntax and Perses-specific patterns as schemas are created
- Import common types: Import for shared types (
github.com/perses/shared/cue/common,#format,#thresholds) rather than redefining them#calculation - Validate incrementally: Test after each schema file is written, not only at the end
Optional Behaviors (OFF unless enabled)
- Grafana migration: Write with
migrate/migrate.cueand#grafanaTypefor converting Grafana panels#mapping - Strict mode: Treat all fields as required unless the user explicitly marks them optional
What This Skill CAN Do
- Define CUE schemas for any Perses plugin type (panel, variable, datasource)
- Create matching JSON example files that validate against schemas
- Write Grafana migration schemas with field mappings via references
#panel - Explain CUE syntax: , optional fields (
close()), arrays (?), nested types ([...#type])#name - Debug CUE compilation errors and schema/example mismatches
- Import and use shared Perses types from
common
What This Skill CANNOT Do
- Create Perses dashboards or layouts (use perses-dashboard-create)
- Scaffold full plugin projects with Go code (use perses-plugin-create)
- Deploy or configure Perses server instances (use perses-deploy)
- Write DaC pipeline CUE definitions (use perses-dac-pipeline)
Error Handling
CUE Compilation Error: Wrong Package Name
Symptom: or similar CUE loader error.
Cause: Schema file uses a package name other than .
Fix: Change the first line of the file to . Migration files use instead.
package is "foo", want "model"model.cuepackage modelpackage migrateCUE Compilation Error: Unclosed Spec or Bad Import
Symptom: , , or .
Cause: Missing closing brace in , typo in import path, or missing import statement.
Fix: Verify braces are balanced in the block. Confirm the import path is exactly (not shortened or aliased incorrectly).
cannot find packageexpected '}' found EOFimport path not validclose({...})close({})github.com/perses/shared/cue/commonJSON Example Mismatch: close() Rejects Unknown Fields
Symptom: fails with on a field present in the JSON but absent from the CUE schema.
Cause: enforces a strict field set — the JSON example contains fields the schema does not declare.
Fix: Either add the missing field to the CUE spec (with if optional) or remove it from the JSON example. Also check for type mismatches (e.g., in schema but in JSON).
percli plugin test-schemasfield not allowedclose({})?stringnumberGrafana Migration Schema Error
Symptom: value not matching, field path references fail, or lookups resolve to (bottom).
Cause: does not match the Grafana plugin ID exactly, or references a field path that does not exist on .
Fix: Verify matches the Grafana plugin field exactly (e.g., , not ). Check that field paths use with the correct Grafana JSON structure.
#grafanaType#mapping#panel_|_#grafanaType#mapping#panel#grafanaTypetype"timeseries""time_series"#mapping#panel.<field>percli plugin test-schemas Failure: Schema/Example Not Found
Symptom: or — test runner skips or errors on the plugin.
Cause: Directory structure does not follow the expected convention, or files are misnamed.
Fix: Ensure files are at and . Names must match exactly.
no schema foundno example foundschemas/<plugin-type>/<plugin-name>/<plugin-name>.cueschemas/<plugin-type>/<plugin-name>/<plugin-name>.jsonAnti-Patterns
| Anti-Pattern | Why It Fails | Correct Approach |
|---|---|---|
Open specs (no | Allows any field through — invalid JSON passes validation silently | Always wrap spec fields in |
| Not importing shared types | Redefining | Import from |
| Schema without JSON example | | Always create the |
| Migration without real Grafana JSON | | Test migration schemas against an actual exported Grafana panel JSON |
Using | CUE loader expects | Reserve |
| Nested type defined outside close() | Nested | Define nested types inside the |
Anti-Rationalization
| Rationalization | Reality | Required Action |
|---|---|---|
| "The schema looks correct" | CUE has subtle constraints — looking correct is not being correct | Run |
| "close() is optional for simple schemas" | Without close(), any misspelled field passes silently | Always use close() — no exceptions |
| "I'll add the JSON example later" | Schema without example is untested; bugs compound | Write the JSON example before moving on |
| "The migration mapping is straightforward" | Grafana field paths vary across plugin versions | Test against real Grafana export JSON |
| "Common types aren't needed for this schema" | Diverging from upstream types causes runtime incompatibility | Import common types unless genuinely unused |
FORBIDDEN Patterns
- NEVER use names other than
package(schemas) ormodel(migration files)migrate - NEVER omit around spec definitions
close({}) - NEVER declare a schema complete without a passing run
percli plugin test-schemas - NEVER hardcode values in migration — always reference
#mappingfield paths#panel - NEVER place migration files outside the subdirectory
migrate/
Blocker Criteria
Stop and ask the user before proceeding if:
- The plugin type is not one of the standard Perses plugin types (panel, variable, datasource)
- The user wants to modify shared types in — these are upstream
github.com/perses/shared - is not installed or
percliis unavailable in the environmentpercli plugin test-schemas - The target directory already contains schemas that would be overwritten
Instructions
Phase 1: DEFINE DATA MODEL
Goal: Create the CUE schema for the plugin spec.
Location:
schemas/<plugin-type>/<plugin-name>/<plugin-name>.cuecue
package model
import "github.com/perses/shared/cue/common"
kind: "<PluginKind>"
spec: close({
// Required fields
requiredField: string
// Optional fields (note the ?)
optionalField?: int
// Constrained fields using shared types
format?: common.#format
thresholds?: common.#thresholds
calculation?: common.#calculation
// Arrays of typed items
items: [...#item]
// Nested type definitions (inside close)
#item: {
name: string
value: number
}
})Gate: Schema file written and syntactically valid. Proceed to Phase 2.
Phase 2: CREATE JSON EXAMPLE
Goal: Write a JSON example that validates against the schema.
Location:
schemas/<plugin-type>/<plugin-name>/<plugin-name>.jsonThe JSON must include all required fields and valid values for any constrained types. Optional fields should be included to demonstrate their usage.
Gate: JSON example file written. Proceed to Phase 3.
Phase 3: WRITE MIGRATION (optional)
Goal: Define Grafana-to-Perses field mapping.
Location:
schemas/<plugin-type>/<plugin-name>/migrate/migrate.cuecue
package migrate
import "github.com/perses/shared/cue/migrate"
#grafanaType: "<GrafanaPluginType>"
#mapping: {
// Map Grafana panel fields to Perses spec fields
perses_field: #panel.grafana_field
}Only proceed if the user requests migration support.
Gate: Migration file written. Proceed to Phase 4.
Phase 4: VALIDATE
Goal: Confirm all schemas and examples pass validation.
bash
percli plugin test-schemasIf validation fails, return to the relevant phase and fix. Do not declare completion until tests pass.
Gate: passes. Task complete.
percli plugin test-schemasReferences
- Perses Plugin Development Guide — official plugin documentation
- CUE Language Specification — CUE syntax and semantics
- Perses Shared CUE Types — ,
common.#format, etc.common.#thresholds - percli CLI Reference — and other commands
percli plugin test-schemas - Grafana Panel Schema Reference — for migration values
#grafanaType