../

Helm commands

The exact helm command and flag for each task, for Helm 4 (v4.3), with the Helm 3 spelling where a flag was renamed. Charts, templating and what changed in Helm 4 are explained in Helm; the objects a release creates are inspected with kubectl commands.

Install the CLI

PlatformInstall
macOS, Linux with Homebrewbrew install helm
Windowswinget install Helm.Helm, choco install kubernetes-helm or scoop install helm
Fedorasudo dnf install helm
Snapsudo snap install helm --classic
Debian, Ubuntuan apt repository (setup steps in the install guide), then sudo apt-get install helm
Anythe installer script or a binary from the GitHub releases page

Only the script and the release binaries come from the Helm project; the package managers are community-maintained and can lag a release behind.

u=https://raw.githubusercontent.com/helm/helm/main/scripts
curl -fsSL -o get_helm.sh "$u/get-helm-4"
chmod 700 get_helm.sh && ./get_helm.sh
helm version --short
CommandDoes
helm versionclient version, Git commit, Go version; --short for just v4.3.x
helm envevery HELM_* setting in effect; helm env HELM_CACHE_HOME for one
helm completion bash, zsh, fish, powershellshell completion script, e.g. source <(helm completion zsh)
helm help upgrade, helm upgrade -ha command's flags

Renamed in Helm 4

Scripts written for Helm 3 mostly keep working: old flag names print a deprecation warning.

Helm 3Helm 4
--atomic--rollback-on-failure
--force--force-replace
--wait (yes or no)--wait means --wait=watcher; hookOnly (the default) and legacy are the other strategies
bare --dry-run (client)--dry-run=client, server or none; the bare form still works but is deprecated
helm list showed deployed and failed; -a for allevery status by default; no -a
helm status --show-resourcesresources are listed by default
helm template --validatehelm template --dry-run=server
helm registry login with a URLhost name only: helm registry login ghcr.io
--post-renderer ./script.sh--post-renderer NAME of a post-renderer plugin
helm plugin install https://github.com/…tarballs are signature-checked; Git sources need --verify=false

Global flags and environment

