Skip to main content
kx — kubectl, indexed.

kubectl, indexed

PyPI version License CI

kx is a kubectl wrapper that adds index-based resource selection. Run kx get <resource> once, then reference any result by number instead of typing full resource names.

kx demo

Install

Requires kubectl on your PATH. Every install path delivers the same prebuilt binary — no Python runtime, no dependencies.

With uv (recommended), pipx, or pip:

uv tool install kx-cli
pipx install kx-cli
pip install kx-cli

As a kubectl plugin via krew, where kx is published as idx:

kubectl krew install idx
alias kx="kubectl idx"

Or run it without installing — the package is kx-cli, the command is kx:

uvx --from kx-cli kx get pods
pipx run --spec kx-cli kx get pods

Standalone binaries for linux, macOS and Windows are attached to every GitHub Release.

Full guide →

Usage

A kx session at a glance — one listing, then everything after it by number.

kx get pods    # lists pods, numbering each row
kx logs 3      # the third pod
kx diag 3      # why it's unhealthy

Indexes come several at a time, as ranges, or narrowed.

kx delete 3 5                   # several at once
kx delete 3..7                  # an inclusive range, walking either direction, trimmed to the listing
kx delete ..5                   # open at the start
kx delete 5..                   # open to the end of the listing
kx get pods -m api              # --match/-m filters rows by name substring
kx get pods -n prod -l app=api  # anything else passes through to kubectl

kubectl's own flags pass through everywhere they mean something — kx delete 3 --force --grace-period=0, kx rollout undo 3 --to-revision=2, kx scale 3 0 --timeout=1m, kx logs 3 -f --tail=100. A namespace flag is the exception: an index already carries the namespace it was listed from, so -n beside one is refused rather than silently retargeting the command.

-A listings are indexed too: each row records its own namespace, so kx describe 7 reaches a resource in a namespace you aren't in, and two pods sharing a name keep separate numbers.

Known kinds can drop the get — kx pods, kx deploy -n kube-system, kx svc -m api — kubectl's shorthands and your CRDs included. A CRD resolves from kubectl's on-disk discovery cache, with no API call.

--watch/-w redraws the table in place, rather than appending lines the way kubectl -w does.

kx completion <bash|zsh|fish|powershell> completes indexes with the resource behind them, so kx describe <TAB> offers 1 api-7d8f (Pod) rather than a bare number.

Triage a namespace

Bare kx diag sweeps the current namespace — every workload kind, plus Services, PVCs, Ingresses and pods nothing owns — and ranks what's unhealthy. It reads live usage too, so a pod running hot against its memory limit is flagged as an OOMKill risk before it dies.

kx diag demo

kx diag <index> diagnoses a single resource: a top level verdict, a findings summary, a per-pod status table, log tails from broken containers and warning events — one screen instead of four kubectl commands.

Full guide →

Read a Secret in plaintext

kx secret <index> --decode prints an indexed Secret's keys and values decoded. --key/-k prints a single value raw — no banner, no wrapping — so it drops straight into a shell.

export PGPASSWORD=$(kx secret 1 --decode -k password)

Bare kx secret --decode decodes every Secret in the namespace in one call, confirming first — that prints every credential you have.

kx secret --decode demo

Full guide →

Scan images for CVEs

kx scan <index> scans the unique container images of an indexed workload. Bare kx scan sweeps every workload in the namespace. Results come back as a severity summary, or the full per-image CVE report with --full.

Requires the CLI for the selected engine — Docker Scout by default, or Trivy and Grype via kx engine.

kx scan demo

Full guide →

See what owns what

kx tree <index> walks the ownership graph — Deployment to ReplicaSet to Pods — and indexes every node it draws, so anything in the tree is one number away. Bare kx tree graphs the whole namespace.

kx tree dashboard

Full guide →

Reports in the browser

--html on kx diag, kx scan, kx tree, and kx top renders the same analysis as a page and opens it in your browser. It binds 127.0.0.1 only and writes nothing to disk.

The page is drawn in your active theme. Sweep rows expand into that resource's full report, image rows into the CVEs behind their counts — detail the terminal has no room for.

--out <path> writes the page to a file instead of serving it, which is what you want in CI — kx diag --out report.html is the whole command.

kx diag --html dashboard

Full guide →

Spend an index anywhere

