Skip to content

Helm Concepts

llms.txt lists every page for an agent

Every exported resource declaration becomes part of the generated Helm chart.

chant generates a standard Helm chart directory:

Output FileChant TypeDescription
Chart.yamlChartChart metadata (name, version, appVersion, dependencies)
values.yamlValuesDefault configuration values
templates/*.yamlResource constructorsKubernetes manifests with template expressions
templates/NOTES.txtHelmNotesPost-install usage instructions
templates/tests/*.yamlHelmTestHelm test pods
crds/*.yamlHelmCRDCustom Resource Definitions

The values proxy writes .Values.* paths into templates. Instead of writing raw template strings, use typed property access:

import { values, Deployment } from "@intentius/chant-lexicon-helm";
export const deployment = new Deployment({
name: "my-app",
replicas: values.replicaCount,
image: values.image.repository,
tag: values.image.tag,
});

This generates template expressions:

replicas: {{ .Values.replicaCount }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

The proxy supports arbitrarily deep nesting. Every property access appends to the .Values path, so values.global.ingress.tls.enabled becomes {{ .Values.global.ingress.tls.enabled }}.

Helm provides several built-in objects accessible at render time. The lexicon exposes these as typed references:

import { Release } from "@intentius/chant-lexicon-helm";
const labels = {
"app.kubernetes.io/instance": Release.Name,
"app.kubernetes.io/managed-by": Release.Service,
};
// Generates: {{ .Release.Name }}, {{ .Release.Service }}

Available properties: Release.Name, Release.Namespace, Release.Service, Release.Revision, Release.IsUpgrade, Release.IsInstall.

import { ChartRef } from "@intentius/chant-lexicon-helm";
const labels = {
"helm.sh/chart": ChartRef.Name,
"app.kubernetes.io/version": ChartRef.AppVersion,
};
// Generates: {{ .Chart.Name }}, {{ .Chart.AppVersion }}
import { Capabilities } from "@intentius/chant-lexicon-helm";
// Any property path works — `Capabilities` is a proxy, not a fixed set
const kubeVersion = Capabilities.KubeVersion.Version;
// Generates: {{ .Capabilities.KubeVersion.Version }}

Property access is all the proxy supports; the paths are not calls. For a predicate like APIVersions.Has, drop to a raw template expression:

import { HelmTpl } from "@intentius/chant-lexicon-helm";
const usePDB = new HelmTpl('{{ .Capabilities.APIVersions.Has "policy/v1" }}');
import { Template } from "@intentius/chant-lexicon-helm";
const source = Template.BasePath;
// Generates: {{ .Template.BasePath }}

The lexicon provides typed wrappers for Helm/Sprig template functions:

import { include, required, helmDefault, toYaml, quote } from "@intentius/chant-lexicon-helm";
// Named template inclusion — the second arg is the context string, default "."
const labels = include("my-app.labels");
// Generates: {{ include "my-app.labels" . }}
// Required values with error messages
const image = required("image.repository is required", values.image.repository);
// Generates: {{ required "image.repository is required" .Values.image.repository }}
// Default values — the default comes first, mirroring Sprig's `default`
const pullPolicy = helmDefault("IfNotPresent", values.image.pullPolicy);
// Generates: {{ default "IfNotPresent" .Values.image.pullPolicy }}
// YAML serialization for nested objects
const resources = toYaml(values.resources);
// Generates: {{ toYaml .Values.resources }}
// Pass an indent to get the nindent pipe that block scalars need
const indented = toYaml(values.resources, 12);
// Generates: {{ toYaml .Values.resources | nindent 12 }}
// Quoting string values
const name = quote(values.nameOverride);
// Generates: {{ .Values.nameOverride | quote }}

Use If, ElseIf, Range, and With to control template rendering:

import { If, Range, With, values } from "@intentius/chant-lexicon-helm";
// Conditional block
const ingressBlock = If(values.ingress.enabled, {
apiVersion: "networking.k8s.io/v1",
kind: "Ingress",
metadata: { name: values.ingress.hostname },
});
// Iteration
const envVars = Range(values.env, (item) => ({
name: item.name,
value: item.value,
}));
// Scoped context
const tlsBlock = With(values.ingress.tls, (tls) => ({
secretName: tls.secretName,
hosts: tls.hosts,
}));

Helm hooks run at specific points in the release lifecycle:

import { HelmHook } from "@intentius/chant-lexicon-helm";
export const migration = new HelmHook({
name: "db-migrate",
type: "pre-install,pre-upgrade",
weight: -5,
deletePolicy: "before-hook-creation",
image: values.image.repository,
command: ["migrate", "--target", "latest"],
});

This generates a Job manifest with helm.sh/hook annotations. The weight property controls execution order (lower runs first).

Chart dependencies are declared as properties of Chart:

import { Chart, HelmDependency } from "@intentius/chant-lexicon-helm";
export const chart = new Chart({
name: "my-app",
version: "1.0.0",
dependencies: [
new HelmDependency({
name: "postgresql",
version: "12.x",
repository: "https://charts.bitnami.com/bitnami",
condition: "postgresql.enabled",
}),
new HelmDependency({
name: "redis",
version: "17.x",
repository: "https://charts.bitnami.com/bitnami",
condition: "redis.enabled",
}),
],
});

chant