Skip to content
CAI
Software that uses CAICheck a score

derailed/k9s

73.6

Strong · 24 September 2026

43.2k

lines of production code

Go

primary language

5

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is a terminal-based interface for managing and observing Kubernetes clusters, now rebranded as 'derailed'. It provides a rich UI for viewing resource states, executing commands, and visualizing metrics, while also offering built-in capabilities for port forwarding, vulnerability scanning, and performance benchmarking. The architecture has been significantly refactored to modernize its data access, configuration management, and rendering layers, moving away from legacy implementations to support a more modular and extensible experience.

How it got here

2019 — Derail rebrand and architecture rewrite

20 changes.

The project rebranded from K9s to Derailed, migrating its Go module path and modernizing build tooling with Go 1.27 and GoReleaser v2. A comprehensive architectural overhaul removed legacy UI views, resource handlers, and vendored dependencies in favor of a new modular internal structure featuring XDG-compliant configuration, a DAO accessor registry, and a new model layer.

2020–2024 — observability and configuration enhancements

11 changes.

This period focused on expanding the tool's observability capabilities by introducing vulnerability scanning, terminal-based metrics visualization, and detailed Kubernetes resource dependency trees. It also significantly improved usability through a new command-line argument parser, annotation-based port forwarding, and per-context configuration storage.

Features

Add info command to display configuration paths and screen dump directory

Users can now run the \k9s info\ command to view a summary of K9s configuration details, including the version, paths to configuration files (such as custom views, plugins, hotkeys, and skins), and the screen dump directory. The screen dump directory path is dynamically determined by reading the \screenDumpDir\ setting from the K9s configuration file, falling back to the default if not specified or if the config file is invalid. This provides a convenient way to locate where K9s stores its data and logs.

cmd · high confidence

Add internal vulnerability scanning engine

The \internal/vul\ package introduces the core logic for scanning container images for vulnerabilities using the Grype library. This change adds the \imageScanner\ component responsible for initializing the vulnerability database, enqueuing images for asynchronous scanning, and managing scan results. It includes the \Scan\ and \Scans\ types to track per-image findings, a \tally\ system to count vulnerabilities by severity (Critical, High, Medium, Low, Negligible), and a \scorer\ to aggregate risk. The \table\ component handles formatting and deduplicating the output, while \types.go\ defines severity constants. Tests are added for the scoring and table sorting logic.

internal/vul · high confidence

Add kubectl plugin to purge Helm releases

A new kubectl plugin named 'purge' has been added to the kubectl plugin directory. This script allows users to delete and purge a Helm release associated with a specific pod by extracting the release name from the pod's description and executing 'helm delete --purge'. It requires the TILLER\_NS environment variable to be set and accepts namespace and pod name as arguments.

plugins/kubectl · high confidence

Add kubectl-jq plugin for colored log parsing

A new kubectl-jq plugin has been added to the plugins/kubectl-plugins directory. This script processes kubectl logs by attempting to parse JSON output; if the line is not valid JSON, it displays the raw text in red color to distinguish it from structured log entries.

plugins/kubectl-plugins · high confidence

Introduce OSC-52 clipboard backend with native fallback

Users can now copy text to the system clipboard via the OSC-52 terminal escape sequence, providing a reliable alternative when native clipboard tools are unavailable. The clipboard behavior is controlled by the K9S\_CLIPBOARD environment variable, which accepts 'auto' (default, tries native then OSC-52), 'native', or 'osc52'. The maximum encoded payload size for OSC-52 can be tuned via the K9S\_OSC52\_MAX environment variable, and the implementation includes specific passthrough handling for tmux and GNU screen terminals.

internal/view · high confidence

Introduce internal watch package for resource informers and port-forward management

The \internal/watch\ package has been added to centralize the management of Kubernetes resource informers and active port-forward connections. This new component provides a \Factory\ for initializing and tracking dynamic shared informers per namespace, enabling efficient caching and retrieval of cluster resources. It also introduces a \Forwarders\ registry to track, start, and cleanly terminate port-forward sessions, ensuring that forwarders are properly removed when associated pods are deleted or killed.

internal/watch · high confidence

Introduce model1 package for tabular resource rendering

This change introduces the \internal/model1\ package, a new internal model layer for rendering Kubernetes resources in tabular views. It provides core data structures for table data, headers, rows, and row events, along with logic for computing deltas between resource states, applying custom column layouts, and handling row coloring based on resource validity and event type (add, update, delete). The package also includes a parallel worker pool for batch rendering to improve performance and comprehensive tests for the new functionality.

