Helm — Structure#

Layout pattern#

Standard Go Layout (cmd/internal/pkg) — Helm follows the canonical Go project layout with a single binary entry point under cmd/helm/, shared public API under pkg/, and implementation details under internal/. The distinction between pkg/ and internal/ is used meaningfully: pkg/ contains the library API that external callers or tools could import (action, chart, kube, storage, etc.), while internal/ holds utilities and sub-systems that are not part of the public surface.

A notable twist is the presence of versioned sub-packages (pkg/chart/v2/, pkg/release/v1/, internal/release/v2/, internal/chart/v3/) indicating active API evolution toward Helm v4, where older format versions are carried alongside the current ones for compatibility.

Directory map#

helm/
├── cmd/
│   └── helm/               # Single binary entry point (main package)
│       ├── helm.go         # main() — delegates to pkg/cmd
│       └── helm_test.go
├── internal/               # Private implementation packages
│   ├── chart/
│   │   └── v3/             # Internal chart v3 utilities (lint/rules, util)
│   ├── cli/
│   │   └── output/         # Output formatting helpers
│   ├── copystructure/      # Deep-copy utility (vendored from mitchellh)
│   ├── fileutil/           # File system helpers
│   ├── gates/              # Feature gate internals
│   ├── logging/            # Structured logging setup (log/slog)
│   ├── monocular/          # Helm Hub / Monocular search client
│   ├── plugin/
│   │   ├── cache/          # Plugin download cache
│   │   ├── installer/      # Plugin install/uninstall logic
│   │   └── schema/         # Plugin manifest schema
│   ├── release/
│   │   └── v2/             # Internal release type v2 (in-progress migration)
│   ├── resolver/           # Chart dependency resolver
│   ├── statusreaders/      # Custom Kubernetes status readers
│   ├── sympath/            # Symlink-safe path walking
│   ├── test/
│   │   └── ensure/         # Test helper utilities
│   ├── third_party/        # Inlined third-party code (dep, k8s.io fragments)
│   ├── tlsutil/            # TLS configuration helpers
│   ├── urlutil/            # URL manipulation helpers
│   └── version/            # Version info (populated via ldflags)
├── pkg/                    # Public library packages
│   ├── action/             # Core Helm actions (install, upgrade, rollback, …)
│   ├── chart/
│   │   ├── common/         # Shared chart utilities (util, testdata)
│   │   ├── loader/
│   │   │   └── archive/    # Chart loader (dir, archive, stream)
│   │   └── v2/             # Chart format v2 (lint/rules, util)
│   ├── cli/
│   │   ├── output/         # Output table/JSON/YAML formatting
│   │   └── values/         # --set / --values flag parsing
│   ├── cmd/                # Cobra command definitions (one file per subcommand)
│   │   ├── require/        # Argument validation helpers
│   │   └── search/         # Hub/repo search logic
│   ├── downloader/         # Chart dependency downloader
│   ├── engine/             # Go template rendering engine (sprig)
│   ├── gates/              # Public feature gate API
│   ├── getter/             # Chart repository HTTP/OCI/file getters
│   ├── helmpath/
│   │   └── xdg/            # XDG base directory spec for Helm data paths
│   ├── ignore/             # .helmignore parser
│   ├── kube/
│   │   └── fake/           # Fake Kubernetes client for testing
│   ├── postrenderer/       # Post-render hook interface + exec implementation
│   ├── provenance/         # PGP chart provenance / signing
│   ├── pusher/             # Chart pusher interface (OCI)
│   ├── registry/           # OCI registry client (push, pull, login)
│   ├── release/
│   │   ├── common/         # Shared release constants
│   │   ├── v1/             # Release format v1 (Helm v3 compatible)
│   │   └── (root)          # Current release types + interfaces
│   ├── repo/
│   │   └── v1/             # Repository index format v1
│   ├── storage/
│   │   └── driver/         # Release backends: secrets, configmaps, memory, SQL
│   ├── strvals/            # --set value parser (key=value, JSON, file refs)
│   └── uploader/           # Chart uploader interface
├── scripts/                # Shell scripts: install helpers, release notes
└── testdata/               # Top-level golden/fixture files

Entry points#

FileBinaryPurpose
cmd/helm/helm.gohelmSingle CLI entry point. Sets kube.ManagedFieldsManager = "helm", calls pkg/cmd.NewRootCmd, then executes. All command logic lives in pkg/cmd/.

There is exactly one binary. Helm is a pure CLI tool; no daemon, no server process.

Package organization#

Internal packages (internal/)#

