Plugins can use inline configuration or separate packages.
To create a package, see Create a plugin package.
Packages support named commands, validated inputs, JSON reports, and managed port-forwards.
Enter :plugin-cancel to stop the active plugin run.
sofka ships one plugin: :sanitize, which deletes the pods a namespace has
finished with. It needs nothing installed - see Sanitize pods.
An inline entry or a user package of the same name replaces it.
For core plugins maintained and shipped by the sofka project, Rust is the preferred language. External plugins can use any programming language that follows the plugin protocol. See Language choice.
[[plugins]] assigns an external command to a key or palette command. key is a chord: a single
character ("g"), a modifier combination ("ctrl-g", "alt-x", "shift-b"), or
a function or named key ("f5", "ctrl-f2"). A built-in key wins over a plugin
on the same chord. You can change or disable that built-in binding
to release the key. :config reports bindings hidden by built-in actions.
For the minus key, use "-" alone or "ctrl--", "alt--", or "ctrl-alt--"
with modifiers. The final two hyphens are the separator and the minus key.
"shift--" is not supported. Bind the character that your keyboard produces
instead. For example, use "_" if Shift+minus produces an underscore, or
"ctrl-_" to add Ctrl.
[[plugins]]
key = "shift-y"
name = "yaml-summary"
command = "kubectl"
args = ["get", "$RESOURCE", "$NAME", "-n", "$NAMESPACE", "-o", "yaml"]
scopes = ["pods", "deployments"] # omit for all resources
mutating = false # read-only: still runs under --readonly
output = "popup" # captured into a scrollable view (see below)
[[plugins]]
key = "ctrl-x"
name = "restart-rollout"
command = "kubectl"
args = ["rollout", "restart", "$RESOURCE/$NAME", "-n", "$NAMESPACE"]
scopes = ["deployments"]
dangerous = true # confirm (showing the exact command) first- Placeholders are substituted as whole arguments, never spliced into a shell
string:
$NAME,$NAMESPACE/$NS,$CONTEXT,$CLUSTER,$RESOURCE(plural),$GROUP,$VERSION,$KIND,$FILTER. outputselectsterminal,popup,background, orreport.terminalis the default. It suspends the TUI for an interactive command.popupshows captured text.backgroundshows a completion message.reportshows a JSON report. Captured modes usetimeout("30s"by default) and enforce output limits.paletteassigns a command name, such aspalette = "scan"for:scan. Thekeyfield is optional whenpaletteis present.target = "context"runs once without a selected row. The default,selection, uses selected or marked rows.requireslists required executables.installsupplies instructions when an executable is absent.inputsdefines validatedname=valuearguments. See Inputs.network_load = trueidentifies a load test. It requires confirmation and blocks the plugin in read-only mode.mutating(defaulttrue): read-only mode blocks a mutating plugin. Set it tofalseto allow a known read-only one.confirm/dangerous: prompt before running, showing the exact executable and arguments.dangerousalso shows ⚠.shell = true: opt intosh -c. Placeholders still arrive as positional parameters ($1,$2, …), never interpolated into the script.- Bulk: with rows marked (
space), apopuporbackgroundplugin runs over every marked row and reports partial failures. An interactiveterminalplugin can't run over a set and refuses a marked run.
Guardrails match plugin actions with plugin:<palette>, or plugin:<name> when no palette command exists.
On an invalid value (a bad chord, an unknown output, a malformed timeout)
sofka disables just that plugin or falls back to the default and shows a warning
in :config. Plugins appear in ? help with their chord and scope.
[[bookmarks]] are saved navigation commands. One keystroke jumps to a resource
and can switch context or namespace and apply a filter, sort, and view. The key
chord is optional - bookmarks are always in the command palette (★, ranked
above resources).
[[bookmarks]]
key = "shift-1" # optional
name = "Prod API failures"
resource = "pods"
context = "prod-eu" # optional: switched first
namespace = "checkout" # optional; all/* = all namespaces
filter = "status!=Running -l app=api" # optional, same syntax as `/`
sort = "RESTARTS:desc" # optional: COLUMN[:asc|:desc]
view = "xray" # optional: xray | pulseWithout an active workspace, Tab / Shift-Tab cycle pods → services →
deployments → statefulsets → daemonsets → secrets → configmaps → ingresses →
PVCs in the current namespace, including all namespaces. The cycle wraps and
skips kinds absent from API discovery. From a resource outside this set, Tab
starts at pods and Shift-Tab starts at PVCs (or the next available kind in
that direction). Switching resources clears filters and drill-down scope, as
with :resource; [ / ] still navigate view history.
[[workspaces]] group several views into a named set for one task - checkout
ops, a cluster upgrade, cert renewal. Open one with a chord or the palette (▦).
sofka switches the optional context once and shows the first view. Tab /
Shift-Tab cycle the other views. You stay in the workspace.
[[workspaces]]
key = "ctrl-w"
name = "Checkout ops"
context = "prod-eu" # optional: switched once on open
[[workspaces.views]]
name = "API pods"
resource = "pods"
namespace = "checkout"
filter = "-l app=api"
sort = "RESTARTS:desc"
[[workspaces.views]]
name = "Ingress"
resource = "ingresses"
namespace = "checkout"Port-forwards started with f/F run in the background and are managed with
:pf. [[forwards]] adds named entries that appear in :pf even while stopped
(⏎ starts one), with optional autostart on connect and on matching context
switches.
[[forwards]]
name = "argocd"
target = "svc/argocd-server" # kubectl syntax: pod/…, svc/…, deploy/…
namespace = "argocd"
ports = "8080:443" # LOCAL:REMOTE
autostart = true # start when sofka connects (default false)
contexts = ["home"] # optional: only these contextssofka stops every forward on quit instead of orphaning it.