internal/model1 · high confidence

New UTF-8 aware color highlighting for log search results

The internal color package now includes a new \Highlight\ function that applies ANSI 256-color codes to specific byte ranges within log output. This implementation is specifically designed to handle UTF-8 character boundaries correctly, ensuring that multi-byte characters are highlighted as whole units rather than being corrupted by partial byte coloring. This capability supports the improved log search and highlighting experience, allowing users to see search matches rendered clearly in the terminal without encoding artifacts.

internal/color · high confidence

New benchmarking capability for performance testing

A new benchmarking module has been added to the internal performance tools, allowing users to run HTTP-based load tests against a target endpoint. This feature supports configurable concurrency and request counts, basic authentication, custom HTTP headers, and HTTP/2. Benchmark results are automatically saved as text files in a cluster-specific directory, with a built-in timeout to prevent indefinite hangs.

internal/perf · high confidence

New dialog components for confirmations, deletions, and plugin inputs

The \internal/ui/dialog\ package now includes dedicated UI components for common user interactions: \ShowConfirm\ and \ShowConfirmAck\ for simple and string-verification confirmations, \ShowDelete\ for resource deletion with propagation and force options, \ShowError\ for displaying error messages with a cow-themed animation, \ShowPluginInputs\ for collecting structured plugin arguments (strings, numbers, booleans, dropdowns), \ShowPrompt\ for asynchronous background actions, \ShowRestart\ for pod restarts with field manager configuration, \ShowSelection\ for choosing from a list, and \ShowUploads\ for file transfers with retry and container selection. Unit tests have been added for the confirm, delete, error, and prompt dialogs.

internal/ui/dialog · high confidence

New model layer for cluster info, command input, and resource views

The internal model package has been restructured with new files that define the core data models and logic for the application. This includes \cluster.go\ and \cluster\_info.go\ for managing cluster metadata, version checks, and metrics; \cmd\_buff.go\ and \fish\_buff.go\ for handling command-line input, filtering, and auto-suggestions; \describe.go\ and \log.go\ for rendering resource descriptions and live logs; and \history.go\ for command history navigation. These changes establish the foundational model components that drive the UI views.

internal/model · high confidence

New renderers for aliases, benchmarks, contexts, and custom columns

The internal render package introduces new view renderers for Aliases, Benchmarks, and Kubernetes contexts, alongside a new base struct and comprehensive support for custom column definitions and realization. Users can now view alias mappings, benchmark results, and cluster contexts in the UI, while the custom column system allows flexible, spec-driven column rendering for various resources.

internal/render · high confidence

New terminal charting components for metrics visualization

Added a new \internal/tchart\ package providing terminal-based UI primitives for displaying metrics, including a \SparkLine\ for time-series trends, a \Gauge\ for OK/Fault status with delta indicators, and a \DotMatrix\ for numeric dial rendering. These components support configurable series colors, legends, and focus states, enabling richer in-terminal observability views.

internal/tchart · high confidence

New xray renderers for Kubernetes resources

The xray view now supports rendering for Deployments, DaemonSets, StatefulSets, ReplicaSets, Pods, Services, Namespaces, ServiceAccounts, and Containers. This adds visual dependency trees and health status indicators (e.g., replica counts, missing references) for these resource types, allowing users to see how they connect to underlying pods, config maps, and secrets.

internal/xray · high confidence

Removals

Removal of Kubernetes resource management layer

The entire Kubernetes resource management implementation in the \resource/k8s\ package has been removed. This includes the deletion of the API connection layer (\api.go\), the metrics server integration (\metrics.go\), and all individual resource handlers for Kubernetes objects such as Deployments, Pods, Services, ConfigMaps, Secrets, and Custom Resource Definitions. Users will no longer be able to view, list, or manage these Kubernetes resources through this component.

resource/k8s · high confidence

Removal of legacy resource definitions and tests

The \resource\ package has removed a large set of legacy Kubernetes resource implementations and their corresponding unit tests. Specifically, the code for managing ConfigMaps, ClusterRoles, ClusterRoleBindings, Custom Resources, CronJobs, Deployments, DaemonSets, and other core resources (along with their test files) has been deleted. This cleanup removes the internal logic for listing, displaying, and marshaling these specific resource types from this location.

