{"slug": "show-hn-k10s-a-clickable-kubernetes-tui-go-bubble-tea", "title": "Show HN: K10s – A Clickable Kubernetes TUI (Go, Bubble Tea)", "summary": "Developer p10node released k10s, a clickable Kubernetes terminal UI written in Go with the Bubble Tea framework, offering mouse support, a ctrl+p search across resource kinds and objects, and a ctrl+a AI assistant that injects the current context, namespace, kind and selected object into its prompt. k10s registers zero watches at startup and starts informers lazily per kind, and it ships an opt-in offline demo backend with a labelled sample cluster including a CrashLoopBackOff. The tool installs via a curl script for macOS and Linux on amd64 and arm64, or through go install github.com/p10node/k10s@latest, and supports k9s-style command plugins in ~/.k10s/plugins.yaml.", "body_md": "**k9s taught us to live in the terminal. k10s makes that terminal\npoint-and-click, instantly searchable, themeable - and gives it an AI that\nalready knows your cluster, namespace and selected object.**\n\n[Install](#install) · [Try it with no cluster](#try-it-in-30-seconds-no-cluster-required) ·\n[Features](#what-you-get) · [k9s → k10s](#coming-from-k9s) · [Docs](https://github.com/p10node/k10s/blob/main/docs/README.md) ·\n[Build log](https://github.com/p10node/k10s/blob/main/docs/build-in-public.md)\n\n<sub>A real terminal capture of `k10s demo` running - `just screenshot`, on the offline demo backend. Every frame in these docs comes out of the running binary, never hand-drawn.</sub>\n\nA cluster dashboard is something you open twenty times a day, usually while\nsomething is on fire. The two things that matter are **how fast it opens**\nand **how little you have to remember**.\n\n- **Nothing is hidden behind memorised keys.** The actions that apply to the\nthing you selected are listed, right there, in their own pane. Click one,\nor press the letter next to it.\n- **Your mouse works.** Click a row, click a pane, click`[ zoom ]` , click`ns default ▾` , scroll the table. Every border button is real.\n- **One search box for the whole cluster.**`ctrl+p` searches resource kinds*and* objects together. No prefix language to learn.\n- **It opens instantly.** Startup registers**zero** watches and waits for\nnothing - informers start lazily, per kind, the first time you look at\none. Opening Pods watches pods, not every Secret and Event you own.\n([how, and the regression guards](https://github.com/p10node/k10s/blob/main/docs/performance.md) )\n- **AI that can see the screen.**`ctrl+a` , ask in plain English. The current\ncontext, namespace, kind and selected object are injected into the prompt,\nso \"why is this pod unhealthy?\" means*this* pod.\n- **It updates itself.**`/update` installs the newest release over the\nrunning binary - checksum-verified, atomic, offers to restart into it.\n- **Your k9s-style command plugins fit.** Put scoped shortcuts in`~/.k10s/plugins.yaml` ; they appear beside built-in actions and receive the\nselected object, namespace, context and column values.\n\nk10s ships an offline demo backend: a realistic cluster to click around in,\nincluding a CrashLoopBackOff to poke at. It is **opt-in**, because sample\ndata should never be mistaken for your machine.\n\n```\ngit clone https://github.com/p10node/k10s && cd k10s\ngo run . demo     # the sample cluster - fake data, clearly labelled\ngo run .          # your real cluster, or \"No cluster\" if there isn't one\n```\n\nThe demo is a **context**, not a mode. `k10s demo` opens on it, `/demo`\nswitches to it from anywhere, and `:ctx` always lists it (labelled\n`k10s demo · sample data`, with a legend under the list). **To leave it,\npick any other context** - there is no separate exit. While it is up the\nheader carries a `DEMO` marker, so no frame of it can be mistaken for a real\ncluster.\n\nPlain `k10s` reads the same kubeconfig `kubectl` does (`$KUBECONFIG`, else\n`~/.kube/config`) and shows what that context can reach - and nothing else.\nWith no kubeconfig, or a context whose API server does not answer, the main\npanel says **No cluster** and points at the way in: `r` retries, `:ctx` picks\nanother context, `/setup` has the kubectl and kubeconfig links.\n[docs/cluster-setup.md](https://github.com/p10node/k10s/blob/main/docs/cluster-setup.md) is the same guide, longer.\n\n```\ncurl -fsSL https://p10node.com/k10s/install.sh | sh\n```\n\nmacOS and Linux, `amd64` and `arm64`. It picks the right prebuilt binary,\nverifies its sha256 against the release manifest, and installs it into\n`/usr/local/bin` (or `~/.local/bin` when that needs a password it cannot\nask for). `--dir`, `--version` and `--no-sudo` are in [docs/install.md](https://github.com/p10node/k10s/blob/main/docs/install.md),\nalong with how to read it before you run it and the matching\n`uninstall.sh`.\n\nWith Go on the box:\n\n```\ngo install github.com/p10node/k10s@latest\n```\n\nOr from a clone, which also stamps the version into the binary:\n\n```\ngit clone https://github.com/p10node/k10s && cd k10s\njust install                 # → $GOBIN/k10s, version-stamped\n```\n\nPrebuilt static binaries for **darwin/amd64, darwin/arm64, linux/amd64,\nlinux/arm64 and windows/amd64** are published on every tag — Windows is the\none platform the installer script sends to the\n[release page](https://github.com/p10node/k10s/releases) instead. Every later\nupgrade is just:\n\n```\nk10s update\n```\n\nThen run it:\n\n```\nk10s                  # your current kubeconfig context\nk10s demo             # the built-in sample cluster, no cluster needed\nk10s --readonly       # look, never touch: nothing that changes the cluster\nk10s --version        # which build is this\n```\n\n30 kinds across **Workloads · Network · Config · Storage · RBAC · Cluster ·\nCustom Resources**, each with a live row count for the current namespace.\nYour CRDs are discovered automatically - no configuration.\n\nGroups fold: `space`, `left` or a click on the header, remembered across\nrestarts, with Config/Storage/RBAC folded to begin with. A folded group also\nasks your cluster for nothing - the sidebar is what decides which kinds get\ncounted, and counting is one `limit=1` request per *visible* kind, six at a\ntime, with refusals remembered.\n\nPods · Deployments · ReplicaSets · StatefulSets · DaemonSets · Jobs · CronJobs · HPAs · Services · Endpoints · Ingresses · NetworkPolicies · ConfigMaps · Secrets · ResourceQuotas · LimitRanges · PDBs · PVCs · PVs · StorageClasses · ServiceAccounts · Roles · RoleBindings · ClusterRoles · ClusterRoleBindings · Nodes · Namespaces · Events · CRDs · Custom Resources\n\n| `d` describe | real `kubectl describe` output, from the API | \n| `y` YAML | the live object | \n| `l` logs | **follows** (`-f` ), newest at the bottom, scroll back 500 lines | \n| `s` shell | a real interactive exec session - raw TTY, resize-aware, in-panel | \n| `p` port-forward | real SPDY forward, start/stop from the pane | \n| `m` top | pod/node metrics, per container, with requests vs limits | \n| `e` edit ·`r` restart ·`c` scale | rollout restart, scale, `$EDITOR` | \n| `o` /`u` | cordon-uncordon / drain - offered only when Nodes is selected | \n| `D` delete | red confirm modal, because it should be scary | \n\nAdd your own scoped actions with the core k9s `plugins.yaml` format. They can\nrun foreground or background commands, request confirmation, override a\nbuilt-in shortcut deliberately, and are clickable in the same pane. See the\n[plugin guide and installable example](https://github.com/p10node/k10s/blob/main/docs/plugins.md).\n\n```\n╭─ logs -f billing-worker-6f8d9c5b7-qq91x ────────────────────────────────── [ close ] [ restore ] ╮\n│   8 2026-08-25T08:12:18.331Z INFO  http          GET  /v1/users/me         200 3.1ms             │\n│     trace=44b1e2f9                                                                               │\n│   7 2026-08-25T08:12:21.660Z INFO  worker        flushed batch size=250 dur=41ms                 │\n│   6 2026-08-25T08:12:25.019Z INFO  http          GET  /healthz             200 0.3ms             │\n│   5 2026-08-25T08:12:31.402Z INFO  http          DELETE /v1/sessions/9a1   204 5.7ms             │\n│     trace=7c0d19ba                                                                               │\n│   4 2026-08-25T08:12:33.881Z WARN  gc            pause=18ms heap=412Mi                           │\n│   3 2026-08-25T08:12:40.117Z INFO  http          GET  /v1/orders/88213     200 7.4ms             │\n│     trace=e21f8b05                                                                               │\n│   2 2026-08-25T08:12:44.590Z INFO  metrics       scrape ok series=1842                           │\n│   1 2026-08-25T08:12:51.008Z INFO  http          GET  /healthz             200 0.3ms             │\n│ ● following  newest at bottom                                        500 loaded · ↑ for older    │\n╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n╭─ Prompt · plain text → AI · /commands still work · esc close ─ [ grow ] [ AI · claude-sonnet-5 ] ╮\n│ ✦ ask about your cluster…   ·   /settings to change provider/model                               │\n╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n ● AI mode — plain text goes to claude-sonnet-5    tab panes · enter open · ctrl+p search · f find…\n```\n\n`ctrl+a` toggles it. Bring your own key - **OpenAI-compatible** (so also\nGroq, Together, OpenRouter, vLLM, Ollama, LM Studio, any local gateway) or\n**Anthropic**. Answers open as a normal text view you can scroll, zoom and\nclose. No cluster data leaves your machine unless you press enter in AI\nmode. The only other network call k10s makes on its own is the once-a-day\nupdate check, which asks GitHub for a version number and nothing else.\n\n`tokyo-night` (default) · `catppuccin-mocha` · `dracula` · `nord` ·\n`gruvbox-dark` · `solarized-dark` · `solarized-light` · `matrix`\n\n`T` cycles, `/theme` opens a picker that **applies each theme as you move\nthrough the list** - you judge it on the real UI, not on a name - and `esc`\nputs back whatever you had. Drop a YAML palette into `~/.k10s/themes`, restart,\nand it appears in the same picker — no rebuild needed. See the\n[custom-theme guide and installable demo](https://github.com/p10node/k10s/blob/main/docs/themes.md).\n\n- **Copy mode** (`ctrl+s` ) releases the mouse so your terminal can drag-select\nand copy - the one thing every mouse-capturing TUI breaks.\n- **An honest loading state** instead of \"no resources found\" while a watch\nis still syncing.\n- **Namespace and context pickers that never ask you to type a name.**\n- **No setup screen.** First run opens the cluster; every setting has a\nworking default and`/settings` is one keystroke away when you want it.\n- **A grow-able prompt** (`ctrl+z` ) - because a long kubectl line or an AI\nquestion does not fit in a one-row field that scrolls sideways.\n- **A terminal-too-small notice** instead of a garbled layout.\n\nk10s exists because of [k9s](https://github.com/derailed/k9s). Credit where\nit is due: k9s is mature, enormous in scope, plugin-extensible, and it is the\nreason a whole generation of us stopped typing `kubectl get pods` all day.\n\nk10s is younger and deliberately narrower. The difference is philosophy:\n\n|  | k9s | k10s | \n|---|---|---|\n| Primary input | keyboard-first, command-driven | **mouse *and* keyboard, equally** | \n| Discovery | you learn the commands | **the actions for the selected object are listed on screen** | \n| Search | per-view filter, plus `:` to jump between views | **one box (`ctrl+p`) over kinds *and* objects** | \n| AI | plugin territory | **built in, with cluster context injected** | \n| Scope | very large, plugin ecosystem | **small, opinionated, core command-plugin compatibility** | \n| Upgrades | your package manager | **`k10s update`, self-replacing** | \n\n**Use k9s if** you want the biggest feature surface, its full plugin ecosystem,\nand years of production mileage. **Use k10s if** you want something you can hand\nto a teammate who has never opened a TUI, and have them find `logs` on their\nown in ten seconds.\n\nThe short version - the [full reference is here](https://github.com/p10node/k10s/blob/main/docs/keybindings.md).\n\n| Key | Action | \n|---|---|\n| `tab` /`shift+tab` | cycle panes | \n| `↑↓` (`j` /`k` ) ·`pgup/pgdn` ·`g` /`G` | move · page · first/last | \n| type (Resources focused) | instant kind filter · `esc` clears | \n| `f` | find: search every column of the open table | \n| `ctrl+p` | **search everything** - kinds and objects in one box | \n| `enter` / double-click | open it: logs if it has them, else describe | \n| `z` | zoom / restore the centre pane | \n| `:` /`/` | command prompt (with a suggestions popup) | \n| `ctrl+a` | AI prompt mode ✦ | \n| `T` /`ctrl+t` | cycle themes | \n| `ctrl+s` | copy mode - release the mouse to select & copy | \n| click / wheel | anywhere in a pane selects it, blank space included | \n| `q` /`ctrl+c` | quit | \n\nTwo prefixes, and each one only ever shows its own set. **`/` is k10s itself\n(theme, settings, updates). `:` is the cluster, in the k9s vocabulary** - a\nresource view, the namespace, the context, or something acting on what is on\nscreen. `enter` runs the highlighted suggestion immediately - no second trip\nthrough the prompt.\n\n```\n/theme  /settings  /mouse  /update  /version  /demo  /setup  /help    k10s itself\n\n:po  :deploy  :rs  :sts  :ds  :job  :cj  :hpa      workloads\n:svc  :ep  :ing  :netpol                           network\n:cm  :sec  :quota  :limits  :pdb                   config\n:pvc  :pv  :sc                                     storage\n:sa  :role  :rb  :crole  :crb                      rbac\n:no  :ns  :ev  :crd  :cr                           cluster + custom\n\nthe short form is what the popup lists; every kind also answers to its\nplural and singular - :pods, :pod, :deployments, :persistentvolumes ...\nand `:aliases` prints the lot\n\n:po kube-system                 that kind, in that namespace (`all` works)\n:svc api                        an argument that is not a namespace filters\n:ns   :ctx                      namespace / context picker\n:ns <name>   :ctx <name>        switch either outright\n:aliases  :search <term>  :filter <term>  :scale <n>  :q\n```\n\n**`/` is k10s, `:` is the cluster** - namespace and context are `:ns` and\n`:ctx`, not `/ns` and `/context`. `:aliases` prints the whole `:` vocabulary.\n\nAnything that is not a `/` or `:` command **runs as a shell command** and its\noutput opens in the main panel - `date`, `kubectl get pods -o wide`,\n`helm list`. Run through your own `$SHELL`, capped at 30s, with no terminal\nattached (use `s` on a pod for an interactive shell).\n[Full command reference](https://github.com/p10node/k10s/blob/main/docs/commands.md).\n\nk10s opens on **kubeconfig's current-context** — the cluster `kubectl` would\ntalk to. `:ctx <name>` switches for the session without touching kubeconfig;\n`kubectl config use-context` is what changes where it opens next time.\n\nTheme, namespace, folded sidebar groups, AI settings and the update check\npersist to `~/.k10s/config.yaml` (override with `K10S_CONFIG`), saved on\nevery change.\nSee [config.md](https://github.com/p10node/k10s/blob/main/docs/config.md).\n\n**Note:** the AI API key is stored as plain text in that file (mode 0600)\nand masked in the UI. If that is not acceptable in your environment, leave\nit empty and AI mode simply stays off.\n\n| [architecture.md](https://github.com/p10node/k10s/blob/main/docs/architecture.md) | packages, the `Source` boundary, render pipeline, mouse zones | \n| [performance.md](https://github.com/p10node/k10s/blob/main/docs/performance.md) | lazy watches, cheap counts, and the guards that keep it fast | \n| [ui.md](https://github.com/p10node/k10s/blob/main/docs/ui.md) | layout, panes, focus, zoom, overlays | \n| [keybindings.md](https://github.com/p10node/k10s/blob/main/docs/keybindings.md) | full key + mouse reference | \n| [commands.md](https://github.com/p10node/k10s/blob/main/docs/commands.md) | prompt modes, slash commands, AI settings | \n| [themes.md](https://github.com/p10node/k10s/blob/main/docs/themes.md) | theme list, picker, palette contract | \n| [config.md](https://github.com/p10node/k10s/blob/main/docs/config.md) ·[update.md](https://github.com/p10node/k10s/blob/main/docs/update.md) | what persists · how self-update works | \n| [cluster-setup.md](https://github.com/p10node/k10s/blob/main/docs/cluster-setup.md) | no cluster? installing kubectl and getting a `~/.kube/config` | \n| [backends.md](https://github.com/p10node/k10s/blob/main/docs/backends.md) ·[dev.md](https://github.com/p10node/k10s/blob/main/docs/dev.md) | live vs demo backend · build, tests, headless renderer | \n| [roadmap.md](https://github.com/p10node/k10s/blob/main/docs/roadmap.md) | what is done, what is missing, and the known limits | \n| [marketing.md](https://github.com/p10node/k10s/blob/main/docs/marketing.md) ·[build-in-public.md](https://github.com/p10node/k10s/blob/main/docs/build-in-public.md) | how this project is being shared | \n\nThe barrier is low on purpose. `just` lists every recipe:\n\n```\njust dev            # run from source\njust shot 140 44    # render one frame headlessly - no TTY, no cluster\njust screenshot     # capture the README hero from a real terminal (vhs)\njust check          # fmt + vet + test, in the order that fails fastest\n```\n\n`cmd/shot` is why UI work here is pleasant: you can iterate on layout, replay\nkeystrokes (`just shot 140 44 j,j,d`) and diff frames without a terminal or a\ncluster. Nothing in these docs is drawn by hand - the frames come from that\nrenderer, the hero image from `just screenshot` driving the real binary in a\nreal terminal.\n\nGood first issues live in [roadmap.md → possible next\nsteps](https://github.com/p10node/k10s/blob/main/docs/roadmap.md#possible-next-steps): more kinds, click-to-sort\ncolumns, multi-select bulk delete, grep inside the log stream, saved views.\n\n**Honest status:** every live path is implemented against the real\nclient-go/kubectl APIs and covered by tests with fake clientsets, but this\ntree has not yet been smoke-tested against a production cluster by its\nauthor. Try it on `kind` first. The known limits are listed\n[in the roadmap](https://github.com/p10node/k10s/blob/main/docs/roadmap.md#known-limits) rather than buried.\n\nTo my colleagues - the people whose questions, over-the-shoulder debugging sessions and \"can you just check if that pod is up?\" pings are the entire reason this exists. k10s was not built to be a project; it was built so that looking at our clusters would stop being the annoying part of your day. Every pane in it is an answer to something one of you asked me. Thank you for the inspiration, the patience, and for being the first users.\n\n*Cảm ơn các đồng nghiệp của tôi - repo này được viết ra để phục vụ các bạn,\nvà chính các bạn là nguồn cảm hứng cho k10s.*\n\nTo [@derailed](https://github.com/derailed) and **k9s**, for proving a\nKubernetes TUI could be something you actually want to open.\n\nTo [Charm](https://github.com/charmbracelet) - **Bubble Tea**, **Lip Gloss**,\n**Bubbles** - and to [BubbleZone](https://github.com/lrstanley/bubblezone),\nwhich is the reason any of this is clickable at all.\n\n[Apache-2.0](https://github.com/p10node/k10s/blob/main/LICENSE) - the same license as Kubernetes, Helm and k9s. Use it,\nfork it, ship it inside your company.", "url": "https://wpnews.pro/news/show-hn-k10s-a-clickable-kubernetes-tui-go-bubble-tea", "canonical_source": "https://github.com/p10node/k10s", "published_at": "2026-10-08 18:29:06+00:00", "updated_at": "2026-10-08 18:48:45.559333+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "ai-agents"], "entities": ["p10node", "k10s", "Kubernetes", "Go", "Bubble Tea", "k9s"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-k10s-a-clickable-kubernetes-tui-go-bubble-tea", "markdown": "https://wpnews.pro/news/show-hn-k10s-a-clickable-kubernetes-tui-go-bubble-tea.md", "text": "https://wpnews.pro/news/show-hn-k10s-a-clickable-kubernetes-tui-go-bubble-tea.txt", "jsonld": "https://wpnews.pro/news/show-hn-k10s-a-clickable-kubernetes-tui-go-bubble-tea.jsonld"}}