Skip to main content

TUI for kubectl port-forward

Project description

kpf - A TUI for port-forwarding with kubectl

kpf is a Python utility that (attempts to) dramatically improve the experience of port-forwarding with kubectl.

It is essentially a wrapper around kubectl port-forward that adds interactive service selection with automatic reconnects when pods restart or your network connection is interrupted (computer goes to sleep, etc.).

This should be compatible with the kpf alias that you may already have.

If you like this, check out https://github.com/jessegoodier/kdebug, a TUI for debug containers in Kubernetes pods with interactive shell access and backup capabilities.

Demo

Demo of the TUI and the reconnect when a pod is restarted: kpf demo

Features

  • Automatic Connection Restarting: Monitors endpoint changes and restarts port-forward automatically
  • Multi-resource Support: Services, pods, deployments, etc.
  • Smart Port Handling: Automatically detects privileged port issues (< 1024) and suggests alternatives
  • History (MRU): Run kpfh to jump straight to a frecency-ranked history of your most-used port-forwards, or press h in the interactive selector to do the same inline

Installation

Note: The oh-my-zsh kubectl plugin will conflict with this kpf command. You must unalias kpf before using this tool.

echo "unalias kpf 2>/dev/null" >> ~/.zshrc

Homebrew (Recommended)

Other methods do not automatically install command completions.

brew tap jessegoodier/kpf
brew install kpf

Or install directly:

brew install jessegoodier/kpf/kpf

Using uv

uv tool install kpf

from source:

uv tool install .

Usage

Interactive Mode

Warm Tip: You can use the interactive mode to find the service you want, and it will output the command to connect to that service directly next time.

Note: You might think that "warm tip" is something that AI wrote, but that's not the case. It really is just a little bit cooler than a hot tip.

Visual explanation of the features. TUI selection not shown, just the output after selection. screenshot1

Check which endpoints are up on entire cluster (can be slow): screenshot2

Select services interactively:

Interactive selection in current namespace:

kpf

Interactive selection in specific namespace:

kpf -n production

Interactive selection with namespace prompt:

kpf -p

Show all services across all namespaces:

kpf --all

Include pods and controllers with ports defined:

kpf --all-ports

Combine a few options (interactive mode, all services, and endpoint status checking, debug mode):

kpf -pAdl

History Mode

kpfh is a dedicated command that jumps straight to the frecency-ranked history of your most-used port-forwards — no service-list browsing required. You can also press h at any service selection screen inside kpf to open the same history menu inline.

Enable history once, then use kpfh or press h anytime:

By default, kpf does not have a settings file and does not record command history. You must enable this using the configuration wizard or by creating the ~/.config/kpf/kpf.json file.

kpf --create-config

or

mkdir -p ~/.config/kpf
echo '{"saveCommandHistory": true}' > ~/.config/kpf/kpf.json

Entries are ranked by frecency — a blend of frequency and recency — so services you use often and recently float to the top. Selecting an entry replays the exact session (service, namespace, ports, and cluster context). Press Esc or q to return to the full service list without making a selection.

Health Check Mode

Add endpoint status checking to service selection (slower but shows endpoint health):

# Interactive selection with endpoint status
kpf --check

# Show all services with endpoint status
kpf --all --check

# Include pods and deployments with status
kpf --all-ports --check

Direct Command Mode

Direct port-forward (maintains expected behavior for previous kpf aliases):

# Traditional kubectl port-forward syntax can be used with kpf
kpf svc/frontend 8080:8080 -n production
kpf pod/my-pod 3000:3000

Command Options

Example usage:
  kpf                                           # Interactive mode
  kpf svc/frontend 8080:8080 -n production      # Direct port-forward (maintains expected behavior)
  kpf -n production                             # Interactive selection in specific namespace
  kpf --all (or -A)                             # Show all services across all namespaces
  kpf --all-ports (or -l)                       # Include pods and controllers with ports defined
  kpf --check -n production                     # Interactive selection with endpoint status
  kpf --prompt-namespace (or -p)                # Interactive namespace selection
  kpf --listen-all (or -z)                      # Listen on 0.0.0.0 (all interfaces)
  kpfh                                          # Jump straight to frecency history

Examples

Interactive Service Selection

Fast mode (without endpoint checking):

$ kpf -n kube-system

Services in namespace: kube-system

#    Type     Name                    Ports
1    SERVICE  kube-dns                53, 9153
2    SERVICE  metrics-server          443
3    SERVICE  kubernetes-dashboard    443

Select a service [1]: 1
Local port (press Enter for 53): 5353

With endpoint status checking:

$ kpf --check -n kube-system

Services in namespace: kube-system

#    Type     Name                    Ports           Status
1    SERVICE  kube-dns                53, 9153          2    SERVICE  metrics-server          443               3    SERVICE  kubernetes-dashboard    443               ✗

✓ = Has endpoints   = No endpoints

Select a service [1]: 1
Local port (press Enter for 53): 5353

Cross-Namespace Discovery

$ kpf --all

Services across all namespaces

#    Namespace    Type     Name           Ports        Status
1    default      SERVICE  kubernetes     443            2    kube-system  SERVICE  kube-dns       53, 9153       3    production   SERVICE  frontend       80, 443        4    production   SERVICE  backend        8080           

Smart Low Port Handling

When you try to use privileged ports (< 1024), kpf will detect the permission issue and offer to use a higher port automatically:

$ kpf -n monitoring svc/grafana 80:80

Error: Port 80 requires elevated privileges (root/sudo)
Low ports (< 1024) require administrator permissions on most systems

Suggested alternative: Use port 1080 instead?
This would forward: localhost:1080 -> service:80

Use suggested port? [Y/n]: y
Updated port mapping to 1080:80

