Skip to content

Latest commit

 

History

History
469 lines (393 loc) · 45.3 KB

keys.md

File metadata and controls

469 lines (393 loc) · 45.3 KB

Key reference

The default keymap. All built-in keyboard actions are configurable. See Configure key bindings for scopes and action names. ? inside sofka shows the effective bindings, including your own plugin, bookmark, and workspace chords. : and ? work from every navigation screen; closing either returns to the screen where it was opened. Text-entry pickers keep both characters available as input.

Table views

At launch, sofka ctx or sofka contexts opens the context picker before connecting. Press Enter to connect to the selected context and open its default resource, or pods if none is set.

Use :resource -n namespace --context context /filter to apply a complete query. Use :resource @context [namespace] for cross-context navigation. Context names fuzzy-complete after @; Tab/Shift-Tab or Down/Up fill the selected context in the command. Add a namespace if needed, then press Enter to run the query. Without a namespace, a context switch uses its remembered or default namespace. This does not change kubeconfig's current-context.

Scope options precede the slash. Structured filter terms combine with spaces or &&, with || for OR and !(...) for group negation. / edits the active filter and Esc clears it. See filtering for the grammar and selector persistence rules.

A normal context switch through :ctx keeps the current resource type if the target cluster supports it. Otherwise, sofka opens that context's configured default resource, or Pods, and shows a fallback message. Filters and object ownership scope are cleared. Startup still uses the configured default resource.

