2026-07-15 · 8 min read

CRD Browser: Finally Visualize Your Custom Resources

crdfeatures

CRD Browser: Finally Visualize Your Custom Resources

Custom Resource Definitions are everywhere. Cert-manager has Certificates and Issuers. ArgoCD has Applications. Istio has VirtualServices. Prometheus has ServiceMonitors. Every operator you install adds its own resource types to your cluster.

And yet, browsing them is stuck in 2018:

kubectl get certificates -n production
kubectl describe certificate my-tls-cert -n production
kubectl get certificate my-tls-cert -n production -o yaml | less

Raw text. No structure. No conditions summary. No cross-referencing. You need to know the resource name, the API group, and the right kubectl command. For a cluster with 20+ CRDs, this becomes an exercise in memory.

Krust has a CRD browser that discovers every Custom Resource Definition in your cluster, lists all instances with dynamic columns, and shows status conditions in a structured inspector — without you configuring anything.


How It Works

Automatic Discovery

When you connect to a cluster, Krust watches the CRD API (customresourcedefinitions.apiextensions.k8s.io). Every CRD in the cluster appears in the CRD tab automatically:

NameGroupKindScopeVersionsAge
certificates.cert-manager.iocert-manager.ioCertificateNamespacedv1180d
applications.argoproj.ioargoproj.ioApplicationNamespacedv1alpha190d
virtualservices.networking.istio.ionetworking.istio.ioVirtualServiceNamespacedv1beta1, v145d
prometheusrules.monitoring.coreos.commonitoring.coreos.comPrometheusRuleNamespacedv1120d

No configuration. No “add this CRD to your tool.” No plugin to install. If it exists in the cluster, it’s in the list.

New CRD installed? It appears in real-time via the watch stream. CRD deleted? It disappears.

Dynamic Table Columns

Click “Browse Instances” on any CRD, and Krust opens a table of all instances. But here’s the key feature: the table columns are dynamic, generated from the CRD’s additionalPrinterColumns spec.

CRD authors define printer columns — the same columns kubectl get uses. Krust reads these from the CRD definition and builds the table accordingly.

For certificates.cert-manager.io:

NameNamespaceReadySecretIssuerStatusAge
my-tls-certproductionTruemy-tls-secretletsencrypt-prodCertificate is up to date30d
api-certstagingFalseapi-secretletsencrypt-stagingIssuing2h

For applications.argoproj.io:

NameNamespaceSync StatusHealthProjectAge
frontendargocdSyncedHealthydefault15d
backendargocdOutOfSyncDegradeddefault15d

Different CRDs, different columns. The browser adapts to whatever the CRD defines. Up to 6 printer columns are displayed, plus Name, Namespace (if namespaced), and Age.

JSONPath Evaluation

Each printer column in a CRD spec includes a JSONPath expression that points to a field in the custom resource. For example:

additionalPrinterColumns:
  - name: Ready
    type: string
    jsonPath: .status.conditions[?(@.type=="Ready")].status
  - name: Secret
    type: string
    jsonPath: .spec.secretName

Krust evaluates these JSONPath expressions against each custom resource instance to populate the table cells. The evaluation handles nested fields (.status.phase), metadata fields (.metadata.creationTimestamp), and returns the values as strings for display.

This means: any well-defined CRD works out of the box. If the CRD author specified printer columns (and most do), Krust displays them correctly.


The Inspector

Click on any custom resource instance to open the inspector panel. This is where a GUI adds real value over kubectl describe.

Status Conditions

Most custom resources use the Kubernetes conditions pattern:

status:
  conditions:
    - type: Ready
      status: "True"
      reason: CertificateIssued
      message: "Certificate is up to date and has not expired"
    - type: Issuing
      status: "False"
      reason: ""
      message: ""

The inspector renders these as a structured list with visual indicators:

  • Ready: True (green checkmark) — CertificateIssued
  • Issuing: False (orange X)

In kubectl describe, conditions are buried in a wall of text. In the inspector, they’re the first thing you see. At a glance, you know if the resource is healthy.

Printer Column Values