Direct command: kpf svc/grafana 1080:80 -n monitoring

http://localhost:1080

🚀 port-forward started 🚀

This feature prevents confusing "port already in use" errors when the real issue is insufficient permissions.

How It Works

  1. Port-Forward Thread: Runs kubectl port-forward in a separate thread
  2. Endpoint Watcher: Monitors endpoint changes using kubectl get ep -w
  3. Network Watchdog: Checks both K8s API connectivity and local port health every 5 seconds to detect zombie connections (e.g., after laptop sleep/wake). This catches cases where the API is reachable but the port-forward tunnel is dead.
  4. Automatic Restart: When endpoints change or connectivity is lost, gracefully restarts the port-forward
  5. Service Discovery: Uses kubectl to discover services and their endpoint status

Requirements

  • kubectl configured with cluster access

Configuration

kpf can be configured via ~/.config/kpf/kpf.json (follows XDG Base Directory Specification).

If you create this file, it is suggested to only change the values you want to override in case improvements are made in the future.

{
  "autoSelectFreePort": true,
  "alwaysListenAll": false,
  "showDirectCommand": true,
  "showDirectCommandIncludeContext": true,
  "showDirectCommandIncludeKubeconfig": true,
  "autoReconnect": true,
  "reconnectAttempts": 30,
  "reconnectDelaySeconds": 5,
  "saveCommandHistory": false,
  "saveHistoryLocation": "~/.config/kpf/command-history",
  "restartThrottleSeconds": 5,
  "networkWatchdogEnabled": true,
  "networkWatchdogInterval": 5,
  "networkWatchdogFailureThreshold": 2
}

Example: Disable auto-reconnect

mkdir -p ~/.config/kpf
echo '{"autoReconnect": false}' > ~/.config/kpf/kpf.json

Configuration Options

Option Type Default Description
autoSelectFreePort boolean true When the requested local port is busy, automatically try the next free port
alwaysListenAll boolean false Always bind to 0.0.0.0 instead of localhost
showDirectCommand boolean true Show the direct kpf command for future use
showDirectCommandIncludeContext boolean true Include kubectl context in the command display
showDirectCommandIncludeKubeconfig boolean true Include non-default kubeconfig paths in the command display
autoReconnect boolean true Automatically reconnect when connection drops
reconnectAttempts integer 30 Number of reconnection attempts before giving up
reconnectDelaySeconds integer 5 Delay in seconds between reconnection attempts
saveCommandHistory boolean false Record session details locally; enables the h history menu in the TUI
saveHistoryLocation string ~/.config/kpf/command-history Where to store usage detail logs
restartThrottleSeconds integer 5 Minimum seconds between automatic restarts
networkWatchdogEnabled boolean true Monitor K8s API and local port connectivity to detect zombie connections
networkWatchdogInterval integer 5 Seconds between connectivity checks
networkWatchdogFailureThreshold integer 2 Consecutive failures before triggering restart

Notes:

  • All settings are optional - kpf will use defaults if the config file doesn't exist
  • Use ~ in path values to refer to your home directory
  • The config file location respects the XDG_CONFIG_HOME environment variable
  • Invalid JSON or unknown keys will show warnings but won't prevent kpf from running
  • CLI arguments override config file values when provided

Development

Prerequisites

Setup Development Environment

# Clone the repository
git clone https://github.com/jessegoodier/kpf.git
cd kpf
# Install with development dependencies and create venv
just dev-setup

Code Quality Tools

# Format and lint code
just format
# Run tests
just test

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests and linting
  5. Submit a pull request

Shell Completion

Shell completions can be generated using the --completions flag.

Homebrew

If you install via Homebrew, completions should be installed automatically. You may need to follow Homebrew's shell completion instructions to ensure it's loaded. You may find the bash and zsh examples here useful.

Manual Installation

Bash

# User-local installation (recommended)
kpf --completions bash > ~/.local/share/bash-completion/completions/kpf

# Or system-wide
kpf --completions bash | sudo tee /etc/bash_completion.d/kpf > /dev/null

Zsh

# Add to a directory in your fpath
kpf --completions zsh > /usr/share/zsh/site-functions/_kpf

# Or for oh-my-zsh users
kpf --completions zsh > ~/.oh-my-zsh/completions/_kpf

Then reload your shell: exec $SHELL

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kpf-0.12.5.tar.gz (48.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kpf-0.12.5-py3-none-any.whl (55.5 kB view details)

Uploaded Python 3

File details

Details for the file kpf-0.12.5.tar.gz.

File metadata

  • Download URL: kpf-0.12.5.tar.gz
  • Upload date:
  • Size: 48.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for kpf-0.12.5.tar.gz
Algorithm Hash digest
SHA256 3d58a9b7f2af74222a32fd37cb114a3abd183b2b72c182e1df0fe1d1083dbe40
MD5 e8c843e59e0d55f4e187ed8046d7e2db
BLAKE2b-256 6bbef5dbc12d0e548e84f8922a49fb79fa5957c6acc3680d0a08cedd5f5acf74

See more details on using hashes here.

File details

Details for the file kpf-0.12.5-py3-none-any.whl.

File metadata

  • Download URL: kpf-0.12.5-py3-none-any.whl
  • Upload date:
  • Size: 55.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for kpf-0.12.5-py3-none-any.whl
Algorithm Hash digest
SHA256 bb9b3a564584ff505963bdadcbeaa76ebd37ffc5fc1574687332bc302720e277
MD5 2636f88eebe8ebc3dcb6cfe221bed7c9
BLAKE2b-256 89220f9817b35a4dcced2d00ad3e2f67e7ea3aa81698deb47a037e85e778ffd0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page