konoma 0.18.8

Terminal file browser built for AI pair-programming — full-screen previews (Markdown, images, PDF, CSV), git suite, and an agent-watch mode that follows your AI's edits (macOS and Linux)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
# Example konoma config. Place it at ~/.config/konoma/config.toml.
# Everything works with defaults, so the file is optional.
# (A Japanese-annotated copy lives at config.example.ja.toml.)

[ui]
show_hidden = false
# Display language. "auto" (default) | "en" | "jp". Applies to help (?), key hints, the mode chip, messages, etc.
# "auto" follows the OS language (jp when macOS is set to Japanese, en otherwise).
lang = "auto"
tabbar = "auto"            # always | auto | hidden
# Status-line layout.
#   split  = context (mode / path / zoom) on top (right of the tab row), key hints on the bottom (default).
#   bottom = put both the context and the key hints on a single bottom line.
# Key hints are shown "most-useful first", as many as fit the width, with the rest elided with a trailing … .
statusbar = "split"
# Show Nerd Font icons at the start of each tree row. Requires a Nerd Font. Add "Symbols Nerd Font"
# as a fallback in your terminal to keep your usual font. Set to false if you see tofu (□) / have no Nerd Font.
# Icons are uncolored (they inherit the terminal's default foreground). Color is reserved for git-status files.
icons = true
# How long lines are handled in text previews.
#   true  = wrap and show the whole line (default).
#   false = do not wrap; scroll horizontally with h/l and ←/→ (less-style).
wrap = true
# Whether to show a line-number gutter in code/text previews.
#   false = hidden (default, minimal display).
#   true  = show line numbers at the start of each line (dim). Large files stream through a less-style
#           windowed reader, and G (end) still shows the correct number derived from the total line count.
line_numbers = false
# Editor-style git change gutter (Zed-style). For code/text previews of files with working-tree changes,
# a change marker is drawn at the left edge:
#   green ▌ = added line / amber ▌ = modified line / red ▔ = the top edge of the line below a deletion.
#   true  = shown (default; nothing is drawn for unchanged files or outside a git repo).
#   false = hidden.
git_gutter = true
# Tab stop width (default 4). In code/text previews, tabs expand to a "visible marker (→) plus spaces up to
# the next tab stop". Terminals do not align tabs, so this keeps indentation aligned while still showing that
# it is a tab. Set to 0 to keep raw tabs (columns may not line up).
tab_width = 4
# Whether to syntax-highlight code.
#   true  = color with syntect (default). The first open of a language compiles its grammar (absorbed by
#           preview_loading below).
#   false = plain text, fastest (syntect is never used). Use false if highlighting feels heavy / is unwanted.
syntax_highlight = true
# How the wait is shown for a heavy code preview (a language opened for the first time = grammar compile needed).
# Note: an already-opened language is warm, so display is instant regardless of this setting.
#   indicator   = show a loading indicator in the center, then render the colored body (default).
#   progressive = show the body as plain text immediately, then swap to highlighted once ready (no freeze).
preview_loading = "indicator"
# Default path style in titles (tree/preview). The p key cycles relative → home → full.
#   relative = relative to the launch directory name (e.g. konoma/src/main.rs). Default.
#   home     = relative to HOME (e.g. ~/work/konoma).
#   full     = full path (e.g. /Users/me/work/konoma).
path_style = "relative"
# Default page-turn key profile for previews. j/k line moves, arrows, and PageUp/Down are common to both.
#   vim  = Ctrl-f/Ctrl-b page, Ctrl-d/Ctrl-u half-page (default).
#   less = Space/b page, d/u half-page (preview surfaces only; the tree's Space is already the file-management
#          leader, so even under less the tree keeps vim paging).
# Note: this is the "default page-turn profile". Individual keys can be overridden under the top-level
#   [keys.<surface>] sections below (those take precedence and are a separate thing).
keys = "vim"
# Display-size scale for image previews (0.1–1.0). Shrinks the display rect by this factor.
# At the default 1.0: "initial = image size (fit), + zooms in, pan with hjkl once it overflows the viewport".
# Below 1.0 the display is smaller but fewer pixels are sent to kitty (= less zoom/display latency).
# The image is always centered with correct aspect ratio. Lower it when you need speed (e.g. 0.6 ≈ 1/3 the transfer).
# Shared by GIF animation and all images (also use this to make GIF transfers lighter).
image_render_scale = 1.0