resource · high confidence

Removal of legacy terminal UI views

The entire legacy terminal UI implementation in the \views\ package has been removed. This includes the main application shell (\app.go\), resource and pod views, command handling, colorers, and all associated test files. Users will no longer have access to this specific terminal-based interface layer.

views · high confidence

Removed vendored Kubernetes apps API client code

The vendored Kubernetes client-go code for the apps API group (versions v1, v1beta1, and v1beta2) has been removed. This includes all generated client interfaces and implementations for managing ControllerRevisions, DaemonSets, Deployments, ReplicaSets, Scales, and StatefulSets. Applications relying on these vendored packages for direct Kubernetes API interaction will need to update their dependencies or import the client-go library directly.

vendor/k8s.io/client-go/kubernetes/typed/apps/v1, vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta1, vendor/k8s.io/client-go/kubernetes/typed/apps/v1beta2 · high confidence

Architecture

Introduce DAO accessor registry and resource-specific handlers

The internal DAO layer now uses a centralized accessor registry to route resource requests to specialized handlers. This change adds a new \accessor.go\ file that maps Kubernetes GroupVersionResources (GVRs) to specific DAO implementations (e.g., \Pod\, \Deployment\, \CronJob\, \HelmChart\) and provides a fallback to a generic \Scaler\ accessor for unregistered types. It also introduces new DAO files for handling specific resources like \Alias\, \Benchmark\, \Dir\, \Container\, and \Context\, enabling more targeted operations such as listing aliases, managing benchmark files, browsing directories, and viewing container details with metrics. This refactoring separates concerns by allowing each resource type to implement its own \List\, \Get\, \Describe\, and other methods, improving maintainability and extensibility of the data access layer.

internal/dao · high confidence

Refactor internal UI architecture with new key-action and configuration systems

The internal UI layer has been restructured to improve modularity and maintainability. A new \KeyActions\ system in \action.go\ centralizes keyboard shortcut definitions and mappings, replacing ad-hoc key handling. The \App\ struct in \app.go\ now explicitly manages these actions and initializes core UI primitives like the prompt, menu, and logo. Configuration management is consolidated in \config.go\, which introduces a \Configurator\ struct and dedicated file watchers for skins, custom views, and custom jumps, enabling real-time UI updates when configuration files change. Supporting components such as breadcrumbs (\crumbs.go\), status indicators (\indicator.go\), and delta calculations (\deltas.go\) have been introduced or refactored to integrate with this new structure, while extensive test coverage (\\*\_test.go\) has been added to validate the new behavior.

internal/ui · high confidence

Behavioural changes

Introduce per-context configuration storage with namespace favorite limits

K9s now stores configuration data per Kubernetes context in the \internal/config/data\ package, allowing settings like skins, read-only modes, and views to be maintained independently for each cluster context. The namespace configuration enforces a hard limit of 9 favorite namespaces, automatically trimming any excess entries during merge or validation operations. Additionally, the system now supports context-level proxy configuration and a NodeShell feature gate, with file paths sanitized to handle special characters in cluster names (such as AWS EKS ARNs).

internal/config/data · high confidence

Introduces new internal client package with optimized context switching and metrics handling

The \internal/client\ package has been introduced to centralize Kubernetes API interactions, featuring a new \SwitchContext\ method that pre-warms dynamic and connectivity clients to reduce redundant API calls during context changes. The client now defaults to a higher QPS (50) and burst (100) for improved performance, paginates metrics API calls to prevent timeouts on large clusters, and respects the \KUBECACHEDIR\ environment variable for configuration caching. It also includes robust handling for missing metrics servers and validates namespace access efficiently.

internal/client · high confidence

K9s configuration system refactored to XDG Base Directory Specification

The internal configuration system has been restructured to adhere to the XDG Base Directory Specification, moving configuration, state, and data files out of the user's home directory to prevent pollution. This change introduces new file paths for aliases, hotkeys, skins, and screen dumps, and adds support for context-specific configuration files. Additionally, the configuration now includes dedicated modules for managing aliases, benchmarks, and color inversion logic using Oklch color space, along with comprehensive validation schemas for all configuration types.

internal/config · high confidence

K9s rebrands to derailed, upgrades to Go 1.27, and modernizes build tooling

