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

Contents

Install

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

With uv (recommended):

uv tool install kx-cli

With pipx:

pipx install kx-cli

With pip:

pip install kx-cli

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

kubectl krew install idx
alias kx="kubectl idx"

Standalone binaries for linux, macOS and Windows (amd64/arm64) are attached to each GitHub Release, with checksums in SHA256SUMS.

On macOS, the first run of a freshly installed krew plugin or standalone binary takes a few seconds while Gatekeeper scans the binary; later runs are unaffected until the next install. Get it over with up front:

kx --version >/dev/null

Or try 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

Usage

kx get <resource> fetches resources and assigns each row an index; every other command takes those indexes. Several can be given at once (kx delete 3 5), and a run of consecutive ones can be written as a range instead of listing them out (kx delete 3..7, walking either direction); either end can be left open (kx delete ..5 from the start, kx delete 5.. to the end of the current listing). Extra flags pass through to kubectl (-n <namespace>, selectors, ...), and --match/-m filters rows by name substring. All-namespace listings (-A) are indexed like any other: each row records the namespace it came from, so kx describe 7 reaches a resource in a namespace you aren't in, and two pods sharing a name in different namespaces both keep their own number.

--watch redraws the table live as resources are added, changed, or removed, instead of printing a table that never finishes. It's display-only — a watch never completes, so there's nothing to index. Non-tabular output (-o json/yaml/etc.) streams kubectl's own watch output directly instead.

Known kinds can drop the get: kx pods, kx deploy -n kube-system, kx svc --match api — kubectl shorthands (po, deploy, svc, sts, ...) included. An integer after a kind relists just that index: kx po 3. CRDs work the same way — a CRD's own short name, kind, or plural — resolved from kubectl's own on-disk API-discovery cache, so kx never calls the API server just to look one up. A spelling that resolves neither way still falls back to kx get <resource>.

Global flags: --no-color disables styled output, -v/--version prints the installed version and how the binary was built, and -h/--help on any command shows usage, arguments, examples, and aliases.

kx completion <bash|zsh|fish|powershell> prints a completion script. It completes indexes from the saved listing with the resource each one points at, so kx describe <TAB> offers 1 api-7d8f (Pod) rather than a bare number — plus resource types, rollout actions, themes, engines, and namespaces for -n. Everything is answered from ~/.kx/state.json and needs no API call.

Commands

Command Description
kx annotate <index> [<key=value>...] [--overwrite] [--remove str] 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 cp <src> <dest> [--container/-c str] [--no-preserve] [--retries int] [kubectl flags...] Copy files to or from an indexed pod via kubectl cp.
kx debug <index> [<command>...] [--image str] [--target str] [kubectl flags...] Attach an ephemeral debug container to an indexed pod, for images with no shell.
kx delete <index>... [--yes/-y] Delete one or more indexed resources (prompts for confirmation unless --yes).
kx describe <index>... [kubectl flags...] Show full kubectl describe output for one or more indexed resources.
kx diagnostic [<index>] [--all-namespaces/-A] [--full] [--html] [--namespace/-n str] [--no-open] [--port int] Diagnose an indexed Deployment, StatefulSet, DaemonSet, Job, CronJob, Service, PersistentVolumeClaim, Ingress, or Pod, or triage a whole namespace when no index is given (-n to pick one, -A for every namespace); alias: kx diag.
kx edit <index> [kubectl flags...] 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>...] [kubectl flags...] Open an interactive shell in an indexed pod (bash, falling back to sh).
kx get <resource> [<index>...] [--all-namespaces/-A] [--decode] [--key/-k str] [--match/-m str] [--namespace/-n str] [--watch/-w] [--yes/-y] [kubectl flags...] 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>...] [--overwrite] [--remove str] Set or remove labels on an indexed resource.
kx labels <index>... [--selector/-s] Show labels for one or more indexed resources; --selector formats output as a label selector.
kx logs <index>... [kubectl flags...] Stream logs for an indexed resource; aggregates across pods for Deployments, StatefulSets, DaemonSets, and Services.
kx namespace [<index>] List namespaces, or switch to an indexed one; alias: kx ns.
kx port-forward <index> <port> [kubectl flags...] Forward a local port to an indexed resource (Pod, Deployment, ReplicaSet, StatefulSet, DaemonSet, Service).
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>] [--all-namespaces/-A] [--engine str] [--full] [--html] [--namespace/-n str] [--no-open] [--port int] [scanner flags...] 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, https://docs.docker.com/scout/; or Trivy via --engine trivy, https://trivy.dev/ — see kx engine).
kx secret [<index>...] [--all-namespaces/-A] [--decode] [--key/-k str] [--match/-m str] [--namespace/-n str] [--watch/-w] [--yes/-y] [kubectl flags...] List Secrets like kx get, or show an indexed Secret's data with --decode; alias: kx secrets.
kx top [<resource>] [--all-namespaces/-A] [--html] [--match/-m str] [--namespace/-n str] [--no-limits] [--no-open] [--port int] [kubectl flags...] 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>] [--all-namespaces/-A] [--html] [--namespace/-n str] [--no-index] [--no-open] [--port int] 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 yaml <index>... [--show str] Print the raw YAML manifest for one or more indexed resources; --show filters to specific top-level fields.
kx state [<position>] [--all/-a] [--targets/-t] 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).

