# kubernetes-el: running kubectl from inside Emacs

> kubernetes-el is an Emacs Lisp package that puts a Kubernetes client in the editor, with views for pods, deployments, services, ingresses, logs and exec, and a mode that takes over the buffer the way a Dired view would. The whole client is written in Emacs Lisp and talks to the cluster with kubectl under the hood.

**kubernetes-el/kubernetes-el** — Manage Kubernetes clusters with Emacs.

- Repository: https://github.com/kubernetes-el/kubernetes-el
- Website: https://kubernetes-el.github.io/kubernetes-el
- Stars: 689 · Forks: 68
- Language: Emacs Lisp
- License: GPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/kubernetes-el-kubernetes-el

## A cluster client written in Emacs Lisp

kubernetes-el manages Kubernetes clusters with Emacs, and the implementation detail that defines it is the language: the package is Emacs Lisp, and the primary language of the repository is recorded as Emacs Lisp.

The consequence is visible in the file listing. There is no compiled binary and no separate runtime, just a long run of .el files at the top level, one per area of the API. You have kubernetes-pods.el, kubernetes-deployments.el, kubernetes-services.el, kubernetes-ingress.el, kubernetes-jobs.el, kubernetes-cronjobs.el, kubernetes-statefulsets.el, kubernetes-replicasets.el, kubernetes-persistentvolumeclaims.el, kubernetes-configmaps.el, kubernetes-secrets.el, kubernetes-networkpolicies.el, kubernetes-namespaces.el, kubernetes-nodes.el, kubernetes-contexts.el, kubernetes-labels.el, kubernetes-events.el and kubernetes-overview.el.

Then there are the pieces that make it an editor integration rather than a client library. kubernetes-modes.el is the major mode, kubernetes-core.el is the shared machinery, kubernetes-ast.el is the syntax tree handling, kubernetes-yaml.el is the YAML side, kubernetes-commands.el holds the interactive commands, kubernetes-popups.el the popups, kubernetes-mode.el the minor mode, kubernetes-errors.el the error handling, kubernetes-utils.el the helpers, and kubernetes-vars.el the customisation variables. There are also kubernetes-exec.el for running commands in a container, kubernetes-logs.el for logs, kubernetes-describe.el for describing a resource, and kubernetes-kubectl.el, which is the piece that actually invokes kubectl.

Because it is Emacs Lisp, the client inherits Emacs' own interaction model. The buffer becomes the interface, which is why the known issues section below is about a refresh frequency and a redraw frequency rather than about a UI framework.

## A mode that borrows the buffer, and the Evil integration

Two files in the listing describe how the package meets the user in the editor.

kubernetes-modes.el and kubernetes-mode.el are the major and minor mode. The design is that a resource view is a buffer, with the entries in it arranged as the buffer's lines, so the usual Emacs navigation applies: point movement, marking, narrowing and search work on the list of pods the same way they work on any text buffer. That is the trick that makes the package feel native rather than embedded, and it is why the redraw frequency is a meaningful setting rather than a cosmetic one.

The second is kubernetes-evil.el, and the repository carries a separate file for the Evil package, which is the vi-like modal editing layer for Emacs. Having a dedicated Evil file means the package supports the vi editing mode properly rather than as an afterthought, and the Makefile treats it as a distinct entry alongside the main package file, naming kubernetes.el as the main package file and kubernetes-evil.el as the Evil package file.

The other piece of the editor integration is kubernetes-el-tramp.el, which is a TRAMP integration. TRAMP is Emacs' file access layer for remote hosts, and a TRAMP file for Kubernetes resources means the same thing you can do to a remote file, you can do to a pod.

The views are not all the same. There is kubernetes-loading-container.el for a progress view, kubernetes-pod-line.el for the per-pod line rendering, and kubernetes-overview.el for the cluster-wide overview that the use-package example registers as the command kubernetes-overview.

## Automatic refresh is the known issue, and it has a config answer

The known issues section names one problem and gives a concrete fix, which is the most useful thing a small project can do.

Disabling automatic refresh helped many people to solve issue 100. The suggested configuration is:

```elisp
(use-package kubernetes
  :ensure t
  :commands (kubernetes-overview)
  :config
  (setq kubernetes-poll-frequency 3600
        kubernetes-redraw-frequency 3600))
```

The two settings are the heart of it. kubernetes-poll-frequency controls how often the client asks the cluster for new information, and kubernetes-redraw-frequency controls how often the buffer is redrawn. Setting both to 3600, which is an hour in seconds, effectively turns the automatic behaviour off for practical purposes while keeping the variables in place.

Why this matters is a design consequence rather than a bug. A Kubernetes cluster is a moving target, and a view that refreshes itself is genuinely useful when you are watching a rollout progress. But the same behaviour makes the buffer rewrite itself under the cursor, which is hostile if you are reading a log line or selecting text. Polling the cluster on a loop and redrawing the buffer are two separate costs, and the package exposes them as two separate variables precisely so you can tune them independently.

The use-package snippet is also a useful template. The :ensure t line installs from package archives, the :commands entry registers the interactive entry point so the package does not load until you actually call it, and the :config block sets the variables after load. That is a well formed use-package declaration, and it is the shape you would copy.