kx wraps two dozen of kubectl's verbs. kx ref covers the rest, and every tool that isn't kubectl: it prints what an index refers to, as an argument fragment that drops straight into another command.

kx ref 3                                     # pod/web-abc-xyz -n prod
kubectl exec $(kx ref 3) -- sh               # a verb kx doesn't wrap
kubectl get $(kx ref 1..3)                   # one line each, so ranges work too
stern $(kx ref 3 --name) -n $(kx ref 3 --namespace)
kx ref 1..9 --name | xargs -n1 some-tool

--name, --namespace and --kind print that field alone, for tools that take the pieces separately. A cluster-scoped resource gets no -n, because there is no namespace for it to be in.

Nothing here touches the cluster: kx ref reports what the index means, so it answers instantly and works with nothing reachable. The command you spend it on is what discovers whether the resource is still there.

Marks

An index is a position, and positions move — the next kx get renumbers everything out from under it. A mark is a name you choose instead, pinned to one resource, so it keeps working across every listing that comes after it.

kx mark api 3          # pin what index 3 is right now
kx logs @api -f        # spend it where a command takes an index
kx exec @api -- sh
kx mark                # list marks
kx unmark api
kx unmark --all

A mark survives re-listing, which is what an index cannot do. It is pinned to the cluster it was taken in, and will not resolve in another — the same name means a different resource there, or none at all. kx state drop --all leaves marks alone; kx unmark --all is what removes them.

kx ns and kx context take an index but not a mark, because a slot is not a resource; kx cp parses its own index:path and takes one too.

Use kx in CI

--fail-on <severity> turns a sweep into a build gate, and --json prints the same analysis as a document for anything downstream.

kx diag -A --fail-on critical                        # 0 if the cluster is healthy, 2 if not
kx scan -A --fail-on high                            # the same, for image vulnerabilities
kx scan -n prod --fail-on high --json | jq '.images[] | select(.counts.critical > 0)'
kx diag -A --fail-on critical --out report.html      # publishes the report *and* fails the build
kx diag -A --fail-on warning --since 24h             # ignore what failed before today

--since bounds how far back the report looks — a warning event, an OOMKill a container recovered from, a pod or run that failed. Without it a failure from last month holds the gate red forever. Whatever is still going wrong — a CrashLoopBackOff, a Pending pod — is reported either way. Set the window once with diag_max_age in config.toml, or KX_DIAG_MAX_AGE in the job's environment.

kx events and kx logs take --since too. kx events has a key of its own, events_max_age / KX_EVENTS_MAX_AGE, and it does not affect kx diag — narrowing the evidence behind a verdict is not a request for a shorter event listing. Neither key falls back to the other.

Exit 2 means findings breached the threshold, 1 means kx itself failed — so a pipeline can tell "the cluster is sick" from "the check never ran".

Full guide →

State and history

kx keeps up to 10 kx get results in ~/.kx/state.json, with a cursor marking the entry indexes resolve against.

kx state              # the listing indexes currently resolve against
kx state --all        # the whole history, with positions
kx state 2            # jump to position 2
kx state back         # step back one (forward steps the other way)
kx state drop 2       # remove position 2 (--all clears everything, slots included, marks untouched)
kx state drop --empty # drop the entries whose listing found nothing

A listing that found nothing is saved like any other, so the indexes it replaced stop resolving rather than quietly pointing at the listing before it. kx offers the way back when it happens, and kx state drop --empty sweeps those entries up.

Each entry remembers the context it was listed in, so a staging index is never resolved against production — kx refuses and relists instead. KX_STATE points kx at a different state file, so a second terminal keeps its own history.

Full guide →

Configuration

kx reads ~/.kx/config.toml, and every setting takes a KX_* environment override. The two worth changing have commands of their own — kx theme and kx engine both persist your choice.

Styling is dropped when stdout isn't a terminal, so kx get pods | grep worker stays clean. NO_COLOR is honored too.

Full guide →

Themes

kx theme lists the available themes with a preview of each. kx theme <name> persists your choice, by name or index.

kx theme demo

Eleven prefabs ship with it: github-dark (default), dracula, nord, gruvbox, solarized-dark, catppuccin-mocha, tokyo-night, rose-pine, mono, light and plain.

Full guide →

Commands

