A container ship at night, bow lifting through a breaking wave in a violent storm, one amber lamp lit on its mast.

Safina: The Kubernetes TUI
for teams that ship.

Safina is fast, keyboard-driven and written for terminal hackers. It’s a single Go binary on lazy client-⁠go informers, with session history in SQLite and an MCP server for your agent.

Deep dive

safina listing every workload in the cluster with its kind, readiness and CPU and memory trend lines; ledger-api and search-indexer show none ready, in red. The cursor rests on the ledger-db StatefulSet, two rows below ledger-api and healthy at 1 of 1.

Press a key, or click one.Tap a key to see that screen.

Enter goes from cluster to namespace to workload to pod, and Esc comes back up.

Chat

It already knows what you’re looking at.

Press i and ask what’s wrong. The model gets the cluster, namespace and resource you’re on and, from the Logbook, what you’ve already tried there, so you don’t paste stack traces into a browser tab. Open a logs entry in the Logbook and c hands it the lines you read.

It answers with keys to press, like e for events or U to roll back, and it can’t press them itself. The cluster stays your amanah, your trust and your call.

The chat panel beside the workloads list, answering from the crash logs attached from the Logbook: ledger-api starts v2.14.0 at 11:15:50, can’t reach the database on three retries, fails the lookup of ledger-db-primary with no such host, and panics. The cause: the cluster’s DNS has no record for ledger-db-primary, so no Service has that name or the config names the wrong one, and pressing R won’t help. Next: press d to find where the host is set, filter the Services for ledger-db to find the real name, and press E to change it.

Barbarossa mode

Lowercase reads. Uppercase writes.

A slipped finger can only ever read. The keys that write are Barbarossa mode, named for the red-⁠bearded Ottoman admiral. They all need Shift, and they’re red, like every confirmation. Scaling asks how many, an edit shows you the diff before it’s applied, and everything else asks for a yes.

Then Rollout watch takes over. A scale, restart or edit isn’t done just because the API accepted it, so safina follows it until the pods are ready. If they still aren’t after five minutes, it tells you.

No autopilot means safina never picks a cluster for you, not even yesterday’s.

An edit to the ledger-api Deployment waiting for confirmation in a red frame: a one-line diff changes DATABASE_URL from ledger-db-primary to ledger-db, with a red y to apply and n to cancel.

Read

d
Describe
l
Logs
e
Events
s
Shell
f
Port-forward
v
Reveal secret
y
Copy
n
Next failing
h
Hot pods

Write, in Barbarossa mode

Shift S
Scale
Shift U
Roll back
Shift R
Restart
Shift E
Edit YAML
Shift C
Cordon
Shift D
Drain
Shift K
Delete

Logbook

Still there in the morning.

Kubernetes keeps events for an hour by default, and a replaced pod takes its logs with it. The Logbook keeps what you saw: the logs and events you read, and every write with the state before and after it.

Afterwards, export the night, from the bismillah before your first look to the alhamdulillah when the pods are ready, as a timeline with a postmortem template. That works without cluster access, which helps when the cluster was the problem. Every entry keeps its isnad, the chain it came through: which cluster, which session, when it happened and when you saw it.

It lives on your machine, readable only by you, with secrets redacted. It records what you did and saw in safina, so it isn’t an audit log of the cluster.

The Logbook for ledger-api, newest first: the DATABASE_URL edit, timestamped from requested, through the before snapshot, the changed fields, the API accepting it and the after snapshot, to progress at 0 and then 1 of 2 ready, and completed at 2 of 2 ready eight seconds after it was requested.
The same ship later that night, riding a heavy swell after the storm, its amber lamp still lit under breaking cloud.

Also on board

Shell anywheres
A shell in any container. If the image doesn’t have one, safina asks before adding a debug container that does.
Forward listCtrlF
All your port-forwards in one list, so none of them keeps running in a terminal tab you forgot about.
Quick switchCtrlK
Switch clusters without quitting safina. It leaves kubectl’s current context alone, so your other terminals stay where you left them.
Jump search:
Type part of a name to jump to anything safina has loaded, or to a view like the Logbook.
Copy over SSHy
The selection, the YAML or the logs go to your own clipboard, even when safina runs on a box you SSHed into.
Beacon
If your terminal shows tab status, safina’s tab tells you when the model is answering or a write is waiting for your yes, so you can work in another tab.

Compare

Safina and k9s

Both read the same kubeconfig, so you can run them side by side.

safinak9s
Write actions need ShiftYesNo
Confirmation on every writeYesSome
Rollout status after scale, restart or editYesNo
Cluster picker at launchYesNo
AI assistantYesNo
Incident timeline exportYesNo
All resource types by defaultSomeYes
Read-only modeNoYes
Plugins and skinsNoYes
Windows supportNoYes
Package manager installNoYes

k9s as of v0.51.0, June 2026.

FAQ

Fair questions

What does the model see?

Chat sends names, status and numbers for what you’ve selected and your recent Logbook entries for it, plus logs when you attach them. Through safina’s MCP server, an agent reads logs on its own, up to 200 lines at a time. Neither ever sees a Secret’s data. Apart from the model, safina talks only to your clusters.

Can the model change my cluster?

Not through safina. Chat gives it text to read, not keys, and over MCP it can only propose a change, which waits until you approve it. If you’ve already let your agent run kubectl without asking, safina can’t take that back.

What does it leave on my machine?

Everything it keeps is under ~/.safina, and the Logbook keeps it as long as its config says:
history:
  actionDays: 90    # writes
  evidenceDays: 14  # logs and events read
  redactPatterns:   # on top of the built-ins
    - 'customer-[0-9]+'
  enabled: true     # false turns it off
An agent’s MCP sessions and proposals stay until you delete them. The claude CLI keeps chat conversations under ~/.claude, like its other sessions.

What does it cost?

Nothing. It’s MIT-licensed. Chat runs on your own subscription.

What does onboarding the team take?

A binary on each laptop. Nobody needs an account, and everyone works through their own kubeconfig. Logbooks stay personal; export one for the team’s postmortem.
The same ship at first light, in calm water.

Get safina

Binaries for macOS and Linux come with the first release, in sha Allah. Until then, build from source:

git clone https://github.com/YunusAndreasson/safinacd safinamake install

You’ll need Go 1.27 or newer, and access to the repo while it’s private.

  • Runs on your machine. It reads the kubeconfig you already have, auth plugins included, and never writes to it.
  • Nothing to install in the cluster. No in-cluster agent, operator or CRDs. Safina can only do what your RBAC lets you do.
  • Chat is optional. It runs through the claude CLI you already have, so there’s no API key to set up.