Configuration
konoma reads a single TOML file:
~/.config/konoma/config.tomlEverything is optional — no config file is required. A missing or broken file never
prevents startup; konoma falls back to the defaults described below (invalid values fall
back per-key). A fully commented example lives in
config.example.toml; copy it as a
starting point (a Japanese-annotated copy is at
config.example.ja.toml):
mkdir -p ~/.config/konomacp config.example.toml ~/.config/konoma/config.tomlQuick start
Section titled “Quick start”[ui]lang = "en" # UI language ("auto" follows the OS)wrap = false # no soft-wrap; h/l scroll long linesline_numbers = truedetails = ["size", "modified"]
[ui.theme]bg = "#282c34"
[keys]copy_prefix = "y"[ui] — appearance & behavior
Section titled “[ui] — appearance & behavior”| Key | Default | Description |
|---|---|---|
show_hidden |
false |
Show dotfiles at startup (toggle at runtime with .). |
tabbar |
"auto" |
Tab bar visibility: "always" / "auto" (only with 2+ tabs) / "hidden". |
icons |
true |
Nerd Font icons in the tree, Markdown links and task checkboxes. Set false on terminals without a Nerd Font — konoma falls back to plain ASCII symbols (no tofu). |
wrap |
true |
Soft-wrap text previews. false = no wrap + horizontal scrolling (h/l, 0/$). |
line_numbers |
false |
Line-number gutter in code/text previews. |
git_gutter |
true |
Editor-style git change gutter (green added / blue modified / red deleted) in code/text previews of files with uncommitted changes. |
tab_width |
4 |
Tab stop width in code/text previews (0 keeps raw tabs). |
syntax_highlight |
true |
Syntax highlighting for code previews (false = plain text, fastest). |
preview_loading |
"indicator" |
First-open wait for heavy code previews: "indicator" (loading screen) or "progressive" (plain text first, colors swap in when ready). |
path_style |
"relative" |
Title-bar path form: "relative" / "home" (~/...) / "full". Cycle at runtime with p. |
keys |
"vim" |
Paging-key scheme for previews: "vim" (Ctrl-f/b, Ctrl-d/u) or "less" (f/b, d/u, Space). |
lang |
"auto" |
UI language for help/hints/messages: "auto" (OS language) / "en" / "jp". |
statusbar |
"split" |
Status chrome layout: "split" (context top, hints bottom) / "bottom" / "top". |
image_render_scale |
1.0 |
Image display scale (0.1–1.0). Smaller = fewer pixels sent to the terminal = faster draws, smaller image. |
svg_max_px |
800 |
Max rasterization side (px) for SVG previews. Larger = crisper but heavier. |
details |
[] |
Metadata columns on tree rows, in order. Available: "size", "modified", "perm", "type", "items" (directory entry count). |
graph_max_branches |
12 |
Cap on branches drawn simultaneously in the commit graph (o → g). 0 = unlimited. Toggle branches at runtime with b inside the graph. |
graph_base_branches |
[] |
Ordered list of preferred base branches, e.g. ["main", "develop"]. In the graph, the first one that exists becomes the base (pinned to lane 0) and the array order becomes the display priority. A worktree’s diff (o w, then d) treats these as candidates and picks whichever shares the most recent common ancestor with that worktree, so the order only breaks ties. |
commit_meta_align |
"right" |
Author/date column in git log & graph: "right" (aligned right-edge column) or "inline" (directly after the subject). |
confirm_quit |
true |
Ask before quitting (q/y/Enter = quit, n/Esc = cancel; qq quits quickly). false = quit immediately. |
confirm_jj_sync |
true |
Ask before R in the hub lets jj snapshot the working copy — the one thing konoma writes to a jj repository, and only when asked. It exists for what konoma cannot see on its own: a file whose contents changed while its timestamp did not. false = snapshot without asking. |
confirm_bookmark_overwrite |
true |
Ask before a bookmark key (m) overwrites a different existing path (y/Enter = overwrite, n/Esc = cancel). Re-registering the same path or an unused key never prompts. false = overwrite silently. |
csv_rainbow |
true |
Rainbow column colors in CSV/TSV table previews. false = monochrome (alignment and navigation unchanged). |
filter_mode |
"fuzzy" |
How the / tree filter matches: "fuzzy" (ranked subsequence match, fzf-style; space-separated words are AND-ed) or "substring" (the older plain substring test). Case is ignored either way. |
follow_view |
"diff" |
How follow mode (F) opens a changed file: "diff" (full-screen diff since follow-start — pre-existing uncommitted changes stay hidden; press f in the diff to switch to the full git diff) or "file" (normal preview scrolled to the first changed hunk). Files without a diff and media always open as "file". |
busy_indicator |
true |
Small spinner + job label at the top-right while background work runs (git-ignored scan, media decode, highlight warm-up, image fetches). Idle shows nothing and costs nothing. A file operation in progress (copy / move / duplicate / delete, with its N/M progress) is always shown regardless of this setting — it is what you are waiting on, not background bookkeeping. |
mermaid |
"image" |
How mermaid diagrams render. "image" rasterizes them in-process (pure Rust, mermaid.js-quality — no browser/Node): standalone .mmd files show full screen with zoom/pan (zooming re-rasterizes so it stays sharp), and ```mermaid fences in Markdown render inline (Tab focuses a diagram — cyan frame + auto-scroll; +/- zoom in place without moving the layout, hjkl pan while zoomed, 0 fits, Enter opens full screen, q returns). "text" keeps the legacy Unicode box-drawing rendering. Failures and non-graphics terminals degrade to text automatically. |
mermaid_theme |
"dark" |
Color theme for image-mode diagrams: "dark", "light", "classic", "forest", "neutral". The background is always transparent (blends with the terminal). Has no effect when mermaid_routing = "konoma-orthogonal" — that mode always uses konoma’s own designed palette instead. |
mermaid_curve |
"basis" |
Curve a flowchart’s edges are drawn in — mermaid’s flowchart.curve (mermaid’s most-requested flowchart feature: a straight/right-angle line instead of a spline, mermaid-js#2817 / #2549). All 13 of mermaid’s own curve names are implemented; an unrecognized value falls back to "basis". "basis" (default) is a smooth spline and never changes the look unless you set this. "linear" draws straight segments; "step" / "stepBefore" / "stepAfter" draw a right angle, differing in where the corner sits (midpoint / vertical-first / horizontal-first). "natural" / "cardinal" / "catmullRom" are smooth splines that pass through every waypoint; "monotoneX" / "monotoneY" never overshoot a waypoint, along the named axis; "bumpX" / "bumpY" draw an S-curve offset on the named axis; "rounded" is straight segments with every corner cut to a small rounded curve (mermaid’s own curve, not part of d3-shape). Three ways to set the curve, weakest first: this setting < the diagram’s own %%{init: {"flowchart": {"curve": "..."}}}%% directive < a linkStyle <n> interpolate <curve> naming one edge. Only a flowchart’s own edges read any of this. |
mermaid_routing |
"splines" |
How a flowchart’s edges are routed — a konoma-only extension, independent of mermaid_curve above. "splines" (default) is the classic mermaid layout: edges follow the diagram’s own curve (mermaid_curve) — the look never changes unless you set this. "konoma-orthogonal" is konoma’s own orthogonal router (flowchart and stateDiagram-v2; every other diagram kind is unaffected): every edge bends only at 90° with sharp corners (zero radius) and always meets a node or subgraph border head-on. Decision nodes ({}) draw as a chamfered rectangle (6px cut corners) instead of a diamond, so every edge lands on a flat face. Multiple edges on the same side of a node spread across 16px-spaced ports, widening the node on that axis if there isn’t room. A straight-through edge between adjacent ranks aligns to a shared centerline — a true zero-bend straight lane. Where edges cross, the one passing over (a back-edge or detour) opens a 12px gap so the stacking order reads at a glance. Back-edges and detours route around the diagram’s outer lane (16px outside every element; multiple such edges offset 8px apart). A label sits on a plate on the line itself, and its segment is padded to at least the label’s width plus margin — widening the rank gap automatically when it doesn’t fit. Arrowheads are painted the edge’s own color (after linkStyle/classDef) and stop 1px short of the node border. Named after ELK’s edgeRouting: ORTHOGONAL and Graphviz’s splines=ortho; the konoma- prefix marks it as konoma’s own value so it can never collide with a future mermaid-defined "orthogonal". mermaid_curve has no effect in this mode. This mode also switches the diagram to konoma’s own designed palette and style — dark node fill with rounded corners and thin strokes, dashed subgraph frames, and classDef/style colors applied consistently to a node’s border, its edges, arrowheads, and label — so mermaid_theme has no effect here either. An unrecognized value falls back to "splines". |
mermaid_rows |
24 |
Upper limit on the height (rows) of an inline mermaid diagram inside Markdown. A diagram is shown at its natural size — matching the surrounding body text — and is never enlarged; it’s only shrunk (aspect preserved) when that natural size exceeds this cap or the available width. Diagrams re-rasterize at the needed density on zoom and stay sharp (the display size itself doesn’t change). The initial view also fits the viewport: shorter windows shrink the diagram further so the whole block is visible. 0/invalid falls back to the default. |
math |
"image" |
How LaTeX math renders. "image" (default) rasterizes $…$ / $$…$$ in-process via RaTeX (pure Rust, KaTeX quality, no browser/Node) and shows each as an inline image (inline math is always drawn in the running text, like ordinary Markdown — an expression too wide for the line shrinks to fit instead of being lifted onto its own line; display math is centered). "text" leaves the raw LaTeX as plain text. Non-graphics terminals and render failures degrade to the raw LaTeX automatically. |
math_color |
"#d0d0d0" |
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). |
restore_tabs |
true |
Restore the previous tab set per start directory: each tab’s root, tree cursor, and open preview come back on the next launch in the same directory. Saved on tab open/close/switch and on quit under ~/.config/konoma/sessions/. false = always start fresh (nothing is read or written). |
restore_single_tab |
true |
When restore_tabs is on: also persist/restore a session that has only one tab. false = don’t save 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. |
tree_cursor |
"origin" |
Where the cursor lands after moving to the parent directory (h). "origin" puts it back on the directory you just left (the same spirit as q returning from a preview — you land where you came from, not at the top); "top" always lands on the first row (the older behavior). An unrecognized value is treated as "origin". If the left directory isn’t in the parent’s listing (e.g. it’s hidden and show_hidden is off), this falls back to the top. Descending into a directory (l) always starts at the top either way — there is no “came from” row there. |
md_task_states |
[" ", "x"] |
Task-checkbox states cycled by Space in a Markdown preview, in order. Each entry is exactly one character. E.g. [" ", "/", "x"] adds an Obsidian-style in-progress state (shown as [/]). Invalid configs fall back to the default. |
md_autolink |
true |
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). Never applied inside code spans / code fences. false = leave them as plain text. |
md_alerts |
true |
Render GitHub-style alerts as colored callout boxes (icon + label) instead of plain blockquotes. Markers (case-insensitive, plus common aliases): > [!NOTE] / [!TIP] / [!IMPORTANT] / [!WARNING] / [!CAUTION]. false = ordinary blockquote (marker kept literal). |
md_emoji |
true |
Convert :shortcode: emoji to real Unicode in Markdown previews, like GitHub (:rocket: → 🚀). Shortcodes with no Unicode equivalent (GitHub-custom like :shipit:) and shortcodes inside code stay literal. false if emoji width upsets column alignment. |
md_frontmatter |
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. false renders it as ordinary Markdown. |
md_footnotes |
true |
Render GFM footnotes: text[^1] references become superscript numbers and the [^1]: … definitions are collected into a numbered footnotes section at the end. false leaves them literal. |
md_inline_html |
true |
Render common inline HTML 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. (<mark>/<ins> keep only their text either way.) false strips all of them. |
md_details |
"auto" |
How <details> blocks start out. "auto" honors the open attribute like GitHub (<details> collapsed, <details open> expanded); "open" always expanded; "closed" always collapsed. Either way Tab focuses the <summary> and Space/Enter toggle it. |
md_table_align |
"left" |
Where a table sits in a Markdown preview: "left" (the grid starts at the left edge), "center", "right". Moves the whole box — GFM pipe tables and HTML <table> alike, and any image inside a cell travels with it. It does not change alignment within a cell (a column’s :---: and an HTML cell’s align= still decide that). A table as wide as the pane stays flush left. |
md_image_align |
"center" |
Where a block image sits in a Markdown preview: "left", "center", "right". Covers a standalone , a packed row of badges, and a mermaid fence’s diagram (its caption and focus frame follow it). It does not cover an image inside a table cell (its cell’s alignment places that) or display math (centered by typesetting convention). An image as wide as the pane stays flush left. |
[ui.sort] — default tree order
Section titled “[ui.sort] — default tree order”| Key | Default | Description |
|---|---|---|
key |
"name" |
Sort key: "name" / "size" / "modified" / "ext". |
reverse |
false |
Descending order. |
dirs_first |
true |
Group directories before files. |
Change at runtime with the s menu (n/s/m/e, r = reverse, . = dirs first).
[ui.theme] — colors
Section titled “[ui.theme] — colors”Colors accept "#rrggbb", color names ("black", "lightblue", …), terminal indexes
("8"), or "none".
| Key | Default | Description |
|---|---|---|
bg |
"none" |
App background. "none" keeps the terminal’s default background (terminal transparency keeps working). |
code_bg |
"#2b303b" |
Background band for Markdown code (inline + blocks). "none" removes it. |
code_label_align |
"right" |
Code-block language badge position: "right" or "left". |
code_label_bg |
"auto" |
Language badge background: "auto" (brightened code_bg) / "none" / any color. |
code_theme |
"TwoDark" |
Syntax-highlight theme (shared by code files and Markdown fences). Others: "OneHalfDark", "Dracula", "Nord", "gruvbox-dark", "Catppuccin Mocha", "Monokai Extended", "Solarized (dark)", "GitHub", … Separators/case are ignored; unknown names fall back to TwoDark. |
[[preview.rules]] — what renders each file type
Section titled “[[preview.rules]] — what renders each file type”konoma’s core model: file format → viewer is declared in TOML. Rules are evaluated
top to bottom; the first match wins. A rule matches by glob (file name,
case-insensitive) or mime (content sniffing, e.g. "image/*"), and renders via either
a built-in renderer or an external command.
Note: if your config defines any
[[preview.rules]], your list replaces the built-in defaults — copy the full rule list fromconfig.example.tomland edit, rather than adding a single rule.
Built-in renderers (builtin = "..."):
| Name | Renders |
|---|---|
markdown |
Decorated Markdown (headings, tables, links, task checkboxes, inline images, ```mermaid fences as diagrams). |
mermaid |
Standalone .mmd/.mermaid files as diagrams. Renders as a real image by default (pure Rust, full-screen zoom/pan); [ui] mermaid = "text" switches to Unicode box-drawing. |
image |
Full-screen image drawn with the terminal’s graphics protocol (zoom/pan; GIFs animate automatically). |
svg |
Rasterized in-process (resvg; pure Rust) and shown as an image. |
video |
A single representative frame, shown as a thumbnail. H.264 and HEVC inside .mp4/.m4v/.mov and .mkv/.webm are decoded natively in Rust — no external tool needed (HEVC covers what an iPhone records by default). Everything else (VP9, AV1, older codecs, the .avi container, and the uncommon profiles — H.264 in 10-bit / 4:2:2 / 4:4:4 / monochrome, HEVC outside Main / Main 10 4:2:0) is extracted with ffmpegthumbnailer/ffmpeg if installed, and shows a hint if not. No in-terminal playback either way — delegate to mpv via command if you want playback. |
pdf |
Pages rasterized natively in Rust (hayro; one page at a time, no external tool needed) — J/K turn any page. On macOS only, a PDF hayro can’t render (encrypted, corrupt, or otherwise unsupported) falls back to the system’s own qlmanage/sips — always present, nothing to install — but those can only produce the first page. |
csv / tsv |
Aligned table with rainbow columns and a cell cursor (hjkl moves, y → copies cell/row/column). |
archive |
Lists entries (name / size / modified) for .zip/.tar/.tar.gz/.tgz in the same aligned-table renderer as CSV/TSV — metadata only, nothing is extracted (hjkl / y → c/r/C copy work the same). |
code |
Syntax-highlighted source (grammar resolved by extension → file name → first line). |
text |
Plain text. Also the automatic fallback for anything that looks like text. |
External command delegation:
[[preview.rules]]glob = "*.{mp4,mov}"command = "mpv {path}" # {path} = the file, {out} = a temp output pathdetached = true # don't block the TUI (opens in a separate process)
[[preview.rules]]glob = "*.{dot,gv}" # No builtin for Graphviz -- delegate it. (Mermaid needs no rule: konomarender_as = "image" # renders it natively.) render_as = treat the command's output as an image.command = "dot -Tpng -o {out}.png {path}" # No shell: write the command as argv, not as a pipeline.Omitting render_as (or setting it to anything other than "image") captures the
command’s output and shows it as plain text through the ordinary windowed reader — a
missing/failing command (binary not found, non-zero exit, {out} never produced)
degrades safely to [can not preview: <ext>] with the reason attached, instead of
crashing.
Mermaid needs no rule of its own. konoma renders .mmd/.mermaid files and
```mermaid fences itself — pure Rust, no Node, no browser — and the [ui] mermaid
options above control it. If what you specifically want is the output of mermaid.js itself
(the same engine behind mermaid.live and GitHub), you can delegate standalone files to
mmdc, the official mermaid CLI:
[[preview.rules]]glob = "*.{mmd,mermaid}" # replaces the default builtin = "mermaid" rulerender_as = "image"command = "mmdc -q -i {path} -o {out}.png -t dark -b transparent -s 3"-i/-o are the input and output files (mmdc picks svg/png/pdf from the output
extension), -t is the theme (default / forest / dark / neutral), -b the
background color, -s the Puppeteer scale factor (3 renders at 3×, so the PNG still has
pixels to spare when you zoom in), and -q keeps mmdc’s progress log out of the error
line. {out} deliberately has no extension, so the .png you append in {out}.png is
what tells mmdc which format to write — konoma accepts the suffixed file it produces.
Unlike everything else konoma leans on, mmdc is a heavyweight dependency. You install
it with npm install -g @mermaid-js/mermaid-cli; it wants Node 18.19+ / 20+, and it drives
a real browser through Puppeteer, so the install brings a bundled Chromium with it and every
preview starts one — expect a second or two per diagram rather than an instant one (konoma
gives any delegated command 30 seconds before it gives up). konoma’s own mermaid path needs
none of that. Take the trade deliberately.
Two limits of this rule:
- It covers standalone files only.
```mermaidfences inside a Markdown document are composited by themarkdownrenderer and always take konoma’s built-in path — a[[preview.rules]]entry matches whole files, so it cannot reach inside one. - Don’t aim it at
*.md. Given a Markdown input,mmdcrewrites the whole document (replacing each fence with a generated image file) instead of producing one diagram — not what a preview wants.
If mmdc isn’t installed, the rule degrades exactly like any other missing command, and
[external] preview_commands = false switches it off (along with every other delegation)
without touching your rule list.
Anything that matches no rule and doesn’t look like text shows a safe
[can not preview: <ext>] screen — konoma never crashes on unknown input, and missing
optional tools degrade to a hint.
[editor] — external editor
Section titled “[editor] — external editor”konoma never edits file contents itself; e delegates to your editor.
[editor]command = "nvim" # global default[editor.ext]md = "code -w" # per-extension override (extension without the dot)rs = "nvim +{line} {path}" # {line} = the preview line you were onResolution order: [editor.ext] match → editor.command → $VISUAL → $EDITOR →
vim. Values are command + args, whitespace-separated; {path} is substituted if
present, otherwise the file path is appended.
Opening at the preview line. Pressing e from a windowed preview (plain text, code,
or raw Markdown via R) opens the editor at the caret line. Use a {line} token to place
it explicitly (code -g {path}:{line}, hx {path}:{line}, nvim +{line} {path}). Without
a {line} token, common editors are handled automatically — vim family (+N, plus zt
to scroll that line to the top of the window), VS Code (-g path:N), and Sublime/Helix/Zed
(path:N); other editors open at the top. Rendered Markdown reflows the source, so e opens
at the line whose text is at the top of your view — it searches the source for the on-screen
text and lands on it (R gives an exact caret open). If you have Tab-focused an item
(link, checkbox, code block) that is on screen, e opens at that item’s line instead.
Mermaid and images always open at the top.
[git] — git integration
Section titled “[git] — git integration”| Key | Default | Description |
|---|---|---|
tool |
"lazygit" |
External git tool launched with ! inside the changes hub (command + args). |
diff |
"unified" |
Initial diff layout: "unified" (vertical) / "split" (side by side) / "auto" (by width). Cycle at runtime with s while viewing a diff. |
worktree_dir |
"../" |
Where n in the worktree list puts a new worktree, resolved against the main worktree so the location doesn’t depend on which worktree you started from. The directory is named after the branch, with / replaced by -. Pointing this inside the repository works, but then that path needs a .gitignore or .git/info/exclude entry of your own — konoma never writes one for you. |
[jj] — jj (Jujutsu) integration
Section titled “[jj] — jj (Jujutsu) integration”Preview. The surface is complete for the tree, diffs and the hub, but jj workspace has no list
yet, and jj is pre-1.0 and ships breaking changes monthly. konoma pins nothing: it probes the jj
on your machine once and falls back to git if it cannot answer.
Only what has no git counterpart lives here; everything else about a jj repository is decided by
[external] vcs and by jj itself. konoma only reads a jj repository — every call carries
--ignore-working-copy, so it never snapshots the working copy, and keys that would write are
hidden rather than offered.
| Key | Default | Description |
|---|---|---|
tool |
"lazyjj" |
External jj tool launched with ! inside the hub, the way [git] tool is for git. A missing binary flashes what could not be launched. |
[external] — external process on/off switches
Section titled “[external] — external process on/off switches”One on/off switch per external process konoma can launch. Every key defaults to true,
so an absent [external] section (or an absent field within it) changes nothing.
| Key | Default | Description |
|---|---|---|
git |
true |
git integration: status colors, the gutter, the Git views, stage/unstage/commit/checkout/branch (src/git.rs, via the git CLI and the embedded git2/libgit2). false behaves exactly like building with --no-default-features (no git feature) — every read returns empty/None, every write returns an error. o (open the Git view) flashes a message distinct from “not a git repo”, since it may well be one. Whatever this setting says, git integration also turns itself off automatically when no git executable is found on the machine (probed once, on first use); o then says git is not installed rather than blaming the directory. |
git_tool |
true |
The external git tool launched with ! ([git] tool, default lazygit). |
vcs |
"auto" |
Which version-control system answers. jj support is a preview — see the git suite guide. "auto" keeps git wherever git can answer, so a repository that already worked shows exactly what it showed before; jj answers only where there is no git repository to ask (jj git init --no-colocate, or a jj workspace). "git" is always git. "jj" uses jj wherever a .jj exists, colocated or not — ask for this when jj is the system you actually work in. With no jj binary on the machine, konoma falls back to git. |
pdf |
true |
The external fallback rasterizer — macOS’s bundled qlmanage/sips, tried only when the primary renderer (hayro, pure Rust — parses/renders in-process regardless of this flag) fails on page 1 of a given PDF (encrypted, corrupt, or otherwise unsupported). false never launches those tools, but PDF preview itself (page rendering and the page count) keeps working via hayro. On every other platform this flag is effectively a no-op: there is no external PDF tool to launch. |
video |
true |
The external fallback thumbnail extractors (ffmpegthumbnailer/ffmpeg), tried only when the built-in decoder (pure Rust, in-process regardless of this flag) can’t handle the file — i.e. anything that isn’t H.264 or HEVC in .mp4/.m4v/.mov and .mkv/.webm. false never launches them, but H.264 and HEVC thumbnails from those containers keep working. Same relationship pdf has with hayro above. |
remote_images |
true |
Fetching http(s):// images referenced from Markdown — the only outbound network call konoma makes. Done in-process via ureq (rustls), not an external tool. |
open_links |
true |
Opening URLs/files with the OS handler (open on macOS, xdg-open elsewhere) — Markdown links, pasted-path jump (P), etc. |
preview_commands |
true |
Running a [[preview.rules]] command = "..." delegation. false makes a matching rule behave as if it hadn’t matched (falls through to [can not preview]); builtin renderers (markdown, image, pdf, …) are unaffected. |
Disabled mechanisms degrade the same way a missing optional tool already does: PDF/video
fall back to the existing “cannot render” hint, a disabled remote image shows the text
placeholder instead of the image, and a disabled command rule falls through to
[can not preview] — nothing crashes.
Prefer [external] over trying to disable one thing through [[preview.rules]]: as noted
above, writing even a single user rule there replaces the entire builtin rule table, so
it can’t selectively turn off just PDF or video without also breaking Markdown, images, and
CSV.
[ui] lang already has its own explicit-vs-"auto" switch for OS-language detection (via
the sys-locale crate — no external process is launched) — setting it explicitly
("en"/"jp") skips that lookup entirely, so there is no separate [external] flag for it.
[keys] — keybindings
Section titled “[keys] — keybindings”Every command is rebindable. The model: each screen (“surface”) maps keys to actions, helix-style:
[keys.tree]"J" = "navigate:half_down" # capital = Shift included"ctrl-g" = "open_git_view" # ctrl-x / c-x"space d" = "file_delete" # two tokens = chord (leader + key)"o" = "noop" # disable a default binding
[keys.global] # inherited by every non-input surface"Q" = "quit"Surface names: global, tree, tree_visual, preview_text, preview_text_visual,
preview_image, preview_table, table_cell (the full-cell popup opened by Enter in
preview_table), sort, bookmarks, tabs, outline, info, help, and (git builds)
preview_git_diff, git_changes, git_log, git_graph, git_graph_picker, git_branches,
git_worktrees (the linked-worktree list, w in the changes hub), git_detail.
Key tokens: single characters (uppercase = Shift), space, literals like 0 $ ! + - = . / ',
modifiers ctrl-<k> (alias c-<k>), named keys tab enter esc backspace delete up down left right home end pageup pagedown. Two whitespace-separated tokens form a chord
("y f" = y then f). Esc/Enter/Tab/arrows and text-input keys are fixed and
cannot be rebound.
Action names are snake_case strings — the full annotated list is in
config.example.toml. The main groups:
- Movement:
navigate:down|up|top|bottom|page_down|page_up|half_down|half_up|left|right|line_home|line_end - Tree:
quit,close_tab_or_quit,tree_descend,tree_leave,tree_activate,filter_start,toggle_hidden,refresh,open_sort_menu,toggle_info,request_edit,cycle_path_style,set_anchor,reset_anchor,enter_visual,toggle_select,open_in_new_tab(Ctrl-t: open the entry under the cursor in a new foreground tab) - Bookmarks:
mark_set(m),mark_jump('— opens the list; plain letters inside it jump),bookmark_edit(ctrl-e),bookmark_delete(ctrl-d),bookmark_close.m/'are bound in both the tree and previews (a preview bookmarks the shown file). - Path copy (
yleader):copy_name,copy_relative,copy_full,copy_parent,copy_at_ref(@relative/pathfor AI chats),copy_code_block(y c— copy the Markdown code block currently focused withTab; the entry only appears in the menu while one is focused) - File management (
Spaceleader):file_create,file_rename,file_delete,file_copy,file_cut,file_paste,file_duplicate(Space→D: duplicate the cursor/selection in place, e.g.note copy.md) - Preview:
preview_back,search_start,search_next,search_prev,preview_enter_visual(v),preview_enter_visual_line(V),preview_copy_selection,preview_copy_selection_ref(Y=@path#L12-34),toggle_markdown_raw(R),link_focus_next/prev,link_open(Enter= current tab),open_link_new_tab(Ctrl-t= new tab),image_zoom_in/out/reset,pdf_next_page,pdf_prev_page,preview_next_file/preview_prev_file(Ctrl-n/Ctrl-p— page to the next/previous file in tree order, skipping directories, wrapping at the ends) - Table (
preview_table):table_copy_cell/row/column(yleader),toggle_table_cell(Enter: a full-text popup for the cursor cell — the grid truncates wide cells with…, this shows the untruncated value, wrapped and scrollable withj/k/g/G/PageUp/PageDown;q/Esc/Enterclose it;[keys.table_cell]covers the popup’s own keys) - Agent Watch:
toggle_follow(F),toggle_changed_filter(C),jump_next_change(n),jump_prev_change(N),toggle_follow_diff_scope(f, in a follow diff: switch between “since follow start” and the full git diff) - Git:
open_git_view(o),open_git_diff_cursor(d),git_stage,git_unstage,git_stage_all,git_unstage_all,git_discard,git_commit,git_open_log,git_open_graph,git_open_branches,git_launch_tool(!, in the changes hub),cycle_diff_layout,git_copy_*,branch_* - jj (
git_changes):jj_sync(R— let jj snapshot the working copy; konoma’s only write to a jj repository, and only after a confirmation. Does nothing in a git repository.) - Git graph (
git_graph):git_graph_toggle_all(a— show every revision instead of the range the backend considers current; only jj has a narrower one),git_graph_set_base,git_graph_clear_base,git_graph_open_picker(b, opens the branch panel). Inside the branch panel ([keys.git_graph_picker]):git_graph_picker_toggle,git_graph_picker_all,git_graph_picker_current_only,git_graph_picker_move_up,git_graph_picker_move_down - Git worktrees (
git_worktrees— a linked working tree fromgit worktree add, a different concept from the “worktree” meant everywhere else on this page, which is always the uncommitted working tree):git_open_worktrees(w, in the changes hub),worktree_filter_start(/, filter by branch name / path),worktree_goto(Enter, fixed key: switch this tab’s root — andopen_dir— to the selected worktree; still config-rebindable to another key),worktree_goto_new_tab(Ctrl-t: open the selection in a new tab, leaving this tab as-is),worktree_create(n: open an input dialog for a branch name — new vs. existing is auto-detected, no separate prompt for it — thengit worktree addit under[git] worktree_dir(see above) next to the main worktree, and switch this tab into it),worktree_show_changes(d: show the selected worktree’s diff since the base branch — committed and uncommitted content together, since an agent working in a worktree often commits along the way and an uncommitted-only diff would otherwise go blank; falls back to an uncommitted-only diff when there’s no resolvable base or nothing has piled up — seegraph_base_branchesabove),worktree_close(q/Esc). A bare main worktree, a locked/prunable one, or the currently-active one all refuse to switch (a flash explains why);worktree_show_changesstill works on the currently-active one. - Paste-jump (
global):paste_jump(P) — reads a path or GitHub link from the clipboard and jumps there (reveal + preview). Understands local absolute/relative paths, GitHubblob/rawURLs, and#L123/:123line anchors; switches root to the target’s repository when it lies outside the current root. - Tabs / app (
global):tab_new(t),toggle_tab_list(T— tab list;tab_list_close=dinside it),tab_prev/tab_next([/]),quit(Q),toggle_help(?).tab_closehas no default key (closing isqon the tree; rebind with"w" = "tab_close"if you want it back) noop(aliasdisabled) removes a default binding.
Conflicting bindings that would break essential defaults (stealing a leader prefix, tab keys, …) are detected at startup, reported in the footer, and reverted — a bad config never bricks the UI.
Backward-compatible aliases for path copy also exist at the [keys] top level
(copy_prefix, copy_name, copy_relative, copy_full, copy_parent).
Data files
Section titled “Data files”| Path | Contents |
|---|---|
~/.config/konoma/config.toml |
This configuration. |
~/.config/konoma/bookmarks.toml |
Global (uppercase) bookmarks — absolute paths. |
~/.config/konoma/bookmarks/<dir>.toml |
Local (lowercase) bookmarks, one file per start directory. |
~/.config/konoma/sessions/<dir>.toml |
Tab session (restore_tabs), one file per start directory. |
~/.cache/konoma/remote-images/ |
Cache for remote images embedded in Markdown. |
Fonts & terminal requirements
Section titled “Fonts & terminal requirements”- Images / SVG / Mermaid / LaTeX math / video thumbnails / PDF pages are drawn as real pixels in any terminal that speaks a graphics protocol — kitty graphics (Ghostty, kitty, WezTerm, Konsole), iTerm2, or sixel. konoma has its own compressed transfer for the kitty protocol, so those terminals are the fastest. Anywhere else the picture degrades to a half-block approximation — coarse, but visible. Text previews (Markdown, code, git diffs, CSV, tables) work in any terminal.
- Icons (
ui.icons = true, the default) need Nerd Font glyphs: either addSymbols Nerd Font Monoas a fallback font in your terminal, or use an NF-bundled font (HackGen Console NF, UDEV Gothic NF, …). Without one, setui.icons = falsefor plain-symbol fallbacks. - Optional tools:
ffmpegthumbnailer/ffmpeg(thumbnails for video konoma can’t decode itself — VP9, AV1, the older codecs,.avi),git+lazygit(git suite / external tool). PDF, images, SVG, Markdown, Mermaid, LaTeX math, CSV and H.264/HEVC video thumbnails (.mp4/.m4v/.movand.mkv/.webm) need nothing extra at all — they are rendered in pure Rust. Everything degrades gracefully when absent.