sofka
A Kubernetes TUI written in Rust, on kube-rs and
ratatui. Async everywhere, so the UI never blocks on the
cluster.
| Pod list + command palette | Namespace switcher | Flux suspend/resume/reconcile menu |
|---|---|---|
![]() |
![]() |
![]() |
Why "sofka"
That's Sophie, a Russian Blue. She sits behind the monitor and watches the
screen. Constantly, not sometimes. She has the narrow-eyed look of someone who
has seen a pod in CrashLoopBackOff. She catches every state change and doesn't
get distracted. She is, in effect, a cluster watchman that is a cat.
sofka is the Serbian short form of Sophia, which means "wisdom". A good cluster
TUI and a good cat both watch things closely, and both know when something is
wrong.
What it does
sofka is a reimagining of k9s with one generic object pipeline instead of a renderer per resource kind. Same purpose, different architecture. The short version:
- Every CRD works on day one - one generic render pipeline, curated columns
for common kinds, NAME/AGE for the rest, and
enteron a CRD drills into its custom resources. - Flux CD built in -
tsuspends, resumes, and reconciles through native API patches. Nofluxbinary. Plus a native Helm inspector that decodes release Secrets itself. - It tells you why something is broken -
Xopens a deterministic, evidence-based incident view. No AI, no external service. - Bulk actions -
spacemarks rows for delete, kill, or Flux actions across many resources at once. - Port-forwards run in the background - starting one doesn't freeze the TUI,
and
:pfmanages them all. - Guardrails and read-only mode - "never delete in prod" is enforced, not remembered.
- Skins - Catppuccin, Gruvbox, Solarized, Nord, Dracula, Tokyo Night, One Dark, Rosé Pine, Monokai, with auto dark/light detection.
The full feature list is long. So is the comparison with k9s, including why it's faster.
Installation
Every release ships prebuilt binaries for macOS (aarch64/x86_64) and Linux (aarch64/x86_64).
Or build from source: cargo build --release (see
Development).
macOS: "cannot be opened because the developer cannot be verified"
The release binaries aren't signed or notarized yet, so Gatekeeper refuses a tarball you downloaded in a browser. Nothing is broken. Clear the quarantine flag once:
(Or right-click the binary in Finder, pick Open, confirm once.) Signing and notarization are on the roadmap.
Usage
sofka [RESOURCE] [-n NAMESPACE] [-A] [--readonly | --write]
RESOURCE resource to open (alias/plural/kind), default: pods
-n, --namespace namespace to start in
-A, --all-namespaces
--readonly disable every mutating action for the session
--write force write mode, overriding any config `readonly`
--readonly and --write set the mode for the whole session and win over the
config readonly option, including per-cluster and per-context overrides, on
every :ctx switch. With no flag, switching into a context whose config sets
readonly = true enables read-only mode (shown as [read-only] in the header),
and switching away restores write mode.
Headless modes need no TTY and double as CI smoke tests:
Keys
The essentials. ? in the app shows everything, or see the
full key reference.
| Key | Action |
|---|---|
: |
command palette - fuzzy over kinds, commands, bookmarks, workspaces (:deploy social also works) |
/ |
filter: fuzzy · !inverse · -l/-f selectors · status=X cpu>500m age<2h |
enter / esc |
drill down / go back |
j/k, g/G |
navigate |
n / 0 / :ctx |
namespace switcher / all namespaces / context switcher |
space |
mark row for bulk actions |
y / d / E |
YAML / describe / live events |
l / L |
logs / VictoriaLogs history |
X / T |
explain why it's unhealthy / state-change timeline |
s / e / a |
shell or scale / edit in $EDITOR / attach |
f |
port-forward, in the background (:pf manages them) |
t |
Flux menu · CronJob trigger · pod file transfer |
r / i |
rollout restart / set container image |
ctrl-d / ctrl-k |
delete / force-delete (marked rows, or current) |
S / w / ctrl-e |
sort picker / wide columns / compact mode |
? / :q |
help / quit |
Configuration
$XDG_CONFIG_HOME/sofka/config.toml (or ~/.config/sofka/config.toml). All
optional - an empty config behaves like no config. :reload re-reads it live.
= "kube-system"
= "deployments"
= false
= ["kube-system", "monitoring"]
[]
= "deployments"
[]
= "gruvbox-dark" # omit to auto-detect dark/light
Any option can be overridden per cluster or per kubeconfig context, so prod can be read-only in a light skin while everything else stays as is. See the configuration reference for the rest.
Docs
| Doc | What's in it |
|---|---|
| Features | the complete feature list |
| vs k9s | design differences and why it's faster |
| Performance benchmark | measured TUI latency, memory use, and binary size |
| Keys | full keymap, per-view keys |
| Configuration | every config section, per-cluster/per-context overrides |
| Views and thresholds | custom columns, CRD printer columns, coloring bands |
| Plugins | plugins, bookmarks, workspaces, saved forwards |
| Safety | read-only mode, guardrails, :can-i, action journal |
| Providers | right-sizing, VictoriaLogs, fleet dashboard |
| Debugging | explain, timeline, diff, notifications, debug pods, bundles |
| Architecture | module layout, data flow, dev loop, release process |
| Roadmap | milestone status |
License
Dual-licensed under MIT or Apache-2.0, at your option - the Rust ecosystem standard.


