shiki (私記)
← Full changelog

shiki v0.9.1

Released 2026-08-13.

Share: X Bluesky Reddit Hacker News WhatsApp Telegram Email
shiki v0.9.1, running in a terminal

Added

  • <details>/<summary> blocks in a note's body are now truly collapsible in PREVIEW: a collapsed block shows only its summary (▸ plus a hidden-line count) and hides everything inside it — a plain mouse click on the summary row toggles it (instead of entering edit mode there), and the fold state is kept per note for the session (not persisted to config.toml). Previously every <details> block rendered fully expanded with no way to fold it.
  • shiki notebook rekey <name>: changes an encrypted notebook's passphrase in one step — verifies the old one against the canary, prompts for a new one twice, and re-encrypts every note in place, never writing plaintext to disk mid-operation (the old decrypt then encrypt two-step still works but leaves notes unencrypted in between).
  • Hidden notebooks can now be restored from Settings → NOTEBOOKS: the list includes notebooks that were untracked via the notebook-delete dialog's "just remove the reference" answer (marked (hidden)), and drilling into one has a hidden field whose Enter clears the flag and brings the notebook back — previously the only way to un-hide was hand-editing config.toml.
  • Cross-notebook [[wikilink]] resolution: a link that doesn't match any note in the current notebook now falls back to every other notebook (local resolution always wins, so same-titled notes in different notebooks still resolve to the current one). Both Ctrl+click in PREVIEW and the links modal use it, and jumping to a cross-notebook result switches notebooks automatically — this fixes the daily-note "Due today" agenda's links to tasks living in other notebooks, which previously reported "doesn't match any note".
  • Code fences in PREVIEW now render as real code blocks instead of literal ` markers: the opening fence becomes a header row (▌ rust main.rs — accent-colored ▌ + language tag, with an optional file:<path> token from the fence line shown muted after it), the closing fence renders nothing, and the code body keeps its per-token syntax highlighting. The file: token is shown exactly as written (only the language tag is lowercased), so a real path like App.tsx isn't mangled; an untagged fence gets a plain ▌ code header.
  • Code-fence colors now adapt to the active shiki theme instead of two fixed bundled syntect palettes: a Theme is built in memory from the active theme's own color slots (accent/success/warning/link/tag/muted/fg), so switching themes changes code-block colors too — gruvbox's code now looks gruvbox. Language coverage also comes from two-face's extra syntax bundle on top of syntect's defaults, which adds ~150 more languages including TypeScript/TSX — a ```tsx fence previously rendered as flat dimmed text because plain syntect doesn't bundle it at all.
  • $$...$$ math blocks in PREVIEW no longer show the literal $$ delimiters — a single-line block like $$E = mc^2$$ renders just the formula (accent/italic), and a multi-line block's bare $$ opener/closer lines produce no rows at all. This also fixes a real bug where a single-line $$...$$ block left the math state on, silently styling the following paragraphs as math until the next $$ line.
  • $$...$$ math content is now prettified to readable Unicode instead of raw LaTeX source (shiki-tui/src/mathfmt.rs): \frac{a}{b} → a/b, \sqrt{x} → √x, ^2 → ², _0 → ₀, \pi → π, \int → ∫, \infty → ∞, \times → ×, Greek letters and common operators — so $$\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}$$ renders as ∫₀^∞ e⁻ˣ² dx = √π/2 instead of the markup verbatim. A lightweight hand-rolled converter, not a TeX engine: anything it doesn't recognize passes through unchanged. Inline $$...$$ mid-line (e.g. "Inline math $$a^2 + b^2 = c^2$$ stays on its line.") gets the same prettification as full blocks.
  • `mermaid fences now render as real diagrams in PREVIEW instead of flat accent-colored text (shiki-tui/src/mermaid.rs, a small hand-rolled parser): flowcharts (graph TD/flowchart LR …) are laid out as an indented tree with box-drawing connectors, node shapes (A[Label]/A(Label)/A{Label}/A((Label))/A[[Label]]) and edge labels, and sequence diagrams (sequenceDiagram with participant + ->>/-->>/->/--x messages) render as participant columns with arrows drawn between them. A diagram that can't be parsed falls back to the previous flat styling rather than breaking.
  • PREVIEW's Markdown renderer now handles nested lists, nested blockquotes, strikethrough, and indented code blocks, which previously rendered as literal text: list items at any nesting depth (leading spaces then - /* /+ or N. ) indent and step the bullet glyph • → ◦ → ▪; >> nested quote repeats the ▏ gutter per level; ~~struck~~ renders crossed-out; a line with 4+ leading spaces that isn't a list/quote renders dim like fenced code.
  • Code fences in PREVIEW now show a line-number gutter: each code row is prefixed with a right- aligned N │ (muted, not the italic dim of the code itself) that resets per fence — so reading a highlighted block references "line 3" the same way a real editor would, and the header row (▌ rust main.rs) plus gutter make the block read as one unit.
  • shiki capture "text": near-instant note capture with no $EDITOR and no TUI drawn — meant for scripts, launchers (rofi/waybar/Raycast/AutoHotkey), or an OS hotkey. Targets general.default_notebook by default (-n <notebook> overrides), auto-generates a timestamped title. general.enable_capture_daemon (off by default, toggle from Settings → GENERAL) lets a running TUI pick up captures live over a local loopback socket instead of only writing to disk; shiki capture always works with or without it. Also supports: reading the text from stdin when no argument is given; --tags (same format as shiki new --tags); --daily (append as a bullet to today's daily note instead of creating a new one); --json (machine-readable output); and --check (reports whether a daemon is reachable, for status-bar modules, exits non-zero if not); --folder (create the note inside a subfolder instead of the notebook root); content-prefix routing (shiki capture "work: call Ana" routes into the work notebook automatically when no -n is given); and --undo (reverses the single most recent capture — trash for a plain note, strips the bullet back off for a --daily append). Every daemon-handled capture is also recorded in the TUI's log history (leader then l).
  • Writing-comfort improvements to the native note editor (Mode::Edit), each independently toggleable from the EDITOR tab in Settings (leader then s): list/checkbox auto-continuation on Enter (with ordered-list auto-increment, empty-item exit, and Backspace cleanup), bold/italic wrap shortcuts (Ctrl+B/Ctrl+Alt+I), bracket/quote auto-pairing ((, ` `, "), pasting a bare URL over a selection as a markdown link, move line (Alt+↑/Alt+↓), duplicate line (Alt+D), block indent/outdent on a selection (Tab/Shift+Tab), snippet expansion via trigger + Tab`, and opt-in typewriter scrolling.
  • Zen mode (leader then z): forces the full-screen single-panel layout for distraction-free writing.
  • Outline modal (PREVIEW o, or Ctrl+O while editing): jump to any heading in the note.
  • [editor] config gained move_line, duplicate_line, and block_indent_select toggles (all on by default) so the move/duplicate/block-indent behaviors above can be turned off the same way every other editor convenience already can.
  • [export] gained export_dir (where PDFs are saved — empty means the app's own data dir) and ask_export_path (prompt for the exact save path on every publish instead of using it silently), both editable from the EXPORT tab in Settings.
  • [theme].icons (Settings, THEME tab): turn off to fall back to plain text everywhere instead of Nerd Font glyphs, for a terminal font that isn't Nerd-Fonts-patched.
  • Six new [general] toggles, all editable from the GENERAL tab in Settings: show_coffee_link (hide the footer's Buy Me a Coffee segment), skip_delete_confirm (delete a note/folder immediately, still restorable via leader+u), show_dates (persists the notes-scope D toggle instead of resetting every launch), wikilink_autocomplete (disable the [[ menu), daily_agenda (skip the "Due today" section on new daily notes), and compact_footer (hide char/word count and reading time, leaving just the essentials).
  • Eight more [general] tuning knobs, all editable from the GENERAL tab in Settings: status_message_timeout_secs (how long a footer message stays visible), drawer_width (the notebook drawer's width in columns), tasks_show_done_default (whether the tasks view starts showing done tasks too), default_note_sort (which order NOTES sorts by on launch — "filename"/"title"/"date"), log_history_limit (max entries kept in the logs modal/file), trash_retention_days (auto-purge trash older than N days at startup — 0 means never), reading_wpm (words-per-minute for the "N min read" estimate), and page_step (how many rows PageUp/PageDown move at once, everywhere).
  • The which-key modal (?) now doubles as a unified command palette: once the filter query is non-empty, it also fuzzy-matches notes across every notebook (title/body/notebook name, same scoring the standalone global search modal uses) and lists up to 8 under a "notes" section — Enter on one jumps straight to it, same as it already runs the highlighted action on a keybinding row. Replaces shiki-tui/src/command.rs's CommandPalette, which was unused dead code that only duplicated the existing title-only note search (/, leader+g) without ever being wired up to anything — removed rather than kept alongside the real thing.
  • The /-menu gained two more ready-to-insert blocks, bold and italic — type /bold (or /italic), and the wrapped text/*text* around wherever the cursor sits is inserted, same as every other block command. Contributed by @elsieej (#63).
  • Note templates and snippets gained two more substitution variables, {{time}} and {{notebook}}, alongside the existing {{title}}/{{date}}/{{cursor}} — available in note templates (a, the @-dropdown), the daily note, and /-menu snippets alike.
  • Note history (PREVIEW H) gained a real diff view: d on a revision shows a unified diff against its parent (colored -/+ lines, computed by libgit2 itself) instead of the full file content — "what did this commit actually change here," the same thing git log -p shows for one commit. Works from either the revision list or the existing full-content view; r (revert) still acts on whichever revision is currently being looked at, in either view.
  • Recurring tasks: an @every(<spec>) tag (day/daily, week/weekly, month/monthly, year/yearly, or Nd/Nw/Nm) marks a checkbox task as recurring. Completing one (never un-completing) inserts its next occurrence right below it, unchecked, with @due advanced by that interval from the task's existing due date (or from today if it had none) — a repeat icon plus the raw spec shows next to the task text in the tasks view.
  • Dataview-style queries over note frontmatter: shiki query 'where status = pending sort due asc' filters/sorts notes across every notebook from the CLI, and leader+q opens the same live-editable query modal in the TUI (type the DSL at the top, matching notes render as a table below). Both share one parser/evaluator (shiki_core::query), so a query means the same thing in either place. --count/--json/--notebook are there for status bars and scripting, and DSL strings can be saved by name under [queries] and run with shiki query --saved <name>.
  • Per-notebook encryption at rest (age::scrypt, passphrase-based): shiki notebook encrypt <name> re-encrypts every note as an age-armored blob (still plain ASCII text, so git diff doesn't flip to "binary files differ") and writes an encrypted .shiki-encryption canary used to verify a passphrase attempt without risking a real note; shiki notebook decrypt <name> reverses it. The TUI unlocks a locked notebook by sniffing the age armor header and prompting for the passphrase, regardless of what any machine's config says. The passphrase itself is never stored anywhere — not in config.toml, not in the repo. Write paths (shiki new/shiki daily) prompt for it; non-interactive read commands (list/tasks/graph/show/search) fail with a clear error against a locked notebook instead of printing garbage.
  • Metadata editor (notes-scope/preview-scope M): view and edit a note's tags and custom frontmatter fields (status, priority, due, or anything else) without leaving the TUI — a adds a field, Enter edits the selected one, d deletes it. PREVIEW also gained a read-only header showing the same tags/fields above the note body, so they're visible without opening the editor. Field-value prompts show a suggestions dropdown: built-in defaults for status/priority/due, plus every value already used for that field anywhere in the vault; the Tags prompt suggests every tag already in use — Tab accepts one and keeps typing, Enter still saves the full comma-separated list as typed.
  • Query mode (leader+q, or leader+g then !) now opens straight into a "here's what you can ask" suggestions list generated from your own notes — every distinct value per field, both sort directions, and relative-date variants (today, overdue, upcoming, this week, this month) — instead of a blank box, and narrows live as you type. Queries can now be saved from the TUI itself: Ctrl+S on a valid query prompts for a name and writes it to config.toml's [queries] table (already supported by shiki query --saved, but previously CLI-only to manage); saved queries show up first in the suggestions list with a ★, and Ctrl+D on one deletes it.
  • Tag rename/merge (r in the tags modal, leader+T, level 1): renames a tag across every note in every notebook, not just the current directory being browsed — typing an existing tag's name merges into it instead of creating a duplicate.
  • scripts/query-demo.sh: seeds an isolated "demo" notebook with example notes carrying varied frontmatter, for trying out query mode without touching real data.

Fixed

  • The notebook drawer (leader+b) no longer hides the left edge of the panel underneath it: while the drawer is open the panels are pushed right by drawer_width instead of being covered by the overlay. Previously a pure left-anchored overlay sat on top of the panels, so the first ~28 columns of every PREVIEW line — the first half of a long math formula, the start of a code fence, the beginning of any wrapped line — disappeared behind the drawer the moment it opened.
  • The template picker's {{cursor}} marker (a → title → pick a template) was never actually handled — it saved the literal text {{cursor}} into the new note's file and always opened the editor at the top, unlike the identical marker in /-menu snippets, which already worked correctly. Fixed to split it out before saving (so it's never written to disk) and jump the cursor to exactly where it was in the template, same as snippets already do.
  • Pressing i in PREVIEW used to open the editor at line 1 no matter where you were reading — the scroll offset that was the only positional context in the read-only view was thrown away. It now jumps the cursor to whichever line was at the top of the preview viewport, reusing the same source-line mapping click-to-edit already uses.
  • shiki-managed git repos now force core.autocrlf off (per-repo config, not a global setting). Git for Windows commonly defaults it to true globally, which made libgit2 rewrite committed \n into \r\n on disk — silently corrupting real notebooks on Windows, where every note is parsed and written assuming plain \n line endings.
← v0.9.0 All releases No newer release →