Triage a namespace

Bare kx diag sweeps the current namespace — Deployments, StatefulSets, DaemonSets, Jobs, CronJobs, Services, PersistentVolumeClaims, and Ingresses, plus pods nothing owns — and prints a ranked table of what's unhealthy. Findings also draw on live resource usage (kx top): a pod running hot against its memory limit is flagged as an OOMKill risk before it dies. The rows are indexed, so kx diag 1 or kx logs 2 drill straight in. -A sweeps every namespace and indexes that too, adding a NAMESPACE column beside the numbers.

kx diag demo

kx diag <index> diagnoses a single resource: a verdict banner, a SUMMARY of findings (CrashLoopBackOff, image pull failures, OOMKills, unschedulable pods, stalled rollouts, missing Service endpoints, Pending PVCs, failed CronJob runs, Ingresses referencing missing Services, usage near limits), a per-pod status table, recent log tails from broken containers, and warning events — one screen instead of four kubectl commands.

Read a Secret in plaintext

kx secret <index> --decode prints an indexed Secret's keys and values decoded, instead of the base64 kubectl returns. Values that aren't text show a <binary, N bytes> placeholder rather than garbling the table. --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), or redirect a binary value to a file. Bare kx secret --decode decodes every Secret in the namespace in one call, -n included — it confirms first unless you pass --yes/-y, since that prints every credential in the namespace.

kx secret --decode demo

Scan images for vulnerabilities

kx scan <index> scans the unique container images of an indexed workload (init containers and CronJob job templates included); 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 via kx engine trivy (see Configuration).

kx scan demo

View reports in a browser

kx diag --html, kx scan --html, kx tree --html, and kx top --html render the same analysis as a page and open it in your browser as well as printing to the terminal; Ctrl-C stops the server. It binds 127.0.0.1 only, and nothing is written to disk — the report lives in memory for as long as the command runs.

The page is drawn in your active theme, so kx theme dracula restyles it too. Sweep rows expand into that resource's full report, and image rows expand into the CVEs behind their severity counts — detail the terminal has no room for. None of it costs an extra API or scanner call: both were already gathered to build the table you'd see without --html.

--port serves on a specific port instead of picking a free one, and --no-open skips launching a browser — the URL still prints, so you can open it yourself.

kx diag --html

A namespace sweep's severity-sorted findings, filterable and sortable by any column, with a group-by for larger sweeps.

kx diag --html dashboard

kx scan --html

Per-image severity counts up top; the CVE table below groups by image and expands each row into its full detail.

kx scan --html dashboard

kx tree --html

The ownership graph as a collapsible tree, indexed like every other kx listing.

kx tree --html dashboard

History

kx maintains a history of up to 10 kx get results in ~/.kx/state.json. A cursor tracks your current position; index-based commands resolve against the entry at the cursor. kx state --all lists the history, kx state <position> jumps to an entry, kx state back/kx state forward step through it, and kx state drop <position> removes one (kx state drop --all clears everything, including the namespace/context slots below). The older kx back/kx forward/kx drop spellings still work too.

Each entry records the kubeconfig context it was listed in, since a resource name means nothing without the cluster it was read from. kx state names it beside the namespace; kx state --all captions the table with it, or gives it a column when the history spans more than one.

Switching contexts therefore retires the indexes you had. Rather than resolve them against the new cluster — where the same name is a different resource — kx refuses, names both contexts, and re-runs the listing here so there are usable numbers on screen: kx get pods in staging, kx context 2, then kx delete 1 deletes nothing and relists. kx ns <index> is refused the same way and tells you to run kx ns, since a namespace listing is per-cluster too. kx context <index> is the one exception — contexts live in kubeconfig rather than in any cluster, so switching back always works.

Namespaces and contexts are kept separately, outside that history. kx ns and kx contexts each save their listing to their own slot, so kx ns 2 counts against the namespaces you last listed no matter what you have listed since — and switching namespaces, which is frequent, never pushes work out of the history. kx state --all summarizes those slots under the history table, and kx state --targets expands them to the indexed listings the switch commands read, so you can pick a number without re-listing.

To operate on a namespace rather than switch to it, list it like any other resource with kx get ns; that puts it in the history too, so kx describe <index> and kx label <index> work as usual. It refreshes the slot as well, so the two spellings never disagree about what index 2 means. A narrowed listing counts, though: after kx get ns -l team=platform, kx ns <index> indexes into those namespaces rather than all of them. Run kx ns to list them all again.

Configuration

kx reads ~/.kx/config.toml; environment variables override file settings.

