Configuration Reference

July 10, 2026 · View on GitHub

The configuration file is located at ~/.config/lfk/config.yaml. All fields are optional — only the values you specify will override the defaults.

Editor autocompletion (JSON Schema)

A JSON Schema is published at docs/config.schema.json. Add this modeline to the top of your config.yaml to get autocompletion, inline docs, and typo warnings in any editor running a YAML language server (VS Code's YAML extension, Neovim with yamlls, etc.):

# yaml-language-server: $schema=https://raw.githubusercontent.com/janosmiko/lfk/main/docs/config.schema.json

Prefer a local copy? Point $schema at a relative or absolute path instead of the URL.

Top-Level Fields

FieldTypeDefaultDescription
appearanceobject(see Appearance section)Visual settings group: colorscheme, icons, no_color, transparent_background, min_contrast_ratio, dim_overlay. Canonical home for these knobs. See Appearance.
colorschemestring"tokyonight-storm"Deprecated — use appearance.colorscheme. Built-in color scheme name (460+ available). Press T to browse. Supports dual-mode syntax for auto dark/light switching: "dark:X,light:Y". Custom theme overrides are applied on top.
transparent_backgroundboolfalseDeprecated — use appearance.transparent_background. Use the terminal's own background for bars. Selection highlights remain opaque.
iconsstring"auto"Deprecated — use appearance.icons. Icon display mode. One of: "auto" (detects Nerd Font terminals; default), "unicode", "nerdfont" (Material Design Icons; requires Nerd Font in terminal), "simple" (ASCII labels), "emoji", or "none". Unknown values fall back to "unicode". Can be overridden at runtime by the LFK_ICONS environment variable.
log_pathstring"~/.local/share/lfk/lfk.log"Path to the application log file.
kubeconfig_dirstring or list[string]"~/.kube/config.d"Directory (or list of directories) recursively scanned for kubeconfig files, in addition to ~/.kube/config (unless KUBECONFIG is set, which is exclusive like kubectl). Tilde paths are expanded against $HOME. The --kubeconfig-dir CLI flag (repeatable) and KUBECONFIG_DIR env var (colon-separated) override this; the --kubeconfig flag bypasses directory discovery entirely. See Kubeconfig Directory.
kubeconfig_exclusivebooltrueWhen KUBECONFIG is set, load only the files it lists (kubectl semantics), skipping ~/.kube/config and the default ~/.kube/config.d scan. Set false to merge everything like releases before 0.15. Overridden by --kubeconfig-exclusive and LFK_KUBECONFIG_EXCLUSIVE.
dashboardbooltrueShow cluster dashboard when entering a context. Set to false to go directly to resource types.
monitoringmap[string]object{}Per-cluster monitoring endpoint configuration. Keys are context names or "_global". See Monitoring section.
viewsmap[string]object{}Per-resource-type column and sort configuration. Keys are GVR (apps/v1/deployments) or Kind (deployment, case-insensitive); GVR wins when both match. Supersedes resource_columns. See views.
resource_columnsmap[string]list{}Per-resource-type column configuration. Keys are resource Kind names (case-insensitive). Deprecated — use views instead. Bridged automatically; views wins when both are set for the same Kind.
clustersmap[string]object{}Per-cluster configuration overrides. Keys are context names. See Clusters section.
themeobject(see Theme section)Custom color theme overrides.
keybindingsobject(see Keybindings section)Custom keybinding overrides for direct actions.
abbreviationsmap[string]string(see Abbreviations section)Custom search abbreviation overrides/extensions.
custom_actionsmap[string]list{}User-defined actions per resource type.
filter_presetsmap[string]list{}User-defined quick filter presets per resource type.
goto_targetsmap{}Extra g-prefix goto chords. Key = full chord (e.g. gA); value = {kind, group, name}. Overrides built-ins on collision.
which_key_enabledbooltrueShow the which-key popup while the g prefix is pending.
which_key_delay_msint0Delay before the popup appears (ms, 0-2000).
terminalstring"pty"How exec/shell commands run: "pty" (embedded in TUI), "exec" (takes over terminal), or "mux" (opens in a new tmux/zellij window/pane; errors out if no multiplexer is detected).
pinned_groupslist[string][]CRD API groups to pin after built-in categories. Also manageable in-app with p key (stored per-context and per-union-set in ~/.local/state/lfk/pinned.yaml).
union_setsmap[string]object or list[object][]Named multi-cluster groups that the --union-set <name> CLI flag expands. See Union Sets.
tipsbooltrueShow a random tip in the status bar on startup. Set to false to disable.
log_viewerobject(see Log Viewer section)Log viewer settings: tail sizes, ANSI rendering, and startup-toggle defaults for preview/prefixes/timestamps. See Log Viewer. Note: log_path (above) is the application's own log file, not a viewer setting.
yaml_viewerobject(see Viewer Defaults)YAML viewer startup-toggle defaults. See Viewer Defaults.
diff_viewerobject(see Viewer Defaults)Diff viewer startup-toggle defaults. See Viewer Defaults.
describe_viewerobject(see Viewer Defaults)Describe viewer startup-toggle defaults. See Viewer Defaults.
object_explorerobject(see Viewer Defaults)Object Explorer startup-toggle defaults. See Viewer Defaults.
api_explorerobject(see Viewer Defaults)API Explorer startup-toggle defaults. See Viewer Defaults.
split_previewbooltrueStartup default for the split preview pane. Set to false to start with it hidden.
watch_modebooltrueStartup default for live watch/polling. Set to false to start with manual refresh.
watch_intervalstring2sPolling interval in watch mode. Go duration string, clamped to [500ms, 10m]. Override with --watch-interval.
background_watch_intervalstring10sWatch cadence while the window is unfocused or focused-idle. Same form and [500ms, 10m] clamp as watch_interval. Set equal to watch_interval to disable background throttling.
foreground_idle_timeoutstring120sNo-input window before a focused window throttles to background_watch_interval. Go duration; 0 disables focused-idle throttling (background throttling still applies). Clamped to [0, 10m].
watch_throttlebooltrueMaster switch for focus/idle watch throttling. Set false to disable it entirely; the watch tick then always uses watch_interval.
all_namespacesbooltrueStartup namespace scope: true shows all namespaces, false scopes to the context's default namespace. The --namespace CLI flag and per-bookmark/session scope override this.
eventsobject(see Events section)Events view startup-toggle defaults. See Events.
log_tail_linesint100Deprecated — use log_viewer.tail_lines. Number of log lines to load initially via --tail.
log_tail_lines_shortint10Deprecated — use log_viewer.tail_lines_short. Number of log lines loaded by the action menu "Tail Logs" entry. Non-positive values are ignored.
log_render_ansibooltrueDeprecated — use log_viewer.render_ansi. Render ANSI SGR sequences from log producers.
log_top_default_profilestringautoDefault Log Top parser: auto, traefik-json, ingress-nginx, nginx-combined, envoy, json, logfmt.
confirm_on_exitbooltrueShow quit confirmation when pressing ctrl+c on the last tab. Set to false to exit immediately.
dim_overlaybooltrueDeprecated — use appearance.dim_overlay. Fade the rest of the screen while any overlay is up. Set to false for terminals where SGR faint looks awkward; no-op when no_color: true.
scrolloffint5Number of lines to keep visible above/below the cursor when scrolling. Used by all views with cursor-based navigation.
mousebooltrueCapture mouse input for click navigation, scroll, and tab switching. Set to false to allow native terminal text selection. Also available as --no-mouse CLI flag.
read_onlyboolfalseDisable all mutating actions (delete, edit, scale, restart, exec, port-forward, drain, cordon, etc.) globally. Per-context overrides under clusters.<name>.read_only and the --read-only CLI flag take precedence. See Read-Only Mode.
clusters.<name>.read_onlybool(unset)Per-context read-only override. Wins over the global read_only so you can mark specific clusters (e.g. prod) read-only while leaving others mutable.
show_rare_typesboolfalseShow the rarely-used resource types (CSI internals, admission webhooks, leases, runtime classes, and the "Advanced" category) in the sidebar from startup, as if H were pressed — so the full type list is always visible. The H toggle still flips it for the session; it resets to this value on the next launch.
security.enabledbooltrueEnable the built-in security findings dashboard (Security category + SEC badge). false turns the dashboard and all source probing off. Per-context overrides under clusters.<name>.security take precedence. See Security Dashboard.
security.hide_badgesboolfalseHide the per-resource SEC severity badge by default. The dashboard still scans; only the inline row badge is suppressed. Toggle at runtime with the security badge key (B). Per-context overrides under clusters.<name>.security.hide_badges take precedence.
security.sources.<name>booltrueEnable/disable individual sources (heuristic, advisor, rbac, trivy, kyverno, kubescape, falco, gatekeeper). A source omitted from the map stays enabled.
security.ignore_patternslist(empty)Declarative glob-based ignore rules applied at load. Each entry has cluster, source, group, namespace (globs; empty = any), an optional labels map (label key -> glob value; all entries must match), and an optional comment. A finding is hidden when every non-empty field matches. A labels entry is resource-scoped (hides matching resources, never the whole group) and matches when the finding's resource has resolvable labels (heuristic-observed pods and same-pod findings, plus workload labels resolved from the live object for standard kinds when a label pattern is set). See Security Dashboard for coverage details. An all-empty entry is dropped. Read-only (not un-ignorable from the UI); the i toggle still reveals them.
security.heuristic.secret_env_includelist(empty)Extra env-var name globs (*, ?; case-insensitive) the heuristic secret_env check flags, on top of the built-in credential keywords. An explicit match overrides a built-in exemption. Top-level security section only.
security.heuristic.secret_env_excludelist(empty)Env-var name globs the heuristic secret_env check never flags, on top of the built-in exemptions. Wins over secret_env_include. Top-level security section only.
security.heuristic.scan_secretsbooltrueAllow the heuristic source to list Secret objects, enabling the legacy_sa_token_secret and tls_secret_expiry checks and Secret-reference verification. false means the source never reads Secrets. Top-level security section only.
clusters.<name>.securityobject(unset)Per-context security override (enabled, hide_badges, and/or sources). Wins over the global security settings for that context.
secret_lazy_loadingboolfalseWhen true, Secret listing fetches metadata only and decoded values load on hover. Much faster in clusters with many Helm release secrets (each release is a multi-hundred-KB Secret) or large TLS payloads, at the cost of an extra GET per hovered Secret. When false (default), Secrets list like every other resource type — full objects are pulled and data is eagerly decoded, so the Type column and decoded values are visible immediately. See Secret lazy loading for trade-offs.
informer_cachebool or stringautoSelects the list strategy. Accepts off (round-trip every list — matches kubectl), auto (default; promote a resource type to a shared informer once a list crosses 1000 items, demote when sustained below 500), and always (open a watch eagerly on first use). Legacy bool form is still accepted: truealways, falseoff. See Informer cache for trade-offs.
min_contrast_ratiofloat0.0Deprecated — use appearance.min_contrast_ratio. Normalized readability knob in [0.0, 1.0]. When above zero, foreground colors are nudged in HSL lightness space to meet a minimum WCAG contrast ratio against their paired background. See Minimum Contrast Ratio.

Auto dark/light mode

When colorscheme uses the dark:X,light:Y dual-mode syntax (either segment may be omitted), lfk subscribes to your terminal's operating system color-scheme preference via the standard CSI 2031/996 protocol:

  • On startup lfk sends CSI ?2031h (subscribe to notifications) and CSI ?996n (request current preference).
  • The terminal responds with CSI ?997;1n (dark) or CSI ?997;2n (light).
  • Whenever the OS appearance changes, the terminal sends another notification and lfk switches to the configured scheme in real time.

Supported terminals: Ghostty, kitty ≥ 0.27, Contour, WezTerm (recent nightly builds). Other terminals silently ignore the sequences.

# Example: dark → Catppuccin Mocha, light → Catppuccin Latte
colorscheme: "dark:catppuccin-mocha,light:catppuccin-latte"

# Spaces in scheme names are fine — they are normalised to hyphens internally:
colorscheme: "dark:Rose Pine,light:Rose Pine Dawn"

When only one side is configured the other side performs no automatic switch. Plain (non-dual) colorscheme values continue to work as before and disable automatic dark/light switching entirely.

Icon mode auto-detection

When icons: auto (the default), lfk inspects your environment at startup to choose between nerdfont and unicode:

  1. LFK_ICONS environment variable wins if set to any valid mode value.
  2. TERM is checked for substrings ghostty, kitty, wezterm (works with tmux-through-ghostty setups where TERM=xterm-ghostty but TERM_PROGRAM=tmux).
  3. TERM_PROGRAM is checked for ghostty, WezTerm, kitty.
  4. Falls back to unicode otherwise.

If detection guesses wrong for your setup, set icons: nerdfont (or the mode you want) in your config, or export LFK_ICONS=nerdfont in your shell.

Appearance

Visual settings, grouped. The flat keys of the same name (colorscheme, icons, no_color, transparent_background, min_contrast_ratio, dim_overlay) are deprecated aliases; when both a flat key and its appearance equivalent are set, appearance wins. The theme object (custom color overrides) and per-cluster overrides remain top-level.

appearance:
  colorscheme: tokyonight-storm
  icons: auto
  no_color: false
  transparent_background: false
  min_contrast_ratio: 0.0
  dim_overlay: true
FieldTypeDefaultDescription
colorschemestring"tokyonight-storm"Built-in color scheme name. Dual-mode "dark:X,light:Y" supported.
iconsstring"auto"Icon display mode (auto/unicode/nerdfont/simple/emoji/none).
no_colorboolfalseStrip all colors (monochrome). NO_COLOR env var takes precedence.
transparent_backgroundboolfalseUse the terminal's own background for bars and surfaces.
min_contrast_ratiofloat0.0Readability knob in [0.0, 1.0]. See Minimum Contrast Ratio.
dim_overlaybooltrueFade the screen behind overlays. No-op when no_color: true.

Log Viewer

Settings for the log viewer (L key). The startup-toggle defaults let you skip pressing the toggle keys on every open (issue #377). log_path is the application's own log file and is intentionally not part of this group.

log_viewer:
  tail_lines: 100
  tail_lines_short: 10
  render_ansi: true
  show_preview: true
  show_prefixes: true
  show_timestamps: false
  preview_live: false
FieldTypeDefaultDescription
tail_linesint100Log lines loaded initially via --tail (per container). Scrolling to the top loads older history.
tail_lines_shortint10Log lines loaded by the action menu "Tail Logs" entry. Non-positive values are ignored.
render_ansibooltrueRender ANSI SGR sequences (color, bold, underline) from log producers. false strips them (every ESC byte becomes U+FFFD); non-SGR CSI sequences are always stripped. Toggle at runtime with :set ansi / :set noansi.
show_previewbooltrueStartup default for the structured preview side panel. Runtime toggle: toggle_preview (P).
show_prefixesbooltrueStartup default for the [pod/name/container] line prefixes. Runtime toggle: toggle_prefixes (p).
show_timestampsboolfalseStartup default for log line timestamps. Runtime toggle: toggle_timestamps (s).
preview_liveboolfalseStartup default for the right-pane live-log preview. When true the explorer opens with live logs streaming in the right pane for the selected pod. Runtime toggle: toggle_preview_logs (L).
max_linesint50000Max streamed log lines retained per tab; once exceeded, the oldest lines are dropped so a long-running follow stays bounded in memory. Clamped to [1000, 1000000].

The deprecated flat keys log_tail_lines, log_tail_lines_short, and log_render_ansi are still accepted as aliases; when both a flat key and its log_viewer equivalent are set, log_viewer wins.

Viewer Defaults

Startup defaults for the fullscreen YAML / diff / describe viewers, so display toggles you always want don't need re-pressing on every open. Each viewer mirrors the log_viewer group.

yaml_viewer:
  wrap: false
diff_viewer:
  wrap: false
  line_numbers: true
  unified: false
describe_viewer:
  wrap: false
object_explorer:
  live: true
  tree: false
api_explorer:
  tree: false
FieldTypeDefaultRuntime toggleDescription
yaml_viewer.wrapboolfalsetoggle_wrap (>)Line wrapping in the YAML viewer.
diff_viewer.wrapboolfalsetoggle_wrap (>)Line wrapping in the diff viewer.
diff_viewer.line_numbersbooltruetoggle_line_numbers (#)Gutter line numbers in the diff viewer.
diff_viewer.unifiedboolfalsetoggle_unified (u)Unified (vs side-by-side) diff layout.
describe_viewer.wrapboolfalsetoggle_wrap (>)Line wrapping in the describe viewer.
object_explorer.livebooltruewatch_mode (w)Live-refresh the browsed object as the resource changes under watch mode. Manual refresh with refresh (R).
object_explorer.treeboolfalsetree_view (T)Open the Object Explorer in the ASCII-art tree view.
api_explorer.treeboolfalsetree_view (T)Open the API Explorer in the ASCII-art tree view (sticky across navigation).

A toggle changed at runtime sticks for the session and resets to the configured default the next time the viewer opens.

Events

Startup defaults for the events view.

events:
  warnings_only: true
  grouping: true
FieldTypeDefaultDescription
events.warnings_onlybooltrueStart filtered to Warning events only.
events.groupingbooltrueStart with related events grouped by reason.

Monitoring

Configure Prometheus and Alertmanager endpoints for the monitoring dashboard (@ key) and alert views. By default, lfk auto-discovers monitoring services by trying common service names across common namespaces. Use this section to override the endpoints per cluster or set a default for all clusters.

Keys are kubeconfig context names. The special key "_global" applies to any cluster without an explicit entry.

monitoring:
  # Override for a specific cluster context:
  my-prod-cluster:
    prometheus:
      namespaces: ["monitoring"]
      services: ["thanos-query"]
      port: "9090"
    alertmanager:
      namespaces: ["monitoring"]
      services: ["alertmanager-main"]
      port: "9093"
    node_metrics: prometheus   # "prometheus" or "metrics-api" (default: auto-detect)
  # Global fallback for all other clusters:
  _global:
    prometheus:
      namespaces: ["monitoring", "observability"]
      services: ["prometheus-server", "prometheus"]

Monitoring Entry Fields

Each monitoring entry accepts the following top-level fields:

FieldTypeDefaultDescription
prometheusobject(auto-discovery)Prometheus endpoint configuration. See endpoint fields below.
alertmanagerobject(auto-discovery)Alertmanager endpoint configuration. See endpoint fields below.
node_metricsstring(auto-detect)Metrics source for node and pod usage: "prometheus" (use Prometheus queries), "metrics-api" (use metrics.k8s.io API). When empty, uses Prometheus if a prometheus endpoint is configured, otherwise metrics-api. Either way the other source is tried as a fallback, so pod metrics resolve on clusters served only by Prometheus.

Node Uptime Column

The nodes list shows an Uptime column (how long since each node last booted) when Prometheus is the configured monitoring source — that is, a prometheus endpoint is set, or node_metrics: prometheus. One of the two is required; the column stays hidden on clusters with no monitoring config. With node_metrics: prometheus and no prometheus block, the endpoint itself is auto-discovered from the well-known namespaces and services listed below.

RequirementDetail
Sourcenode_exporter's node_boot_time_seconds metric, queried via Prometheus
Needsnode_exporter, not just Prometheus (e.g. kube-prometheus-stack ships both)
Kubernetes APIDoes not expose node boot time, so there is no fallback source

Clusters without node_exporter never show the column. A node missing from the query result shows n/a, as does every node if Prometheus stops responding.

Monitoring Endpoint Fields

Each endpoint (prometheus and alertmanager) accepts:

FieldTypeDefaultDescription
namespaceslist[string](auto-discovery)Namespaces to search for the service. Tried in order.
serviceslist[string](auto-discovery)Service names to try. Tried in order within each namespace.
portstring"9090" / "9093"Service port (default: 9090 for Prometheus, 9093 for Alertmanager).

When not configured, the following defaults are used for auto-discovery:

ComponentDefault NamespacesDefault Services
Prometheusmonitoring, prometheus, observability, kube-prometheus-stackprometheus-kube-prometheus-prometheus, prometheus-server, prometheus, prometheus-operated
Alertmanagermonitoring, prometheus, observability, kube-prometheus-stackalertmanager-operated, alertmanager, prometheus-kube-prometheus-alertmanager, alertmanager-main

Clusters

Per-cluster configuration overrides allow you to customize settings for individual kubeconfig contexts. Keys are context names.

Currently supported per-cluster overrides:

FieldTypeDescription
viewsmap[string]objectPer-resource-type view overrides for this cluster. Same format as the global views. Wins over global views for matching keys.
resource_columnsmap[string]listPer-resource-type column overrides for this cluster. Deprecated — use views instead.
read_onlyboolPer-context read-only override. Same semantics as the top-level read_only.
securityobjectPer-context security override (enabled and/or sources). Same semantics as the top-level security; wins over it for this context.
k8s_client_qpsintPer-context foreground API client QPS override. Wins over the global scheduler.k8s_client_qps. See API client rate limits.
k8s_client_burstintPer-context foreground API client burst override. Wins over the global scheduler.k8s_client_burst.

Per-cluster views take precedence over the global views setting.

clusters:
  my-prod-cluster:
    views:
      apps/v1/deployments:
        columns: ["Name", "Replicas", "Available", "REV"]
        sort_column: "REV"         # defaults to desc for REV
    resource_columns:              # deprecated; still works
      Pod: ["IP", "Node", "Image", "CPU", "MEM"]
  my-staging-cluster:
    views:
      pod:
        columns: ["Name", "IP", "Node", "Image"]

Security

Controls the built-in security findings dashboard. Disable it globally or per cluster, or enable only specific sources. Source keys: heuristic, advisor, rbac, trivy, kyverno, kubescape, falco, gatekeeper (the internal ids trivy-operator and policy-report are also accepted). Any source omitted from sources stays enabled.

security:
  enabled: true            # global default (omit = true)
  sources:
    falco: false           # disable Falco everywhere

  ignore_patterns:        # declarative, glob-based ignore rules (applied at load)
    - source: trivy-operator
      group: "CVE-2024-*"  # CVE id / check label / rule name
      namespace: kube-system  # "" or "*" = any namespace (hides the whole group)
      cluster: "prod-*"    # kube-context glob; "" = any cluster
      comment: accepted in system namespaces
    - labels:              # exclude infra pods by label (key -> glob value; all must match)
        k8s-app: cilium    # silence findings on Cilium pods
      comment: CNI managed separately

clusters:
  prod:
    security:
      enabled: false       # turn the whole dashboard off on prod
  staging:
    security:
      sources:
        trivy: false       # keep the dashboard, drop Trivy on staging only

Precedence: clusters.<ctx>.security.* overrides the global security.*. The interactive per-cluster ignore-list (action menu) and ignore_patterns are applied together; config patterns are read-only. See Security Dashboard for the source catalog, ignore scopes, and behavior.

API client rate limits

lfk caps how fast it calls each cluster's API server (client-side QPS/burst). The stock client-go default (QPS 5 / burst 10) is low for a multi-resource TUI and lets a background scan stall foreground lists, so lfk defaults to QPS 50 / burst 100. Tune globally under scheduler, or per cluster under clusters.<name>.

FieldTypeDefaultDescription
scheduler.k8s_client_qpsint50Sustained foreground requests/sec to the API server.
scheduler.k8s_client_burstint100Burst capacity above QPS for short spikes.
clusters.<name>.k8s_client_qpsint(global)Per-context QPS override. Wins over the global value.
clusters.<name>.k8s_client_burstint(global)Per-context burst override.
scheduler:
  k8s_client_qps: 50
  k8s_client_burst: 100

clusters:
  big-prod-cluster:
    k8s_client_qps: 200      # raise the ceiling on a large, dedicated cluster
    k8s_client_burst: 400
  shared-cluster:
    k8s_client_qps: 20       # be gentle on a shared/throttled API server
    k8s_client_burst: 40

Precedence: clusters.<ctx>.k8s_client_* overrides scheduler.k8s_client_*, which overrides the built-in default. Security source scans run on a separate, deliberately lower budget (QPS 10 / burst 20) so background finding scans never starve foreground lists — see Security Dashboard.

Background task scheduling

lfk runs API work in a per-context worker pool, classified into priority lanes: Critical (API discovery, RBAC, namespaces, mutations), High (the view you are looking at — resource lists, drill-in, preview), and Low (background work — security scans, metrics, events, dashboards). Three knobs keep background work flowing without slowing the foreground, which matters most on slow-responding clusters where calls hold a worker for seconds:

FieldTypeDefaultDescription
scheduler.workers_per_contextint8Concurrent workers per cluster context (clamped 1–16). More slots drain the metrics/events backlog faster on slow clusters.
scheduler.critical_reserved_slotsint1Workers that prefer Critical work (clamped to ≤ half the pool).
scheduler.low_reserved_slotsint2Workers that prefer Low (background) work so metrics/events/dashboards always have a slot even while the foreground floods the pool. Clamped to leave ≥1 general worker.
scheduler.aging_thresholdint8Max higher-priority dispatches a background task waits behind before it is promoted for one task. 0 disables aging (strict priority).

Reserved workers are not idle: a reserved worker prefers its lane but falls back to any other queued work when its lane is empty, so reservations bias capacity without wasting it. Critical is never aged. The low-reserved floor and aging are complementary: the floor guarantees throughput for background work under a saturated pool, while aging bounds queue-ordering latency when High and Low are both backed up.

To keep API load bounded on slow clusters, the scheduler avoids redundant work: an identical fetch that is already in flight (same kind, target, and navigation generation) absorbs new submissions instead of running twice. This gives watch-mode its effective cadence under load — a tick that fires while the previous identical refresh is still running is coalesced away rather than stacking a duplicate fetch, so metrics/list refreshes never pile up faster than the cluster can serve them. Automatic and not configurable.

scheduler:
  workers_per_context: 8
  critical_reserved_slots: 1
  low_reserved_slots: 2   # always keep slots for metrics/events/dashboards
  aging_threshold: 8      # 0 = strict priority; higher = background waits longer

Theme

All theme colors accept CSS hex color codes (e.g., "#7aa2f7"). Only specify the colors you want to change; unspecified colors keep their defaults from the selected colorscheme.

FieldDefault (Tokyonight)Description
primary#7aa2f7Borders, headers, breadcrumbs, active column highlight
secondary#9ece6aHelp keys, running/success status, selection markers
text#c0caf5Normal text color
selected_fg#1a1b26Foreground of selected/highlighted items
selected_bg#7aa2f7Background of selected/highlighted items
border#3b4261Inactive column borders
dimmed#565f89Placeholder text, help descriptions, dimmed items
error#f7768eError messages, failed status, delete confirmations
warning#e0af68Warning messages, pending status, namespace indicator
purple#bb9af7Special values
base#1a1b26Dark background base
bar_bg#24283bTitle and status bar backgrounds
surface#1f2335Surface color for overlays

Keybindings

All keybindings can be overridden. Only specify the keys you want to change -- defaults apply for everything else. See keybindings.md for the full list.

The fullscreen viewers (YAML, diff, describe, log, events) honor the shared search, help, next_match, prev_match, and toggle_preview bindings, plus the toggle_* display toggles below. The log viewer additionally honors filter (live text filter: ~fuzzy, regex auto-detected, \literal) and severity_up/severity_down (step the minimum log severity shown). The fullscreen binding (default F / Shift+F) maximizes/minimizes everywhere it applies — the explorer's middle column and dashboard, the event timeline, and the error log. Core cursor navigation inside these viewers (hjkl, g/G, page motions, vim word-motions) remains fixed and is not yet rebindable.

FieldDefaultAction
logsctrl+lOpen the fullscreen log viewer for the selected resource
refreshRRefresh current view
restartrRestart resource (action menu only)
execsExec into container (action menu only)
describevDescribe selected resource
deleteDDelete resource (force delete Pod/Job if already deleting)
force_deleteXForce delete (Pod/Job only)
scaleSScale resource (deployments, statefulsets, daemonsets)
editEEdit selected resource in KUBEEDITORorKUBE_EDITOR or EDITOR
label_editoriEdit labels/annotations
secret_editoreSecret/ConfigMap editor
column_toggle,Column visibility toggle
session_managerCOpen the session manager (save/switch/delete named workspace sessions).
toggle_wrap>Toggle line wrapping in the YAML, diff, describe, log, and event viewers. Shares the > default with sort_next, but they apply in separate contexts (viewers vs. resource list).
toggle_line_numbers#Toggle line numbers (diff, log viewers).
toggle_foldzToggle fold on the section/region under the cursor (YAML, diff viewers; also folds tree-view branches in the Object/API Explorers, alongside Space).
toggle_fold_allZToggle all folds (YAML, diff viewers).
toggle_followFToggle follow / auto-scroll (log viewer). Moved from f, which now opens the log filter.
severity_upoRaise the minimum log severity shown — cycles off → INFO+ → WARN+ → ERROR+ (log viewer).
severity_downiLower the minimum log severity shown (log viewer). Structured logs use the parsed level; plain-text logs are classified by keyword (error/warn/debug), defaulting to INFO. Shares the i default with label_editor / security_ignore_toggle, but they apply in separate contexts (log viewer vs. resource list).
toggle_timestampssToggle timestamps (log viewer).
toggle_prefixespToggle [pod/name/container] line prefixes (log viewer).
toggle_unifieduToggle unified vs side-by-side layout (diff viewer).
tree_viewTToggle the ASCII-art tree view (Object Explorer, API Explorer). Shares the T default with theme_selector, but they apply in separate contexts (explorers vs. resource list).
toggle_previewPToggle the structured preview side panel (log viewer) / details↔YAML preview (explorer).
toggle_preview_logsLToggle the right-pane live-log preview for the selected pod or container (explorer; deeper levels only).
fullscreenFExplorer: cycle layout (hide sidebar -> fullscreen -> restore). Dashboard / event timeline / error log: fullscreen toggle.
sort_next>Sort by next column
sort_prev<Sort by previous column
sort_flip=Toggle sort direction
sort_reset-Reset sort to default
error_log!Error log overlay
finalizer_searchctrl+gFinalizer search and remove
terminal_togglectrl+tCycle terminal mode (pty/exec/mux)
mouse_togglealt+ctrl+ySuspend/resume mouse capture (Ctrl+Option+Y) for native text selection
toggle_rareHToggle rarely used resource types in the sidebar

Views

Use views to configure columns and default sort for specific resource types. Keys are either a GVR (apps/v1/deployments) or a Kind name (deployment, case-insensitive). When both match, GVR takes precedence.

View entry fields

FieldTypeDefaultDescription
columnslist[string](auto-detected)Ordered column specs. See Column spec syntax.
sort_columnstring(none)Default sort column. Format: "COL" or "COL:asc" / "COL:desc". When direction is omitted, REV defaults to desc; all other columns default to asc.

Column spec syntax

NAME[:.jsonpath][|flag]*
FormMeaning
NameBuilt-in column resolved by the renderer (Name, Age, Ready, REV, etc.)
Name:.jsonpathCustom column — JSONPath evaluated against the source object. Uses k8s.io/client-go/util/jsonpath (kubectl-flavored).
Name:.jsonpath|flagCustom column with one or more display flags (stackable with multiple |).

Flags (case-insensitive):

FlagEffect
RRight-align the column
THumanize value as a timestamp
WWide-only — hidden until the terminal width crosses the wide threshold

JSONPath notes: compile errors at config load emit a logger.Warn and skip that view (the rest of config loads normally). A miss at row-render time produces an empty cell with no log spam. The JSONPath dialect is kubectl-flavored (k8s.io/client-go/util/jsonpath); advanced filter expressions that differ from k9s's dialect may not be portable.

Example

views:
  # GVR key — wins over a matching Kind key
  apps/v1/deployments:
    columns: ["Name", "Namespace", "Replicas", "Available", "REV", "Age"]
    sort_column: "REV"            # desc by default for REV
  # Kind key (case-insensitive)
  pod:
    columns:
      - "Name"
      - "IP"
      - "Node"
      - "GitSHA:.metadata.labels.git-sha|W"   # custom JSONPath column, wide-only
      - "Age"
    sort_column: "Age:asc"

Per-cluster overrides follow the same format under clusters.<name>.views and win over global views for matching keys.

Resource Columns (Deprecated)

Deprecated. Use views instead. resource_columns is bridged automatically — each entry becomes a views entry with the same columns and no sort_column. A one-time warning is logged when bridging occurs. When views is set for the same Kind, views wins.

Use resource_columns to configure which columns are displayed for specific resource types. When not configured for a kind, columns are auto-detected from the resource data.

Available column keys depend on the resource type. Common examples:

Column KeyShown ForDescription
IPPods, ServicesIP address
NodePodsNode the pod is running on
ImagePodsContainer image
QoSPodsQuality of Service class
ReplicasDeployments, StatefulSetsReplica count
AvailableDeploymentsAvailable replicas
CPUPods, DeploymentsCPU usage
MEMPods, DeploymentsMemory usage
CPU/RPodsCPU request percentage
CPU/LPodsCPU limit percentage
MEM/RPodsMemory request percentage
MEM/LPodsMemory limit percentage

Use ["*"] to show all available columns for a given resource type.

resource_columns:
  Pod: ["IP", "Node", "Image", "CPU", "MEM"]
  Deployment: ["Replicas", "Available"]
  Service: ["*"]                  # Show all for Services
  StatefulSet: ["Replicas"]

Keys are resource Kind names and are case-insensitive (e.g., Pod, pod, POD all work).

Abbreviations

Search abbreviations allow typing short names to jump to resource types. The default abbreviations include all standard kubectl short names.

To override or extend:

abbreviations:
  po: pod
  dep: deployment
  deploy: deployment
  svc: service
  ing: ingress
  cm: configmap
  sec: secret
  ns: namespace
  no: node
  pvc: persistentvolumeclaim
  hpa: horizontalpodautoscaler
  # Add your own:
  myapp: myapplication.example.com

Default Abbreviations

AbbreviationResource Type
popod
dpdeployment
depdeployment
deploydeployment
rsreplicaset
stsstatefulset
dsdaemonset
svcservice
ingingress
cmconfigmap
secsecret
nsnamespace
nonode
pvcpersistentvolumeclaim
pvpersistentvolume
scstorageclass
saserviceaccount
hpahorizontalpodautoscaler
vpaverticalpodautoscaler
cjcronjob
jobjob
crdcustomresourcedefinition
evevent
ependpoint
epsendpointslice
rbrolebinding
crbclusterrolebinding
crclusterrole
rolerole
limitlimitrange
quotaresourcequota
pdbpoddisruptionbudget
netpolnetworkpolicy
rcreplicationcontroller

Custom Actions

Define custom shell commands for specific resource types. Custom actions appear in the action menu (x key) after the built-in actions.

custom_actions:
  Pod:
    - label: "SSH to Node"
      command: "ssh {Node}"
      key: "S"
      description: "SSH into the pod's node"
    - label: "Copy Logs"
      command: "kubectl logs {name} -n {namespace} --context {context} > /tmp/{name}.log"
      key: "C"
      description: "Copy pod logs to /tmp"
      read_only_safe: true   # safe to run when read-only mode is on
  Deployment:
    - label: "Image History"
      command: "kubectl rollout history deployment/{name} -n {namespace} --context {context}"
      key: "H"
      description: "Show rollout history"
      read_only_safe: true

Custom Action Fields

FieldRequiredDescription
labelYesDisplay name in the action menu
commandYesShell command to execute (supports template variables)
keyYesShortcut key in the action menu
descriptionNoDescription shown next to the action
read_only_safeNoWhen true, available in read-only mode. Defaults to false (treated as mutating). Set true for view-only commands (e.g. kubectl describe, kubectl logs).

Template Variables

Template variables are substituted before execution:

VariableDescription
{name}Resource name
{namespace}Resource namespace
{context}Kubeconfig context name
{kind}Resource kind (e.g., "Pod", "Deployment")
{<ColumnKey>}Any column value from the resource (e.g., {Node}, {IP}) — case-insensitive

Custom action commands are executed via sh -c with KUBECONFIG set in the environment. Interactive commands (like ssh) hand over the terminal to the subprocess.

Substituted values are shell-quoted before insertion, so cluster data (context names, labels, image strings) containing shell metacharacters is passed literally and cannot inject commands. Quoting is transparent for normal argument use — ssh {Node} and /tmp/{name}.log work as written.

Pinned Groups

Pin CRD API groups so they appear right after the built-in categories (Workloads, Networking, etc.) instead of being sorted alphabetically under Custom Resources.

pinned_groups:
  - karpenter.sh
  - monitoring.coreos.com
  - argoproj.io

Pinned groups can also be managed interactively: press p at the resource types level to pin/unpin the selected CRD group. In-app pins are stored per-context, and for named union sets per union set, in ~/.local/state/lfk/pinned.yaml; they are merged with the config file pins at runtime. Anonymous --union-context sessions have no durable name, so interactive pinning remains disabled there.

Union Sets

Define named groups of clusters that the --union-set <name> CLI flag expands into a merged ("union") view. Avoids retyping long --union-context lists for the same recurring groups (blue/green/canary, region triplets, etc.). The flag is mutually exclusive with --union-context and --context.

union_sets:
  ski-staging-west:
    contexts:
      - context: operator/block-sre-operator/square-staging-green-us-west-2
        color: green
      - context: operator/block-sre-operator/square-staging-yellow-us-west-2
        color: yellow
      - context: operator/block-sre-operator/square-staging-blue-us-west-2
        color: blue
    namespace: kube-policies
  ski-prod-east:
    contexts:
      - prod-green-east
      - name: prod-blue-east
    # namespace omitted: --namespace is required on the CLI for this set
    # color omitted on each context: rows render with a blank reserved cell

Top-level fields:

FieldTypeRequiredNotes
set namemap keyyesIdentifier referenced by --union-set <name> and shown under the cluster picker's Union Sets group. List form with - name: ... is also accepted; duplicate names log a warning and the last definition wins.
contextslist[string or object]yesContext entries to merge. Each entry can be a plain string or an object with context:/name: and optional color: (see below). The total count is capped at MaxUnionContexts (currently 8) — the same cap that governs repeated --union-context flags.
namespacestringnoDefault namespace for the set. Optional: when omitted, --namespace is required on the CLI. The CLI flag always overrides whatever the set declared, so you can keep one canonical set and retarget the namespace per launch.

Per-cluster entry fields:

FieldTypeRequiredNotes
context / namestringyesKubeconfig context name. Must exist; verified at startup. Plain string entries are shorthand for context: <name>.
colorstringnoOne of: red, yellow, green, blue, magenta, cyan, white, gray. Drives the 1-cell row tile in the merged view (see below). Unknown color names log a warning and the cluster renders untinted rather than failing the config.

Validation runs at startup: an unknown set name, a missing context, a duplicate context within the set, more than MaxUnionContexts clusters, or no namespace from either source produces a clear error before the TUI starts. Malformed list-form entries (no name), empty contexts:, and nameless context entries are dropped at config load time with a warning rather than failing the whole config.

See the union view docs in usage.md for the runtime semantics — what's editable at the merged level, how drill-down routes to a single cluster, and how the per-row Context column identifies the source.

Per-row color tiles

When a cluster entry has a color: set, every row sourced from that cluster gets a 1-cell colored tile at its leading edge — quick visual identification of the source cluster while scanning a merged list. Rows from clusters without a configured color get a blank reserved cell at the same position so column boundaries stay aligned across the table.

The colors live inside the union_sets definition (not the global cluster_colors state file used by the cluster picker) so you can pick deliberate "traffic light" semantics per view — for example, the same kubeconfig context can be tinted blue here and untinted in another set, without affecting how it appears in the cluster picker. The textual Context column remains the source of truth for unambiguous reads (sortable, copyable, fits screen-readers); the tile is purely visual shorthand.

Filter Presets

Define custom quick filter presets per resource type. These appear alongside the built-in presets when you press . at the resource level.

filter_presets:
  Pod:
    - name: "On GPU Nodes"
      key: "g"
      match:
        column: "Node"
        column_value: "gpu"
  Deployment:
    - name: "Single Replica"
      key: "1"
      match:
        column: "Replicas"
        column_value: "1"

Filter Preset Fields

FieldRequiredDescription
nameYesDisplay name in the filter overlay
keyYesSingle-character shortcut key (must not conflict with built-in presets)
matchYesFilter criteria object (all fields are AND-ed)

Match Criteria

FieldDescription
statusSubstring match against the resource status (case-insensitive)
ready_nottrue to match resources where ready count != desired (e.g., "1/3")
restarts_gtMatch pods with restart count greater than this number
columnColumn key to check (case-insensitive, e.g., "Node", "IP")
column_valueSubstring match against the column value (case-insensitive)
inverttrue to negate the entire match. Other fields still AND together; the final boolean is flipped. Useful for "anything except X" filters, e.g., status: Bound + invert: true matches every PVC that is NOT Bound.

Built-in Presets

Press . on any resource list to see the presets available for that kind. The built-ins are:

KindPresets (key)
PodFailing (f), Pending (p), Not Ready (n), Restarting (r), High Restarts (R), Not Running (x)
Deployment / StatefulSet / DaemonSetNot Ready (n), Failing (f), Not Running (x)
JobFailed (f), Not Running (x)
PersistentVolumeAvailable (a), Released (r), Failed (f), Not Bound (x)
PersistentVolumeClaimPending (p), Lost (l), Not Bound (x)
NodeNot Ready (n), Cordoned (c)
Certificate / CertificateRequestNot Ready (n), Expiring Soon (e)
ServiceLB No IP (l)
CronJobSuspended (s)
Argo ApplicationOut of Sync (s), Degraded (d)
Flux HelmRelease / KustomizationSuspended (s), Not Ready (n)
EventWarnings (w)

The x key (Not Running / Not Bound) is the shared "show me anything not in a healthy state" mnemonic across the kinds where it applies — k9s Ctrl-Z equivalent. Universal presets Old (>30d) (o) and Recent (<1h) (h) are also available on every list.

Secret lazy loading

By default, Secret resources list like every other resource type: the full objects are pulled from the API server and their data map is eagerly base64-decoded into each row. This keeps the Type column and decoded values visible immediately, at the cost of potentially heavy list responses — Helm v3 stores every release (and every revision) as a Secret of type=helm.sh/release.v1, typically 100 KB to 1 MB per release, so clusters with many Helm apps can push tens of megabytes on a single Secrets list.

Set secret_lazy_loading: true to opt into a different strategy:

  • The list fetches metadata only via the Kubernetes PartialObjectMetadataList API (name, namespace, age, owner references, deletion timestamp). No data payload crosses the wire for the list.
  • The right-hand detail pane lazily fetches each Secret's decoded values on hover (one per-item GET, cached until the secret is edited or the list refreshes). Masked-bullet rendering is unchanged — toggle visibility with the secret-toggle key as usual.

Trade-offs

false (default)true
List payload for 100 Helm releases~50–100 MB (full objects)Kilobytes (metadata only)
Type column visible in listYesNo — dropped; the metadata API doesn't return it
Decoded values on first hoverInstant (already on the item)Brief delay until per-item GET returns, then cached
API calls per hover at LevelResources0 extra1 per distinct Secret (cached thereafter)

Turn this on if you notice hovering Secrets in the left pane is noticeably slower than hovering other resource types — that's the symptom this option is designed to fix.

secret_lazy_loading: true

Informer cache

Without the cache, every navigation event in the resource list — drill-in, namespace switch, watch tick, shift+r refresh — issues a fresh LIST against the API server. On large clusters this becomes visible: a 7k-pod list takes 1–2 seconds to round-trip, and switching the namespace filter re-pays that cost every time even though filtering is conceptually a client-side operation against an already-known list (issue #86).

The informer_cache knob has three modes:

  • off — every list round-trips to the API server, matching kubectl semantics. Pick this when the apiserver is sensitive to extra watch connections or when you are debugging server-side behavior.
  • auto (default) — start in off mode per (context, resource type), but the moment a list returns ≥ 1000 items, promote that resource type to a shared informer. Subsequent lists for that resource type — including namespace switches — are served from the in-memory index. Once cached size has stayed below 500 for three consecutive cached calls, the watch is closed and the resource type goes back to direct lists. Hysteresis between the promote (1000) and demote (500) thresholds prevents flapping when a list size hovers near the edge.
  • always — every resource type starts a watch on first use, regardless of size. Use when you know the cluster is large and want to skip the one-time direct list before promotion.

Promoted resource types serve namespace switches as in-memory walks; the watch keeps the cache fresh so deleted pods drop out and Age advances on the next render even though we never re-issue a LIST.

Trade-offs

offauto (default)always
Namespace switch on 7k-pod list1–2 s API round tripIn-process walk (after first list)In-process walk (after first list)
API server load (small clusters)One LIST per navOne LIST per nav (never promoted)One LIST + one watch per opened type
API server load (large clusters)One LIST per navOne initial LIST then one watch per promoted typeSame as auto
Memory in lfkView onlyCached objects for promoted typesCached objects for every opened type
One-off large list strands a watchn/aNo (auto-demote closes it)Yes (until shutdown)

The legacy bool form is still accepted for backward compatibility:

  • informer_cache: true is treated as always.
  • informer_cache: false is treated as off.
# Default — adapts per resource type without configuration:
informer_cache: auto

# Force everything through informers:
# informer_cache: always

# Disable entirely (kubectl-equivalent semantics):
# informer_cache: off

Minimum Contrast Ratio

min_contrast_ratio is a normalized knob in [0.0, 1.0] that makes lfk automatically adjust foreground colors to be more readable against their backgrounds. It is useful when a built-in theme happens to produce low-contrast text on your particular terminal or display.

WCAG mapping

The value is mapped linearly to a WCAG 2.1 contrast ratio target:

wcagTarget = 1.0 + value * 20.0
Config valueWCAG ratioStandard
0.0 (default)Off; colors unchanged
0.1754.5:1WCAG AA (normal text)
0.37.0:1WCAG AAA
1.021.0:1Maximum (forces pure black or white fg)

How it works

  • Only HSL lightness is adjusted. Hue and saturation are preserved, so chromatic colors keep their identity at moderate values.
  • Nudge direction preserves the designer's existing fg/bg relationship: if fg was darker than bg the mutator nudges it further darker; if lighter, further lighter. This avoids flipping a dark-on-light pair past the bg toward the opposite extreme, which would silently collapse the contrast for mid-luminance backgrounds.
  • The adjustment runs per color pair, so some colors may shift more than others depending on how far they are from the target. At value=1.0 expect some colors to collapse toward achromatic white or black.
  • Named colors (e.g. red) and malformed hex values are left unchanged rather than causing an error.

Pairs adjusted

ForegroundBackground
textbase
dimmedbase
errorbase
warningbase
secondarybase
primarybase
purplebase
selected_fgselected_bg

border is intentionally not in this list. It doubles as the background for the left-pane selected-row highlight (ParentHighlightStyle renders text on border), so enforcing its contrast as a foreground color would drive it toward text's luminance and collapse that highlight.

When to use this

Enable when text is hard to read on your terminal. Start at 0.175 (WCAG AA); raise toward 0.3 if still too dim.

min_contrast_ratio: 0.175

Terminal Mode

Controls how interactive shells (exec, attach, debug, debug pods, node shell) run.

terminal: pty
ValueDescription
pty (default)Embedded in the TUI via an internal vt10x terminal — output appears inside lfk
execHands the host terminal to the shell via tea.ExecProcess; lfk suspends until the shell exits
muxOpens the shell in a new window (tmux) or floating pane (zellij) of the surrounding multiplexer; lfk stays foregrounded alongside it

Ctrl+T cycles modes at runtime: pty -> exec -> mux -> pty. The mux step is skipped automatically when no tmux/zellij is detected, so the cycle becomes pty -> exec -> pty in that case. Setting terminal: in the config picks the default at startup.

Selecting and copying text in pty mode

Inside the embedded PTY view, the host terminal handles text selection. shift+drag copies a region; on macOS, shift+option+drag (or alt+drag on Linux/Windows) selects a rectangular block, which is useful when several panes share the screen.

For lines that have already scrolled off the visible viewport, lfk keeps an in-app scrollback ring (~5000 lines per PTY tab, ANSI-stripped). Use Ctrl+] Ctrl+U / Ctrl+D to scroll by half a viewport, Ctrl+] Ctrl+B / Ctrl+F for full-viewport pages, Ctrl+] g to jump to the oldest captured line, Ctrl+] G to snap back to live. Typing a real character also snaps to live so subsequent input goes to the visible prompt.