# Maximum edge (px) for SVG rasterization. Vectors are resolution-free, so they are rendered up to this many px
# (small SVGs stay crisp). Larger is sharper but heavier to draw/transfer. Default 800.
# SVG only: raster images / GIFs are unaffected (a GIF's transfer size is governed by image_render_scale).
svg_max_px = 800

# Detail-list columns: extra metadata shown to the right of each row. Empty [] (default) for a plain display.
# Available columns: "size" / "modified" / "perm" (rwx) / "type" (file/dir/link) /
#   "items" (number of entries in a directory; this read_dir's each dir row, so it is a bit heavy in trees
#   with many directories). Columns appear left-to-right in the given order.
# Long names are auto-truncated (…), and columns are right-aligned so they line up vertically.
# All info for a single entry (symlink target, absolute path, …) is available in the `i` popup.
details = []           # e.g. ["type", "size", "modified"]

# Maximum number of local branches drawn at once in the commit graph (o→g). Default 12.
# With many branches the lanes/colors/legend overflow, so at startup they are auto-selected up to this limit,
# ordered by base/priority + HEAD + recent commits. The graph's `b` panel toggles visibility and reorders
# priority (Space:toggle / J/K:reorder / a:all / n:current only / Enter:apply; HEAD is always shown). 0 = unlimited.
graph_max_branches = 12

# The graph's "base / priority branches" (ordered; default []). e.g. ["main", "develop"]
# 1. Branches listed here are shown with priority (placed at the front of the limit).
# 2. The first one that exists becomes the "base" = pinned to lane0 in a straight line.
# 3. The order also drives the legend/panel display order (array → HEAD → recency).
# The graph's `b` panel J/K reorders for the current session only (never written back to the config).
graph_base_branches = []

# In the log (o→l) / graph (o→g) commit rows, how the right-side metadata (author, date; also short hash in the
# graph) is aligned.
#   "right"  (default) … align to the panel's right edge as a "column". Dates/authors line up vertically so you
#                        can scan new vs old at a glance (SourceTree / VS Code Git Graph style). When narrow, the
#                        subject is truncated first, and if still narrow the metadata itself is dropped (a
#                        non-essential column).
#   "inline"           … place it right after the subject (the classic layout, metadata next to the subject).
commit_meta_align = "right"

# Quit confirmation. When q (top-level tree) / Q (from anywhere) quits the whole app, whether to confirm.
#   true  (default) … ask "Quit?" (q / y / Enter = quit, n / Esc = cancel; qq exits quickly).
#   false           … quit immediately (no confirmation).
confirm_quit = true

# Bookmark-overwrite confirmation. When m registers a bookmark and that key already points to a **different** path,
# show a confirmation dialog (to avoid an accidental overwrite). Re-registering the same path or an unused key
# registers without asking.
#   true  (default) … confirm before overwriting (y / Enter = overwrite, n / Esc = cancel).
#   false           … overwrite immediately without confirmation.
confirm_bookmark_overwrite = true

# Rainbow columns in the CSV/TSV table preview. Rotates a color per column for easier scanning (Rainbow CSV /
# csvlens style).
#   true  (default) … color per column.
#   false           … single color (alignment, cell moves, and copy are unchanged).
# Keys: hjkl=move cell / g·G=first/last row / 0·$=first/last column / y→ c:cell r:row C:column f:full path / q:back.
csv_rainbow = true

# How follow mode (F) opens the file it jumps to.
#   "diff" (default) … the file's full-screen git diff (what changed, hunk by hunk; an untracked file is an
#                      all-added diff). q goes back, s cycles the layout.
#   "file"           … a normal full-screen preview (auto-scrolls to the first changed hunk, gutter on changed lines).
# Either way, files with no diff (unchanged / outside a repo) and images/SVG/video/PDF open as a normal preview.
# The follow diff shows changes SINCE you pressed F (pre-existing uncommitted changes stay hidden); press f in
# the diff to toggle the full git diff. Follow is sticky — only q / another F / entering text input stops it
# (scrolling, n/N and f keep it on).
follow_view = "diff"

