Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Kubernetes & Helm By James Joyner IV · · 9 min read

Writing Your Own kubectl Plugins With AI Help

Turn the kubectl command you keep retyping into a real plugin. AI drafts the script and krew manifest; you review and install it locally for the whole team.

  • #kubernetes
  • #kubectl
  • #krew
  • #ai

I had a one-liner I retyped a dozen times a day — list every pod across all namespaces that’s been restarting, sorted by restart count, so I could spot the flapping workloads before they paged anyone. It lived in my shell history and nowhere else, which meant nobody else on the team had it. The fix was to turn it into a proper kubectl plugin. The part that used to stop me was the boilerplate: argument parsing, help text, the krew manifest. That’s exactly the boilerplate an AI model drafts well, leaving me to review the logic and the safety of the commands it runs.

How kubectl plugins actually work

There’s no SDK and no registration. kubectl plugins are just executables on your PATH named kubectl-<something>. Drop a script called kubectl-restarts somewhere on your PATH, make it executable, and kubectl restarts works. That simplicity is why a plugin is the right home for a command you run constantly — and why AI can scaffold one in minutes.

# Anything named kubectl-* on PATH becomes a subcommand
kubectl plugin list   # shows what kubectl discovered

Describe the command, not the cluster

The model needs to know what the plugin should do and what kubectl queries it should run. It does not need — and never gets — my kubeconfig or any cluster access. The plugin runs against the cluster on my machine, with my credentials, after I’ve reviewed it. The model only writes the script.

My prompt:

Write a kubectl plugin as a bash script named kubectl-restarts. It should list pods across all namespaces sorted by container restart count, descending, hiding pods with zero restarts. Support an optional -n NAMESPACE flag to scope to one namespace, and a -h flag that prints usage. Use only read-only kubectl get calls. Fail clearly if kubectl isn’t found.

The “only read-only” constraint is deliberate. I want this plugin to observe, never mutate, so even if I forget to read a line, the worst case is a wasted query.

What the draft looks like

The model produced a clean, reviewable script:

#!/usr/bin/env bash
set -euo pipefail

usage() {
  echo "Usage: kubectl restarts [-n NAMESPACE]"
  echo "  Lists pods sorted by restart count (zero-restart pods hidden)."
  exit 0
}

NS_FLAG="--all-namespaces"
while getopts "n:h" opt; do
  case "$opt" in
    n) NS_FLAG="-n ${OPTARG}" ;;
    h) usage ;;
    *) usage ;;
  esac
done

command -v kubectl >/dev/null || { echo "kubectl not found"; exit 1; }

kubectl get pods $NS_FLAG \
  --sort-by=.status.containerStatuses[0].restartCount \
  -o custom-columns='NS:.metadata.namespace,POD:.metadata.name,RESTARTS:.status.containerStatuses[0].restartCount' \
  | awk 'NR==1 || $3+0 > 0'

I read every line before trusting it. The set -euo pipefail is right, the command -v kubectl guard is right, and crucially every kubectl call is get — read-only. The awk filter to hide zero-restart rows is a nice touch I’d have skipped writing myself.

Verify it before it goes anywhere near a shared PATH

I test the plugin against a non-prod cluster first, because even read-only commands deserve a careful first run:

chmod +x kubectl-restarts
sudo mv kubectl-restarts /usr/local/bin/
kubectl plugin list | grep restarts
kubectl restarts -n kube-system

If it works against staging, I trust it against prod — but I read the script’s every command first, because a plugin on my PATH runs with my full credentials. That review is the human-in-the-loop step: the model wrote it, but I’m the one accountable for what it executes.

Pro Tip: Before installing any AI-generated plugin, grep it for mutating verbs — apply, delete, patch, scale, edit, rollout. A plugin that only contains get, describe, and logs is safe to run anywhere; one that mutates needs the same scrutiny as a deploy script.

Packaging it for the team with krew

A loose script works for me, but to share it I package it for krew, the plugin manager. The krew manifest is pure boilerplate — another good delegation. I ask the model:

Write a krew plugin manifest (restarts.yaml) for this plugin. Single platform, linux/amd64, pointing at a tarball of the script.

apiVersion: krew.googlecontainertools.github.com/v1alpha2
kind: Plugin
metadata:
  name: restarts
spec:
  homepage: https://example.com/kubectl-restarts
  shortDescription: "List pods sorted by restart count"
  version: v0.1.0
  platforms:
    - selector:
        matchLabels:
          os: linux
          arch: amd64
      uri: https://example.com/kubectl-restarts-v0.1.0.tar.gz
      sha256: "<fill in real checksum>"
      bin: kubectl-restarts

I fill in the real sha256 myself — the model leaves a placeholder, and I’d never trust a checksum it invented. With the manifest validated, teammates install with kubectl krew install --manifest=restarts.yaml.

Going beyond bash when it earns its keep

Bash is perfect for a thin wrapper around a few kubectl get calls, and most useful plugins are exactly that. But once a plugin needs to parse JSON, branch on cluster state, or talk to the Kubernetes API directly, bash gets ugly fast and I switch the model to a different target. Go is the native choice — the cli-runtime library gives you the same flag conventions kubectl itself uses — but the build-and-distribute overhead is real. For most internal tooling I ask the model for a Python script using the official client, which stays readable and still installs as a plain kubectl- executable.

The prompt barely changes: I describe the same behavior and add “write it in Python using the kubernetes client library, read-only API calls only.” The model handles the client boilerplate — loading kubeconfig, listing pods, paging results — which is the tedious part. What does not change is the review discipline. A Python plugin can call any API the kubeconfig allows, so I read it as carefully as a bash script, confirming every API call is a read or list and never a patch, delete, or create. The richer the language, the easier it is for a mutating call to hide in plain sight, so the human review gets more important, not less.

Things AI gets wrong in plugin scripts

A few recurring issues I catch on review:

  • Unquoted variables that break on namespaces with unusual characters. The model sometimes drops quotes around $NS_FLAG interpolation.
  • Assuming the first container. containerStatuses[0] ignores multi-container pods. For a quick tool that’s acceptable, but the model should flag the limitation.
  • Silent mutation creep. If you later ask it to “add a feature,” it may slip in a kubectl delete. Re-grep for mutating verbs after every change.

Wrap up

A kubectl plugin is the right home for the command you keep retyping, and the boilerplate around it — flag parsing, help text, krew manifests — is exactly what AI drafts well. The model writes the script; you read every line, confirm it’s read-only or scrutinize it if it isn’t, and install it under your own credentials. The model never holds your kubeconfig and never runs against your cluster.

Find more tooling guides in the Kubernetes & Helm category, grab scripting prompts or the Kubernetes prompt pack, and run any plugin script through the code review dashboard before it lands on a shared PATH.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.