helm‑schema
Generate a JSON Schema for a Helm chart's values.yaml by analyzing the chart's templates — not by guessing from the defaults file. Open source, MIT-licensed.
A chart’s values.yaml is a documented default, not a contract. It says what a value is set to, never what it must be — a port that happens to be 80 could be typed as a string, an object, or anything else. helm-schema recovers the real contract by reading the templates: it follows each .Values.* into the resource field it renders, and types it from what Kubernetes expects there.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: {{ .Values.replicaCount }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}{
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"replicaCount": {
"anyOf": [
{
"description": "Number of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1.",
"format": "int32",
"type": "integer"
},
{
"pattern": "^(([+-]_*)?(0|[1-9][0-9_]{0,17}|0[xX][0-9a-fA-F]{1,15}|0[bB][01]{1,62}|0[oO][0-7]{1,20}|0[0-7]{1,20})|[+-]_*0[0-7]{0,8}[89][0-9]{0,8})$",
"type": "string"
}
]
},
"revisionHistoryLimit": {
"anyOf": [
{
"description": "The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10.",
"format": "int32",
"type": "integer"
},
{
"pattern": "^(([+-]_*)?(0|[1-9][0-9_]{0,17}|0[xX][0-9a-fA-F]{1,15}|0[bB][01]{1,62}|0[oO][0-7]{1,20}|0[0-7]{1,20})|[+-]_*0[0-7]{0,8}[89][0-9]{0,8})$",
"type": "string"
}
]
}
},
"required": [
"replicaCount",
"revisionHistoryLimit"
],
"type": "object",
"x-helm-schema-generated": true,
"x-helm-schema-policy": {
"annotation-format-version": 1,
"modifiers": {
"overrides": {
"count": 0,
"digest": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945"
},
"reference-mode": "fully-inlined"
},
"narrowing": [],
"policy-fingerprint": "4e6202505d786965bede4b949c4a0b5f7f80a1e2cf66fd3321a17aaf7276b29b",
"policy-vocabulary-version": 1,
"requested-profile": "full",
"resolved": {
"kind-partitions": true,
"local-conditionals": true,
"root-anchored-conditionals": true,
"terminal-clauses": true
}
}
}replicaCount lands in a Deployment’s spec.replicas, so it is typed as an int32 and annotated with Kubernetes’ own field description — recovered from the template, never stated in values.yaml. (The second arm covers Helm’s quoted-number form, e.g. "1".)
What it does#
Template-aware
Parses Helm templates and statically extracts every .Values.* path from the actual render logic — not from the defaults file.
Control-flow aware
Understands if, with, range, and patterns like eq, not, or, and default, so the schema mirrors the template's real logic.
Resource-aware
Tracks which Kubernetes resource and field a value flows into, so it can type the value against the upstream API.
Schema-backed
Types values from upstream Kubernetes JSON schemas and CRD catalogs, and merges everything into one Draft-07 schema.
Get started#
# Install the CLI (or: brew install --cask romnn/tap/helm-schema)
cargo install --locked helm-schema-cli
# Generate a schema for a chart directory
helm-schema ./mychart --output mychart/values.schema.jsonHelm picks up a values.schema.json next to values.yaml automatically and validates user-supplied values against it on install, upgrade, lint, and template.
Documentation#
- Introduction and Installation.
- Quick start — a first run and how to read the output.
- How it works — the analysis pipeline, phase by phase.
- Guide — template analysis, defaults, Kubernetes & CRD schemas, subcharts, overrides.
- Reference — every CLI flag, the output shape, diagnostics, and caching.