App SDK Concepts
Grafana LabsOfficialPublished by Grafana Labs
- Skill
- Tool integration
- Cloud and DevOps
- Apache-2.0
- Medium risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The grafana-app-sdk provides a CLI and Go library for building schema-centric applications on the Grafana App Platform. It supports a workflow where developers define resources using CUE schemas, generate Go and TypeScript code, and implement business logic through reconcilers and admission controllers. The SDK supports multiple deployment modes, including standalone Kubernetes operators and in-process applications within the Grafana repository.
What it does
- Initializes new application projects with the required directory structure and build files
- Scaffolds Kubernetes operator components or frontend plugin structures
- Generates Go types, clients, and TypeScript definitions from CUE schemas
- Provides commands for local development and testing of application logic
- Facilitates the creation of Kubernetes YAML bundles for deployment
- Supports configuration management for environment-driven application settings
When to use it
- When starting a new project on the Grafana App Platform
- When you need to define custom resources using CUE schemas
- When building a standalone Kubernetes operator for Grafana-related tasks
- When integrating a new application directly into the Grafana repository
- When you need to generate boilerplate code for reconcilers and admission handlers
Advantages
- Ensures consistent project structure across different deployment modes
- Automates the generation of boilerplate code from schema definitions
- Simplifies the integration of business logic with Kubernetes-style resources
- Provides a unified CLI for the entire development lifecycle
- Supports both standalone and in-process deployment architectures
Usage examples
- “How do I start a new Grafana app project?”
- Use the command grafana-app-sdk project init github.com/your-org/your-app to create the project structure, including kinds, package skeletons, and build files.
- “How do I add an operator to my project?”
- Run grafana-app-sdk project component add operator to scaffold the necessary reconciler stubs, admission handlers, and the operator entrypoint.
- “How do I update my Go types after changing a CUE schema?”
- Execute the command grafana-app-sdk generate to update Go types, clients, and TypeScript definitions based on your latest CUE definitions.
- “How do I run my app locally?”
- Use the command grafana-app-sdk local/up to start a local Kubernetes-compatible API server for testing your application logic.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/grafana/app-sdk-concepts/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip app-sdk-concepts.zip -d .agents/skills
Documentation by Grafana Labs
Grafana App SDK Concepts
The grafana-app-sdk is a CLI + Go library for building schema-centric apps on the Grafana App Platform. Apps define resources via CUE schemas ("kinds"), generate Go + TypeScript code, and implement business logic via admission control and reconcilers.
Prerequisites
go install github.com/grafana/grafana-app-sdk/cmd/grafana-app-sdk@latest
grafana-app-sdk version # verifyCommon Workflows
Scaffold a standalone operator app
# 1. Init the project (use the Go module path)
grafana-app-sdk project init github.com/example/my-app
# 2. Add operator scaffolding — ASK THE USER FIRST.
# They may prefer to write app.App by hand.
grafana-app-sdk project component add operator
# 3. Verify scaffolded layout
ls pkg/app pkg/watchers cmd/operator
# Expected: app.go, watchers/<kind>.go, main.goCommon failure: forgetting go install updates the binary — verify with grafana-app-sdk version before init.
Scaffold a grafana/apps-style app (inside grafana/grafana)
Only available inside the Grafana repo (or fork) — the init command detects apps/ and pkg/registry/apps/ at the repo root.
mkdir -p apps/my-app && cd apps/my-app
grafana-app-sdk project init github.com/grafana/grafana/apps/my-app
# Keep ONLY: kinds/ pkg/ go.mod go.sum — delete everything else.
cp apps/example/Makefile apps/my-app/Makefile
cp apps/example/kinds/config.cue apps/my-app/kinds/config.cue # overwrite
go work use ./apps/my-appThen register the app inside Grafana (pkg/registry/apps/apps.go + register.go). Full walkthrough in references/deployment-modes.md.
End-to-end development loop
1. project init → module, Makefile, kinds/
2. project kind add MyKind → CUE kind scaffold
3. Edit kinds/*.cue → schemas, validation, versions
4. grafana-app-sdk generate → Go types, clients, TS types, AppManifest, CRDs
5. Implement logic → fill in reconciler / admission stubs
6. (optional) project component add frontendAlways rerun generate after every CUE change — generated code is the API your reconciler sees.
Deployment modes (one-line table)
| Mode | When to pick | Where it runs |
|---|---|---|
| Standalone operator | Outside Grafana repo, want your own binary | Kubernetes operator with its own webhook server |
| grafana/apps | Inside github.com/grafana/grafana (or fork) | In-process inside Grafana's API server |
| Frontend-only | UI-only app, no Go logic needed | No backend — TS types only |
Full per-mode init, runtime, and wiring detail in references/deployment-modes.md.
References
references/deployment-modes.md— per-mode init, runtime semantics, grafana/apps registration walkthroughreferences/project-structure.md— standalone project layout, what's hand-edited vs generatedreferences/cli-reference.md— everygrafana-app-sdksubcommand with flagsreferences/specific-config.md—app.Config.SpecificConfigpattern for feature-flag-driven app configreferences/local-development.md— Tilt + k3d local dev loopreferences/local-config.md—local/config.yamlreference
Resources
Files
- ATTRIBUTION.mdAdded by AutoGineer855 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md4.3 KiB
- references/cli-reference.md8.6 KiB
- references/deployment-modes.md5.4 KiB
- references/local-config.md4.2 KiB
- references/local-development.md6.5 KiB
- references/project-structure.md1.6 KiB
- references/specific-config.md975 B
references/cli-reference.md
grafana-app-sdk CLI Reference
Installation
# Latest version
go install github.com/grafana/grafana-app-sdk/cmd/grafana-app-sdk@latest
# Specific version
go install github.com/grafana/grafana-app-sdk/cmd/[email protected]
# Verify
grafana-app-sdk versionProject Commands
project init
Initialize a new app project.
grafana-app-sdk project init <module-path>Arguments:
<module-path>— Go module path (required), e.g.github.com/example/my-app
What it creates:
kinds/— empty kinds directory with an initializedcue.modpkg/— Go package skeletongo.mod/go.sum— Go module filesMakefile— build targets includinggeneratelocal/— local development config
project kind add
Add a new kind scaffold to the kinds/ directory.
grafana-app-sdk project kind add <KindName> [flags]Arguments:
<KindName>— PascalCase kind name (required), e.g.IssueTracker
Flags:
| Flag | Description |
|---|---|
--overwrite | Overwrite existing kind files (use when re-scaffolding) |
What it creates:
kinds/<kindname>.cue— common kind metadatakinds/<kindname>_<version>.cue— <version> schema scaffold with comments
Notes:
Always use
--overwriteto regenerate when the scaffold changes in newer SDK versionsThe generated file is heavily commented — read the comments carefully
It will always generate only a single version, the
preferredVersioninmanifest.cue. To add additional versions, see thecue-kind-definitionskill
project component add
Add a component scaffold to an existing project.
grafana-app-sdk project component add <component>Components:
| Component | Description |
|---|---|
operator | Adds operator (standalone binary) scaffolding: reconciler stubs, admission handler stubs, cmd/operator/main.go |
frontend | Scaffolds a Grafana plugin frontend using create-plugin (requires yarn) |
operator — what it creates:
cmd/
└── operator/
└── main.go # operator entrypoint
pkg/
├── app/
│ └── app.go # app.App implementation stub with TODOs
└── watchers/
└── watcher_<kind>.go # <kind> watcher with stubbed methodsfrontend — what it creates:
plugin/
├── src/
│ ├── module.ts
│ └── pages/
├── package.json
└── plugin.jsonGenerate Command
generate
Generate Go types, TypeScript types, AppManifest, and CRD files from CUE kind definitions.
grafana-app-sdk generate [flags]Flags:
| Flag | Description |
|---|---|
--source | Path to CUE definitions (default: kinds/) |
--config | The CUE selector of the config object (see CUE Config Object section) |
What it generates:
| Output | Location | Controlled by |
|---|---|---|
| Go type structs | pkg/generated/<group>/<version>/types_gen.go | codegen.go.enabled |
| Go client | pkg/generated/<group>/<version>/zz_generated_*.go | codegen.go.enabled |
| TypeScript types | configured output dir | codegen.ts.enabled |
| AppManifest (Go) | pkg/app/appmanifest_gen.go | always |
| AppManifest (JSON) | appmanifest.json | always |
| CRD (JSON or YAML) | config/crd/ | CUE config output setting |
⚠ Generated files must not be edited manually — they are overwritten on every generate run.
YAML Bundle Command
generate yaml-bundle
Generate a Kubernetes YAML bundle for deployment.
grafana-app-sdk generate yaml-bundle [flags]Produces CRDs, webhook configurations, and RBAC manifests ready for kubectl apply.
Local Development
local
Commands for running the app locally with a mocked API server.
# Start the local development environment
grafana-app-sdk local/upStarts a local Kubernetes-compatible API server for development without a full cluster.
Common Makefile Targets
Projects generated by project init include a Makefile with these targets:
| Target | Description |
|---|---|
make generate | Run grafana-app-sdk generate |
make build | Build the operator binary and/or frontend plugin |
make test | Run tests |
make lint | Run Go linter |
make deps | Vendor in any missing go dependencies |
make local/up | Create a local k3d development environment with Tilt |
make local/push_operator | Pust the built operator image to the local development enviroment k3d cluster |
make local/deploy_plugin | Deploy the latest built plugin to the local development environment's grafana |
make local/down | Take down the Tilt-deployed resources |
make local/clean | Delete the local development environment k3d cluster |
CUE Config Object
Control generation behavior via a CUE config object in your kinds. This is typically in the top-level kinds file:
// Codegen output configuration
config: {
codegen: {
// goModule allows explicitly setting the module path.
// If empty the module path is read from go.mod
// Default: ""
goModule: ""
// goModGenPath anchors generated Go output relative to the module root, instead of execution directory
// Default: ""
goModGenPath: ""
// goGenPath sets the output directory for generated Go types.
// Default: "pkg/generated/"
goGenPath: "pkg/generated/"
// tsGenPath sets the output directory for generated TypeScript types
// Default: "plugin/src/generated/"
tsGenPath: "plugin/src/generated/"
// enableK8sPostProcessing runs the Kubernetes code generators after writing files.
// This option is unnecessary when using the k8s.apiserver's DefaultAppInstaller
// Default: false
enableK8sPostProcessing: false
// enableOperatorStatusGeneration toggles standard status information to be joined onto kinds' schema's status:
// {
// #OperatorState: {
// // lastEvaluation is the ResourceVersion last evaluated
// lastEvaluation: string
// // state describes the state of the lastEvaluation.
// // It is limited to three possible states for machine evaluation.
// state: "success" | "in_progress" | "failed"
// // descriptiveState is an optional more descriptive state field which has no requirements on format
// descriptiveState?: string
// // details contains any extra information that is operator-specific
// details?: {
// [string]: _
// }
// }
// // operatorStates is a map of operator ID to operator state evaluations.
// // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
// operatorStates?: {
// [string]: #OperatorState
// }
// // additionalFields is reserved for future use
// additionalFields?: {
// [string]: _
// }
// }
// Default: true
enableOperatorStatusGeneration: true
}
definitions: {
// genManifest controls whether manifest files are written
// Default: true
genManifest: true
// genCRDs controls whether CRD files are written
// Default: true
genCRDs: true
// path sets where definition files are written
// Default: "definitions"
path: "definitions"
// encoding determines JSON or YAML serialization of CRDs and manifest, allowed values are "json" and "yaml"
// Default: "json"
encoding: "json"
// manifestVersion lets you pin the manifest schema format (legacy v1alpha1 vs default v1alpha2).
// The v1alpha1 manifest uses CRD-compatible schemas for kinds, the v1alpha2 version contains more information but requires transformation to make kind schemas CRD-compatible.
// Default: "v1alpha2"
manifestVersion: "v1alpha2"
}
}Troubleshooting
grafana-app-sdk: command not found
The Go bin directory is not in PATH. Add it:
export PATH="$PATH:$(go env GOPATH)/bin"generate fails with CUE errors
CUE is strict about types and constraints. Common causes:
Undefined field reference
Type mismatch (
stringwhereintexpected)Missing import (such as
timefortime.Time)
Run cue vet ./kinds/... to get more detailed error output.
generate produces no TypeScript output
Check that codegen.ts.enabled: true is set in the kind's CUE file and that an output path is configured.
go mod tidy needed after generate
After running generate, newly generated Go files may import packages not yet in go.sum. Run:
go mod tidyRequirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
What our scanner noticed· Medium risk
- References to credential files
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Grafana Labs
- Publisher
- Grafana Labs (Official)
- Source
- grafana/skills · skills/grafana-app-sdk/app-sdk-concepts · commit 8fb72a5
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Grafana Labs or Grafana Labs.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download app-sdk-concepts.zip