Repository: github.com/mdadul/K · npm: kubectl-k (installs the k command)
A small kubectl developer-experience layer: remembers context and namespace, resolves partial pod and deployment names, and uses fuzzy searchable pickers when something is ambiguous. It is not a replacement for kubectl.
Runtime: Bun (TypeScript, no separate build step for the CLI binary).
- Bun >= 1.0
kubectlon yourPATHand a valid kubeconfig
From the repo root:
bun install
bun link # makes the `k` command available globallyFrom npm (still need Bun on your PATH):
npm install -g kubectl-kOr run without linking:
bun run src/cli/index.ts -- <args>k use dev/backend # context + namespace (or `k use` for an interactive context list)
k status
k pods
k pods checkout-payments # grep-like filter (see below)
k logs api # substring / prefix match; multiple hits → fuzzy picker
k logs # no query → pick a pod, then stream or print logs
k exec api -- bash -lc 'pwd'
k pf api 8080:8080 # port-forward (alias: `k port-forward`)
k desc api # describe pod (alias: `k describe`)
k restart api # rollout restart deployment (smart match on name)
k raw get nodes # passthrough kubectl; no injected --context / -nPersistent state lives in ~/.k/state.json:
context— Kubernetes context name (required for cluster commands; set withk use)namespace— optional; when set,kpasses-non every injected kubectl call. When omitted, kubectl uses the default namespace for that context in your kubeconfig (same as plainkubectl get pods).
Commands such as k use and k ns update this file (and align kubeconfig where appropriate). Injected calls always include --context from effective state; -n is added only when a namespace is set (file, env, or flag).
Before the subcommand you can pass:
| Flag | Effect |
|---|---|
--context <name> |
Override context for this run only |
-n / --namespace <name> |
Override namespace for this run only |
Environment variables (same precedence idea, applied with flags overriding file state):
| Variable | Effect |
|---|---|
K_CONTEXT |
Default context if not set by flags or file |
K_NAMESPACE |
Default namespace if not set by flags or file |
Precedence: CLI flags → env → ~/.k/state.json.
k status shows the merged “effective” values and hints when they differ from what is stored on disk.
| Command | Aliases | Summary |
|---|---|---|
help |
-h, --help |
List commands, or k help <cmd> for one command |
use |
Switch context; ctx/ns form; interactive with no arg |
|
ctx |
Print current context; k ctx ls lists contexts |
|
ns |
Print/set namespace; k ns ls lists namespaces |
|
status |
Context + namespace (effective vs file) | |
pods |
List pods; optional filter (grep-like, see below); -w / --watch |
|
logs |
Pod logs; optional query; supports extra kubectl logs flags | |
exec |
kubectl exec -it; default shell sh; k exec -- cmd |
|
restart |
kubectl rollout restart deployment/… (smart match) |
|
describe |
desc |
kubectl describe pod (smart match) |
port-forward |
pf |
Port-forward to a pod (smart match); ports as trailing args |
raw |
Forward arguments to kubectl unchanged |
|
completion |
k completion bash or k completion zsh |
Run k with no arguments for a short status blurb, or k help for the full in-terminal list.
Plain grep scans each line for a literal pattern (or a regex with -E). The whole pattern must match the rule you give; a typo usually matches nothing.
k pods … builds tokens by splitting your arguments on spaces and hyphens, then keeps a pod only if every token matches (AND), where a token matches if:
- it is a substring of the full pod name, or
- it is a substring of some hyphen-separated segment of the name, or
- some segment is within 2 character edits of the token (for tokens and segments at least 5 characters long) — so small typos in a segment still match.
Example: k pods checkout-payments is like grepping checkout and payments on the same line (tokens checkout and payments). A mistyped middle segment such as paymnts can still match a pod whose segment is payments.
If nothing matches that way, k falls back to fuzzy search on the full name, then the same segment rules again.
For pods (logs, exec, describe, port-forward) and deployments (restart):
- Case-insensitive substring match on the resource name.
- If several match, prefer a unique prefix match.
- Otherwise you get an interactive list with type-to-filter (Fuse.js) over name and status.
Omitting the query where supported opens the picker against all resources in the current namespace.
Bash
source <(k completion bash)Zsh
source <(k completion zsh)Completion currently covers the first word (subcommands and aliases). For a machine-readable list: k __complete commands.
bun install
bun test
bunx tsc # typecheck (noEmit)