skip to content

What does a Helm plugin's plugin.yaml declare, and how do you install one?

level: juniorimportance: should knowfreq 45%

answer

  1. A directory with a descriptor file
  2. Two fields carry the design
  3. Which extension point, and how it runs
  4. apiVersion v1, type, runtime
  5. helm plugin install, list, uninstall

basics

~20 s

plugin.yaml is a Helm plugin's descriptor: apiVersion v1, a name and version, a required type naming the extension point (such as cli/v1), and a runtime, either subprocess or extism/v1. You add one with helm plugin install.

solid answer

~50 s

A Helm plugin extends the `helm` CLI itself; it is not part of any chart and it does not change how templates render. It is a directory holding a `plugin.yaml` plus whatever the plugin needs to run. In Helm 4 that file declares `apiVersion: v1`, the plugin `name` (for a CLI plugin, the word that becomes `helm <name>`), a `version`, help text, a required `type` naming the extension point — `cli/v1` for a new subcommand, `getter/v1` for a downloader, `postrenderer/v1` for a post-render step — and a `runtime`, either `subprocess` (Helm runs a native executable) or `extism/v1` (Helm runs a WebAssembly module), together with that runtime's configuration. You install with `helm plugin install <source>`, and manage with `helm plugin list`, `helm plugin update` and `helm plugin uninstall`. Installed plugins live under the directory `helm env` reports as `HELM_PLUGINS`.

code

yaml · 5 lines
yaml
apiVersion: v1
name: values-lint
version: 0.4.2
type: cli/v1
runtime: subprocess

go deeper

for a junior

Be ready to say what a Helm plugin is in one sentence, name the descriptor file, and run helm plugin install and helm plugin list without hesitating. Knowing that a plugin extends the CLI and is not part of a chart is the whole floor here.

for a middle

An interviewer expects you to explain the fields: apiVersion v1, the required type naming the extension point, and the runtime saying how Helm executes it. Be able to say where installed plugins live and how a CLI plugin becomes a helm subcommand.

for a senior

Show that you treat plugin installs as environment state you control: pinned versions baked into CI images, an explicit install step, and awareness that a subprocess plugin inherits your kubeconfig and cloud credentials.

for a principal

Own the policy question. Decide which plugins are sanctioned across the org, how they reach every engineer and runner consistently, and when to set HELM_NO_PLUGINS in hardened images so automation only ever runs stock Helm.