# The states Space cycles through in Markdown task lists (checkboxes), in cycle order.
# Each element is one character. Default [" ", "x"] = GFM-standard incomplete ⇄ done.
# e.g. [" ", "/", "x"] inserts an Obsidian-style "in progress [/]". Standard states show the Nerd Font
# checkbox icon (or [ ]/[x] when ui.icons=false); custom states are shown as [/].
# Keys: in the decorated view, Tab/⇧Tab cycles links and checkboxes → Space (or Enter) toggles.
# Toggling verifies the file before writing, and if it changed externally it reloads instead of writing (safe).
# A box in a state not in the array is normalized to the first state. An invalid setting (2-char element,
# ≤1 element) falls back to the default.
md_task_states = [" ", "x"]

# Auto-link bare URLs and emails in Markdown previews (GFM autolink), like GitHub: a plain
# https://…, www.…, or foo@bar.com becomes a focusable link (Tab to it, Enter opens it). Links
# inside code spans / code fences are never auto-linked. false leaves bare URLs as plain text.
md_autolink = true

# Render GitHub-style alerts as colored callout boxes with an icon and label, instead of a plain
# blockquote. Recognized markers (case-insensitive, plus common aliases): [!NOTE] [!TIP]
# [!IMPORTANT] [!WARNING] [!CAUTION]. false renders them as ordinary blockquotes (marker kept literal).
#   > [!NOTE]
#   > Body text here.
md_alerts = true

# Convert :shortcode: emoji to real Unicode emoji in Markdown previews, like GitHub (:rocket: → 🚀).
# Shortcodes with no Unicode equivalent (GitHub-custom like :shipit:) are left as text. Inside code
# they stay literal. Set false if emoji width upsets column alignment in your terminal/font.
md_emoji = true

# Recognize leading YAML front matter (--- ... --- at the very start) and show it as a compact dim
# metadata block instead of a rule + raw YAML. Default true. false renders the leading --- and YAML
# as ordinary Markdown.
md_frontmatter = true

# Render GFM footnotes: text[^1] references become superscript numbers and the [^1]: ... definitions
# are collected into a numbered footnotes section at the end. Default true. false leaves them literal.
md_footnotes = true

# Render common inline HTML that GitHub shows but the Markdown engine strips: <del>/<s>/<strike> as
# strikethrough, <kbd> as an inline-code keycap, <sup>/<sub> as Unicode (when the text maps), <br> as
# a hard line break. Default true. (<mark>/<ins> have no faithful terminal form — only their text is
# kept either way.) false leaves all these tags to be stripped.
md_inline_html = true

# How <details> blocks start out. Either way Tab focuses the <summary> and Space/Enter toggle it.
#   "auto"   (default) … honor the `open` attribute like GitHub (<details> collapsed, <details open> expanded)
#   "open"             … always start expanded
#   "closed"           … always start collapsed
md_details = "auto"

# Background-activity indicator. While something runs in the background (git ignore-file scan, media load,
# highlight warm-up, inline-image fetch, …), a spinner and job name (+n when several) is shown at the top-right.
# Nothing is shown when idle (= zero idle load).
#   true  (default) … show it.
#   false           … hide it (per-item displays like a centered "loading…" are unaffected).
busy_indicator = true

# How mermaid diagrams are rendered.
#   "image" (default) … rasterize them in-process (pure Rust SVG → raster), at mermaid.js quality (no browser/Node).
#                       Standalone .mmd opens full screen (+/-:zoom hjkl:pan); ```mermaid fences inside Markdown
#                       render as inline images with Tab→Enter to go full screen. Zooming re-rasterizes to match
#                       the zoom level, so it stays sharp. Non-graphics terminals, unsupported diagrams, and render
#                       failures degrade to text automatically (safe).
#   "text"            … the classic Unicode box-drawing text rendering only.
mermaid = "image"

