README
¶
km8 — KubeMate
A terminal UI for Kubernetes, inspired by Lens IDE, lazygit, lazydocker, and k9s. Built with Go and Bubble Tea.

Features
- 17 built-in resource types + CRD support -- dynamic discovery of Custom Resources at startup
- Real-time Watch updates -- resources refresh automatically via Kubernetes Watch API
- Vim-style navigation --
j/k,u/dpage scroll,gg/G,/search - 3-panel lazygit-style layout -- numbered sidebar, list, and detail panels with scroll indicator
- Drill-down navigation -- Deployment → Pods → Containers
- YAML detail view with syntax highlighting --
[YAML]tab shows the resource serialized exactly likekubectl get -o yaml; container drill-down shows the extractedspec/statusfor that container - Pod log streaming with auto-follow -- multi-container support with
<container>|<log>format; the Logs tab sticks to the tail by default (a▼marker in[3] Logs ▼shows follow is active). Scroll up (k/↑/u/gg) to pause and read history; pressGto catch up and resume following - Container shell exec --
kubectl execinto any container - In-place resource editing -- fetches YAML with
kubectl get -o yaml, opens$EDITOR, applies withkubectl apply -fif the file changed; skips apply on no-op saves. Uses declarative apply semantics — see Editing Resources for implications - Resource deletion --
Dwith confirmation dialog - Search/filter --
/to search in all three panels and in the namespace/context picker popups - Clipboard copy (
y) -- copies the focused panel's content via OSC 52 (works through tmux/SSH, noxclip/pbcopyrequired) - Namespace and context switching --
n/c - Detail tabs -- YAML / Events / Logs (Logs tab only for Pods)
- Long values wrap, never truncate -- applies to YAML, Events, and Logs; wrap points reflow on panel resize
- Panel expand --
=/-to toggle full-screen Table or Detail panel - Theme system -- drop a
theme.yamlinto config directory to override colors - Help & App Log overlays --
?/!popup on top of main UI - Error notifications -- status bar badge + status line message
- Crash logging -- panics written to the km8 log directory
- Audit logging -- every
kubectl editandkubectl deleterecorded toaudit-*.log
Installation
Quick Install (macOS/Linux)
curl -fsSL https://raw.githubusercontent.com/vulcanshen/km8/main/install.sh | sh
Quick Install (Windows PowerShell)
irm https://raw.githubusercontent.com/vulcanshen/km8/main/install.ps1 | iex
Homebrew (macOS/Linux)
brew install vulcanshen/tap/km8
Scoop (Windows)
scoop bucket add vulcanshen https://github.com/vulcanshen/scoop-bucket
scoop install km8
From source
go install github.com/vulcanshen/km8/cmd@latest
Uninstall
# macOS/Linux
curl -fsSL https://raw.githubusercontent.com/vulcanshen/km8/main/uninstall.sh | sh
# Windows PowerShell
irm https://raw.githubusercontent.com/vulcanshen/km8/main/uninstall.ps1 | iex
Build locally
git clone https://github.com/vulcanshen/km8.git
cd km8
go build -o km8 ./cmd/
./km8
Quick Start
km8
Connects to your current kubeconfig context. Use n to switch namespaces, c to switch contexts.
Key Bindings
Navigation
| Key | Action |
|---|---|
j / k |
Move cursor up / down |
u / d |
Page up / down |
gg / G |
Jump to top / bottom |
1 / 2 / 3 |
Switch panel |
Tab |
Cycle panels |
Table (Panel 2)
| Key | Action |
|---|---|
/ |
Search / filter |
Enter |
Drill down |
e |
Edit resource (get → editor → apply) |
D |
Delete resource |
s |
Shell into container |
Detail (Panel 3)
| Key | Action |
|---|---|
h / l |
Switch tab (YAML / Events / Logs) |
= / - |
Expand / restore panel |
G |
Jump to bottom (on Logs: also resumes follow-tail) |
k / ↑ / u / gg |
Scroll up (on Logs: pauses follow-tail) |
Global
| Key | Action |
|---|---|
n |
Switch namespace (/ to filter inside the popup) |
c |
Switch context (/ to filter inside the popup) |
y |
Copy focused panel content to clipboard (OSC 52) |
! |
App log |
? |
Toggle help |
q / Esc |
Quit / back |
Editing Resources
Pressing e on a resource runs a three-step flow:
- Fetch —
kubectl get <resource> -o yaml --context <ctx>writes the YAML to a temp file - Edit — your
$EDITORopens the temp file (editor resolution:config.yaml editor→$VISUAL→$EDITOR→vi/notepad) - Apply — if the file changed,
kubectl apply -f <tmpfile> --context <ctx>is run; if nothing changed, the apply is skipped entirely
Differences from kubectl edit:
km8 e |
kubectl edit |
|
|---|---|---|
| Apply method | kubectl apply (declarative) |
Strategic merge patch |
| Concurrency check | None — no resourceVersion enforcement |
Uses resourceVersion to detect conflicts |
| Annotation side-effect | Sets last-applied-configuration |
Does not set it |
Because km8 uses kubectl apply, it is not suitable for resources actively managed by Helm or operators — the annotation may interfere with their reconciliation loop. For those resources, use kubectl edit directly.
Context Isolation
km8 maintains its own session-local context. Switching context with c inside km8 does not modify ~/.kube/config or the KUBECONFIG environment variable in any other terminal.
All kubectl subprocesses spawned by km8 (edit, delete, shell exec) receive an explicit --context <name> flag, so they always target the cluster km8 is showing — regardless of what kubectl's default context is set to.
This means you can safely run km8 in one terminal while using kubectl in another without either session interfering with the other's context.
Configuration
Config files are in the OS-appropriate config directory. Set XDG_CONFIG_HOME to override on any platform:
| OS | Default Path |
|---|---|
| Linux | $XDG_CONFIG_HOME/km8/ or ~/.config/km8/ |
| macOS | ~/Library/Application Support/km8/ |
| Windows | %APPDATA%/km8/ |
Logs (crash and audit) are written to the logs/ subdirectory of the config directory.
config.yaml
default_context: "" # kubeconfig context (default: current-context)
default_namespace: "" # namespace filter (default: all namespaces)
editor: "" # editor override (default: $VISUAL → $EDITOR → vi)
theme.yaml
Drop a theme.yaml to customize colors. Only override what you need -- unspecified fields keep defaults.
sidebar:
background: "" # empty = terminal transparent
foreground: "#cdd6f4"
selected_bg: "#45475a"
selected_fg: "#cdd6f4"
category_fg: "#89b4fa"
table:
header_bg: "#313244"
header_fg: "#89b4fa"
row_fg: "#cdd6f4"
selected_row_bg: "#45475a"
selected_row_fg: "#cdd6f4"
alternating_bg: ""
detail:
border_color: "#585b70"
label_fg: "#89b4fa"
value_fg: "#cdd6f4"
tab_active_bg: "#45475a"
tab_active_fg: "#cdd6f4"
tab_inactive_fg: "#6c7086"
status_bar:
background: "#181825"
foreground: "#cdd6f4"
cluster_fg: "#a6e3a1"
namespace_fg: "#f9e2af"
context_fg: "#89b4fa"
status_line:
background: "#313244"
foreground: "#a6adc8"
status:
running: "#a6e3a1"
pending: "#f9e2af"
error: "#f38ba8"
unknown: "#6c7086"
Requirements
- kubectl on
$PATH(for edit, delete, and shell exec) - A valid kubeconfig (
~/.kube/configor$KUBECONFIG) - A running Kubernetes cluster