kpf is a drop-in replacement for kubectl port-forward that makes it
easier to manage port forwarding sessions.
kpfalways starts connections in the background and just prints out a port number you can use.- If a session is already running, it succeeds immediately and just returns the existing port.
- The session manager runs as a single daemon process that you can connect to from any terminal.
- Sessions are kept alive for a configurable TTL that defaults to 30 minutes.
- Type any name like
kpf prometheusto search all ports for prometheus (services, pods, etc., across all namespaces). - Search can be scoped within a namespace, e.g.
-n my_namespaceand then get a fuzzy search with the options matching that search. - It uses
kubectlto live query the available ports, and also keeps a history of ports you've forwarded most recently, to speed up the search if you've forwarded before.
- Assign aliases for quick forwarding, e.g.
kpf -a prometheus- Then when you type
kpf prometheusit will choose that option
- Then when you type
- Aliases also show up first in the fuzzy-matching search options, in case you mistype them.
kpf aims to be compatible with kubectl port-forward:
- Accepts all the same arguments
- Has the same
--helpoutput - Supports tab completion
Modern coding agents can reliably execute this install prompt:
1. Install github.com/bduffany/kpf@latest with go install
2. Install the agent skills from that repo.
3. Set up shell completion for kpf (see kpf repo README)
4. Install fzf, which is needed for kpf's search feature: github.com/junegunn/fzf
Install with go:
go install github.com/bduffany/kpf@latestThis installs kpf into $GOBIN (or $(go env GOPATH)/bin if GOBIN is unset).
Optionally install bash completion by adding this to your .bashrc
(docs for other shells below)
source <(kubectl completion bash)
complete -o default -F __start_kubectl kpfkpf --context=... --cluster=... --namespace=... pod/mypod 8080
# prints the chosen local portkpf --namespace=default svc/my-service 9999:8080
# prints 9999kpf --fg --namespace=default svc/my-service :8080
# runs kubectl port-forward in the foreground (no daemon)kpf -a vmselect
# save or update alias "vmselect"; uses picker if args are underspecifiedkpf -a vmselect -n monitor-prod svc/victoria-metrics-cluster-global-vmselect :8481
# save or update alias "vmselect" from explicit argskpf
# bare picker shows history plus live discovered candidates; alias matches are shown as "<args> # <portname> (alias)"kpf supports kubectl's completion protocol (__complete /
__completeNoDesc) and proxies those requests to kubectl port-forward.
source <(kubectl completion bash)
complete -o default -F __start_kubectl kpfsource <(kubectl completion zsh)
compdef __start_kubectl kpfSupports all options from kubectl port-forward, plus:
--alias, -a NAME:
Save or update NAME from resolved args and exit.
--list:
Print available port-forward targets discovered by kpf and exit.
--fg, -f:
Run kubectl port-forward in the foreground. Do not use the kpf daemon.
--ttl=30m0s:
Session TTL for daemon-managed forwards. Accepts Go duration values like 30m or 1h.
Can also be set via KUBECTL_PORT_FORWARD_TTL (the --ttl flag takes higher priority).
- Uses a background daemon that keeps sessions alive for 30 minutes of
inactivity by default (
KUBECTL_PORT_FORWARD_TTLor--ttlargs allow per-session overrides). - Uses a daemon unix socket:
- Linux:
/run/user/$UID/portfwd.sock - macOS:
/tmp/kpf-$UID/portfwd.sock
- Linux:
- Reuses existing forward sessions only when the request matches exactly
after normalization.
- A match includes all of:
- Normalized
kubectl port-forwardargs (same order, same values). - Resolved kube identity (
context,cluster,server,user,namespace). - Session TTL.
- Normalized
- Normalization rules:
- Leading
port-forwardis removed, sokpf port-forward ...andkpf ...match. --ttlis removed from args and stored as session TTL.- Port mappings are canonicalized:
8080and:8080both become:8080.09999:8080becomes9999:8080.
- Leading
- Examples:
- Reused:
kpf pod/api 8080andkpf pod/api :8080 - Not reused:
kpf -n team-a pod/api 8080andkpf -n team-b pod/api 8080 - Not reused:
kpf -n team-a pod/api 8080andkpf --namespace=team-a pod/api 8080(different arg forms)
- Reused:
- A match includes all of:
- Renews TTL when kubectl logs
Handling connection for .... - If local/source port is omitted, chooses a random local port.