The project has officially rebranded from k8sland to derailed, updating the Go module path, Docker registry, and Homebrew tap to reflect the new identity. The build environment has been upgraded to Go 1.27.1 and Alpine 3.24, with the Dockerfile and CI pipelines adjusted accordingly. Build and release workflows have been modernized by migrating to GoReleaser v2, enabling multi-architecture builds (including arm64, ppc64le, and s390x), and adding support for native package formats like deb, rpm, and apk. Additionally, the application now uses klog for logging instead of logrus, allowing users to customize the log file path via the --logFile flag.

(repo-wide) · high confidence

New command-line argument parser and interpreter

The command-line interface now uses a dedicated \Interpreter\ and \args\ parser in \internal/view/cmd\ to handle user input. This change introduces support for fuzzy filtering (\-f\), label selectors (using \=\, \==\, \!=\), and Kubernetes context switching (\@\). It also adds tab-completion suggestions for namespaces and contexts, and ensures that the \dir\ command correctly handles absolute paths.

internal/view/cmd · high confidence

New internal port-forwarding model with annotation-based configuration

The \internal/port\ package has been replaced with a new implementation that manages port forwards via Kubernetes annotations (\k9scli.io/port-forwards\ and \k9scli.io/auto-port-forwards\). This change introduces structured types for container port specifications (\ContainerPortSpec\) and port-forward annotations (\PFAnn\), allowing users to define precise local-to-container port mappings using a specific string format (e.g., \container::localPort:containerPort\). The new logic handles parsing these annotations, matching them against exposed container ports, validating host port availability, and generating the necessary tunnel configurations for port forwarding.

internal/port · high confidence

Removed vendored Kubernetes API types

The vendored copies of the Kubernetes \k8s.io/api/apps/v1\ and \k8s.io/api/apps/v1beta1\ API packages have been removed from the repository. This deletion includes all associated generated code, type definitions, and protobuf files for core workload resources such as Deployments, DaemonSets, StatefulSets, and ReplicaSets, indicating a shift away from bundling these dependencies directly within the vendor directory.

(repo-wide) · high confidence

Test coverage

Added test fixtures for Kubernetes resources and benchmarking; Added test helpers for K9s configuration and Kubernetes client mocking.

Dependencies

Major dependency overhaul and module migration

The project has migrated its Go module path from github.com/k8sland/k9s to github.com/derailed/k9s and upgraded the Go version requirement to 1.26. This change includes a comprehensive update of dependencies, notably upgrading Kubernetes libraries (api, client-go, kubectl, etc.) to v0.37.0, Helm to v3.22.0, and the UI framework to github.com/derailed/tview v0.8.5. Additionally, the vendored copy of the old k8sland/tview has been removed, and several legacy dependencies such as google.golang.org/appengine and gopkg.in/yaml.v2 have been dropped in favor of modern alternatives like sigs.k8s.io/yaml and gopkg.in/yaml.v3.

(dependencies) · high confidence

Removed vendored Google Cloud and go-spew dependencies

The vendored copies of the \cloud.google.com/go\ (including \compute/metadata\) and \github.com/davecgh/go-spew\ packages have been removed from the repository. This eliminates the bundled source code, license files, and author/contributor metadata for these libraries, indicating a shift away from vendoring these specific dependencies.

vendor · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Score

  • CAI 69 → 74 (+5.0)
  • Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 80 → 89 (+8.3)
  • Architecture 100 → 92 (-7.3)
  • Maturity 68 → 65 (-3.5)
  • Readiness 68 → 79 (+11.6)
  • Security 63 → 76 (+13.3)
  • Domain Modelling 100 → 100 (-0.0)

Resolved (100)

  • Coverage not included — suite not readable by the collector
  • Critical CVE: [GHSA redacted] (go.mod)
  • Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
  • Duplicated block (10 lines × 2) (internal/dao/helm_chart.go)
  • Duplicated block (10 lines × 2) (internal/dao/rbac.go)
  • Duplicated block (10 lines × 2) (internal/ui/dialog/restart.go)
  • Duplicated block (10 lines × 2) (internal/view/browser.go)
  • Duplicated block (10 lines × 2) (internal/view/cm.go)
  • Duplicated block (10 lines × 2) (internal/view/container.go)
  • Duplicated block (10 lines × 4) (internal/dao/dp.go)
  • Duplicated block (10 lines × 4) (internal/model/describe.go)
  • Duplicated block (10 lines × 4) (internal/view/dp.go)
  • Duplicated block (11 lines × 2) (internal/dao/ds.go)
  • Duplicated block (11 lines × 2) (internal/dao/rbac_subject.go)
  • Duplicated block (11 lines × 2) (internal/dao/reference.go)
  • Duplicated block (11 lines × 2) (internal/model/describe.go)
  • Duplicated block (11 lines × 2) (internal/model/tree.go)
  • Duplicated block (11 lines × 2) (internal/view/browser.go)
  • Duplicated block (11 lines × 2) (internal/view/browser.go)
  • Duplicated block (11 lines × 2) (internal/view/container.go)
  • …and 80 more

