Argo CD — Structure#

Layout pattern#

Custom domain-service layout (not standard Go layout)

Argo CD does not use the conventional cmd/internal/pkg layering. Instead, each top-level directory corresponds to a deployable service component or a distinct domain concern. The services (server/, controller/, reposerver/, etc.) are peers at the root, and a very large util/ tree acts as the cross-cutting library. There is no internal/ directory — code visibility boundaries are managed by convention rather than Go’s package access rules. The gitops-engine/ sub-directory is a vendored-in module (the core sync/diff engine), making this functionally a light monorepo.

Directory map#

argo-cd/
├── cmd/                        # Single main.go dispatching to all sub-commands
├── server/                     # API server (gRPC + HTTP gateway) — 20 sub-packages
├── controller/                 # Application controller (reconciliation loop)
├── reposerver/                 # Repository server (renders manifests from Git/Helm/Kustomize)
├── cmpserver/                  # Config Management Plugin server (plugin sandbox)
├── commitserver/               # Commit server (hydrator write-back to Git)
├── applicationset/             # ApplicationSet controller (app-of-apps generator)
├── notification_controller/    # Notification controller
├── pkg/                        # Public Go packages (CRD types, generated clients, API client)
│   ├── apis/                   # CRD Go types (Application, AppProject, ApplicationSet)
│   ├── apiclient/              # gRPC client factories for each server service
│   ├── client/                 # Generated Kubernetes clientsets and informers
│   └── ratelimiter/            # Shared rate-limiter
├── util/                       # Cross-cutting utility library (50+ sub-packages)
├── gitops-engine/              # Vendored sub-module: core sync, diff, cache, health
│   ├── pkg/cache/              # Kubernetes resource cache
│   ├── pkg/diff/               # Three-way diff engine
│   ├── pkg/engine/             # GitOps reconciliation engine
│   ├── pkg/health/             # Resource health assessment
│   └── pkg/sync/               # Sync wave, hook, and apply logic
├── common/                     # Shared constants (binary names, label keys, env vars)
├── resource_customizations/    # YAML health/status overrides for 100+ third-party CRDs
├── manifests/                  # Kubernetes install manifests (Kustomize-based)
│   ├── base/                   # Core component definitions
│   ├── cluster-install/        # Cluster-scoped installation variant
│   ├── namespace-install/      # Namespace-scoped installation variant
│   ├── ha/                     # High-availability overlays
│   └── crds/                   # CRD YAML definitions
├── test/                       # E2E test infrastructure
│   ├── e2e/                    # E2E test suites
│   └── fixture/                # Test helpers and fixtures
├── ui/                         # React/TypeScript web UI (not Go)
├── docs/                       # MkDocs documentation
├── hack/                       # Code generation and CI tooling scripts
└── examples/                   # RBAC, known-hosts, plugin examples

Entry points#

All binaries compile from a single cmd/main.go that dispatches on the binary name (or ARGOCD_BINARY_NAME environment variable). This is a multi-binary-from-one-binary pattern — the same binary image serves multiple roles at runtime:

Binary nameRole
argocdCLI client (user-facing)
argocd-serverAPI server (gRPC + HTTP/REST gateway)
argocd-application-controllerApplication reconciliation controller
argocd-repo-serverManifest rendering server
argocd-cmp-serverConfig Management Plugin server (runs in sidecar)
argocd-commit-serverCommit / hydrator write-back server
argocd-applicationset-controllerApplicationSet controller
argocd-notificationNotification controller
argocd-dexEmbedded Dex OIDC provider wrapper
argocd-git-ask-passGit credential helper subprocess
argocd-k8s-authKubernetes token auth helper

Each sub-command lives in cmd/<binary-name>/commands/ and exposes a NewCommand() *cobra.Command.