# Color theme for mermaid diagrams. The background is always transparent (blends with the terminal).
#   "dark" (default) … mermaid.js dark theme (for dark terminals).
#   "light"          … a modern light palette / "classic" … mermaid.js default / "forest" / "neutral".
mermaid_theme = "dark"

# Target height (rows) of an inline mermaid diagram inside Markdown (default 24). It scales UP too:
# diagrams are vector-backed, so growing beyond the base raster re-rasterizes at the needed density and stays
# sharp (width-capped, aspect-preserving). The initial view also fits the viewport: when the window is shorter
# than the target, it shrinks so the whole block is visible.
# A focused diagram can be zoomed in place with +/- (reserved area unchanged) and fit with 0.
# 0 or an invalid value falls back to the default 24.
mermaid_rows = 24

# How LaTeX math is rendered.
#   "image" (default) … rasterize $...$ / $$...$$ in-process via RaTeX (pure Rust, KaTeX quality, no browser/Node)
#                       and show each as an inline image. A terminal cannot place an image mid-text, so inline
#                       math is lifted onto its own line; display math ($$...$$, \[...\]) is centered.
#                       Non-graphics terminals and render failures degrade to the raw LaTeX text automatically.
#   "text"            … leave the raw LaTeX ($...$) as plain text (no rendering).
math = "image"

# Glyph color for image-mode math. RaTeX paints equations pure black, invisible on a dark terminal;
# konoma is dark-terminal-first, so equations are recolored to this over a transparent background
# (the terminal shows through, like mermaid). On a LIGHT terminal, set a dark color (e.g. "#202020").
# Accepts any color usvg parses (#hex, rgb(...), or a CSS color name); an unrecognized or
# fully-transparent value falls back to the default (a typo can't silently blank equations).
math_color = "#d0d0d0"

# Tab-session save/restore. Per launch directory (project), the open tab layout (each tab's root, cursor
# position, and previewed file) is saved and restored the next time konoma starts in the same directory.
# A tab left in preview reopens in preview (scroll starts at the top).
# Save timing: tab open/close/switch and on exit. Saved to ~/.config/konoma/sessions/ (one file per directory).
#   true  (default) … restore (pick up where you left off).
#   false           … always start with a single blank tab (the session is neither read nor written).
restore_tabs = true
# When restore_tabs is on: also persist/restore a session that has only ONE tab (default true). Set
# false to skip saving single-tab sessions — quitting with a lone tab deletes that directory's session
# file so the next launch starts fresh; sessions with two or more tabs still save/restore.
restore_single_tab = true

# Default tree sort (at startup). At runtime, switch with the `s` sort menu
# (key n/s/m/e, r=reverse, .=dirs first).
[ui.sort]
key        = "name"    # sort key: "name" (default) | "size" | "modified" | "ext"
reverse    = false     # descending? (default false = ascending)
dirs_first = true      # keep directories at the top (default true). false = mixed with files

[ui.theme]
# Colors are given as "#rrggbb" / a color name ("black","lightblue", …) / a terminal index ("8") / "none".
#
# The app-wide background color. Default "none" = keep the terminal's default background (the terminal's own
#   transparency setting stays active too).
#   Specifying a color fills the whole screen with it (transparency is disabled).
bg = "none"
#
# Background color for Markdown "code" (shared by inline code `...` and code blocks ```).
#   "none" = no background. Removes the inline-code box and renders it with the foreground color only, like
#            bold/italic/links (code blocks keep the left gutter ▎ and color only). Use this for a flat look.
# The default is a slightly bright slate. Set code_bg = "none" if you do not want a background.
code_bg = "#2b303b"
# Alignment of the language label (badge) at the top of a code block. "right" (default) or "left".
code_label_align = "right"
# Background color of the language badge.
#   "auto" (default) = code_bg slightly brightened (to distinguish it from the code body).
#   "none"           = no background (dim text only).
#   any color        = "#rrggbb" / a color name / etc.
code_label_bg = "auto"
# Syntax-highlight theme for code (bundled with two-face; shared by standalone code and md fences).
# Default "TwoDark" = Zed's One Dark palette. Separators (space/-/_) and case are ignored; unknown names → TwoDark.
#   Main choices: "TwoDark" (=one-dark) / "OneHalfDark" / "Dracula" / "Nord" /
#                 "gruvbox-dark" / "gruvbox-light" / "Catppuccin Mocha" (Frappe/Latte/Macchiato) /
#                 "Monokai Extended" / "Solarized (dark)" / "Solarized (light)" /
#                 "base16-ocean.dark" / "GitHub" / "zenburn" / "Sublime Snazzy" / "DarkNeon", etc.
code_theme = "TwoDark"