New (180)

  • ClassTooLong: App (internal/view/app.go)
  • ClassTooLong: Browser (internal/view/browser.go)
  • ClassTooLong: Table (internal/ui/table.go)
  • ClassTooLong: Xray (internal/view/xray.go)
  • Concentrated knowledge decay
  • Dependency pinned to a stale untagged commit: github.com/google/shlex
  • Documentation: no architecture or design documentation (README.md)
  • Documentation: no installation or build instructions (README.md)
  • Documentation: no usage examples (README.md)
  • Duplicated block (10 lines × 2) (internal/render/ep.go)
  • Duplicated block (10 lines × 2) (internal/ui/dialog/restart.go)
  • Duplicated block (10 lines × 2) (internal/view/browser.go)
  • Duplicated block (10 lines × 2) (internal/view/details.go)
  • Duplicated block (10 lines × 2) (internal/view/node.go)
  • Duplicated block (10 lines × 2) (internal/view/table.go)
  • Duplicated block (10 lines × 20) (internal/render/crb.go)
  • Duplicated block (10 lines × 21) (internal/render/cr.go)
  • Duplicated block (10 lines × 4) (internal/dao/dp.go)
  • Duplicated block (10 lines × 4) (internal/model/describe.go)
  • Duplicated block (10 lines × 5) (internal/xray/dp.go)
  • …and 160 more

Changes since last survey

  • 57 commits — 41 feature/other, 16 fixes

By area

  • (root) — 35 commits
  • internal/view — 5 commits
  • internal/dao — 4 commits
  • internal/render — 3 commits
  • .github/workflows — 2 commits
  • plugins/README.md — 2 commits
  • internal/config — 1 commit
  • internal/model1 — 1 commit
  • plugins/argocd.yaml — 1 commit
  • plugins/cert-manager.yaml — 1 commit
  • plugins/flux.yaml — 1 commit
  • skins/rose-pine-dawn.yaml — 1 commit

Notable commits

  • fix: fix(dao): allow port-forward with get verb on pods/portforward for K8s 1.31+ WebSocket path (#4147)
  • fix: fix(dao): classify k8s.io resources from CRD discovery (#4148)
  • fix: fix(jumps): implement client-side field selector for persistent volume claims (#4079)
  • fix: fix(lint): update golangci-lint version to v2.13 (#4197)
  • fix: fix(plugins): resolve shortcut conflicts with built-in table keys (#4239)
  • fix: fix(plugins/argocd): Shift-J is Jump Owner, so the whole plugin file fails to load (#4233)
  • fix: fix(plugins/argocd): target the on-screen cluster and namespace, guard the mutations (#4229)
  • fix: fix(render): sort CR Age column by duration regardless of column name casing (#4181)
  • fix: fix(render): treat out-of-bounds array index in custom columns as missing value (#4068)
  • fix: fix(schema): enhance conditional validation for plugin properties (#4187)
  • fix: fix(secret): sort decoded keys (#3998)
  • fix: fix(skins): correct Rosé Pine Dawn palette and cover current skin schema (#4183)
  • fix: fix: clarify duplicate hotkey error and update flux plugin example (#3951)
  • fix: fix: don't hang on sync when namespace list is RBAC-denied (#4160)
  • fix: fix: sort wide columns (#4168)
  • fix: test(dao): fix port forwarder test lint issues (#4188)
  • change: Add Karpenter plugin (nodepool <-> node/nodeclaim navigation) (#4223)
  • change: Add stale workflow exemption labels (#4213)
  • change: Always define placeholder and exposed ports in pf (#4154)
  • change: Make scale replicas field responsive (#4211)
  • …and 37 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

derailed/k9s was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 24 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit de93995f13ba16a6f0a49eaf2780b16b5ba0fa5e — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-5f8d0eb43fd7.