The scrollback ring is populated from the byte stream, not the rendered screen, so full-screen curses programs (vim, less, htop) that paint absolute screen positions will produce noisy history while running. If you need precise scrollback, cycle to exec or mux mode for the next shell — the host terminal's own scrollback then takes over.

mux mode requirements

mux mode requires lfk to be running inside tmux or zellij and the corresponding binary to be on PATH. lfk detects this via the $TMUX / $ZELLIJ env vars. When the requirement isn't met, an interactive shell attempt under terminal: mux fails fast with an error in the status bar — either set the env, install the binary, or cycle to exec/pty.

KUBECONFIG and any other per-context env that lfk passes to subprocesses are forwarded to the new pane via inline shell variable assignments, since neither tmux nor zellij propagate parent env reliably across their spawn APIs.

PTY Scrollback

scrollback_lines sets the per-tab capacity of the embedded PTY scrollback ring buffer (in lines). Only applies to pty mode — exec and mux delegate scrollback to the host terminal.

scrollback_lines: 5000
FieldDefaultRangeDescription
scrollback_lines5000[100, 100000]Per-tab line cap for the captured PTY scrollback. Out-of-range values are clamped and a warning is logged.

Memory budget is roughly scrollback_lines × average_line_length per PTY tab. With the default and ~120-character lines, that's around 600 KiB per tab — safe to leave at default for most users. Bump it if you frequently cat large logs from inside the embedded shell and want to scroll back through them; lower it on very memory-constrained systems.

