CRD-Generated Classes
The k8s lexicon generates typed classes from the core Kubernetes OpenAPI spec plus a curated list of third-party CRDs. Each CRD in the list becomes a first-class K8s::* resource — with the serializer, LSP hover, type-checking, and MCP — the same as a built-in Deployment. No hand-written YAML, no as any.
How it works
Section titled “How it works”CRD sources live in lexicons/k8s/src/crd/crd-sources.ts. At generation time (npm run generate) the CRD YAML is fetched from a pinned upstream URL, parsed, and baked into the lexicon output. The group’s first segment maps to a TypeScript namespace via the first-segment rule in crd/parser.ts — e.g. gateway.networking.k8s.io → Gateway, cert-manager.io → CertManager.
group namespace example class───────────────────────────── ─────────────── ─────────────────────────ray.io Ray K8s::Ray::RayClusterargoproj.io Argo K8s::Argo::Applicationgateway.networking.k8s.io Gateway K8s::Gateway::HTTPRoutecrdb.cockroachlabs.com Crdb K8s::Crdb::CrdbClustercert-manager.io CertManager K8s::CertManager::Certificateacme.cert-manager.io Acme K8s::Acme::Challenge*.toolkit.fluxcd.io Flux K8s::Flux::Kustomizationfluxcd.controlplane.io Flux K8s::Flux::FluxInstanceThe Flux rows show the override at work: six distinct groups all map to one Flux namespace (see Flux), rather than each group’s first segment.
Gateway API
Section titled “Gateway API”gateway.networking.k8s.io, pinned to v1.2.1 (standard channel). The modern, portable replacement for Ingress — GRPCRoute in particular is the native way to express a gRPC route, instead of ingress-controller annotations.
| Type | apiVersion / kind |
|---|---|
GatewayClass | gateway.networking.k8s.io/v1 / GatewayClass |
Gateway | gateway.networking.k8s.io/v1 / Gateway |
HTTPRoute | gateway.networking.k8s.io/v1 / HTTPRoute |
GRPCRoute | gateway.networking.k8s.io/v1 / GRPCRoute |
ReferenceGrant | gateway.networking.k8s.io/v1beta1 / ReferenceGrant |
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yamlimport { Gateway, HTTPRoute } from "@intentius/chant-lexicon-k8s";
export const gw = new Gateway({ metadata: { name: "edge", namespace: "infra" }, spec: { gatewayClassName: "istio", listeners: [{ name: "http", protocol: "HTTP", port: 80 }], },});
export const route = new HTTPRoute({ metadata: { name: "api", namespace: "infra" }, spec: { parentRefs: [{ name: "edge" }], rules: [{ backendRefs: [{ name: "api", port: 8080 }] }], },});cert-manager
Section titled “cert-manager”cert-manager.io + acme.cert-manager.io, pinned to v1.16.2. The de-facto controller for issuing and rotating TLS certificates. The bundle is a single multi-doc YAML.
| Type | apiVersion |
|---|---|
Certificate | cert-manager.io/v1 |
CertificateRequest | cert-manager.io/v1 |
Issuer | cert-manager.io/v1 |
ClusterIssuer | cert-manager.io/v1 |
Challenge | acme.cert-manager.io/v1 |
Order | acme.cert-manager.io/v1 |
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.2/cert-manager.yamlimport { ClusterIssuer, Certificate } from "@intentius/chant-lexicon-k8s";
export const issuer = new ClusterIssuer({ metadata: { name: "letsencrypt-prod" }, spec: { acme: { server: "https://acme-v02.api.letsencrypt.org/directory", email: "ops@acme.io", privateKeySecretRef: { name: "letsencrypt-prod" }, solvers: [{ http01: { ingress: { class: "nginx" } } }], }, },});
export const cert = new Certificate({ metadata: { name: "api-tls", namespace: "api" }, spec: { secretName: "api-tls", issuerRef: { name: "letsencrypt-prod", kind: "ClusterIssuer" }, dnsNames: ["api.acme.io"], },});SecureIngress emits a real Certificate
Section titled “SecureIngress emits a real Certificate”When you set clusterIssuer on the SecureIngress composite, it now emits a genuine K8s::CertManager::Certificate (wired to the named issuer) alongside the ingress-shim annotation — no placeholder.
import { SecureIngress } from "@intentius/chant-lexicon-k8s";
export const ingress = SecureIngress("api", { host: "api.acme.io", serviceName: "api", servicePort: 8080, clusterIssuer: "letsencrypt-prod", // → annotation + a real Certificate});CockroachDB operator
Section titled “CockroachDB operator”crdb.cockroachlabs.com, pinned to v2.17.0. The operator-managed path for a CockroachDB cluster — the operator handles version upgrades, scale-down decommissioning, and cert rotation.
| Type | apiVersion / kind |
|---|---|
CrdbCluster | crdb.cockroachlabs.com/v1alpha1 / CrdbCluster |
kubectl apply -f https://github.com/cockroachdb/cockroach-operator/releases/download/v2.17.0/install/operator.yamlimport { CrdbCluster } from "@intentius/chant-lexicon-k8s";
export const db = new CrdbCluster({ metadata: { name: "cockroachdb", namespace: "crdb" }, spec: { dataStore: { pvc: { spec: { resources: { requests: { storage: "60Gi" } } } } }, tlsEnabled: true, image: { name: "cockroachdb/cockroach:v24.1.0" }, nodes: 3, },});KubeRay & Argo CD
Section titled “KubeRay & Argo CD”The first two CRD sources. KubeRay (ray.io, v1.3.0) produces RayCluster, RayJob, and RayService. Argo CD (argoproj.io, v2.13.3) produces Application, ApplicationSet, and AppProject. Both ship value-add composites — see Argo CD Composites and the Ray + KubeRay on GKE tutorial.
The Flux GitOps Toolkit (pinned to flux2 v2.9.1) and the Flux Operator (v0.54.1). The toolkit spreads across five *.toolkit.fluxcd.io groups and the operator adds fluxcd.controlplane.io; all six collapse to a single Flux namespace, so a GitRepository and a Kustomization read as K8s::Flux::* siblings rather than scattering across Source, Kustomize, Helm, Notification, and Image.
Both sources are the release install.yaml — a multi-doc bundle of controllers, RBAC, and CRDs. The parser keeps only the CRD documents, and a kinds allowlist on each CRD_SOURCES entry narrows those to the supported set (the bundle also carries the experimental ExternalArtifact and ArtifactGenerator, left out for now).
| Type | apiVersion / kind |
|---|---|
GitRepository | source.toolkit.fluxcd.io/v1 |
OCIRepository | source.toolkit.fluxcd.io/v1 |
HelmRepository | source.toolkit.fluxcd.io/v1 |
HelmChart | source.toolkit.fluxcd.io/v1 |
Bucket | source.toolkit.fluxcd.io/v1 |
Kustomization | kustomize.toolkit.fluxcd.io/v1 |
HelmRelease | helm.toolkit.fluxcd.io/v2 |
Provider | notification.toolkit.fluxcd.io/v1beta3 |
Alert | notification.toolkit.fluxcd.io/v1beta3 |
Receiver | notification.toolkit.fluxcd.io/v1 |
ImagePolicy | image.toolkit.fluxcd.io/v1 |
ImageRepository | image.toolkit.fluxcd.io/v1 |
ImageUpdateAutomation | image.toolkit.fluxcd.io/v1 |
FluxInstance | fluxcd.controlplane.io/v1 |
FluxReport | fluxcd.controlplane.io/v1 |
ResourceSet | fluxcd.controlplane.io/v1 |
ResourceSetInputProvider | fluxcd.controlplane.io/v1 |
Install the toolkit and, optionally, the operator:
# GitOps Toolkit controllers (source, kustomize, helm, notification, image)kubectl apply -f https://github.com/fluxcd/flux2/releases/download/v2.9.1/install.yaml
# Flux Operator (manages a Flux instance declaratively)kubectl apply -f https://github.com/controlplaneio-fluxcd/flux-operator/releases/download/v0.54.1/install.yamlimport { GitRepository, Kustomization } from "@intentius/chant-lexicon-k8s";
export const podinfo = new GitRepository({ metadata: { name: "podinfo", namespace: "flux-system" }, spec: { interval: "1m", url: "https://github.com/stefanprodan/podinfo", ref: { branch: "master" }, },});
export const apps = new Kustomization({ metadata: { name: "apps", namespace: "flux-system" }, spec: { interval: "10m", path: "./kustomize", prune: true, sourceRef: { kind: "GitRepository", name: "podinfo" }, },});Read-only status
Section titled “Read-only status”Generated CRD classes expose a read-only status accessor alongside name, namespace, and uid. It carries the resource’s server-owned runtime state — never part of the writable constructor.
import { Certificate } from "@intentius/chant-lexicon-k8s";
const cert = new Certificate({ metadata: { name: "web-tls", namespace: "prod" }, spec: { secretName: "web-tls", issuerRef: { name: "letsencrypt" } },});
// Read-only — populated at apply time, typed from the CRD's status schema.cert.status; // Certificate_Status — notAfter, notBefore, renewalTime, revision, conditionsThe per-field status shape is generated from the CRD’s openAPIV3Schema the same way spec field typing is — surfaced through LSP hover, validation, and MCP. Scalar leaves (notAfter, revision, a RayCluster’s head.serviceIP) are typed; deeply nested or x-kubernetes-preserve-unknown-fields status degrades to an opaque record. CRDs without a status schema (config-only kinds like a Prometheus ServiceMonitor) get no status accessor.
Adding your own CRD
Section titled “Adding your own CRD”Append an entry to CRD_SOURCES in lexicons/k8s/src/crd/crd-sources.ts and re-run codegen:
export const CRD_SOURCES: CRDSource[] = [ // ...existing entries { type: "url", url: "https://raw.githubusercontent.com/acme/operator/v1.0.0/config/crd/bases/acme.io_widgets.yaml" },];cd lexicons/k8s && npm run generateGuidelines:
- Pin the version in the URL (a
vX.Y.Ztag or release asset), nevermain. Codegen is deterministic only if the source is. - One URL per CRD, or a single multi-doc bundle URL (the parser uses
loadAll, as with cert-manager). - The group’s first segment becomes the namespace. Add a
GROUP_NAMESPACE_OVERRIDESentry incrd/parser.tsif the default mapping reads poorly. - Document the produced classes and the operator install command in a comment block next to the entry — match the existing entries.