FlagEnvironment variableDoes
-n webHELM_NAMESPACErelease namespace (default: the kubeconfig context's)
--kube-context prodHELM_KUBECONTEXTkubeconfig context
--kubeconfig fKUBECONFIGkubeconfig file
--kube-as-user, --kube-as-groupHELM_KUBEASUSER, HELM_KUBEASGROUPSimpersonation
--kube-token, --kube-apiserverHELM_KUBETOKEN, HELM_KUBEAPISERVERconnect without a kubeconfig
--debugHELM_DEBUGverbose output
--burst-limit, --qpsHELM_BURST_LIMIT, HELM_QPSclient throttling, for clusters with many CRDs
HELM_DRIVERwhere releases are stored: secret (default), configmap, memory, sql
HELM_MAX_HISTORYdefault for --history-max (10)
HELM_NO_PLUGINS=1disable plugins
NO_COLORno colored output
SOURCE_DATE_EPOCHfixed timestamps for reproducible helm package archives
OSCache (HELM_CACHE_HOME)Config (HELM_CONFIG_HOME)Data (HELM_DATA_HOME)
Linux~/.cache/helm~/.config/helm~/.local/share/helm
macOS~/Library/Caches/helm~/Library/Preferences/helm~/Library/helm
Windows%TEMP%\helm%APPDATA%\helm%APPDATA%\helm

HELM_*_HOME wins, then the XDG variables, then the defaults above. Inside them: repositories.yaml and registry/config.json (credentials) live in config, plugins and starters in data, repository indexes in cache/repository.

CommandDoes
helm repo add grafana https://grafana.github.io/helm-chartsregister an HTTP chart repository
helm repo add acme https://charts.acme.dev --username ci --password-stdina private one
helm repo add … --force-updateoverwrite an existing entry with the same name
helm repo updatedownload fresh indexes for all repos; helm repo update grafana for one
helm repo listnames and URLs; -o json
helm repo remove grafanaforget a repo
helm repo index ./public --url https://charts.acme.devwrite index.yaml for hosting your own; --merge old.yaml
helm search repo lokicharts in added repos (from the local index, so repo update first)
helm search repo grafana/loki --versionsevery version (-l)
helm search repo grafana/loki --version '^6.0'versions matching a range
helm search repo -r 'grafana/(loki|tempo)'regular expression
helm search repo … --develinclude pre-releases
helm search hub prometheusArtifact Hub; --list-repo-url adds the repo URL to add
helm install loki loki --repo https://grafana.github.io/helm-chartsuse a repo without adding it

OCI registries have no repo add and no search: use the full oci:// reference (see Chart authoring).

Install and upgrade

helm install api ./api -n web --create-namespace
helm upgrade api ./api -n web -f values/prod.yaml
# install or upgrade in one idempotent command (CI)
helm upgrade --install api ./api -n web \
  --create-namespace -f values/prod.yaml
Chart referenceMeans
./apian unpacked chart directory
./api-1.2.0.tgza packaged chart
grafana/lokirepo/chart from an added repository
loki --repo https://grafana.github.io/helm-chartsrepository URL, no repo add needed
https://charts.acme.dev/api-1.2.0.tgzan absolute URL
oci://ghcr.io/acme/charts/apian OCI registry; --version picks the tag
oci://ghcr.io/acme/charts/api@sha256:…pinned by digest

Release names are at most 53 characters of lowercase letters, digits, - and ., starting and ending with a letter or digit. helm install ./api --generate-name (-g) picks one; --name-template builds one.

Flags

FlagDoes
-n web, --create-namespacerelease namespace; create it if missing (on upgrade only with --install)
-i, --installupgrade installs when the release doesn't exist yet
--version 1.2.0chart version, or a range such as ~1.2.0 or ^1.2; latest stable if omitted
--develallow pre-release chart versions
--dependency-updatefetch missing dependencies of a local chart first
--verifycheck the chart's .prov signature (--keyring)
-f values.yamlvalues file; repeatable, later files win; also a URL or - for stdin
--set, --set-string, --set-json, --set-file, --set-literalsingle values (syntax below)
--waitwait until every resource is ready (watcher strategy, kstatus)
--wait=hookOnlythe default: wait for hooks only
--wait=legacyHelm 3's readiness logic
--wait-for-jobswith --wait, also wait for Jobs to complete
--timeout 10mper Kubernetes operation (hook Jobs, the wait); default 5m0s
--rollback-on-failureHelm 3 --atomic: a failed upgrade rolls back, a failed install is uninstalled; turns on --wait=watcher
--cleanup-on-failupgrade: delete objects this attempt created if it fails
--server-side=falseinstall: client-side apply instead of the default server-side apply
--server-side=true|false|autoupgrade, rollback: default auto keeps the release's previous method
--force-conflictswith server-side apply, take fields owned by another manager
--force-replaceHelm 3 --force: replace objects with a full update (PUT) instead of a patch; client-side apply only, so add --server-side=false
--take-ownershipadopt existing objects that lack Helm's ownership annotations
--skip-crdsdon't install the chart's crds/
--no-hooksskip hooks
--skip-schema-validationignore values.schema.json
--disable-openapi-validationdon't check rendered objects against the cluster's schemas
--dry-run=clientrender and print, no cluster contact
--dry-run=serverrender with cluster access (lookup, real capabilities), store nothing
--hide-secretwith --dry-run, leave Secret contents out of the output
-o json, -o yamlmachine-readable result
--description "deploy 4f2c1a"shown in helm history
-l team=paymentslabels on the release record (--labels); filter with helm list -l
--history-max 20revisions kept per release (default 10, 0 = unlimited)
--post-renderer NAMEpipe rendered YAML through a post-renderer plugin; --post-renderer-args
--enable-dnsallow DNS lookups in templates
--hide-notesdon't print NOTES
--replaceinstall: reuse the name of a release uninstalled with --keep-history (unsafe in production)
--username, --password, --ca-file, --plain-http, --insecure-skip-tls-verifychart download credentials and TLS

Value flags

You wantFlagResult
a nested key--set image.tag=1.4.2image: {tag: "1.4.2"}
several keys--set replicaCount=3,service.port=80or repeat --set
a list--set 'args={serve,--port=3000}'args: [serve, --port=3000]
one list item--set 'hosts[0]=api.acme.dev'indexes from 0
fields of a list item--set 'env[0].name=MODE,env[0].value=prod'env: [{name: MODE, value: prod}]
a comma in a value--set 'ips=10.0.0.1\,10.0.0.2'the string 10.0.0.1,10.0.0.2
a dot in a key--set 'podAnnotations.prometheus\.io/scrape=true'key prometheus.io/scrape
delete a default--set ingress.annotations=nullthe key is removed
a number kept as text--set-string image.tag=110"110", not the integer 110
structured data--set-json 'tolerations=[{"key":"gpu","operator":"Exists"}]'lists and maps as JSON
a file's content--set-file config=./app.tomlthe whole file as one string
no parsing at all--set-literal 'password=a,b=c\d'commas, = and \ kept
values from a pipesops -d secrets.yaml | helm upgrade api ./api -f --f - reads stdin

--set turns true, false, null and plain integers into typed values; everything else, 1.10 included, stays a string. Single-quote the argument so the shell leaves {}, [] and \ alone. Lowest to highest precedence: chart defaults, -f files left to right, --set-json, --set, --set-string, --set-file, --set-literal.

helm upgrade api ./api -f prod.yaml -f eu.yaml --set image.tag=1.4.3 replicaCount image.tag service.type ingress.enabled result 4 1.4.3 ClusterIP true higher wins --set 1.4.3 -f eu.yaml 4 -f prod.yaml 3 true chart values 1 1.4.2 ClusterIP false lowest to highest: chart values, -f files left to right, --set-json, --set, --set-string, --set-file, --set-literal
Each key comes from the highest layer that sets it; keys nobody overrides keep the chart's default.

Values on upgrade

FlagsValues used
-f or --set givennew chart defaults plus exactly what this command passes
no value flags at allnew chart defaults plus the last release's user-supplied values
--reuse-valueslast release's values, old chart defaults included, plus this command's; new chart defaults are ignored
--reset-then-reuse-valuesnew chart defaults, then the last release's user-supplied values, then this command's
--reset-valuesnew chart defaults plus this command's only, even with no value flags

Passing the same -f values/prod.yaml on every upgrade is the only form that is reproducible from Git; see Values and overrides.

Inspecting releases

CommandShows
helm listreleases in the current namespace, any status, alphabetical
helm list -Aevery namespace
helm list --failed, --pending, --deployed, --superseded, --uninstalled, --uninstallingonly those statuses (combinable)
helm list -qnames only
helm list -f '^api'release names matching a regular expression
helm list -l team=paymentsby release labels
helm list -d -rnewest first
helm list -o jsonfor scripts; up to 256 releases unless -m
helm status apistatus, revision, resources and NOTES
helm status api --revision 6 -o yamlan older revision, machine-readable
helm history apievery revision: status, chart, app version, description
helm history api --max 5 -o jsonthe last five, for scripts
helm get values apithe values you supplied
helm get values api -aall computed values, chart defaults included
helm get values api --revision 6 -o jsonas of a revision
helm get manifest apithe rendered objects as applied (hooks excluded)
helm get hooks apirendered hook objects
helm get notes apiNOTES output
helm get metadata apichart, versions, namespace, status, deploy time
helm get all apiall of the above; --template '{{.Release.Name}}' to pick fields
helm show values grafana/loki --version 6.40.0a chart's defaults, without installing
helm show values grafana/loki --jsonpath '{.loki.storage}'one subtree
helm show chart, show readme, show crds, show allChart.yaml, README, CRDs, everything

show takes any chart reference (directory, .tgz, repo/chart, oci://); get takes a release name.

StatusMeans
deployedthe current, successful revision
supersededan older revision that was deployed and has been replaced
failedthe install, upgrade or rollback errored or timed out
pending-install, pending-upgrade, pending-rollbackin progress, or the process died mid-way
uninstalling, uninstalledbeing removed; removed with --keep-history
helm install api ./api helm upgrade api ./api --set image.tag=1.4.3 helm upgrade api ./api --set image.tag=1.4.4 --wait helm rollback api rev 1 deployed superseded image 1.4.2 Install complete rev 2 deployed superseded image 1.4.3 Upgrade complete rev 3 failed image 1.4.4 Upgrade failed rev 4 deployed image 1.4.3 Rollback to 2 copied from rev 2 the cluster runs rev 1: image 1.4.2 the cluster runs rev 2: image 1.4.3 rev 2 stays deployed; objects rev 3 changed before failing stay changed the cluster runs rev 4, rev 2's manifests: image 1.4.3 each revision is a Secret sh.helm.release.v1.api.vN; 10 are kept by default

1/4

helm install creates revision 1, status deployed: Install complete.

Rollback and uninstall

CommandDoes
helm rollback apito the revision before the latest one (current minus 1, even if that one failed)
helm rollback api 7to revision 7, recorded as a new revision "Rollback to 7"
--wait, --wait-for-jobs, --timeout 10mwait for readiness, as on upgrade
--cleanup-on-faildelete objects the failed rollback created
--force-replaceHelm 3 --force
--server-side, --force-conflictsapply method, as on upgrade
--no-hooksskip pre-rollback, post-rollback
--dry-run=clientsimulate
helm uninstall api -n webdelete the release's objects and its history
helm uninstall api web workerseveral releases
--keep-historykeep the records (status uninstalled); helm rollback api N brings it back
--waitreturn only when the objects are gone
--cascade=foreground, orphandeletion propagation; default background
--no-hooksskip pre-delete, post-delete
--ignore-not-foundno error for a missing release
--dry-runsimulate the uninstall

uninstall leaves behind objects annotated helm.sh/resource-policy: keep, hook objects without a delete policy, PVCs created from StatefulSet volumeClaimTemplates, and CRDs from the chart's crds/ directory (Helm never deletes those).

Rendering, linting and tests

helm templateDoes
helm template api ./api -f values/prod.yamlrender to stdout; no cluster needed
-n websets .Release.Namespace
-s templates/deployment.yamlonly that template (--show-only, repeatable)
--output-dir out/one file per template; --release-name adds the release to the path
--include-crds, --skip-testsinclude crds/; leave out test hooks
--is-upgraderender as an upgrade (.Release.IsUpgrade)
--kube-version 1.37.0.Capabilities.KubeVersion
-a gateway.networking.k8s.io/v1add to .Capabilities.APIVersions (--api-versions, repeatable)
--dry-run=serveruse the cluster: real capabilities and working lookup
--debugon a YAML error, print the broken output
chart + values templates/ values.yaml -f and --set render Go templates with values manifests Deployment, Service, … API server applies the objects release one Secret per revision how far each command goes helm template, --dry-run=client no cluster --dry-run=server lookup reads the cluster helm install, helm upgrade: apply, then store revision N helm get, history and rollback read the release record
Helm renders on your machine. The cluster only sees the finished manifests, and the release record keeps a copy of each revision.
CommandDoes
helm lint ./apichart structure, templates, schema, values
helm lint ./api --strict -f values/prod.yamlwarnings fail; lint with real values
helm lint ./api --with-subcharts --kube-version 1.37.0include dependencies; check deprecations for a version
helm lint ./api --quietwarnings and errors only
helm test api -n webrun the chart's helm.sh/hook: test Pods
helm test api --logsprint their logs
helm test api --filter name=api-test-dbsome tests; !name=x excludes

Chart authoring

CommandDoes
helm create apiscaffold a chart
helm create api -p web-starterfrom a starter in $HELM_DATA_HOME/starters, or an absolute path (--starter)
helm dependency list ./apieach dependency and its state: ok, missing, wrong version, unpacked
helm dependency update ./apiresolve version ranges, download into charts/, write Chart.lock
helm dependency build ./apirebuild charts/ exactly from Chart.lock (CI)
helm dependency update ./api --skip-refreshdon't refresh repository indexes first
helm package ./apibuild api-<version>.tgz
helm package ./api --version 1.2.0 --app-version 1.4.2 -d dist/override versions, choose the output directory
helm package ./api -urun dependency update first
helm pull grafana/loki --version 6.40.0download the .tgz
helm pull grafana/loki --untar --untardir vendor/download and unpack
helm pull oci://ghcr.io/acme/charts/api --version 1.2.0from a registry
helm registry login ghcr.io -u acme --password-stdinstore registry credentials
helm registry logout ghcr.ioremove them
helm push api-1.2.0.tgz oci://ghcr.io/acme/chartspublish as ghcr.io/acme/charts/api:1.2.0; prints the digest
helm push … --plain-httpa registry without TLS, such as a local test registry
# release a chart to an OCI registry
helm lint ./api --strict
helm dependency build ./api
helm package ./api --version 1.2.0 --app-version 1.4.2
echo "$GHCR_TOKEN" | helm registry login ghcr.io \
  -u "$GH_USER" --password-stdin
helm push api-1.2.0.tgz oci://ghcr.io/acme/charts

Signing and verification

A provenance file (api-1.2.0.tgz.prov) holds the chart's Chart.yaml, its SHA-256 and a PGP signature. Helm reads only the legacy GnuPG keyring format, so export keys first.

gpg --export-secret-keys > ~/.gnupg/secring.gpg
gpg --export > ~/.gnupg/pubring.gpg
helm package ./api --sign --key 'Acme Charts' \
  --keyring ~/.gnupg/secring.gpg
helm verify api-1.2.0.tgz --keyring ~/.gnupg/pubring.gpg
helm install api ./api-1.2.0.tgz --verify \
  --keyring ~/.gnupg/pubring.gpg
CommandDoes
helm package --sign --key NAMEwrite the .prov next to the .tgz; --passphrase-file for CI
helm verify CHART.tgzcheck signature and hash
helm pull … --provalso download the .prov
helm pull … --verify, helm install … --verifyrefuse an unsigned or tampered chart
helm dependency update --verifyverify dependencies too

Charts in OCI registries are often signed with Sigstore cosign instead, as any OCI artifact.

Plugins

CommandDoes
helm plugin listinstalled plugins with type and signature status; --type cli/v1 (or getter/v1, postrenderer/v1) filters
helm plugin install URL.tgzinstall from a tarball; its .prov signature is checked by default
helm plugin install ./my-plugina local directory, no signature needed
helm plugin install https://github.com/org/repo --verify=falsea Git source, which can't be verified
helm plugin install … --version 3.9.0a version constraint
helm plugin update diffupdate
helm plugin uninstall diffremove
helm plugin verify ./plugin.tgzcheck a plugin archive's signature
helm plugin package ./my-pluginbuild a signed plugin archive (authors)
PluginUse it forExample
helm-diffpreview what an upgrade, rollback or revision change doeshelm diff upgrade api ./api -f values/prod.yaml
helm-secretsSOPS-encrypted values fileshelm upgrade api ./api -f secrets://values/secrets.yaml
helm-unittestunit tests for templates in tests/*_test.yamlhelm unittest ./api
helm-mapkubeapisrewrite removed API versions inside release records so upgrades work againhelm mapkubeapis api -n web

The Helm sheet shows a full helm-diff install with its signing key.

Quick lookup

I want to…Command
find a charthelm search hub loki or helm search repo loki
see a chart's default valueshelm show values grafana/loki > loki-defaults.yaml
list chart versionshelm search repo grafana/loki --versions
install or upgradehelm upgrade --install api ./api -n web --create-namespace -f values/prod.yaml
pin a chart versionadd --version 1.2.0
roll back automatically on failureadd --rollback-on-failure --timeout 10m (Helm 3: --atomic)
wait until everything is readyadd --wait
preview without applyinghelm upgrade api ./api --dry-run=server --hide-secret or helm diff upgrade …
render YAML locallyhelm template api ./api -f values/prod.yaml
render one filehelm template api ./api -s templates/service.yaml
list releases everywherehelm list -A
find failed or stuck releaseshelm list -A --failed --pending
see what is deployedhelm get manifest api
see the values in usehelm get values api (-a for all)
see revision historyhelm history api
roll backhelm rollback api 7
uninstall but keep historyhelm uninstall api --keep-history
adopt existing objectshelm upgrade --install api ./api --take-ownership
change one value, keep the resthelm upgrade api ./api --reuse-values --set replicaCount=4
upgrade the chart, keep my overrideshelm upgrade loki grafana/loki --reset-then-reuse-values
package a charthelm package ./api
push to a registryhelm push api-1.2.0.tgz oci://ghcr.io/acme/charts
install from a registryhelm install api oci://ghcr.io/acme/charts/api --version 1.2.0
vendor a charthelm pull grafana/loki --version 6.40.0 --untar
refresh dependencieshelm dependency update ./api
check a charthelm lint ./api --strict
run chart testshelm test api --logs
find where Helm keeps fileshelm env
store releases in ConfigMapsHELM_DRIVER=configmap helm …
see release records directlykubectl get secret -n web -l owner=helm,name=api

References