# Preview rules are evaluated top to bottom; the first match wins.
# builtin: a built-in renderer ("markdown" | "mermaid" | "image" | "svg" | "video" | "pdf" | "code" | "text")
#   markdown = decorated by tui-markdown (code is syntect-highlighted). ```mermaid inside md is composited as a diagram.
#   mermaid  = a standalone .mmd/.mermaid shown as a diagram. Default is an image (mermaid-rs-renderer → resvg,
#              pure Rust, full-screen zoom/pan). Set [ui] mermaid="text" for the Unicode box-drawing (mermaid-text).
#   image    = full-screen display via kitty graphics (zoom/pan). GIFs animate automatically.
#   svg      = rasterized to an image via resvg/usvg/tiny-skia (pure Rust, no external tools).
#   video    = a representative frame extracted via ffmpegthumbnailer/ffmpeg, shown as a thumbnail (no in-terminal
#              playback). The external tools are optional (a hint is shown if absent). To play, see the command example below.
#   pdf      = each page rasterized to an image (pdftocairo/pdftoppm/qlmanage/sips). macOS always has qlmanage/sips,
#              so it displays essentially anywhere. Falls back to a hint only if every tool is missing.
#              Turn pages with J/K (or PageDown/PageUp) (multi-page needs poppler = pdfinfo for the count + per-page render).
#   csv      = comma-separated shown as an aligned table (rainbow columns + cell cursor). hjkl=move cell / y→=cell/row/column copy.
#   tsv      = tab-separated. Same display/keys as csv (only the delimiter is a tab). Color via [ui] csv_rainbow.
# command:  delegate to an external command. {path}=the target file, {out}=an output path (temp file).
# render_as: how to treat the command's output ("image" shows a PNG etc. as a full-screen image).
# detached: open in a separate process without blocking the TUI (video, etc.).

[[preview.rules]]
glob = "*.md"
builtin = "markdown"

[[preview.rules]]
glob = "*.{mmd,mermaid}"
builtin = "mermaid"        # Default = image rendering ([ui] mermaid). To delegate to an external tool, see the command example below.
# command = "merman -i {path} -o {out}.png --scale 2"
# render_as = "image"

[[preview.rules]]
glob = "*.svg"             # Before raster images (infer classifies svg as image/* too, so order matters).
builtin = "svg"

[[preview.rules]]
mime = "image/*"           # png/jpg/webp/bmp... and GIF (auto-animated).
builtin = "image"

[[preview.rules]]
glob = "*.csv"             # Aligned table (rainbow columns + cell cursor). Color via [ui] csv_rainbow.
builtin = "csv"

[[preview.rules]]
glob = "*.tsv"             # Tab-separated variant.
builtin = "tsv"

[[preview.rules]]
glob = "*.{rs,ts,tsx,js,py,go,toml,json,sh,yaml,yml,c,cpp,h}"
builtin = "code"

[[preview.rules]]
mime = "video/*"           # Default: show a single representative frame as a thumbnail (no in-terminal playback).
builtin = "video"
# To "play" in an external player instead of in the terminal, drop the above and replace with (delegation):
# command = "mpv {path}"
# detached = true          # open in a separate process without blocking the TUI.

[[preview.rules]]
glob = "*.pdf"             # Default: rasterize each page to a full-screen image (turn pages with J/K; macOS built-in tools suffice).
builtin = "pdf"

# A file matching no rule shows [can not preview: <ext>] full screen.