## What the buffer view buys you over kubectl

It is worth asking what a cluster client inside an editor actually gives you that the command line does not, since kubectl exists and is maintained by the Kubernetes project itself.

The answer is about the interface rather than the capability. A kubectl invocation is a process that starts, prints, and exits. The output is a snapshot of the moment it ran, and to look at something else you run something else. The Emacs client keeps a view open, so the resources stay in front of you while you work on something else in another buffer.

The file list shows that this is a substantial client rather than a thin wrapper. There is a dedicated file for each resource type, a shared core, a separate AST module for the syntax tree, a YAML module, a describe module and a logs module, and an exec module for running commands in a container. The describe and logs files in particular are the ones that save the most time in practice, because they are the commands an operator runs most often and least enjoyably from a shell.

The tradeoff runs in the other direction too. Because the client talks to the cluster through kubectl, it inherits kubectl's behaviour, including its permission model and its handling of the current context. And because the interface is the buffer, a view that redraws itself can move text under the cursor, which is exactly what the known issues entry describes. An editor integration is never free; the question is whether the cost is one you would rather pay.

For an Emacs user the answer is usually yes, because the alternative is leaving the editor to run a shell command and coming back.

## Cask, MELPA and a Makefile that does the packaging

The build tooling shows how an Emacs package is assembled and tested, and the Makefile is unusually complete for the size of the project.

The build uses Cask, the project-local dependency manager for Emacs Lisp, and the recipe is a compile step that runs cask-cli/build, pipes the output, greps it for Error, and then cleans the compiled files. The dist target packages a tar named dist/kubernetes-$(VERSION).tar, where the version comes from running cask version through the Emacs binary.

The install target is the interesting one, because it installs into a real package archive rather than into your init file. It adds the MELPA Stable archive to package-archives, initialises the package system, refreshes the contents if the archive has not been fetched, and then installs the tarball with package-install-file. That is the correct way to install a package that has been built locally, and it is why the readme carries both a MELPA badge and a MELPA Stable badge: the package is published to both, and the stable one is what you want.

Testing is done with two frameworks. The unit tests run ert-runner with the ert+duration reporter through cask, and the buttercup suite runs with cask exec buttercup over the tests/ directory. There is also a test-static target that runs pre-commit across all files, and a .pre-commit-config.yaml at the root.

The release target is a chain of dependencies that reads like a checklist: assert a clean worktree, assert you are on master, clean, test, set the package version, build the distribution, and then tag and publish to GitHub. The assert steps are what stop a release from happening with uncommitted changes.

The remaining files at the root are the usual Emacs project furniture: a .dir-locals.el, a .ert-runner file for the test runner configuration, a Brewfile for the Homebrew dependencies, a Cask directory for the Cask dependencies, an .all-contributorsrc, a .mdlrc for the markdown linter, a .docstyle.rb, a mkdocs.yaml for the documentation site, a zizmor.yaml for the workflow security scanner, and directories for docs/, test/ and tests/.

## Conclusion

kubernetes-el suits an Emacs user who already lives in the editor and wants cluster inspection without leaving it, especially for reading logs and describing resources across namespaces. It does not suit a team that wants a graphical interface, and the readme itself documents that automatic refresh has caused trouble for some users, so it needs tuning before it is comfortable. Before adopting it, install it from MELPA Stable rather than MELPA, set kubernetes-poll-frequency and kubernetes-redraw-frequency to a value you can live with, and check the resource views you actually use against the file list in the repository.

## FAQ

### What is kubernetes-el?

It is an Emacs Lisp package for managing Kubernetes clusters from Emacs, with resource views for pods, deployments, services, ingresses, jobs, cronjobs, statefulsets, replicasets, persistent volume claims, configmaps, secrets, network policies, namespaces, nodes, contexts, labels, events and a cluster overview, plus log viewing, describe and exec.

### How do I stop kubernetes-el from refreshing automatically?

Disable automatic refresh, which the documentation says helped many people solve issue 100. Set kubernetes-poll-frequency and kubernetes-redraw-frequency to 3600, as in the use-package configuration given in the known issues section.

### How is kubernetes-el installed?

The package is published on both MELPA and MELPA Stable, so it can be installed with use-package and :ensure t, or with the package system from the stable archive. The repository Makefile also has an install target that builds a local tarball and installs it with package-install-file after adding MELPA Stable to package-archives.

### How is kubernetes-el tested?

The Makefile runs the unit tests with ert-runner through cask using the ert+duration reporter, and runs the buttercup suite over the tests directory. There is also a test-static target that runs pre-commit across all files.

## Sources

- [kubernetes-el/kubernetes-el on GitHub](https://github.com/kubernetes-el/kubernetes-el)
- [License: GPL-3.0](https://github.com/kubernetes-el/kubernetes-el/blob/master/LICENSE)
- [Project website](https://kubernetes-el.github.io/kubernetes-el)
- [README](https://github.com/kubernetes-el/kubernetes-el/blob/master/README.md)
- [Releases](https://github.com/kubernetes-el/kubernetes-el/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/kubernetes-el-kubernetes-el