The inspector also shows all printer column values in a structured section — the same data as the table, but alongside the conditions, labels, annotations, and metadata. Everything about this resource in one panel.

Full Status JSON

Below the structured sections, the raw status JSON is displayed with syntax highlighting. Booleans, numbers, strings — each color-coded. Expandable sections for nested objects. This covers the long tail of status fields that aren’t in conditions or printer columns.

Labels & Annotations

Displayed cleanly, with kubectl.kubernetes.io/last-applied-configuration filtered out (it’s noise in a GUI — you already have the YAML viewer for that).


Why This Matters

Operator Debugging

When a cert-manager Certificate isn’t issuing, you need to check:

  1. The Certificate’s conditions (Ready? Issuing?)
  2. The Issuer or ClusterIssuer it references
  3. The CertificateRequest it created
  4. The Order and Challenge resources (for ACME/Let’s Encrypt)

In kubectl:

kubectl get certificate my-cert -n prod -o yaml
kubectl get certificaterequest -n prod | grep my-cert
kubectl get order -n prod | grep my-cert
kubectl get challenge -n prod | grep my-cert

Four commands, reading raw YAML output, mentally connecting the chain.

In Krust: browse Certificates → click my-cert → see conditions. Browse CertificateRequests → filter by name → see its conditions. The inspector shows structured status at every level.

Inventory & Audit

“What custom resources are in this cluster?”

kubectl api-resources --api-group="" --verbs=list | head -20
# Not enough, need non-core groups too
kubectl api-resources --verbs=list
# Now you have 80+ lines, most are built-in
# Filter to custom...
kubectl get crd
# OK now list instances of each...
kubectl get certificates.cert-manager.io --all-namespaces
kubectl get applications.argoproj.io --all-namespaces
# Repeat for each CRD

In Krust: open the CRD tab. Every custom resource type, listed. Click any one to browse its instances. Two clicks per CRD, no commands.

Multi-Cluster CRD Comparison

Connect to staging and production. Open the CRD tab. See which CRDs exist in each cluster. Notice that staging has canaries.flagger.app but production doesn’t — someone installed Flagger in staging and forgot to deploy it to production.

Browse instances across clusters: same CRD, different clusters, one table. Compare instance counts, status conditions, versions.


Scope-Aware

CRDs can be cluster-scoped or namespace-scoped. Krust handles both:

  • Namespaced CRDs (most common): instances are fetched per-namespace, the table includes a Namespace column, namespace filtering works
  • Cluster-scoped CRDs (e.g., ClusterIssuers, ClusterRoles): instances are fetched cluster-wide, no Namespace column, no namespace filter needed

The scope is detected from the CRD definition. No configuration needed.


Edit & Delete

Right-click any custom resource instance:

  • Edit YAML (Cmd+E) — opens the full YAML in an editor, save to apply changes
  • Delete — with confirmation dialog
  • Batch delete — select multiple instances, delete in one action

For CRDs themselves (not instances), delete shows a warning: “This will also delete all custom resources of this type.” Because deleting a CRD cascades to all its instances — a fact that’s not always obvious.


What’s Not Covered

Krust’s CRD browser is a viewer and editor, not a specialized operator UI. It doesn’t:

  • Render operator-specific visualizations (ArgoCD sync graph, Istio mesh topology)
  • Provide CRD-specific actions (“renew certificate”, “sync application”)
  • Show relationships between resources automatically (Certificate → CertificateRequest → Order)

These would require per-operator plugins, which is a different scope. Krust gives you a universal browser that works with any CRD, showing the same structured data that kubectl get and kubectl describe would show — but in a visual, searchable, multi-cluster interface.


Try It

brew install slarops/tap/krust

Open the CRD tab. See every custom resource type in your cluster. Browse instances with dynamic columns. Check conditions without reading YAML. It works with every CRD — cert-manager, ArgoCD, Istio, Prometheus, Crossplane, your own custom operators.

Website → | Download →


Krust is a native macOS Kubernetes IDE. The CRD browser discovers all custom resource types automatically and displays instances with dynamic printer columns, structured conditions, and multi-cluster support. Free during beta.