PackagePurpose
internal/chart/v3/V3 chart lint rules and chart utilities not exposed publicly
internal/cli/output/Terminal output formatting (tables, etc.)
internal/copystructure/Inlined deep-copy implementation
internal/fileutil/File system path helpers
internal/gates/Feature flag implementation details
internal/logging/log/slog setup and handler initialization
internal/monocular/Client for the Monocular chart search API (Helm Hub)
internal/plugin/Plugin lifecycle: discovery, caching, installation, schema validation
internal/release/v2/Experimental next-generation release record schema
internal/resolver/Chart dependency resolution algorithm
internal/statusreaders/Custom Kubernetes object status readers (for wait/rollout status)
internal/sympath/Symlink-aware filepath walking
internal/test/ensure/Test setup helpers (tempdir creation, etc.)
internal/third_party/Vendored-inline code from dep and k8s.io
internal/tlsutil/TLS config construction from cert/key paths
internal/urlutil/URL path joining and normalization
internal/version/Build-time version string (set via -ldflags)

Public packages (pkg/)#

PackagePurpose
pkg/action/Heaviest package. One type per Helm action (Install, Upgrade, Rollback, Uninstall, List, Status, …). These are the core programmatic API for embedding Helm.
pkg/chart/Chart type definitions, loader (dir + tgz archive), v2 lint rules, utilities
pkg/cli/EnvSettings (from env vars + flags), output formatting, --values/--set handling
pkg/cmd/Cobra command tree for the helm CLI; one file per top-level command or subcommand group
pkg/downloader/Downloads chart dependencies declared in Chart.yaml
pkg/engine/Go text/template + sprig rendering engine for Kubernetes manifests
pkg/gates/Public feature gate definitions and checks
pkg/getter/Pluggable chart source backends (HTTP, OCI, local file)
pkg/helmpath/XDG-compliant path resolution for Helm’s data/config/cache dirs
pkg/ignore/.helmignore file parser (gitignore semantics)
pkg/kube/Kubernetes client abstraction used by actions; fake/ package for tests
pkg/postrenderer/Interface + exec-based implementation for post-render hooks
pkg/provenance/PGP signing and verification of chart packages
pkg/pusher/Interface for chart upload backends
pkg/registry/OCI registry client (ORAS-based) for push/pull/login/logout
pkg/release/Release record types (status, manifest, hooks, metadata), v1 compat format
pkg/repo/Chart repository index (index.yaml) parsing and management
pkg/storage/Release storage abstraction; driver/ has: secrets, configmaps, memory, SQL backends
pkg/strvals/Parses --set value syntax into Go maps
pkg/uploader/Interface for chart upload (symmetric to pusher)

Layering#

The architecture follows a clean layered pattern:

cmd/helm (main) → pkg/cmd (Cobra commands) → pkg/action (business logic)
                                                    ↓
                              pkg/engine   pkg/kube   pkg/storage   pkg/chart
                                    ↓           ↓           ↓
                              internal/*  (utilities, helpers, versioned internals)

pkg/cmd owns CLI concerns only; it delegates all logic to pkg/action. pkg/action is the programmatic API — it knows about chart loading, Kubernetes operations, and release storage, but does not import pkg/cmd. This separation means Helm can be embedded as a library via pkg/action alone.

Build system#

  • Build tool: GNU Make (Makefile at repo root), delegating to go build
  • Cross-compilation: Uses gox for multi-platform cross-compilation (12+ OS/arch combos)
  • Key targets:
    • make build — builds bin/helm from ./cmd/helm; also runs go mod tidy
    • make install — copies binary to /usr/local/bin
    • make test — unit tests with race detector; also runs style checks
    • make test-acceptance — robot-framework acceptance tests against a live cluster
    • make build-cross — static cross-compiled binaries for all targets
    • make dist — packages cross-compiled binaries into tarballs/zips for release
    • make format — runs goimports
  • Version injection: Build metadata (version, git commit, tree state) injected via -ldflags into internal/version package
  • Docker: No Dockerfile in the repository. Helm is distributed as a static binary, not as a container image.

Notable structural decisions#

  1. pkg/action as the embeddable API: The most architecturally intentional choice is the clean separation of pkg/cmd (CLI) from pkg/action (logic). Tools like Flux, Argo CD, and others embed Helm by importing pkg/action directly. This is a deliberate public API contract, as noted in the package doc: “This is a library for calling top-level Helm actions.”

  2. Versioned sub-packages for schema evolution: The presence of pkg/chart/v2/, pkg/release/v1/, internal/release/v2/, internal/chart/v3/ reveals an active effort to carry multiple format versions simultaneously. This allows Helm v4 to read/write older formats while introducing new schemas — a pattern common in protocol-heavy tools.

  3. Storage driver abstraction: pkg/storage/driver/ contains four backends — Kubernetes Secrets, ConfigMaps, in-memory, and SQL (PostgreSQL). The SQL backend is a v4 addition. This is a clean strategy pattern: actions use a storage.Storage wrapper that is backend-agnostic.

  4. Plugin system inlined in internal/plugin/: Plugin management (discovery, schema, caching, installation via git/OCI/tar) is entirely internal. The WASM plugin runtime (noted in overview) is wired in via dependencies but the entrypoint is through this internal package.

  5. cmd/helm/ is minimal by design: The main package is only ~50 lines. It sets one global variable, constructs the root command, and runs it. All complexity is delegated into pkg/cmd and pkg/action, keeping the entry point trivially testable and swappable.