Key Env var Default Description
max_history KX_MAX_HISTORY 10 Number of kx get results kept in history.
shells KX_SHELLS (comma-separated) ["bash", "sh"] Shell candidates for kx exec.
debug_image KX_DEBUG_IMAGE "busybox" Image kx debug attaches to a pod; --image overrides it.
theme KX_THEME "github-dark" Color theme for all output.
theme_disable KX_THEME_DISABLE false Disable styled output (same as --no-color).
engine KX_ENGINE "scout" Default scan engine for kx scan (scout, trivy).

Styled output is emitted only when stdout is a terminal — piped or redirected output is plain text, so kx get pods | grep worker stays clean. The NO_COLOR convention is honored as well.

Themes

kx theme lists the available themes with a preview of each; kx theme <name|index> persists a choice to ~/.kx/config.toml.

kx theme demo

Prefab themes: github-dark (default), dracula, nord, gruvbox, solarized-dark, catppuccin-mocha, tokyo-night, rose-pine, mono, light (for light terminal backgrounds), and plain (no styling at all).

Development

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

go build ./...

Run the CLI directly:

go run ./cmd/kx --help
go run ./cmd/kx get pods

Checks:

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.

Metadata

Release files for kx-cli 0.4.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.4.0
File
kx_cli-0.4.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
kx_cli-0.4.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
kx_cli-0.4.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
kx_cli-0.4.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
kx_cli-0.4.0-py3-none-manylinux_2_17_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
kx_cli-0.4.0-py3-none-manylinux_2_17_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
kx_cli-0.4.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
kx_cli-0.4.0-py3-none-macosx_10_9_x86_64.whl Python 3 none macOS 10.9+ x86-64 Details

Total release size: 391.3 MB

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

Download URL kx_cli-0.4.0-py3-none-win_arm64.whl
Size 47.2 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
6e24b5f94cc9931d444d547be35df09fb25810e0df05c5228f1a5478ba07c4de
BLAKE2b-256 checksum
How to use checksums
29c682350e79eadafd62e6fa216a2ed35faa7321aa2ccd13ef50f32a597d2453
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.4.0-py3-none-win_amd64.whl

Download URL kx_cli-0.4.0-py3-none-win_amd64.whl
Size 51.2 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
e26275642e33d84b39e18b80f8a16c12d2411c1467d0d117c56f0c1b43af8cd3
BLAKE2b-256 checksum
How to use checksums
271b384fae428492f4efbdde3677c1408af03fb18c9b6695a0361408563bb4cb
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.4.0-py3-none-musllinux_1_2_x86_64.whl

Download URL kx_cli-0.4.0-py3-none-musllinux_1_2_x86_64.whl
Size 50.0 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
0ae81869df5e60d57bb88666f93a3b13483d54abe9ab02b6d43dc6fc862b6646
BLAKE2b-256 checksum
How to use checksums
41e2bbbfa616e16f33a7a11501dffc6990f54cf48fa3ae032e7a09c586f7d7ad
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.4.0-py3-none-musllinux_1_2_aarch64.whl

Download URL kx_cli-0.4.0-py3-none-musllinux_1_2_aarch64.whl
Size 46.8 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
beae4bc713523b56776ba0723214bc8074b131707618ebb68d90984c6c2858c0
BLAKE2b-256 checksum
How to use checksums
16137969c020f975c20f3603f026287954e15fb94fddc238bac83d683cb315f7
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.4.0-py3-none-manylinux_2_17_x86_64.whl

Download URL kx_cli-0.4.0-py3-none-manylinux_2_17_x86_64.whl
Size 50.0 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
093977b9a613f471066c591d336222a4bd762258f29ef0a016930ade70807a37
BLAKE2b-256 checksum
How to use checksums
9064453637dd22c619ec76c82ac0462a7d7a6c4cfd73571725c2e63b2d7e472c
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.4.0-py3-none-manylinux_2_17_aarch64.whl

Download URL kx_cli-0.4.0-py3-none-manylinux_2_17_aarch64.whl
Size 46.8 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
ed939aac6ca7041a3777f1f0dd452012ee6eecf43e5202cd0a3eb8885a9b01f2
BLAKE2b-256 checksum
How to use checksums
5b2ca7dd0482126e97ba655c2372d1e05bee34e73b8778f0d6a5032d4fa134cb
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.4.0-py3-none-macosx_11_0_arm64.whl

Download URL kx_cli-0.4.0-py3-none-macosx_11_0_arm64.whl
Size 48.1 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
63bc86214a3ebe3b356e64b96ae8a1a54d4872ddbb8f014c588523c2cf67fb0d
BLAKE2b-256 checksum
How to use checksums
015b48f642f364c04254e2796cc9045bc111988d0595e7d16aa0a817be026970
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.4.0-py3-none-macosx_10_9_x86_64.whl

Download URL kx_cli-0.4.0-py3-none-macosx_10_9_x86_64.whl
Size 51.0 MB
Tags Python 3 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
eb018ef1098000fff0c254aa3b65a482ba23e973cfa20837846f8dc6323a16ec
BLAKE2b-256 checksum
How to use checksums
390aa03ef387a4f29c0d7bfc105d0e114e7bfa2ce9025ff4477ccc3d3abbf85e
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.4.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