Key Action
:resource -n ns --context ctx /filter query resource, namespace, context, and filter together
:resource @context [namespace] switch context and resource; context names fuzzy-complete
:resource -o layout open the resource in a named layout; default returns to the default columns, wide turns on wide mode
:layout / :layout <name> pick the current kind's layout, default first / switch to it (the name tab-completes)
:mouse switch mouse capture on/off for this session; off allows terminal text selection
:<resource> command palette - fuzzy over kinds and built-in commands
:<resource> <ns> switch kind and namespace at once (:deploy social; all/* = all namespaces; the namespace tab-completes)
:ns <name-or-pattern> change namespace and keep the resource view; from Namespaces, return to the previous view or Pods (all/* = all namespaces)
[ / ] view history - back / forward through visited kind+namespace views
Tab / shift-Tab next / previous common resource in the current namespace; cycle workspace views when one is open
enter drill down (workload/svc/node/ns → pods, machinedeployment → machines, cronjob → jobs, pod → containers, CRD → its resources, Argo app → :argo, ResourceSet → :gitops, or views)
esc go back / pop the view stack / clear filter / clear marks
j/k, ↓/↑, g/G navigate
ctrl-f / ctrl-b, PgDn / PgUp page forward / back - one screenful at a time
half_page_down / half_page_up half a page forward / back; unbound by default, see key bindings
S / I sort-column picker (fuzzy; ⏎ on the active column inverts) / invert sort direction; saved per kind by default (remember_sort = false disables this)
A sort by AGE; press again to invert; uses the sort memory setting
ctrl-e compact mode: collapse the header + footer (for tiled/multiplexed panes)
space mark/unmark row for bulk actions
shift-up / shift-down extend or reduce the marked range from the starting row
ctrl-space mark every row from the last space mark to the cursor
/ filter: text · a|b · ~fuzzy · /regex/ · !inverse · label:text local label search · -l/-f selectors (server-side on ⏎) · status=X cpu>500m age<2h
Ctrl+Z toggle faults filter in pod, workload, Flux, and Argo CD views; configured actions take precedence; combine with /; press again to turn off
:workloads [ns] / :wk deployments, statefulsets, daemonsets, cronjobs, jobs and pods in one table; row keys act on the row's own kind
:ns-resources [ns] namespaced kinds with objects in the namespace (default: current; all/* = all namespaces) and how many; ⏎ opens the kind in that namespace, r counts again
R (namespaces view) open :ns-resources for the selected namespace
O (workloads view) show or hide pods and jobs that a listed workload owns
n / 0 namespace switcher / all namespaces; 0 also selects all namespaces inside the switcher while the filter is empty
W switch to the selected resource's namespace and keep the resource kind
1 to 9 select a configured favourite namespace in fixed configuration order; also inside the switcher while the filter is empty
shift-j jump to owner/controller
o show the node the selected row names (pods built in; other kinds via [views."…"].node)
ctrl-r refresh the watch
y / d / E view YAML / describe (native opt-in) / live events
x secrets: show data base64-decoded (as stringData) · PVCs: browse the volume
X / T explain why the selection is unhealthy / session-local state-change timeline
u / :adjacent adjacent view: owners, children, and the objects the selection names or is named by (⏎ opens one)
c (adjacent view) Discover direct children of a namespaced custom resource. Search starts on request. Results can be incomplete; see the limits in Features.
:gitops / :flux Flux owner, source, revisions & reconciliation chain for the selection (⏎ to jump)
:argocd / :argo Argo CD Application sync/health, source, managed resources & what's blocking, for the selection or the Application that manages it (⏎ to jump, c to expand what a resource owns)
:users / :groups List subjects from RBAC bindings across all namespaces. Enter shows directly bound rules.
:policy [u:name | g:name | s:ns/name] Show directly bound rules. Without an argument, use the selected service account.
Enter (Role, ClusterRole, RoleBinding, ClusterRoleBinding) Show rules. Follow the binding's role reference when needed.
t (RBAC rules) Switch rules between the resource and verb matrix and the rule list.
h / l (RBAC rules) Scroll the matrix left / right.
r / Esc (RBAC view) Read the data again / return to the previous view.
:can-i / :can-i <verb> <resource> [ns] what you can do here / check a single action (SelfSubjectAccessReview)
:journal / :audit session-local log of the mutating actions you've taken
:rightsize historical right-sizing: P50/P95/P99 usage → suggested requests + patch preview (needs a metrics backend)
:ctx / :ctx <name> context switcher popup (type to filter, r renames, space toggles fleet membership) / switch directly (the name tab-completes)
:helm Helm releases (native storage-Secret decode): ⏎ history → values · y manifest · d notes · r rollback
:rollout-history Deployment, StatefulSet, or DaemonSet revisions: ⏎ diff against the live template · r rollback
:fleet cross-context health dashboard (opt-in: [fleet] contexts or space in :ctx; ⏎ switches, r refreshes)
:skin pick a color skin with live preview; esc restores the previous skin (:skin gruvbox-dark applies directly)
:reload / :config / :info reload config from disk · config sources + warnings · runtime diagnostics
:check-update check for a newer sofka release and show the upgrade command
l / p logs (marked pods, or current row; a pod with a kubectl.kubernetes.io/default-container annotation shows that container; workload = all matching pods) / previous-container logs
L / :vlogs VictoriaLogs history for the selection (pod, container, workload, service, namespace), or its Cloud Logging / log UI link
c copy resource name to clipboard
Y copy any cell of the selected row: picker over the displayed columns (type to match a column name or value), ⏎ copies
e edit in $EDITOR (kubectl edit)
s shell into pod / shell into a PVC's volume / scale a resource with a discovered scale subresource (context-dependent)
a attach to the pod's default container (kubectl.kubernetes.io/default-container, else the first one)
:debug pod: ephemeral debug container (d in the picker targets one) · node: privileged debug pod (previewed + confirmed)
:debug-clean delete the node debugger pods launched this session
:pvc-explore / :pvc-clean browse the selected PVC (also :pvc-browse; see below) · delete helper pods a previous session left behind (also :pvc-cleanup)
:bundle / :bundle-save assemble a redacted diagnostic bundle for the selection · write the previewed bundle to a file
:snapshot [text|json|yaml] / :snapshots capture the current view to a file · browse, open, and delete saved snapshots
:notify [note] toggle watch notifications on the selected object; note prefixes its messages
:find <text> global fuzzy find over object names across common kinds, all namespaces
:dir [path] browse local manifests and apply or delete them (see below)
i set container image; on a Flux HelmRelease, set spec.chart.spec.version
r rollout restart (marked workloads, or current) / force-sync (ExternalSecrets/PushSecrets) / rollback (Helm or rollout history) / refresh (elsewhere)
f / shift-f port-forward (pods/services) — picker shows declared ports, marks busy local ports in use, or "Custom…" for remote and local ports; active forwards show ● next to the name
t Flux and flux-operator: suspend/resume/reconcile (+ force where supported) · ArgoCD: suspend/resume (+ refresh, hard refresh, sync, sync with prune for App) · CronJobs: trigger/suspend/resume · pods: file transfer
V / N CertificateSigningRequests: approve / deny (marked rows, or current); confirm shows requester, signer and usages; already decided requests are skipped
C / U / D nodes: cordon / uncordon / open drain options
ctrl-d / ctrl-k delete / force-delete (marked rows, or current); in confirm: f toggles force, c cycles cascade (background → foreground → orphan)
w toggle wide-only columns (kubectl -o wide), including node IP addresses and labels
← / → scroll sideways by 5 text positions; NAMESPACE/NAME stay fixed; arrows show more content
:q, ctrl-c quit
? help
(config) plugin / bookmark / workspace key chords — ctrl-/alt-/shift-/fN; listed in ? help

Shift+Arrow selects a range in the visible row order. Reversing direction reduces the range and keeps separate marks made with space. Other keys end the range operation. Normal movement keeps marked rows. Filtering, sorting, view changes, and changes to the row order reset the range before the next Shift+Arrow press.

ctrl-space marks every row between the last row marked with space and the cursor, in the visible row order. Existing marks stay. Without a marked starting row, it marks the current row. Terminals that send ctrl-@ for ctrl-space work the same way.

Node drain (D on a node)

Key Action
Tab / Down Select the next option
Shift-Tab / Up Select the previous option
Space Toggle the selected checkbox
Text / Backspace / Ctrl-U Edit / remove a character / clear the selected duration
Enter Review options, then confirm; close a completed operation
Esc / Ctrl-C Cancel the form or active operation; close its result
PgUp / PgDn Scroll the form, confirmation, or progress

Drain options apply to the current operation only. The final confirmation shows all target nodes and selected options. Configured confirmation rules still apply. During a drain, navigation is disabled. Canceling stops requests and waiting; it cannot reverse a request that the API has accepted. Nodes remain cordoned. See Node drain options for defaults and limits.

Port-forward picker (f on a pod or service)

Key Action
enter start the selected mapping, or ask for remote and local ports for "Custom…"
e edit only the local port of a declared mapping
j / k, ↓ / ↑ select a mapping
PgDn / PgUp move one page down / up
esc / q close the picker

A mapping whose local port is already bound on both loopback addresses when the picker opens shows in use. The port can still change before you press enter, so starting a forward checks it again.

"Custom…" asks for the remote port, a number or a port name, then for the local port. The local port starts as the remote port when the remote port is a number. Forwards bind to localhost, as with the declared mappings.

The local-port prompt contains the current value. enter starts the forward; esc returns to the same picker row. Invalid or unavailable ports keep the prompt open for correction. If the forward process cannot start, the prompt keeps the edited value so you can retry.

PVC explore (x on a PVC)

A two-pane file browser over a PersistentVolumeClaim: your local filesystem on the left, the volume on the right. s on a PVC row opens a shell at the mount point instead. See PVC explore.

Key Action
tab, ← / → switch pane (the focused pane has the bright border)
j/k, g/G move within the focused pane
enter open the selected directory
⌫ or - go up one directory - stops at the mount point, never above it
c copy the selection into the other pane: download from the volume, or upload
s shell into the volume at the directory the remote pane is showing
r re-read both panes
esc / q close (and delete the helper pod, if one was created)

Manifest browser (:dir [path])

Lists the folders and YAML/JSON manifests in path, or in the directory sofka was started from. See Manifest browser.

Key Action
j/k, g/G move
enter open the selected folder, or show the selected manifest
⌫ or - go up one directory
e edit the selected manifest in $KUBE_EDITOR or $EDITOR
a diff the selection against the cluster; a in the diff applies it
d delete the resources the selection describes, after confirmation
r re-read the directory
esc / q close

Logs view

/ filter (substring · /regex/ · !invert) · s/f autoscroll · w wrap · ←/→ or h/l scroll sideways (unwrapped) · J JSON view (raw/record/pretty) · Ctrl+Z warning/error filter · m visual marker · t timestamps · x stop/resume stream · z clear buffer · c copy buffer · a default/all containers (pods with a default-container annotation) · ctrl-s save to a file in save_dir · F fullscreen (no chrome, clean text selection) · 0–5 time anchors (tail · 1m · 5m · 15m · 30m · 1h) · T custom lookback (s/m/h/d/w, compound like 1h30m, decimal like 1.5h, or tail for kubelet logs) (VictoriaLogs views) · esc back. The newest line anchors to the bottom of the viewport.

t shows or hides timestamps in the current buffer without restarting the streams. Log lines keep their timestamp order in both display settings.

m adds a separator after the latest received log line. Repeated presses add separate markers. Markers stay visible through filters and are excluded from sofka copy/save. While paused, a marker is added at the buffer tail without moving the viewport. Markers have no timestamp. They are removed when the buffer is cleared or replaced, or when their position is trimmed. Marker count is limited to the active log buffer cap. Manual terminal selection can include visible markers.

Describe

d uses kubectl by default. Enable the experimental deskribe backend with --experimental-describe or [experimental] native_describe = true in config. Unsupported native resources use a labeled kubectl fallback; errors from that fallback never show cached YAML. See configuration for overrides and reload behavior. Helm rows continue to show release notes.

Document views (YAML, describe, diff, events)

ctrl-f / ctrl-b page forward or back, with PgDn / PgUp as aliases. / searches like vim: the whole document stays on screen and every match is highlighted. n / N go to the next or previous match. w wraps. c copies the document. ctrl-s saves it to a file. esc backs out - the first press clears an active search.

ctrl-s writes the whole document as rendered, whatever the search or scroll position. managedFields are included only after m shows them, and a Helm row saves the rendered manifest or values it shows. The file goes to save_dir, the temp directory by default, as sofka-<view title>-<unix time>.yaml for YAML and diff views and .txt for the others. The file is readable only by your user, since a document can hold Secret values, and a name that is already taken gets a -2, -3, … suffix instead of replacing the earlier save. Log saves follow the same rules. The write happens off the UI thread; the status line shows the path, or the error if the directory cannot be created or the file cannot be written. An empty document is not saved.

F toggles fullscreen for document views and plugin popup output. Fullscreen uses the full terminal area without the application header, status line, key hints, borders, or scrollbars. The title and active search or command prompt remain visible. Search, scrolling, wrapping, copying, and refresh still work. The setting stays on across refreshes and new documents for the current session. It starts off in a new session and is separate from the Logs fullscreen setting. F restores the normal layout. esc and q keep their existing behavior.

In the YAML and describe views, e opens the displayed resource in $EDITOR (kubectl edit), even if the table selection moved while the document was open. Read-only mode blocks it, and a Flux-managed resource asks for confirmation first. sofka reads the resource before opening the editor and refuses if it was replaced under the same name. The document is read again when the editor closes. The diff and events views do not support e. Use keys.detail.edit to change the key binding.

In the decoded Secret view, e opens the text values as stringData in $KUBE_EDITOR or $EDITOR (vi when neither is set). The file is private to your user and is deleted when the editor closes. If sofka exits without deleting it, the next start removes it. Values that are not text are not shown and cannot be overwritten from the editor. Delete a key to remove it, or write stringData: {} to remove every text key. Save the file unchanged to cancel. If the file does not parse, or a value is not a string, the editor opens again with the error on top. sofka then asks for confirmation, naming the keys it will change, add, or remove, and patches only those keys. The patch fails if the Secret changed after e read it. An immutable Secret cannot be edited. Read-only mode and the secret-edit guardrail apply.

In the YAML view, m shows or hides metadata.managedFields. Fields are hidden when a document opens. Showing them reads the full resource from the API. The choice stays in effect during automatic refresh. This key does not change describe, decoded Secret, or diff views. Use keys.detail.managed_fields to change the key binding.

Automatic refresh is available in these resource views:

View Automatic refresh Other refresh controls
YAML, decoded Secret, describe r turns refresh on or off None
Diff r turns refresh on or off R resets the baseline to the displayed resource
Explain R turns refresh on or off r refreshes immediately

Automatic refresh is off when a view opens. It reads immediately, then waits 5 seconds after each result before the next read. Describe retains its selected backend: kubectl by default, or native-first with a labeled kubectl fallback when opted in. Native describe fetches fresh resource, related-object, and event data through the current Kubernetes client. The other views also read through the API. YAML and describe support custom resources.

Refresh keeps the original resource and context. It preserves document search, scroll position where possible, and the selected Explain resource when findings move or its status text changes. Findings without a resource target match by content. If the selected finding disappears, the selection clears. Select another finding before opening its resource, events, or logs. A shorter document can reduce the scroll position. The status indicator shows refresh while automatic refresh is on and stopped when it is off. Documents without refresh support, such as saved snapshots and Helm manifests, show static.

Automatic refresh stops when you leave the view, open help or the command palette, or a request fails. Document search keeps refresh active. A failed request keeps the last result and shows the reason. A deleted resource, or a resource recreated with the same name and a different UID, also stops refresh. Opening events or logs from Explain stops its automatic refresh; returning does not restart it. Its existing manual evidence request can still finish.

Diff keeps the baseline chosen when the view opens, even if the last-applied annotation or session history changes. R makes the currently displayed object the new baseline. A Diff view can stay open when both sides match, so automatic refresh can show later changes. This does not add change highlighting to YAML.

Help panel (?)

Help opens scrolled to the Keys: section of the view it was opened from. The section order is the same from every view. A view without a section opens at the top.

j / k and ↑ / ↓ scroll one line. ctrl-f, PgDn, and space move forward one page. ctrl-b and PgUp move back one page. The page size is the number of visible content rows. g / Home go to the top; G / End go to the bottom. ] jumps to the next section heading and [ to the previous one.

/ filters the bindings. A binding that matches is shown under its section heading. A section heading that matches keeps the whole section, so /table lists every table binding. Starting a filter and clearing a filter reset the scroll position to the top. esc clears an active filter first, then closes help. q or ? closes help and returns to the previous screen.

Explain view (X)

j / k move, ⏎ goes to the resource behind a finding (a blocking pod), E its events, l its logs, r gathers again, esc goes back. After opening logs or events, one esc returns to Explain and another returns to the table. A finding you can drill into has a trailing →.

Long findings wrap onto more rows. w toggles between wrapped and clipped findings here and in the GitOps (:gitops) and Argo CD (:argocd) views. When a finding is taller than the list, j / k scroll through its rows before moving to the next or previous finding.

Adjacent view (u)

Every object directly connected to the selection: what owns it, what it owns, what its spec names (a pod's node, claims, ConfigMaps, Secrets), and what names it (the pods mounting a claim, the claims using a class). j / k move, ⏎ opens the object in its own view - name-filtered, so every action there applies to it - y shows its YAML, d describes it, r gathers again, esc goes back. Not offered on namespaces (enter re-scopes to one) or Helm rows. See Views for adding CRD relations.

Pickers

PgDn and PgUp move one page through every list picker: contexts, namespaces, sort and copy fields, port forwards, containers, set image, skins, snapshots, and the action and transfer menus. The page size is the number of visible list rows. Paging also works while a picker filter is being typed.

half_page_down and half_page_up move half a page in every view and picker that pages. They have no default keys; bind them in key bindings, for example to ctrl-d and ctrl-u. In pickers with a text filter, a shared half-page key that types text or edits the line keeps doing that.

Text inputs (palette, filters, prompts)

Backspace or Ctrl-H removes a character. ctrl-u clears the line, ctrl-w / alt-⌫ delete the previous word.

Palette completion keys

In the : palette, tab/↓ and shift-tab/↑ move through the suggestion list, → fills the highlighted one into the command so you can keep typing, and ⏎ runs the highlighted one. → replaces only the word it completes: the resource or command name, or the namespace or context argument. Rebind them under [keys.command] in config.toml, for example:

[keys.command]
down = "ctrl-n"
up = "ctrl-p"
accept = ["ctrl-y", "enter"]

Each value is one key combination or a list of combinations. It replaces the default set for that action: ["tab", "down"], ["backtab", "up"], ["right"] for complete, or ["enter"]. Include a default in the list to keep it. An empty list disables the action. Invalid values report errors. Explicit completion bindings take priority over text editing and cancellation. To assign ctrl-c or ctrl-e, first move or disable quit or compact under [keys.global].

Legacy palette_next, palette_prev, and palette_accept settings are automatically migrated to this format, with a config.toml.bak backup. If the file cannot be updated, sofka warns and uses the converted settings in memory. See migration for managed configs, conflicts, and invalid values.

What suspends the TUI

Interactive actions (e, s for shell, a) suspend the TUI and shell out to kubectl. e in the manifest browser suspends it for your editor. Delete, scale, restart, set-image, suspend, resume, reconcile, and port-forward go through the kube API (or a backgrounded process) directly.

If the first PVC listing fails because required tools are missing, sofka tries other suitable containers, then offers a helper pod. Accept or cancel the existing confirmation dialog. Volume access restrictions, read-only mode, and guardrails still apply. Canceling keeps the original error visible.

Plugin commands

Command Action
:<plugin> [name=value ...] Run a plugin with validated inputs.
:plugin-activity Reopen the active plugin panel or retained report.
:plugin-cancel Stop the active plugin run and its temporary forward.
:sanitize [states=…] [dry_run=…] Delete the pods the namespace has finished with (pods view).

:sanitize ships with sofka; see Sanitize pods.

A plugin command started from its key chord or with no arguments opens an input form when an input has no default, or when the command sets prompt = "always". Fields start with their default values. In the form:

  • Tab/Shift+Tab or ↓/↑ move between fields.
  • ←/→ cycle a field with choices or a boolean field.
  • Backspace removes a character; Ctrl-U clears the field.
  • Enter validates every field and runs the command. Errors appear under the field.
  • Esc cancels without running anything.

Rebind these keys under [keys.plugin_form]. Popup/report runs open a floating activity panel immediately. In that panel:

  • Ctrl+Alt+T toggles the popup without cancelling or restarting the job.
  • Esc hides without cancelling; :plugin-activity reopens it.
  • After completion, Ctrl+Alt+T restores diagnostics; Enter opens the report.
  • Rebind the toggle with [keys.global].plugin_activity.
  • Ctrl+C cancels the focused run, not sofka. Outside the panel it still quits.
  • ↑/↓ or k/j, PgUp/PgDn scroll; Home/g goes to the start; End/G resumes following. ←/→ or h/l scroll horizontally.
  • : hides the panel and opens the command palette.

Installed packages add their commands and key chords to ? help. Use :reload after a package change. See Create a plugin package.

Confirmation and input popups

PgUp and PgDn scroll text that does not fit in the popup. The action keys stay visible. In an input popup, typing moves the view to the cursor.

Command failures

A failed interactive command opens an error dialog. esc or enter dismisses it; PgUp and PgDn scroll the output. If a pod shell failed because sh is missing, d opens the debug image prompt for the same pod and container. Accept the image to start the debug container, subject to the configured guardrails. Canceling the prompt returns to the original error.