# kafkactl gives Kafka administrators a CLI with contexts, schemas and Kubernetes reach

> kafkactl is a Go command line tool for Apache Kafka with context based configuration, Avro and protobuf support, a schema registry client, and a mode that runs inside your own Kubernetes cluster. It is Apache-2.0 licensed, the module path is on a v5 major, and the last push was on 2026-10-09.

**deviceinsight/kafkactl** — Command Line Tool for managing Apache Kafka

- Repository: https://github.com/deviceinsight/kafkactl
- Website: https://deviceinsight.github.io/kafkactl/
- Stars: 1,074 · Forks: 114
- Language: Go
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/deviceinsight-kafkactl

## Contexts are the unit of configuration, not cluster names

kafkactl is a command line interface for interaction with Apache Kafka, and the design decision that shapes everything else is the context. A config file at $HOME/.config/kafkactl/config.yml holds a list of named contexts, and each context carries its own brokers, TLS, SASL, Kubernetes and client settings.

The README shows the shape. If no config file is found, a default one is generated at that path, and the generated default is described as suitable for getting started with a single node cluster on a local machine. A hand written file looks like this:

```yaml
contexts:
  default:
    brokers:
      - localhost:9092
  remote-cluster:
    brokers:
      - remote-cluster001:9092
      - remote-cluster002:9092
      - remote-cluster003:9092
```

The multi-broker list is the point. Kafka clients are configured with a bootstrap list, and a tool that hard codes one cluster name gets awkward the moment you have a second environment. With contexts, the same command runs against a local single node broker during development and against a three broker production cluster by switching context.

The other thing to notice is that the config file is the only place connection details live. There is no separate credentials file mentioned for the general case, so how you keep that YAML safe is your decision, and the README does offer a hint in the SASL and schema registry sections.

## Secrets come from the keyring or a prompt, not only from the file

Several optional password fields in the config file carry a note saying that if the value is omitted, the password is looked up in the OS keyring or prompted interactively. That applies to the SASL password, the TLS certificate key passphrase, and the schema registry basic auth password.

The keyring support comes from a specific dependency: zalando/go-keyring is a direct requirement in go.mod, and the config comment says that if the key is encrypted, kafkactl will prompt or use the keyring.

This is a sensible design, because a config file that has to hold a plaintext Kafka password is a file that ends up in a backup, in a dotfiles repository, or in a screenshot. Leaving the password out and letting the tool fetch it from the keyring keeps the file shareable. The same applies to the TLS material, where ca, cert and certKey are named separately and an optional certKeyPassphrase field exists for an encrypted key.

There is a deliberate escape hatch too. The TLS block has an insecure option, described as setting it to true to ignore all tls verification, with the default being false. The default is the right one, and the fact that the option exists at all means the tool can talk to a development cluster with a self signed certificate, which is a legitimate reason for it to be there.

## Kubernetes access means a pod, an image and a set of pod options

The kubernetes block in the config file is the most unusual part of the tool, and it deserves a close look because it changes what kind of operation you are running.

A context can be configured to reach clusters running inside Kubernetes, with the block switched off by default and enabled explicitly. It takes a binary to invoke, kubectl by default, a kubeConfig path, a kubeContext name and a namespace. The image to use is configurable, and the comment notes that the tag of the image is suffixed by -scratch or -ubuntu depending on the command, which is why the repository ships both Dockerfile.Scratch and Dockerfile.Ubuntu.

The pod options are extensive and are the same options you would set on a Kubernetes workload: imagePullSecret for a private registry, tlsSecret holding ca.crt, cert.crt and key.key, asUser for impersonation, serviceAccount, keepPod for debugging, labels, annotations, nodeSelector, resources with requests and limits, affinity with a nodeAffinity example, and tolerations.

There is also a security decision built into the SASL handling. A saslSecret block injects SASL credentials into the pod through a Kubernetes secret instead of plaintext environment variables, and it offers two mutually exclusive modes: name an existing secret with username and password keys that kafkactl will not manage, or let kafkactl create a short-lived secret from the local SASL config and delete it after the pod exits. The create option defaults to false.

The consequence is that kafkactl can run as a pod inside your cluster rather than from your laptop, which is how it reaches a Kafka service that is only exposed inside the cluster network.

## Avro, protobuf and the schema registry are first class

The feature list names support for Avro schemas, support for a JSON schema registry, and support for consuming and producing protobuf-encoded messages. Those three items cover most of what a Kafka payload actually is in practice, and the tool's support for them is deeper than a name in a list.

For Avro, the config exposes a jsonCodec setting under the avro block, with the accepted values standard and avro and a default of standard. The README points at an issue in the project tracker about it, which suggests the encoding side is where the complexity lives. The Avro implementation is linkedin/goavro, a direct dependency.

For the schema registry, the config gives a url, a requestTimeout defaulting to 5 seconds, optional basic auth credentials with the same keyring or prompt behaviour as the broker connection, and its own TLS block. The registry client is riferrei/srclient.

For protobuf, the dependency list shows google.golang.org/protobuf together with bufbuild/protocompile, which is a protobuf compiler rather than just a runtime. That combination is what allows a tool to read a .proto file and work with the message definitions it contains rather than only with encoded bytes.

The Kafka client itself is IBM/sarama, pinned at v1.61.1, and the go.mod comment on the sasl version option links to a sarama issue, which is a fair indicator of which client behaviour the configuration is compensating for.