Package organization#

  • Internal packages (no internal/ directory): The codebase does not use Go’s internal/ mechanism. The closest equivalents are packages like controller/cache, server/rbacpolicy, and reposerver/cache which are tightly coupled to their parent service but not formally restricted.

  • Public packages (pkg/):

    • pkg/apis/application/v1alpha1 — CRD types (Application, AppProject, ApplicationSet, ApplicationSetGenerator, etc.), the canonical data model
    • pkg/apiclient/ — gRPC client factories for all server services (application, cluster, project, repository, session, etc.)
    • pkg/client/ — Generated Kubernetes clientsets, listers, and informers for Argo CD CRDs
    • pkg/ratelimiter/ — Shared Kubernetes work-queue rate limiter
  • Service packages (top-level service directories):

    • server/ — 20 sub-packages, one per API domain (application, project, cluster, repository, session, settings, certificate, gpgkey, notification, etc.)
    • controller/ — Reconciliation loop, sharding, cache, hydrator, metrics
    • reposerver/repository/ — Core manifest rendering (Git, Helm, Kustomize, CMP)
    • applicationset/ — Generators (Git, List, Cluster, Matrix, Merge, SCM, PullRequest, Plugin), controllers, services, webhook
  • util/ — Deep utility library (50+ sub-packages): Covers: db (Kubernetes Secret/ConfigMap as storage), settings (operator configuration), git (libgit2/go-git wrapper), helm, kustomize, lua (health Lua scripts), rbac (Casbin wrapper), session (JWT), oidc, grpc, kube, cache, crypto, exec, tls, io, http, webhook, notification, oci, and more.

  • gitops-engine/ — Embedded sub-module: Previously an independent module (github.com/argoproj/gitops-engine), now vendored directly into the repo as a sub-directory. Contains the diff engine, Kubernetes cache, health assessment, and sync primitives that Argo CD (and potentially other tools) depend on.

  • Layering: Loose, domain-service layering. Services depend on util/ and pkg/ but also directly on each other’s apiclient/ packages. There is no strict clean architecture or hexagonal enforcement — the codebase follows organic growth patterns typical of a large CNCF project.

Build system#

  • Build tool: GNU Make (primary), with Docker for container builds
  • Key targets:
    • make build — Compiles all binaries (via Docker build environment)
    • make cli — Builds argocd CLI locally
    • make image — Builds the multi-stage Docker image (Dockerfile)
    • make test — Unit tests (in Docker)
    • make lint — Linting (golangci-lint, in Docker)
    • make codegen — Regenerates protobuf, OpenAPI, CRD specs, and clientsets
    • make e2e — End-to-end tests requiring a running cluster
  • Docker: Yes — multi-stage (Dockerfile). Stage 1: Golang 1.26 builder image (installs Helm, Kustomize, kubectl, etc. and compiles all binaries). Stage 2: Ubuntu 25.10 runtime image. The final image contains all binaries; the active binary is selected at runtime by symlink or ARGOCD_BINARY_NAME.
  • Additional Dockerfiles: Dockerfile.dev and Dockerfile.tilt for local development via Tilt.

Notable structural decisions#

  1. Single binary, multiple personalities: Rather than building separate binaries per service, Argo CD builds one binary and selects the operating mode by binary name or environment variable. This simplifies image distribution (one image tag, many roles) but means all service code is compiled into every deployment even if not used.

  2. Embedded gitops-engine/: The sync and diff engine was originally a separate public module (github.com/argoproj/gitops-engine). It has been migrated back into the monorepo as a sub-directory. This avoids cross-repo versioning friction but gives up the shared-infrastructure benefit with other CNCF tools.

  3. resource_customizations/ as data, not code: Health assessment and status logic for 100+ third-party Kubernetes resources (Cert-Manager, Kafka, Istio, Karpenter, etc.) is expressed as Lua scripts and YAML files under resource_customizations/. This data-driven approach allows the community to contribute new CRD support without modifying Go code.

  4. util/db is a Kubernetes-native database: Rather than using an external database, Argo CD stores configuration (clusters, repositories, credentials, GPG keys) in Kubernetes Secrets and ConfigMaps via util/db. This makes Argo CD self-contained within a cluster and RBAC-compatible but couples the operational model tightly to Kubernetes.

  5. No internal/ enforcement: With 50+ util/ sub-packages all publicly accessible, the codebase relies on team convention rather than Go visibility for layering discipline. This is typical for CNCF projects of this age and size but means architectural drift is harder to detect mechanically.