| name | helm-chart-expert |
| description | Use this skill when a task involves Helm chart templating, values file structure, subchart dependency management, or chart validation (lint/template/dry-run) for the project's charts. Don't use it for Helm deploy orchestration (use deployment), Keycloak config (use keycloak), IaC drift (use infrastructure-as-code), or Docker builds (use docker-build). |
| version | 1.0.0 |
| owner | swarmery-infra |
| docs | {"status":"reviewed","source_sha":"9ca1ca2b31c7","updated":"2026-08-06T00:00:00.000Z"} |
Purpose
Author and validate Helm charts for the project's infrastructure and chart repos (project.json → repos). This skill covers chart structure, Go template patterns, values management, subchart dependencies, and validation workflows (lint, template render, dry-run). It does not cover end-to-end deploy orchestration (use deployment), Keycloak realm/client configuration (use keycloak), IaC drift detection (use infrastructure-as-code), or Docker image builds (use docker-build).
When to use this skill (triggers)
- Creating or modifying Helm chart templates (deployment, service, ingress, networkpolicy, etc.)
- Structuring or reviewing
values.yaml / values.<env>.yaml files
- Managing subchart dependencies in
Chart.yaml and Chart.lock
- Running chart validation:
helm lint, helm template, helm upgrade --dry-run
- Debugging template rendering errors (nil pointer, label mismatch, values not applied)
- Bumping chart versions and synchronizing umbrella/subchart versions
- Reviewing Helm template correctness with file:line citations
When NOT to use this skill (anti-triggers)
- End-to-end deploy orchestration (helm upgrade to a live cluster) -- use
deployment
- Keycloak realm setup, client config, or Auth.js integration -- use
keycloak
- Terraform drift detection or post-incident IaC capture -- use
infrastructure-as-code
- Docker image builds or multi-arch buildx -- use
docker-build
- Migration safety checks or schema alignment -- use
migration-check
- GCP firewall rules or VM-level k8s debugging -- use
kubernetes-deployment
- CI/CD pipeline YAML review -- use
gitlab-ci-cd
Required environment (Runtime: .claude/skills/helm-chart-expert/SKILL.md)
- Tools/libraries:
helm (v3.10+), kubectl (v1.28+), bash
- Repos: the project's infrastructure and chart repos (project.json → repos)
- Validation script:
.claude/skills/helm-chart-expert/scripts/validate-chart.sh
Inputs
chart_path: string -- path to the chart directory (e.g., <infra-repo>/)
values_file: string (optional) -- path to the values file to validate against
operation: enum -- one of: author, validate, review, debug
Outputs
Format: Advice, corrected template YAML, or a shell command sequence.
Length budget: Corrected YAML max 60 lines per template file. Shell command sequences max 20 lines. Review findings max 40 lines.
Output template:
## {operation} Result — {chart_path}
### Findings
| # | File:Line | Issue | Severity | Fix |
|---|-----------|-------|----------|-----|
| {n} | {file}:{line} | {description} | {HIGH|MEDIUM|LOW} | {corrected snippet or instruction} |
### Validation Commands
{ordered command list with pass/fail}
### Confidence
{HIGH|MEDIUM|LOW} — {rationale}
For validate: ordered command list (lint, template, dry-run) with pass/fail assessment.
For review: structured findings table with file:line citations.
For author: corrected template YAML with inline comments.
Procedure (Checkpoint: after each step)
-
Identify chart and operation -- Confirm which chart directory and which values file(s) are in scope.
Checkpoint: chart directory contains Chart.yaml.
-
Run validation first -- Run helm lint and helm template before suggesting any upgrade. These two commands are independent and may run in parallel Bash calls.
Checkpoint: both exit 0.
-
Apply template patterns -- Use defensive | default dict at ALL nesting levels. One resource per file. Namespaced template names via _helpers.tpl.
Checkpoint: every conditional chain protects all levels.
-
Dry-run before apply -- Every upgrade example must show --dry-run as the first step.
Checkpoint: dry-run output reviewed before suggesting live apply.
-
Version sync -- If a subchart version was bumped, verify umbrella Chart.yaml dep matches and Chart.lock is regenerated. A check-chart-sync.sh script typically lives in the chart repo (e.g. scripts/check-chart-sync.sh), not in this skill bundle.
Checkpoint: all three files (subchart Chart.yaml, umbrella Chart.yaml, Chart.lock) updated together.
Self-check before returning (anti-hallucination, confidence labels, format match)
Common mistakes to avoid (DO NOT patterns)
- DO NOT access nested values without
| default dict at every level -- causes nil pointer errors when a values file omits a section
- DO NOT hardcode namespaces in examples -- use
$NAMESPACE or {{ .Release.Namespace }}
- DO NOT put multiple K8s resources in one template file -- one resource per file
- DO NOT show
helm upgrade without a preceding --dry-run step -- silent failures in prod
- DO NOT bump a subchart version without updating the umbrella
Chart.yaml dep and regenerating Chart.lock
- DO NOT embed environment-specific values (hostnames, project IDs) in templates -- put them in
values.<env>.yaml
- DO NOT use mutable image tags (
:latest, :main) in values files or templates -- use immutable digests (sha256:...) or $VARIABLE placeholders
- DO NOT confuse this skill's scope with
deployment -- this skill covers template authoring and validation only; deployment handles end-to-end orchestration
Escalation (stop-and-ask conditions)
- Stop and ask when: the chart directory cannot be found or
Chart.yaml is missing required fields
- Stop and ask when: a subchart dependency cannot be resolved after
helm repo update
- Stop and ask when: the user is attempting a production upgrade without a values file -- redirect to
deployment skill for orchestration
- Stop and ask when: the user asks for end-to-end deploy orchestration -- redirect to
deployment
Examples
## Defensive template for optional feature
The infrastructure chart has an optional NetworkPolicy for Keycloak. If the networkPolicy section is absent from a values file, unprotected access causes a nil pointer error.
Wrong -- only body protected:
{{- if .Values.networkPolicy.keycloak.enabled }}
{{- $config := .Values.networkPolicy.keycloak.ingress | default dict }}
{{- end }}
Correct -- all levels protected:
{{- $networkPolicy := .Values.networkPolicy | default dict }}
{{- $keycloakPolicy := $networkPolicy.keycloak | default dict }}
{{- if (hasKey $keycloakPolicy "enabled") | ternary $keycloakPolicy.enabled false }}
{{- $ingressConfig := $keycloakPolicy.ingress | default dict }}
{{- if (hasKey $ingressConfig "allowFromIngressController") | ternary $ingressConfig.allowFromIngressController true }}
{{- end }}
{{- end }}
Verification -- test all paths (lint and template can run in parallel):
helm template <infra-release> . --values values.localdev.yaml
helm template <infra-release> . --set feature.enabled=true
helm template <infra-release> .
helm template <infra-release> . --values values.init.localdev.yaml
## Subchart version bump workflow
When bumping charts/<app>/Chart.yaml version in the umbrella chart repo:
helm dependency update .
bash scripts/check-chart-sync.sh
git add Chart.yaml Chart.lock charts/<app>/Chart.yaml
## Canonical upgrade with dry-run first
helm upgrade --install <infra-release> . \
-f values.<envAlias>.populated.yaml \
--namespace "$NAMESPACE" \
--dry-run --debug
helm upgrade --install <infra-release> . \
-f values.<envAlias>.populated.yaml \
--namespace "$NAMESPACE" \
--wait --atomic --timeout 8m \
--description "[ci $CI_PIPELINE_ID deploy] infra@$(git rev-parse --short HEAD)"
## requireRealSecret helper
For secret values that must not ship as CHANGE_ME in production:
{{- define "app.requireRealSecret" -}}
{{- $value := index . 0 -}}
{{- $name := index . 1 -}}
{{- if or (eq $value "") (eq $value "CHANGE_ME") -}}
{{- fail (printf "secrets.%s required -- set a real value" $name) -}}
{{- end -}}
{{- $value -}}
{{- end -}}
auth-secret: {{ include "app.requireRealSecret" (list .Values.secrets.authSecret "authSecret") | quote }}
Failure modes (symptom -> detection -> action)
- nil pointer in template: symptom:
nil pointer evaluating interface {}.fieldName -> detect: identify which values key is missing | default dict at the conditional level -> fix: add defensive extraction at every nesting level
- Chart.lock stale after subchart bump: symptom:
can't get a valid version for dependency <name> -> detect: compare subchart Chart.yaml version with umbrella Chart.yaml dep version -> fix: update umbrella dep, run helm dependency update ., commit both
- Values not applied: symptom: default values appear instead of overrides -> detect:
helm get values <release> -n $NAMESPACE shows missing keys -> fix: verify --values <file> flag was passed and check indentation in the values file
- Label mismatch blocking service discovery: symptom: service can't find pods -> detect: compare
kubectl get pods --show-labels with kubectl get svc -o yaml | grep selector -> fix: ensure both use the same selector labels from _helpers.tpl
Related skills (compose vs defer)
deployment -- defer to it for end-to-end deploy orchestration (helm upgrade to live clusters); this skill covers template authoring and validation only. For end-to-end deploy orchestration, use deployment.
keycloak -- defer to it for Keycloak realm/client/Auth.js config; this skill only covers the Helm values structure for the keycloakx subchart
infrastructure-as-code -- defer to it for IaC drift detection; compose with it when a manual helm override needs to be captured in code
kubernetes-deployment -- defer to it for k8s cluster operations, GCP firewall, minikube tunnel; compose when debugging a deployment that uses this chart
migration-check -- no direct overlap; migration scripts are not Helm-managed
docker-build -- defer to it for image builds; this skill only consumes image tags/digests in values files
How to use
What it does
This skill helps you write and validate Helm charts: template files, values files, subchart dependencies, and chart versions. It focuses on getting the chart correct before anything reaches a cluster — defensive template patterns, helm lint, helm template, and helm upgrade --dry-run. It does not push releases to live clusters.
When to use it
- You are writing or fixing a chart template (deployment, service, ingress, network policy) and want the nesting patterns right.
- A render fails with
nil pointer evaluating interface {}.fieldName and you need to find the values key that is missing a guard.
- You bumped a subchart version and need the umbrella
Chart.yaml and Chart.lock to stay in sync.
- You want a chart reviewed with file:line citations and a severity per finding.
When not to use it
- Running an upgrade against a live cluster end to end — use the
deployment skill.
- Keycloak realm, client, or auth integration config — use the
keycloak skill.
- Terraform drift or post-incident capture — use the
infrastructure-as-code skill.
- Building or pushing container images — use the
docker-build skill.
How to invoke
Skill(skill: "infra-pack:helm-chart-expert")
Invoke it directly, or just describe the chart work — the skill's own triggers cover template edits, values structure, dependency bumps, and validation runs.
Inputs
chart_path — the chart directory containing Chart.yaml — required.
values_file — the values file to validate against — optional.
operation — one of author, validate, review, debug — required.
What you get back
A result block headed ## {operation} Result — {chart_path}, with a findings table (File:Line, issue, severity, fix), the ordered validation commands with pass/fail, and a HIGH/MEDIUM/LOW confidence label with its rationale. author returns corrected YAML with inline comments; validate returns the lint → template → dry-run sequence. Nothing is applied to a cluster.
Worked example
Skill(skill: "infra-pack:helm-chart-expert")
Request: "values.<envAlias>.yaml has no networkPolicy section and the render
dies with a nil pointer. chart_path: apps/<mainApp>/chart, operation: debug"
What happens: the skill runs helm lint and helm template first, traces the
failure to a conditional that guards only the leaf key, and returns the
corrected template that extracts every nesting level with `| default dict`,
plus four helm template commands covering full values, --set, defaults only,
and bootstrap values.
Related
deployment — prefer it once the chart is correct and you need the release orchestrated.
kubernetes-deployment — prefer it for cluster-level debugging; compose with it when the failing workload comes from this chart.
infrastructure-as-code — compose with it when a manual override needs to be captured back into code.