### What a plugin is, and what it is not A Helm plugin extends the `helm` command line. It is not a chart, it is not shipped inside a chart, and it cannot change how a chart renders — charts are rendered only by Go text/template inside Helm, and no plugin gets to touch that. A plugin is per-user, machine-local state: it is installed into your Helm data directory, so a chart can never require one. If a workflow depends on a plugin, everyone who runs that workflow — and every CI image — has to install it independently. Physically, a plugin is a directory containing a `plugin.yaml` metadata file plus whatever the plugin needs to execute: a compiled binary, a shell script, or a WebAssembly module. Helm discovers plugins by scanning the plugin directory, which `helm env` prints as `HELM_PLUGINS`. ### The fields in plugin.yaml In Helm 4 the descriptor opens with `apiVersion: v1`. Beyond the obvious identity fields — `name`, `version`, and the description and usage strings that `helm plugin list` and the plugin's own help output show — two fields carry the design: - **`type`** says which extension point the plugin plugs into, and it is required. `cli/v1` adds a new top-level subcommand, so a plugin named `diff` is invoked as `helm diff`. `getter/v1` supplies a downloader for URL schemes Helm does not natively speak. `postrenderer/v1` supplies a post-render step that the `--post-renderer` flag can name. Helm needs the type to know where in its own machinery the plugin belongs; it is not decoration. - **`runtime`** says how Helm executes the plugin. `subprocess` means Helm launches a native executable or script as a child process. `extism/v1` means the plugin ships as a WebAssembly module that Helm runs inside an embedded WASM runtime. The runtime's own configuration — for a subprocess plugin, the command Helm should execute — sits alongside the runtime declaration in the same file. That pairing of `type` and `runtime` is what makes the Helm 4 plugin format a real interface rather than the looser Helm 3 arrangement, where a plugin simply declared a command to run and, if it was a downloader, a separate block listing the protocols it served. There was no runtime choice in Helm 3 and no WebAssembly option at all. ### Installing and managing `helm plugin install <source>` is the entry point. The source can be a version-control URL, a local directory path, or a packaged plugin archive; Helm fetches it, verifies it, and places it in the plugin directory. In Helm 4 that verification step is on by default, which is a change from Helm 3 and the single most common surprise when an existing install script stops working. The rest of the family is small and predictable: `helm plugin list` shows the name, version and description of everything installed; `helm plugin update <name>` refreshes one; `helm plugin uninstall <name>` removes it. Helm 4 also adds `helm plugin package` for producing a distributable plugin archive and `helm plugin verify` for checking one. ### What running a plugin looks like When you type `helm mycmd --flag value` and `mycmd` is an installed `cli/v1` subprocess plugin, Helm hands the remaining arguments to the plugin's command and runs it with Helm's environment attached: `HELM_NAMESPACE` reflecting `-n` or the configured namespace, `HELM_BIN` pointing at the helm binary itself so the plugin can call back into Helm, `HELM_PLUGIN_DIR` for the plugin's own directory, `HELM_PLUGIN_NAME` for its name, and `HELM_PLUGINS` for the plugin root. The plugin's exit code becomes helm's exit code, so a failing plugin fails a pipeline step the way any other command does. That last point is the one worth internalising: a subprocess plugin is an ordinary process on your machine. It inherits your shell environment, your kubeconfig and any cloud credentials sitting there. It is code you chose to trust, running with everything you have. Setting `HELM_NO_PLUGINS=1` tells Helm to load no plugins at all, which is a reasonable default for a hardened automation image that should only ever run stock Helm. ### Practical habits Pin plugin versions in CI images the way you pin anything else, and install plugins as an explicit build step rather than at deploy time, so a network hiccup at a downloader does not break a release. Give plugins distinct names that do not collide with Helm's own subcommands. And keep the mental line clear between a plugin, which changes what your CLI can do, and a chart dependency, which changes what a release contains — they solve different problems and are managed by completely different commands.

  • Can a chart declare that it needs a particular Helm plugin installed?
    No. Plugins are installed per user into the local Helm plugin directory; nothing in Chart.yaml or the chart archive can pull one in or require one. If your deploy workflow depends on a plugin, the install has to be part of the environment — baked into the CI image or run as an explicit pipeline step — and documented for anyone deploying by hand. This is a real constraint on chart design: never make a chart usable only through a plugin your consumers would have to discover for themselves.
  • Which environment variables does Helm set for a subprocess plugin, and why does it matter?
    Helm passes its own resolved context down, including HELM_BIN (the path to helm itself, so the plugin can call back), HELM_PLUGIN_DIR and HELM_PLUGIN_NAME for the plugin's own location and name, HELM_PLUGINS for the plugin root, and HELM_NAMESPACE for the effective namespace. It matters because the plugin also inherits everything else in your environment — kubeconfig and cloud credentials included — so installing a plugin is a trust decision, not a convenience.
  • How do you run Helm with no plugins loaded at all?
    Set HELM_NO_PLUGINS=1. Helm then skips plugin discovery entirely, so no plugin subcommand or downloader is available for that invocation. It is a sensible default in a locked-down automation image where only stock Helm behaviour should ever run, and it is also a fast way to prove that a strange CLI behaviour is coming from a plugin rather than from Helm.

A chart is cargo the truck carries; a plugin is a bolt-on attachment for the truck itself. Loading different cargo never changes the vehicle, and fitting an attachment never changes what is in the trailer.

saying these in an interview costs you the question

  • Says a plugin is packaged inside a chart
  • Thinks plugins change how templates render
  • Claims a chart can declare a required plugin
  • Cannot name the type or runtime field
  • Confuses helm plugin install with helm dependency update
  • Assumes plugins are shared cluster-side, not local

context