Every keybinding, every CLI command, the full config.toml schema, note
format, and included themes — the complete reference for how shiki actually behaves,
kept accurate to the current release rather than a marketing summary.
Panels behind the current focus collapse to a thin strip (Miller-columns style, like Yazi): browsing NOTEBOOKS shows all three panels at their normal width; moving into NOTES collapses NOTEBOOKS down; moving into PREVIEW collapses both NOTEBOOKS and NOTES so the note has (almost) the full width to read comfortably.
This layout is responsive to the terminal's actual size, not just one fixed arrangement:
h/l/tab
still move between panels exactly as always; at this size that just means switching which
one is on screen, one at a time.| Mode | Description |
|---|---|
NORMAL | Navigation, single-key shortcuts |
INSERT | Typing in search / input |
EDIT | Inline editor active (tui-textarea) |
VISUAL | Multi-note selection |
Keybindings aren't one flat list — they're scoped to what's focused, so the same
physical key can mean something different (but locally sensible) in each panel. Navigation
is hardcoded (not configurable, since it behaves the same everywhere); everything else lives
in its own editable config.toml table: [keybindings.global] (needs
the leader key first), [keybindings.notebooks], [keybindings.notes],
[keybindings.preview].
| Key | Action |
|---|---|
j / k / ↓ / ↑ | Navigate lists (down / up); scrolls the note while PREVIEW is focused |
PageDown / PageUp | Jump 10 at a time — same lists/scroll as j/k, just a bigger step |
Home / End | Jump to the first/last notebook or note, or the top/bottom of the note in PREVIEW |
l / → / enter | Go one level deeper (Yazi-style): NOTEBOOKS → NOTES → PREVIEW |
h / ← | Go back one level (Yazi-style) |
tab | Cycle focus between panels |
? | Which-key — near-full-screen list of every binding, doubling as a command palette: type to filter (by key, action, or scope), ↑/↓/PageUp/PageDown/Home/End move the selection, enter runs the highlighted action immediately, Esc just closes |
q | Quit |
Esc | Back to NORMAL / close popup / cancel leader |
PageUp/PageDown/Home/End
also work inside every scrollable modal (which-key, logs, global search, tree view) using the
same list/selection they already navigate with j/k.
[keybindings.global] — press leader (default space), then:| Key | Action |
|---|---|
c | Pick a theme — modal, live preview while browsing, Enter confirms |
g | Search all notes (title + body, every notebook) — modal, Enter/click to jump |
T | Tags panel — j/k browse tags, Enter/l drills into the notes carrying one, Enter/l there jumps to it, h/Esc goes back a level |
l | Logs — persistent scrollback of every status-bar message (survives restarts, ~/.config/shiki/shiki.log), including errors that already scrolled past; j/k scroll, y/c copies the whole log to the clipboard (OSC 52), x clears all logs (confirmation required), Esc/q closes |
b | Notebook drawer — left-side sidebar, every notebook's git status in color (dirty/ahead/behind); j/k or click a row to jump to it, n/click "New" to create a notebook, i/click "Import" to clone from a pasted URL, Esc/b again closes |
e | Toggle general.use_favorite_editor on/off and persist it immediately — no need to hand-edit config.toml. The footer always shows which mode is active: the resolved editor name (e.g. nvim) when on, native (the built-in inline editor) when off |
U | Check for updates — modal; checks GitHub Releases in the background (never blocks the UI), shows "update available" if there's a newer version, and Enter downloads, verifies (against GitHub's own per-asset checksum), installs, and automatically relaunches into it |
u | Undo the last delete — restores the most recently deleted note/folder (or whole batch, from a Visual-mode delete) from the trash (~/.config/shiki/trash/) back to exactly where it came from. A single level of undo, not a full history: only the most recent delete is restorable this way; an older one is still on disk in the trash, just no longer reachable from here. With nothing to undo, reports that instead of doing anything |
[keybindings.notebooks] — active while NOTEBOOKS is focused| Key | Action |
|---|---|
a | New notebook. If the name entered is a git URL (https://, git@host:..., ssh://, git://) instead of a plain name, the notebook name is derived from the repo instead, and the notebook is created, its remote set, and pulled immediately — importing an existing repo is just a + paste URL + Enter |
r | Rename notebook |
d | Delete notebook (with confirmation) |
s | Git sync — commit (message auto-built from the diff, naming files directly for a small change, e.g. "shiki: added (First note.md)"), + push if the resolved policy's auto_push is on |
u | Sync and always push, regardless of auto_push/auto_sync — the explicit "do it now" override |
p | Git pull (fetch + fast-forward merge from the configured remote) |
P | Git pull for every notebook that has a remote configured |
R | Set the notebook's git remote (URL or local path) |
Beyond manual s, a notebook can sync itself in the background:
[git] auto_sync = true (off by default) syncs automatically every
auto_sync_every note changes (new/edited/renamed/deleted/moved), not just on
manual s. auto_push, auto_sync, and
auto_sync_every can all be overridden per notebook under
[notebooks.<name>], falling back to the global [git] values
for anything left unset. A failed push never blocks or loses anything — the commit already
happened locally either way, and the next sync attempt just tries the push again.
[keybindings.notes] — active while NOTES is focused| Key | Action |
|---|---|
a | New note (empty title stamps today's date). After the title, a template picker opens — every .md file in ~/.config/shiki/templates/ plus a "blank" option; j/k browse, Enter picks one and jumps straight to editing ({{title}}/{{date}} already substituted), Esc/q cancels the note entirely |
f | New folder — empty name cancels rather than creating something unnamed. Created at the current breadcrumb depth, so it can be nested arbitrarily by descending first |
r | Rename note |
d | Delete the selected note or folder (with confirmation) — a folder deletes everything inside it too. In v select mode, deletes every selected item at once. Moved to the trash rather than permanently removed, so leader+u can undo it |
i | Edit inline (or the OS favorite editor if general.use_favorite_editor) |
E | Edit externally ($EDITOR) |
/ | Fuzzy-jump to a note by title anywhere in the current notebook (any folder depth) |
t | New/open today's daily note |
m | Move the selected note or folder — prompts for a notebook/path/within/it target, prefilled with the current one; edit the trailing segments to move within the same notebook (missing folders are created), or replace the first segment to move to a different (existing) notebook. In v select mode, moves every selected item at once |
o | Cycle sort order (filename / title A-Z / date newest-first) |
T | Tree view — every folder and note in the notebook, fully expanded, in one scrollable overview; j/k move, enter/l jumps straight to the selected note, esc/q closes |
D | Toggle each note's date next to its title in the list (off by default) |
v | Select mode (Mode::Visual) — anchors a multi-select range at the current item; j/k extend/shrink it, v/Esc cancels. d/m (above) act on the whole range instead of one item |
y | Select-mode only: copies every selected note/folder to a prompted target (same notebook/path syntax as m), leaving the originals in place |
[keybindings.preview] — active while PREVIEW is focused| Key | Action |
|---|---|
i | Edit inline (or the OS favorite editor if general.use_favorite_editor) |
E | Edit externally ($EDITOR) |
H | Note history — every commit that changed this specific note, newest first, real git history (not a separate versioning system). j/k/PageUp/PageDown/Home/End move, Enter views a revision's full content (frontmatter included, since that's what's actually in the commit), r reverts to the highlighted (or currently-viewed) revision — behind a confirmation, since it overwrites the current content. The revert itself doesn't commit; it shows up as a normal pending change, picked up by s/u/auto_sync like any other edit. The footer shows the count while reading a note ({n} changes) |
L | Links — the selected note's outgoing [[wikilinks]] (resolved against every note in the notebook, any folder depth) plus every other note that links back to it ("Outgoing"/"Backlinks" sections; a section with nothing in it is omitted). j/k/PageUp/PageDown/Home/End move, Enter jumps to the selected note (an unresolved outgoing link reports that instead of jumping), Esc/q closes |
shiki # launch TUI shiki new <title> # create note + open $EDITOR shiki daily # create/open today's daily note shiki list # list notes in the default notebook shiki list -n work # list notes in "work" shiki show <note> # show rendered content (ANSI) shiki edit <note> # edit with $EDITOR shiki search <query> # search and show results shiki sync # git commit+push default notebook shiki sync -n work # git sync in "work" shiki config # show config path shiki notebook create <name> shiki notebook list shiki notebook rename <old> <new> shiki theme list # list built-in themes, marking the active one shiki theme set <name> # switch theme (persisted to config.toml) shiki theme create [--from <name>] # scaffold all 19 color overrides from a real palette shiki doctor # environment health check (works even with a broken config)
~/.local/share/shiki/)~/.local/share/shiki/
├── personal/ # one notebook = one directory
│ ├── .git/ # independent git repo per notebook
│ ├── 2026-07-22-daily.md
│ ├── meeting-q3-planning.md
│ ├── rust-ideas.md
│ └── projects/ # notebooks nest folders arbitrarily deep, like `nb` —
│ └── website/ # the NOTES panel browses them one level at a time
│ └── todo.md # (l/→/enter opens a folder, h/← goes back up)
├── work/
│ ├── .git/
│ ├── sprint-review.md
│ └── architecture.md
└── projects/
└── ...
Frontmatter is optional on read: a plain .md file with no ---
block (from nb, an existing repo, or anywhere else) still shows up as a note
— its title comes from the first # heading or the filename, its date from
the file's mtime. It only gains real frontmatter once you touch it through shiki
(rename/edit); until then it's left exactly as it was on disk.
~/.config/shiki/)~/.config/shiki/
├── config.toml # general configuration
├── keybindings.toml # custom shortcuts (optional)
├── theme.toml # custom theme (optional)
├── shiki.log # persistent status/log history (leader+l to view, x to clear)
├── trash/ # deleted notes/folders, restorable with leader+u (see below)
│ └── <notebook>/
└── templates/ # templates
├── default.md
├── daily.md
└── meeting.md
Deleting a note or folder (d in NOTES scope) moves it here instead of removing
it outright, so leader+u can put it right back. Same collision reasoning as
shiki.log: this lives in the config dir, not the data dir, since the data
dir's top level is the set of notebooks themselves (user-named directories), so a fixed
name placed there could collide with one.
--- title: My note date: 2026-07-22 tags: [rust, tui, ideas] notebook: personal links: [[another-note]], [[third-link]] template: default --- # My note Content in **markdown**. - List of items - Code: `let x = 1;` [[wikilink]] to another note — navigable from the TUI.
bg/fg/border are "reset", accents use
the terminal's native ANSI colors) instead of imposing a fixed palette
Each theme defines 19 configurable color slots: bg, fg,
accent, selection, border, statusbar,
highlight, error, warning, success,
inactive, scrollbar, tab_active,
tab_inactive, panel_title, cursor, link,
tag, muted. Slots accept #rrggbb hex, the terminal's
native ANSI names (red, blue, cyan,
darkgray, …), or "reset" to inherit the terminal's own default for
that slot. See the live theme switcher on the home page.
config.toml reference[general] default_notebook = "personal" editor = "nvim" daily_template = "daily" # When true, `i` opens the OS's detected favorite editor (env $VISUAL/$EDITOR, # then the desktop's default text/plain handler) instead of the inline editor. use_favorite_editor = false [keybindings] leader = "space" quit = "q" [keybindings.global] theme_picker = "c" global_search = "g" tags_panel = "T" logs = "l" toggle_favorite_editor = "e" check_update = "U" drawer = "b" undo_delete = "u" [keybindings.notebooks] new = "a" rename = "r" delete = "d" sync = "s" pull = "p" pull_all = "P" set_remote = "R" [keybindings.notes] new = "a" new_folder = "f" rename = "r" delete = "d" edit_inline = "i" edit_external = "E" search = "/" daily_note = "t" move_to_notebook = "m" sort = "o" tree_view = "T" toggle_dates = "D" visual = "v" copy_entries = "y" [keybindings.preview] edit_inline = "i" edit_external = "E" history = "H" links = "L" [theme] name = "gruvbox-dark" # Every one of a theme's 19 color slots can be overridden individually — # accent, bg, fg, selection, border, statusbar, highlight, error, warning, # success, inactive, scrollbar, tab_active, tab_inactive, panel_title, # cursor, link, tag, muted. Override as many or as few as you want; anything # left unset falls back to `name`'s own value for that slot. A couple of # examples: # accent = "blue" # bg = "#1e1e2e" # fg = "#cdd6f4" # # `shiki theme create [--from]` scaffolds *all 19* here at once, # copied from a real palette (defaulting to whichever theme is active) — # a starting point to edit slot-by-slot instead of hand-typing hex codes # from scratch with no example to copy from. [git] auto_commit = true auto_push = false commit_prefix = "shiki: " remote = "origin" branch = "main" sign_commits = false auto_sync = false auto_sync_every = 5 # Auto-configures a notebook's remote on creation (plain name, not a pasted # URL) — "{notebook}" is replaced with the new notebook's name. The remote # still has to already exist on that server; this doesn't create one via # any hosting provider's API. Empty (the default) means don't auto-configure # anything. remote_template = "" # remote_template = "git@git.example.com:notes/{notebook}.git" # Optional per-notebook overrides of [git] — anything left unset here falls # back to the global values above. [notebooks.work] auto_sync = true auto_sync_every = 3 auto_push = true
Every default shown above matches the current release — if this page and a fresh
shiki install ever disagree, trust the install.