## Shell completion is generated, and the binary has to be on PATH

Command auto-completion is listed first in the feature list, and it covers bash, zsh and fish, with dynamic completion for things like topics and consumer groups. Dynamic completion is the interesting part, because it means the completion has to query the cluster, which is why the README attaches a note to the source install instructions: make sure that kafkactl is on PATH otherwise auto-completion won't work.

That note also explains a file in the repository. There is a kafkactl-completion.bash at the top level and a generate_completion.sh script, so the completion scripts are generated from the command definitions rather than written by hand.

The repository topics list includes fish, zsh and golang, and the docs are written in AsciiDoc rather than Markdown, with the README named README.adoc and the site built from index.md and _config.yml. The command documentation is generated too: the Makefile has a docs target that builds the binary and then runs kafkactl docs with a --directory, a --single-page flag and an explicit config file, which is how the command reference on the project site stays in step with the code.

The broader Go tooling in go.mod backs the same point. cobra and viper handle the command tree and configuration loading, pflag does flag parsing, xdg-go/scram and pkcs8 cover the SASL and key handling, and hashicorp/go-plugin provides the plugin mechanism that the oauth tokenProvider configuration refers to.

## The build pipeline, the major version and the release cadence

The project is a v5 module. The go.mod declares module github.com/deviceinsight/kafkactl/v5 and go 1.27.1, which tells you two things at once: the tool is on its fifth major version, so the command surface has been revised before, and it needs a recent Go toolchain to build from source.

The Makefile shows a disciplined pipeline. The default goal runs fmt, lint, cve-check, test, build and docs in sequence. Linting uses golangci-lint as a Go tool, vulnerability checking uses govulncheck, and the test run uses gotestsum with a -short flag. The build sets CGO_ENABLED=0 and stamps the version, commit SHA and build time into the binary with -ldflags. Integration tests live in their own target and run a shell script under docker/.

The pre-commit configuration and the .golangci.yml file mean the same checks run before a commit lands. The dependency list in go.mod is long, mostly indirect linter dependencies pulled in by the tool-based linting, which is a modern Go pattern that keeps the linters in go.mod rather than in a separate binary.

Releases are regular. v5.19.0 shipped on 2026-05-13, v5.20.0 on 2026-07-30 and v5.21.0 on 2026-10-09, and the last push was on 2026-10-09. The repository is not archived, so the tool is being worked on, and a CHANGELOG.md is present for the history.

Installation is a first class path rather than an afterthought. Homebrew, winget on Windows, deb and rpm packages downloaded from the releases page, an AUR package for Arch, and a plain binary copy for the manual route. From source it is a single go install command on the v5 path:

```bash
go install github.com/deviceinsight/kafkactl/v5@latest
```

The licence is Apache-2.0, recorded in LICENSE.md, which is a permissive licence with an explicit patent grant, a reasonable choice for a tool that ships as a binary to many platforms.

## Conclusion

kafkactl suits an operator who lives in a terminal, works with more than one Kafka cluster, and wants shell completion plus Avro, protobuf and schema registry handling without writing scripts against the broker protocol. It is the wrong tool if you want a graphical console, and the wrong tool if the standard Kafka command line scripts already cover your workflow. Before adopting it, read the config file format, because TLS, SASL and Kubernetes settings are all defined in one YAML file, and check that your brokers expose the endpoints you intend to use, since a context can point at a local broker, a remote cluster or a pod launched inside Kubernetes.

## FAQ

### How do I install kafkactl?

The README lists the pre-compiled routes: brew install kafkactl, winget install kafkactl, the deb or rpm packages from the releases page, an AUR package for Arch, or copying the binary manually. From source it is go install github.com/deviceinsight/kafkactl/v5@latest, and kafkactl must be on PATH for auto-completion to work.

### Where is the kafkactl config file and what does it contain?

If no config file is found, a default is generated at $HOME/.config/kafkactl/config.yml. It holds a list of named contexts, each with brokers and optional tls, sasl, kubernetes, avro and schemaRegistry settings.

### How does kafkactl handle Kafka passwords and TLS keys?

If the password or cert key passphrase is omitted from the config, it is looked up in the OS keyring or prompted interactively. The TLS block also has an insecure option to ignore all TLS verification, which defaults to false.

### Can kafkactl reach a Kafka cluster inside Kubernetes?

Yes. The kubernetes block enables access to clusters running in Kubernetes, with settings for the kubectl binary, kubeConfig, kubeContext, namespace, the image to run, image and TLS secrets, service account, labels, nodeSelector, resources, affinity and tolerations. The image tag is suffixed with -scratch or -ubuntu depending on the command.

### Which serialization formats does kafkactl support?

The feature list names support for Avro schemas, the JSON schema registry, and consuming and producing protobuf-encoded messages. Avro has a jsonCodec option under the avro block, and the schema registry is configured with a url, requestTimeout and optional basic auth.

## Sources

- [deviceinsight/kafkactl on GitHub](https://github.com/deviceinsight/kafkactl)
- [License: Apache-2.0](https://github.com/deviceinsight/kafkactl/blob/main/LICENSE)
- [Project website](https://deviceinsight.github.io/kafkactl/)
- [README](https://github.com/deviceinsight/kafkactl/blob/main/README.md)
- [Releases](https://github.com/deviceinsight/kafkactl/releases)

---

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