Command Description
kx annotate <index> [<key=value>...] Set or remove annotations on an indexed resource.
kx annotations <index>... Show annotations for one or more indexed resources.
kx context [<index>] List kubeconfig contexts, or switch to an indexed one; alias: kx contexts.
kx cordon <index>... Mark one or more indexed Nodes unschedulable.
kx cp <src> <dest> Copy files to or from an indexed pod via kubectl cp.
kx debug <index> [<command>...] Open a debug shell on an indexed Pod (an ephemeral container, for images with no shell) or Node (a privileged pod on the host).
kx delete <index>... Delete one or more indexed resources (prompts for confirmation unless --yes).
kx describe <index>... Show full kubectl describe output for one or more indexed resources.
kx diagnostic [<index>] Diagnose an indexed Deployment, StatefulSet, DaemonSet, Job, CronJob, Service, PersistentVolumeClaim, Ingress, Pod, or Node, or triage a whole namespace when no index is given (-n to pick one, -A for every namespace); alias: kx diag.
kx drain <index> Evict the pods from an indexed Node (prompts for confirmation unless --yes).
kx edit <index> Open an indexed resource in your editor via kubectl edit.
kx events <index>... Show Kubernetes events for one or more indexed resources.
kx exec <index> [<command>...] Open an interactive shell in an indexed Pod, Deployment, ReplicaSet, StatefulSet or DaemonSet (bash, falling back to sh).
kx get <resource> [<index>...] List resources and assign index numbers for use with other commands; shorthand: kx (e.g. kx pods, kx po 3).
kx label <index> [<key=value>...] Set or remove labels on an indexed resource.
kx labels <index>... Show labels for one or more indexed resources; --selector formats output as a label selector.
kx logs <index>... Stream logs for an indexed resource; aggregates across pods for Deployments, StatefulSets, DaemonSets, and Services.
kx mark [<name>] [<index>] Pin an indexed resource to a name that survives re-listing; with no arguments, lists marks.
kx namespace [<index>] List namespaces, or switch to an indexed one; alias: kx ns.
kx port-forward <index> <port> Forward a local port to an indexed resource (Pod, Deployment, ReplicaSet, StatefulSet, DaemonSet, Service).
kx ref <index>... Print what an index refers to, for commands kx doesn't wrap.
kx rollout <action> <index> Run a rollout action (status, restart, pause, resume, history, undo) on a Deployment, StatefulSet, or DaemonSet.
kx scale <index> <replicas> Scale an indexed Deployment, StatefulSet, or ReplicaSet to a given replica count.
kx scan [<index>] Scan the unique container images of an indexed workload for vulnerabilities, or a whole namespace when no index is given (-n to pick one, -A for every namespace); prints a severity summary table by default, or the raw scanner output with --full. Requires the CLI for the selected scan engine (Docker Scout by default; Trivy or Grype via --engine — see kx engine).
kx secret [<index>...] List Secrets like kx get, or show an indexed Secret's data with --decode; alias: kx secrets.
kx top [<resource>] List CPU/memory usage for pods (default) or nodes and assign index numbers, like kx get; shows usage as a percent of limits (pods) or capacity (nodes) unless --no-limits.
kx tree [<index>] Show the ownership graph for an indexed resource, or the whole current namespace when no index is given (-n to pick one, -A for every namespace); assigns indexes to tree nodes by default. A Namespace index graphs that namespace.
kx uncordon <index>... Mark one or more indexed Nodes schedulable again.
kx unmark [<name>...] Remove marks by name; --all removes every mark.
kx yaml <index>... Print the raw YAML manifest for one or more indexed resources; --show filters to specific top-level fields.
kx state [<position>] Show current state, jump to a history position, list all entries with --all, or expand the switch targets with --targets.
kx engine [<name>] List available scan engines or persist a default choice by name or index.
kx theme [<name>] List available color themes or persist a choice by name or index.
kx completion Generate a shell completion script for kx (bash, zsh, fish, powershell).

Development

Go, at the version pinned by the go directive in go.mod. Nothing else is required to build or run.

go build ./...
go run ./cmd/kx --help              # run the CLI directly
gofmt -l ./cmd ./internal ./tools   # must print nothing
go vet ./...
go test -race ./...

pre-commit run --all-files runs gofmt and go vet, and regenerates the command table above from the command tree — it fails if the table has drifted from the commands it documents. Tests are not in the hook — run them yourself.

The demo GIFs are rendered from VHS tapes — see demo/README.md for seeding the demo namespace and re-recording.