# ── Keybindings (FR-8) ───────────────────────────────────────────────────────
# [Top-level sections] — write these at the outermost level of the file, NOT inside [ui].
# (Distinct from the ui keys="vim" above — easy to confuse.)
#
# Model: "for each surface, map a key → a command (action)". There is a built-in default map, and here you can
# override / add / disable (anything not written keeps its default). helix-style notation:
#   [keys.<surface>]
#   <key> = "<action>"
#
# ■ Surface names — a separate map per "which screen am I on". snake_case:
#   global        : effective on any surface (tabs t/[/]/1-9, T=tab list, help ?). w is unbound by default
#                  (it clashes with vim's word motion; close is the tree's q; restore with "w"="tab_close").
#   tree          : the full-screen tree      tree_visual   : the tree's visual selection
#   preview_text  : text/Markdown             preview_image : images    preview_git_diff : git diff
#   git_changes   : the Git changes hub (o)   git_log / git_graph / git_branches / git_detail
#   sort  bookmarks  tabs (tab list: d=tab_list_close)  info  help
#
# ■ Key notation: single char (uppercase = with Shift: "G"), "space", literals "0 $ ! + - = . / '",
#   modifiers "ctrl-f" (alias "c-f"), named "tab enter esc up down left right home end pageup pagedown".
#   A chord (leader) is two space-separated tokens: "y f" = y then f, "space d" = Space then d.
#   Note: Esc/Enter/Backspace/Delete/Tab/arrows, and character keys during text input, are fixed (cannot rebind).
#
# ■ Main action names (snake_case):
#   Motion       : "navigate:down|up|top|bottom|page_down|page_up|half_down|half_up|left|right|line_home|line_end"
#   Copy path    : "copy_name" "copy_relative" "copy_full" "copy_parent" "copy_at_ref" (@relative path) "copy_code_block" (md code block)
#   File ops     : "file_create" "file_rename" "file_delete" "file_copy" "file_cut" "file_paste"
#                  "file_duplicate" (Space→D: duplicate the cursor/selection in place = note copy.md)
#   Tree         : "quit" "tree_descend" "tree_leave" "filter_start" "toggle_hidden" "refresh"
#                  "open_sort_menu" "toggle_info" "request_edit" "cycle_path_style" "mark_set"
#                  "mark_jump" "set_anchor" "reset_anchor" "open_git_diff_cursor" "open_git_view"
#                  "enter_visual" "toggle_select" "open_in_new_tab" (Ctrl-t: open the entry under the cursor in a new tab)
#   Agent Watch  : "toggle_changed_filter" (C: show only changed files) "jump_next_change" (n) "jump_prev_change" (N)
#                  "toggle_follow" (F, global: auto-jump to externally changed files = follow the AI's work.
#                    The follow diff shows changes SINCE you pressed F — pre-existing uncommitted changes stay hidden.)
#                  "toggle_follow_diff_scope" (f, in a follow diff: switch between "since follow start" and the full git diff)
#   Path jump    : "paste_jump" (P, global: read a path/GitHub link from the clipboard and go to it = reveal +
#                  preview. Handles local absolute/relative paths, GitHub blob/raw URLs, #L123 / :123 line anchors.
#                  Outside the current root, switches the target's repo to root. @path#L references paste as-is too.)
#   Bookmarks    : m=register, '=list are bound on both tree and preview by default (in preview, register the shown file).
#                  Inside the list ('), a bare letter jumps to that bookmark (a-z local / A-Z global).
#                  "bookmark_edit" (default ctrl-e) "bookmark_delete" (default ctrl-d) "bookmark_close" (q / ')
#                  Note: j/k/q and global t/T/F/Q are taken by key actions, so a bookmark on those letters is opened
#                    with j/k + Enter (or move the key elsewhere in the config).
#   Preview      : "preview_back" "search_start" "search_next" "search_prev"
#                  "preview_copy_selection_ref" (Y: copy the @path#L reference of the selection/caret)
#                  "link_open" (Enter: open the link in the same tab) "open_link_new_tab" (Ctrl-t: open the link in a new tab)
#                  "preview_next_file" "preview_prev_file" (Ctrl-n/Ctrl-p: preview the next/prev file in tree order
#                    = file paging. Directories are skipped; wraps at the ends.)
#                  "toggle_outline" (o: open the heading outline of a Markdown preview; Enter jumps to a heading)
#                  "image_zoom_in" "image_zoom_out" "image_zoom_reset"
#   Sort         : "sort_name" "sort_size" "sort_modified" "sort_ext" "sort_toggle_reverse" "sort_toggle_dirs_first"
#   Git          : "git_stage" "git_unstage" "git_stage_all" "git_unstage_all" "git_discard"
#                  "git_commit" "git_worktree_diff" "git_open_log" "git_open_graph"
#                  "git_open_branches" "git_launch_tool" "cycle_diff_layout" "git_diff_discard"
#   Git graph    : "git_graph_set_base" "git_graph_clear_base" "git_graph_open_picker"
#                  "git_graph_picker_toggle" "git_graph_picker_all" "git_graph_picker_current_only"
#                  "git_graph_picker_move_up" "git_graph_picker_move_down"
#   Disable      : "noop" (alias "disabled") = remove that key's default binding.
#
# ■ Leaders (two-stage keys / which-key): pressing one shows the candidates in the footer.
#   y     → copy path      (n=name r=relative f=full p=parent @=AI-oriented @relative-path reference)
#   Space → file ops       (n=create r=rename d=delete c=copy x=cut p=paste) — tree / visual.
#
# ■ Conflict detection: a setting that steals an important default key on a surface (a single key clobbering a
#   leader prefix, repurposing a global tab key, …) is detected at startup, notified in the footer, and reverted
#   to the default (it will not silently break things).
#
# Example (uncomment to use):
# [keys.tree]
# d = "open_git_diff_cursor"   # diff of the changed file under the cursor (default)
# "space d" = "file_delete"    # Space→d to delete (default)
# "y f" = "copy_full"          # y→f to copy the full path (default)
# x = "noop"                   # disable x
#
# [keys.preview_text]
# "ctrl-f" = "navigate:page_down"
#
# [keys.git_changes]
# g = "git_open_graph"
#
# (Backward compat) The old [keys] copy_name/copy_full/copy_relative/copy_parent (suffix) are still read for now
# and mapped to the y copy leader. copy_prefix is ignored (the prefix is fixed to y in the new scheme).
# All are deprecated — prefer the new [keys.<surface>] form.