Navigate the captured scrollback with Ctrl+] Ctrl+U/Ctrl+D (half page), Ctrl+] Ctrl+B/Ctrl+F (full page), Ctrl+] g/G (oldest/live), or the mouse wheel (1 line per tick).

kubeshark

FieldTypeDefaultDescription
kubeshark.namespacestringkubesharkNamespace probed for Service kubeshark-hub by the Traffic Capture overlay's kubeshark backend.

If the Service isn't found in this namespace, the kubeshark chip is omitted from the backend picker.

Color Schemes

Over 460 built-in color schemes are available, generated from ghostty terminal themes. Sample list:

tokyonight-storm (default), dracula, nord, catppuccin-mocha, catppuccin-latte, rose-pine, gruvbox-dark, gruvbox-light, everforest-dark, one-half-dark, ayu-dark, nightfox, monokai-pro, github-dark, github-light, solarized-dark, solarized-light, and many more.

Switch themes at runtime with T to browse all available themes interactively with live preview. Runtime changes are not persisted — set colorscheme in your config to make it permanent.

To regenerate themes from the latest ghostty source, run make generate-themes.

Session Persistence

The application automatically saves and restores the last visited context, namespace, and resource type across restarts (per tab, including the active tab). It also restores the active list filter (including the Tab broad-match mode) and the highlighted row, so you reopen lfk on the same resource you were looking at. The session state is stored at ~/.local/state/lfk/session.yaml.

