kl

March 22, 2026 · View on GitHub

Latest Release GoDoc Build Status

An interactive Kubernetes log viewer for your terminal.

gif demo of kl
  • View logs across multiple containers, pods, namespaces, and clusters
  • Select containers interactively or auto-select by pattern matching against names, labels, and more
  • See cluster changes in real time
  • Navigate logs from multiple containers interleaved by timestamp
  • Search logs by exact string or regex pattern. Show or hide surrounding context
  • Pretty-print structured logs inline
  • Zoom in and flip through single pretty-printed logs one by one
  • Color themes with accessible ANSI colors by default
  • Archive and share: save logs to a local file or copy a log to your clipboard

Comparable to:

  • kubectl logs supercharged
  • k9s but specializing in logs
  • stern & kail but multi-cluster and with an interactive interface

Usage

Install and run kl in a terminal. See kl --help for all options.

Examples:

# Use the current kubernetes context, defaulting to `default`
kl

# Use context `my-context`, all namespaces
kl --context my-context -A

# Use contexts `my-context` & `other-context`, namespaces `default` & `other-ns` in each context
kl --context my-context,other-context -n default,other-ns

# Auto-select containers with a pod owner (e.g. deployment) containing the word `nginx`
kl --mown nginx

# Auto-select containers with the exact name `my-container`, limited to 10 containers
kl --mc "^my-container$" --limit 10

# Auto-select containers that have labels app=flask and either tier=stage or tier=prod
kl -l 'app=flask,tier in (stage, prod)'

# Ignore containers with the exact name of `my-sidecar`
kl --ic "^my-sidecar$"

# Start focused on logs, ordered by timestamp descending, showing logs from 10 minutes ago onwards
kl --mc "^my-container$" -d --logs-view --since 10m

# Use the classic color theme (256-color/true-color)
kl --theme classic

# Disable colors entirely
kl --theme none
NO_COLOR=1 kl

Press ? in any view to see keyboard shortcuts specific to the current view and across the application.

KeyAction
enterselect/deselect containers
Rdeselect all containers
↓/jdown
↑/kup
dhalf page down
uhalf page up
fpage down
bpage up
gtop
Gbottom
lfocus logs view
Llogs view fullscreen
enterzoom on log
shift+scroll within single log view
escback to all logs
sfocus container selection view
Sselection view fullscreen
Ftoggle fullscreen
/edit filter
rregex filter
icase insensitive regex filter
enterapply filter
escdiscard filter
nnext filter match
Nprev filter match
xshow matching logs only
wtoggle line wrap
ppretty-print logs
←/→pan left/right when unwrapped
oreverse timestamp order
Ppause/resume logs
tshow short/full/no timestamps
cshow short/full/no identifiers
0-9change log start time
ctrl+ssave focused view to file
ctrl+ycopy zoomed log
ctrl+cquit
?show/hide help

Installation

The following installation options are available:

# homebrew
brew install robinovitch61/tap/kl

# upgrade using homebrew
brew update && brew upgrade kl

# nix-shell
# ensure NUR is accessible (https://github.com/nix-community/NUR)
nix-shell -p nur.repos.robinovitch61.kl

# nix flakes
# ensure flake support is enabled (https://nixos.wiki/wiki/Flakes#Enable_flakes_temporarily)
nix run github:robinovitch61/nur-packages#kl

# arch linux
# PKGBUILD available at https://aur.archlinux.org/packages/kl-bin
yay -S kl-bin

# with go (https://go.dev/doc/install)
go install github.com/robinovitch61/kl@latest

# windows with winget
winget install robinovitch61.kl

# windows with scoop
scoop bucket add robinovitch61 https://github.com/robinovitch61/scoop-bucket
scoop install kl

# windows with chocolatey
choco install kl

You can also download prebuilt releases and move the unpacked binary to somewhere in your PATH.

Development

kl is written with tools from Charm.

Feature requests and bug reports are welcome.

Running the app with the environment variable KL_DEBUG=1 will create or append to a kl.log file in your current directory with debug logs.

To manually build the project:

git clone git@github.com:robinovitch61/kl.git
cd kl
go build  # outputs ./kl executable

Run an example flask + postgres + nginx setup in a local k3d cluster for testing locally:

k3d cluster create mycluster
k3d cluster create myothercluster
kubectl --context k3d-mycluster apply -f ./dev/deploy.yaml
kubectl --context k3d-myothercluster create namespace otherns
kubectl --context k3d-myothercluster apply -f ./dev/deploy.yaml -n otherns

# view both clusters and both namespaces in kl
kl --context k3d-mycluster,k3d-myothercluster -n default,otherns

# use -A to include all namespaces (e.g. kube-system) in each cluster
kl --context k3d-mycluster,k3d-myothercluster -A

# access the application's webpage
kubectl --context k3d-myothercluster -n otherns port-forward services/frontend-service 8080:80
open http://localhost:8080

# browser console one-liner to click button every second to generate logs
setInterval(() => { document.getElementsByTagName("button")[0].click(); }, 1000);

# or make requests directly to flask from the terminal
kubectl --context k3d-myothercluster port-forward services/flask-service 5000:5000
curl http://localhost:5000/status

To run with profiling available, set the environment variable KL_PPROF_SERVER=1, run the app, then run e.g.

# web ui for memory profile
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"

# web ui for cpu profile
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/profile?seconds=15"

# explore memory profile in terminal
go tool pprof "http://localhost:6060/debug/pprof/heap"
> top
> peek ...
> traces ...

# explore cpu profile in terminal
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=15"
> top
> peek ...
> traces ...

Manually Specify the kl Version at Build Time

If necessary, you can manually specify the output of kl --version at build time as follows:

go build -ldflags "-X github.com/robinovitch61/kl/cmd.Version=vX.Y.Z"

In this case, you're responsible for ensuring the specified version matches what is being built.