# External editor (launched with the `e` key). Can be specified per extension.
# Resolution order: [editor.ext] per-extension → command (overall default) → $VISUAL → $EDITOR → vim.
# The value is a command + args (space-separated). {path} is where the file path is inserted; if absent it is appended.
# {line} is replaced with "the line you were viewing" (the caret line in text/code/raw Markdown[R]).
# Even without {line}, major editors get a line automatically (vim family = +N plus zt to scroll the line to the top /
#  VS Code = -g path:N / Sublime, Helix = path:N).
# Decorated Markdown has no 1:1 mapping (reflow), so it searches the source for the text visible at the top of the
# screen and opens at that line (for structured docs it lands right on the visible heading/paragraph; for exact
# lines, toggle to raw source with `R`).
# If Tab has focused an on-screen item (link/checkbox/code block), it opens at that item's line. Mermaid and images open at the top.
# (Note: quoting args is not supported — space-separated only. For complex launches, point at a wrapper script.)
[editor]
command = ""          # Default editor. Empty falls back to $VISUAL → $EDITOR → vim.

# Per-extension assignments (keys without the dot).
[editor.ext]
# rs  = "nvim"
# md  = "code -w"            # For GUI editors, a wait flag (-w/--wait) is recommended.
# py  = "nvim +{line} {path}"  # {line} makes the open line explicit (vim/code etc. do it automatically anyway).
# txt = "nano"

# ── Git integration ──────────────────────────────────────────────────────────
# `o` opens the built-in Git view (changes hub). An external git tool is launched from within the hub with `!`.
[git]
tool        = "lazygit"   # The external git tool launched with `!` in the hub (command + args, space-separated). e.g. "tig status"
diff        = "unified"   # Initial diff layout: "unified" (vertical) | "split" (side-by-side) | "auto" (by width). `s` cycles vertical→side-by-side→auto in a diff.
# main_branch: [unimplemented / reserved] for the pinned-base-branch graph (post-release, docs/GRAPH-BASE-SPEC.md).
#              Currently referenced nowhere = has no effect. It will be enabled when implemented.