This is transparent and requires no configuration. To start fresh, delete the session file.

Files

The application follows the XDG Base Directory Specification:

FileDescription
$XDG_CONFIG_HOME/lfk/config.yamlMain configuration file (default: ~/.config/lfk/config.yaml)
$XDG_STATE_HOME/lfk/bookmarks.yamlSaved bookmarks (default: ~/.local/state/lfk/bookmarks.yaml)
$XDG_STATE_HOME/lfk/session.yamlLast session state, auto-managed (default: ~/.local/state/lfk/session.yaml)
$XDG_STATE_HOME/lfk/sort_memory.yamlPer-context and per-resource-kind sort column/order, auto-managed (default: ~/.local/state/lfk/sort_memory.yaml)
$XDG_STATE_HOME/lfk/column_prefs.yamlPer-context and per-resource-kind column visibility/order from the , toggle overlay, auto-managed (default: ~/.local/state/lfk/column_prefs.yaml)
$XDG_STATE_HOME/lfk/pinned.yamlPer-context and per-union-set pinned CRD groups, managed via p key (default: ~/.local/state/lfk/pinned.yaml)
$XDG_STATE_HOME/lfk/hidden_types.yamlPer-context and per-union-set hidden resource types, managed via the action menu (x) at the resource types level (default: ~/.local/state/lfk/hidden_types.yaml)
~/.local/share/lfk/lfk.log (default)Application log file (configurable via log_path)

State files stored at the legacy ~/.config/lfk/ location are automatically migrated to the new XDG state directory on first access.

Directory overrides

For portable installs such as Scoop's persist directory, lfk honors three environment variables that override the XDG variables and OS defaults:

VariableOverridesHolds
LFK_CONFIG_DIRconfig directoryconfig.yaml
LFK_STATE_DIRstate directorybookmarks, session, pinned groups, history, cluster colors, captures
LFK_DATA_DIRdata directorylfk.log

Each variable is used verbatim as the lfk directory — unlike XDG_*_HOME, no lfk component is appended. Resolution precedence per directory:

  1. LFK_<X>_DIR if set.
  2. $XDG_<X>_HOME/lfk if set.
  3. OS default (~/.config/lfk, ~/.local/state/lfk, ~/.local/share/lfk).

The --config flag and the log_path config field are full file-path overrides and still win over LFK_CONFIG_DIR and LFK_DATA_DIR respectively.