Kubernetes Status
An Omarchy bar widget that shows which kubectl context is live, with production highlighted in your theme's accent colour, and cluster health in a popup.
The problem it solves is not monitoring. It is that kubectl acts on whichever context
happens to be current, in every terminal, in every project — and nothing on screen says
which one that is. If one of your contexts is production, that is a mistake waiting to
happen. This puts the answer in the bar.
Cluster health is the secondary payload and lives in the panel, not the bar. A green dot that is green 99.9% of the time is a dot you stop seeing; real alerting belongs in Alertmanager, not a bar pixel.
Install
omarchy plugin add https://github.com/edwardpayne/omarchy-kube-status.git --enable
Requires kubectl and jq on PATH. openssl is optional and enables client-certificate
expiry warnings. k9s is optional and powers the panel's one action.
Usage
| Interaction | Result |
|---|---|
| Left click | Open or close the details panel |
| Right click | Force a re-check now |
r in the panel |
Refresh |
o, Enter, or Space in the panel |
Open the cluster in k9s |
Esc |
Close |
The bar splits its two jobs across two elements, rather than tinting one label with both.
The name tells you which cluster. Accent-coloured and bold when the context matches
prodPattern, normal otherwise. It never dims — leaving the LAN does not make you less
sure of the cluster's name, and the name is the part worth knowing when you are about to
type a command.
The glyph tells you how that cluster is doing.
| Glyph | Meaning |
|---|---|
| normal | healthy |
| accent-red | worth a look — unhealthy pods, or a client cert expiring soon |
| urgent | actually broken — a node down, an expired cert, or authorization refused |
| dim | cannot reach the cluster from here |
Leaving the LAN or dropping the VPN is an ordinary event, not a failure, so it changes the glyph's shape rather than turning it red. The alarm colour stays meaningful by staying rare. A dimmed copy of the normal glyph would read as "switched off", which is a different and wrong message — hence a separate disconnect icon.
Icon-only bars (vertical, or showContextLabel: false) have no name to colour, so there
the glyph carries production as well. Warn is deliberately a blend leaning towards the
alarm colour rather than plain accent, so that on those bars a production cluster with
something wrong is still distinguishable from a healthy one.
The context label comes straight from your kubeconfig, watched for changes, so
kubectl config use-context in any terminal is reflected in about a second without
waiting for the next poll — and it keeps working when the cluster is unreachable.
Configure
Omarchy has no per-plugin config files. Bar widgets are configured inline in their own
entry in ~/.config/omarchy/shell.json, under bar → layout → section. The shell
hot-reloads that file on save, so no restart is needed.
Nothing here is required — every key defaults, and { "id": "io.github.edwardpayne.kube-status" }
on its own is a complete, working configuration.
{
"bar": {
"layout": {
"right": [
{ "id": "omarchy.tray" },
{
"id": "io.github.edwardpayne.kube-status",
"refreshIntervalSec": 120,
"prodPattern": "live",
"k9sCommand": "k9s --readonly"
},
{ "id": "omarchy.power" }
]
}
}
}
| Key | Default | Range | Notes |
|---|---|---|---|
refreshIntervalSec |
60 |
15–3600 | Health poll cadence. The context name does not wait for it — that comes from a file watch and updates in about a second. A long interval costs you nothing on the part that matters |
commandTimeoutSec |
8 |
3–30 | Hard ceiling on every kubectl call. Raise on a slow link; lower to see the disconnect icon sooner when you leave the LAN |
certWarnDays |
30 |
1–365 | How far ahead to warn about client-certificate expiry. Raise for long-lived certs. Ignored for token/OIDC/exec auth |
maxBadPods |
5 |
1–50 | How many unhealthy pods to name in the panel. The count is always exact; the panel says "+N more" when it truncates |
prodPattern |
prod |
— | Case-insensitive substring of the context name, not a regex. "" disables the highlight |
showContextLabel |
true |
— | false renders icon-only. Vertical bars are always icon-only |
k9sCommand |
k9s |
— | Launched in a floating terminal by the panel button. Arguments are fine — k9s --readonly is a good choice if production is one of your contexts |
Every value is clamped on read, so an out-of-range or misspelled number falls back to its default rather than breaking the widget.
example-config.jsonc is the annotated reference — every
option explained in place, plus worked examples for a battery-conscious laptop, production
contexts not named "prod", a read-only cluster browser, and icon-only mode.
Move it with omarchy bar move io.github.edwardpayne.kube-status --section right --index 1.
Check what the plugin currently sees:
jq '.bar.layout | .[] | .[] | select(.id | test("kube-status"))' ~/.config/omarchy/shell.json
The underlying command is runnable by hand, which is the fastest way to tell a plugin problem from a cluster problem:
~/.config/omarchy/plugins/io.github.edwardpayne.kube-status/kube-status.sh
./kube-status.sh 8 90 15 # timeout, cert-warn days, max bad pods
Note: this plugin ships a
barWidget.schemain its manifest describing all of the above. As of Omarchy 4.0.0 the shell stores that schema but no UI renders it — Setup > Plugins only enables, disables, adds, clones, and removes. Configuration means editingshell.json. The schema is there for when a settings panel lands.
Read-only, by design
This widget never writes to a cluster and never changes your context. No restarts, no
deletes, no use-context. A widget one misclick away from acting on production is not
worth the saved keystroke — switching stays a deliberate terminal action.
Notes for the curious
kubectl --request-timeout does not cover TCP connect: against a black-holed API server
it will hang indefinitely. Every call is therefore wrapped in timeout(1), and the widget
refuses to start a second check while one is in flight. Verified under deliberate pressure
(15s timer against 30s calls): concurrent invocations peak at one, and the poll self-paces
instead of stacking.
With client-certificate auth an expired cert does not produce Unauthorized — the API
server drops the TLS connection and kubectl reports a bare error: EOF, indistinguishable
from a dropped VPN. Since the two call for completely different fixes, the cert's expiry is
checked locally and reported as its own state, with a warning 30 days ahead.
Remove
omarchy plugin remove io.github.edwardpayne.kube-status
License
MIT — see LICENSE.