Releases are cut by pushing a release/vX.Y.Z branch — see RELEASING.md.

Metadata

Release files for kx-cli 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for kx-cli 0.6.0
File
kx_cli-0.6.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
kx_cli-0.6.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
kx_cli-0.6.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
kx_cli-0.6.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
kx_cli-0.6.0-py3-none-manylinux_2_17_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
kx_cli-0.6.0-py3-none-manylinux_2_17_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
kx_cli-0.6.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
kx_cli-0.6.0-py3-none-macosx_10_9_x86_64.whl Python 3 none macOS 10.9+ x86-64 Details

Total release size: 411.3 MB

Release files / kx_cli-0.6.0-py3-none-win_arm64.whl

Download URL kx_cli-0.6.0-py3-none-win_arm64.whl
Size 49.7 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
d12c561963a8a8e78fa13ad85e0e380173df8c2c2cd012417db15ad65907080d
BLAKE2b-256 checksum
How to use checksums
371ea450936f437646624f57285c4be4168ec6c8b0f3f00069b59dd91a1ae009
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / kx_cli-0.6.0-py3-none-win_amd64.whl

Download URL kx_cli-0.6.0-py3-none-win_amd64.whl
Size 53.9 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
4475824759ffceddc6a236cc28cdbb28eea4b17c7282d81fb5486975e42b6097
BLAKE2b-256 checksum
How to use checksums
ac26e5b04adc72933c2ddb475d72894e23a29530048cc894baff7e0f977c530b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / kx_cli-0.6.0-py3-none-musllinux_1_2_x86_64.whl

Download URL kx_cli-0.6.0-py3-none-musllinux_1_2_x86_64.whl
Size 52.6 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
277de698ddbd71e970b3a975470aadcfc5911334e176b24c0e5737345e171733
BLAKE2b-256 checksum
How to use checksums
ffe9cc6f43412e6a376ecd3ef945f81609525a3faf60bf0abe89960eff337e96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / kx_cli-0.6.0-py3-none-musllinux_1_2_aarch64.whl

Download URL kx_cli-0.6.0-py3-none-musllinux_1_2_aarch64.whl
Size 49.2 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
0ebbd3ddad5d608c76c0b7bc0a0ee339f492cc24b15e1bd2167246102cced822
BLAKE2b-256 checksum
How to use checksums
b7a6e995f7cad797d96f7e11af36e0d8216e749552a0c5a77e2e0d5eedb58708
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / kx_cli-0.6.0-py3-none-manylinux_2_17_x86_64.whl

Download URL kx_cli-0.6.0-py3-none-manylinux_2_17_x86_64.whl
Size 52.6 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
1bb8b7ed35a05854bb3de07553d520b2fd0e24b0aabf215daeea7f20a99b7b57
BLAKE2b-256 checksum
How to use checksums
1b966778713260c4b35890480a6e785a9211a1230b38b4f8e3abe07a005e6aea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / kx_cli-0.6.0-py3-none-manylinux_2_17_aarch64.whl

Download URL kx_cli-0.6.0-py3-none-manylinux_2_17_aarch64.whl
Size 49.2 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
e310ad0e75c75b21f012434be70af4872454575293d61b3e63212d57fa94812d
BLAKE2b-256 checksum
How to use checksums
bf2257111e0721987594a6b049873b5b9ee654fef0849264e213287f7baff7d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / kx_cli-0.6.0-py3-none-macosx_11_0_arm64.whl

Download URL kx_cli-0.6.0-py3-none-macosx_11_0_arm64.whl
Size 50.6 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
5f819e28cc539f56a34c34ea0a3703cb4df1917d0151dc59abdd0232b60e5a9d
BLAKE2b-256 checksum
How to use checksums
9446d9d5ad74db642975e6cd1244731790204ee050029121cc1e0104288b4a9f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / kx_cli-0.6.0-py3-none-macosx_10_9_x86_64.whl

Download URL kx_cli-0.6.0-py3-none-macosx_10_9_x86_64.whl
Size 53.7 MB
Tags Python 3 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
29294e0f17bfdd470bd0123908899978c410920fa5abe9707c716e94ab9b92a5
BLAKE2b-256 checksum
How to use checksums
4c234141d2678a4e45523a052f2b76d61438e352eddb23a6efd98443ff17175a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for kx-cli 0.6.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page