Inkhaven (blackInkhaven)
Inkhaven is a standalone terminal application for writing books and long-form technical documentation. It pairs a full-screen Typst editor with a local semantic index, an AI writing assistant, versioned snapshots, and a backup pipeline — so the entire writing workflow lives inside one binary, without leaving the terminal.
Your manuscript is organised as a hierarchy of .typ files
(Book → Chapter → Subchapter → Paragraph), with first-class
image (.png / .jpg / …), HJSON data (.hjson), and
Bund script (.bund) leaves alongside paragraphs. Inkhaven
stores metadata in a local DuckDB database, indexes every text
node for full-text and semantic search, keeps versioned
snapshots, embeds the Bund
scripting language for hooks + custom rules, and streams answers
from your chosen LLM provider — six are bundled (Gemini,
Claude, OpenAI, DeepSeek, Grok, Ollama) and any
model genai routes is
one HJSON line away.

Latest release · 1.2.7 — Polish + plumbing
Read the full notes: Documentation/RELEASE_NOTES/1.2.7.md
1.2.7 is a polish cycle on the timeline-heavy 1.2.6 release. Two themes carry the branch: timeline + ergonomics refinements on the user side, a large architecture rework on the source side (zero behavioural delta — verified post-hoc).
User-facing highlights:
- Timeline polish. Tree-style two-level Tab/Enter
navigation,
Spacetrack collapse with▾/▸glyphs, span-aware↑/↓event selection with viewport auto-pan, faint grid stripes,F12book-wide critique inside the swim-lane view, per-book session persistence in.session.json, book-slug prefix on cross-book tracks (project overlay), and selection-awareCtrl+V Shift+Efor one-chord quick-event creation from any pane. Ctrl+B Uparagraph undelete. Single-slot kill-ring that round-trips body + tags + status + linked paragraphs- event timing after a Ctrl+D delete. New uuid; incoming wiki-links to the old id stay broken (status bar warns).
Alt+←/Alt+→navigation history. Browser-style back / forward through every paragraph-open path — tree Enter, fuzzy picker, wiki-link follow, snapshot picker, timeline Enter, undelete. PlusCtrl+V Shift+Precent-paragraph picker (32 entries, deduped).Ctrl+Shift+Mmouse-capture toggle. Flip terminal- native drag-select + system-clipboard copy on / off so you can grab snippets to paste elsewhere without routing throughCtrl+Cchat-selection mode.- External-change auto-reload. Passive watcher on every
autosave tick: clean buffer → silent reload, dirty
buffer → red warning. CLI /
sed/git pull/ Bund scripts that touch the open paragraph file no longer leave stale text on screen. - Snapshot dedupe + today-widget colour + F8 from any pane. Three smaller refinements: F5 / autosave skip byte-identical snapshots, the today-words widget gets colour by goal progress, the typst-diagnostics modal works outside the editor pane.
Around those: 4 new tutorials (32 — 34) plus a "1.2.7 polish" section on tutorial 31; updated keybinding reference.
Under the hood — architecture rework
The TUI brain (src/tui/app.rs) went from a 26,605-LOC
monolith to a 13,939-LOC central dispatcher with 21
sibling / child modules hanging off it. Every commit on the
branch was byte-equivalent modulo visibility downgrades and
import-path rewrites, verified post-hoc by a programmatic
per-method diff (561 method bodies pre vs post; exactly one
differed, and that turned out to be a pre-existing
save_current bug that I fixed). 255 → 260 tests passing;
zero build warnings.
The split makes the source navigable: render painters, modal
state, AI orchestration, timeline navigation, tag picker,
editor buffer methods, etc. each live in named files instead
of being scattered across a single huge impl App {}. See
src/tui/ for the layout.
Bugfix worth flagging
Ctrl+S in the editor was snapping the cursor to the
beginning of the buffer on every save. Pre-existing since
the 1.2.7 external-change auto-reload landed — save wrote
the file but never restamped loaded_mtime, so the next
tick saw the fresh mtime and reloaded the buffer (which
resets the cursor). Fixed in this release. If you ever see
that recurrence, file a bug.
Previous release · 1.2.6 — Tools for the working novelist
Read the full notes: Documentation/RELEASE_NOTES/1.2.6.md
1.2.6 is a wide-front release. Where 1.2.5 was one headline (in-process Typst), this one moves on six themes at once: tagging as project-wide metadata, diagnostics with an editor surface, AI as a writing partner (critique + memory + diff modal), labelled snapshots, a paragraph- mini story view, and a brand-new story timeline with calendar-aware events.
# Opt-in to the timeline (still 1.2.6+).
timeline: {
enabled: true
calendar: { preset: "gregorian" } # or "sols" or "custom"
}
# Opt into the diff modal on AI rewrites (default already on).
ai: {
per_paragraph_memory: true # default false
diff_review_on_apply: true # default true
}
Headlines from 1.2.6:
- Tagging stack.
Ctrl+B ]picker ·Ctrl+B }project search ·Rrename project-wide ·inkhaven export --tagfilter · tree-pane#tagpips · fiveink.tag.*Bund words · Scrivener keyword import. - Diagnostic UX. Red
●in the gutter for every line with a parse / semantic error · F8 diagnostics list ·Ctrl+V N/ Shift+N navigate · Ctrl+F12 AI explain the diagnostic at cursor (was F11; macOS grabs F11). - AI as a partner.
F12mode-aware critique (critique-editplain /critique-changessplit-edit) · per-paragraph memory (ai.per_paragraph_memory: true) · side-by-side diff modal before anyr/gapply · smart marker extraction across model dialects. - Snapshot annotations.
F5pops a one-line prompt;F6picker shows annotations as italic-cyan✎lines beneath each row. - Story view split.
Ctrl+V w(lowercase) for the paragraph mini view;Ctrl+V Shift+Wfor the book. New Bund wordink.story.renderwrites the graph to PNG from a script. - Render preview live zoom.
+ / -zoom in Ctrl+V R;0resets; cursor column anchored. - 🌟 Story timeline. Calendar-aware events (
gregorian/sols/custom),inkhaven event add/list/showCLI,Ctrl+V epicker,Ctrl+V tswim-lane view with scope navigation (u/d/b/p), AI health critique (y/Y/Ctrl+Y), sevenink.event.*Bund words + two new hooks (hook.on_event_added/hook.on_event_orphaned). Opt-in viatimeline.enabled.
The companion Book of Inkhaven at Book/ covers all of
1.2.6 in print form. It stays synced to 1.2.6 until the next
major release; 1.2.7 polish lives in the tutorials.
Previous release · 1.2.5
typst_compile: { engine: "inprocess" }
Flip it and Inkhaven stops shelling out to the host's typst
binary for builds. The full compiler — typst + typst-pdf +
typst-kit (fonts + @preview packages) — is linked into
every 1.2.5+ binary and runs inside the inkhaven process. The
external CLI stays the default; the switch is a runtime
decision.
Around that one switch:
- In-process compile engine.
typst::compile + typst-pdfruns on a worker thread; the foreground TUI keeps the spinner animated. Bundled Computer Modern + Linux Libertine fonts ship in the binary; system fonts are also searched.@preview/<pkg>imports fetch + cache viatypst-kit. Hermetic mode (no system fonts, no package fetch) lives behind two HJSON booleans. - Parse diagnostics on save / idle.
typst-syntaxre- parses the open paragraph on every save and everydiagnostics_idle_secondsof editor idle. First parse error lands on the status bar withline L:C — <message>. Engine-independent — works in bothexternalandinprocess. - Semantic diagnostics (opt-in). When
semantic_diagnostics: trueANDengine = "inprocess", a full compile runs after parse passes. Surfaces unknown functions, type errors, missing fonts. False positives expected for paragraphs that depend on book-level definitions — leave off for preamble-heavy manuscripts. - Ctrl+V N — diagnostic navigation. Jump the editor
cursor to the next typst diagnostic (parse or semantic).
Wraps. Status bar reports
diag 2/5 line 12:5 — <message>. - Ctrl+V R — render paragraph preview. Saves the buffer,
rasterises every page in-process via
typst-render, floats the PNG on top of the editor.← / →navigate pages,Ssaves the current page at full DPI,Asaves every page as<base>-page-NNN.png. Esc closes back to the editor (cancelling the save picker preserves navigation state). - TUI-friendly compiles. Compile splash shows the active
engine line (
internal · fonts: bundled + system · @preview: onorexternal · /usr/local/bin/typst). Esc cancels in-flight compiles — external sends SIGTERM, in-process abandons the worker (it finishes in the background). Ctrl+B A / B / O now autosave the primary editor (and the secondary editor in similar-paragraph mode) before walking.typfiles. inkhaven doctor. New CLI — prints a health report with engine summary, typst path, font + package counts, cache size, and (when run inside an initialised project) hierarchy shape + word counts. Notes section calls out actionable warnings liketypst NOT on PATH. Pipe- friendly.- Embedded logo in credits pane.
include_bytes!embedslogo.pngin the binary;Ctrl+B Vbanners it above the version + dependency list. - Project-wide node tagging. Three entry points,
one tag namespace stored as
Node.tags: Vec<String>:Ctrl+B ]opens the floating tag picker for the open paragraph (Space multi-selects,Tapplies,Aadds a new tag,Ddeletes a tag project-wide with a blast- radius confirm);Ctrl+B }opens the same picker in search mode — Enter on a tag lists every paragraph that carries it, with a typeable filter, and Enter on a hit opens it;gin the tree pane runs the picker against the marked set (or the cursor row), bulk-tagging a whole selection in one go. EditorTreturns focus to the editor; treegstays in the tree. - Story view — Ctrl+V W. Twopi-style radial graph of
the current book: book at the centre, each structural
depth on a concentric ring with sibling wedges sized by
subtree leaf count. Different SVG shape per node kind
(folder / box / octagon / ellipse / note / parallelogram /
chevron / egg / diamond / hexagon); long titles wrap to
multiple lines and node boxes scale to fit. Solid grey
edges for the structural skeleton, dashed purple for
linked_paragraphswiki-links, dashed green from Characters / Places / Artefacts to the paragraphs that mention them. Rasterised viaresvg+tiny-skia, displayed via ratatui-image.Ssaves the PNG. - New tutorial: Typst in-process — engine switch, fonts, packages, diagnostics, render preview, doctor.
Every prior release lives under Documentation/RELEASE_NOTES/.
Why Inkhaven
- Terminal-first. Inkhaven runs over SSH, in tmux, on a tiling WM — no browser, no Electron. The TUI uses ratatui and tui-textarea.
- Your manuscript is plain files. A paragraph lives in a
.typfile on disk; the metadata database tracks hierarchy and search but the prose is text — you can read it, diff it, version-control it, and edit it with another tool any time. - Semantic search out of the box. Embeddings via fastembed and HNSW are computed locally. Search for "the moment the lighthouse fails" and find the paragraph even if it never uses those exact words.
- AI is a co-author you steer. Inferences stream live; you control the
scope (selection / paragraph / subchapter / chapter / book), the
mode (Local-only RAG vs. Full general knowledge), and the
destination (replace, insert, top, bottom, copy, grammar-apply).
Inkhaven does NOT provide inherent privacy when external providers
(Gemini / Claude / OpenAI / DeepSeek / Grok) are used — prompts
travel to their servers under their terms. For privacy, set
llm.default_provider: "ollama"and run a local model; every other inkhaven subsystem (RAG embedding, semantic search, snapshot diff) is already on-device. - Multilingual. Snowball stemmers and multilingual embeddings make Russian, German, French, Spanish, Italian and others first-class. The shipped defaults cover English and Russian.
- Help, characters, places, artefacts, scripts — built in. Nine
system books are seeded on every project:
Notes,Research,Prompts,Places,Characters,Artefacts,Typst,Scripts,Help. Mentions of names from the lexicon books light up in the editor (cyan / amber / peach / underline).Ctrl+B P/C/Y/Gquery each via RAG.F1answers questions about Inkhaven itself by RAG overHelp.Scripts(added in 1.2) holds.bundsource files auto-loaded into the embedded Bund scripting VM at project open — seeDocumentation/Bund/. - First-class images. Drop PNG / JPG / WebP / SVG into the tree;
Book assembly emits the right
wrap_image_*calls and ships the bytes into the typst tree.Ctrl+B Pinside#image("…")opens a sibling picker. Enter on an Image row pops a ratatui-image preview (kitty / sixel / iterm2 / half-block). - From buffer to PDF in two chords.
Ctrl+B Aassembles your tree into a typst-compilable directory;Ctrl+B Bcompiles it;Ctrl+B Obuilds and copies the PDF into your shell's cwd as<book>-YYYYDDMM-HHMM.pdf. Compile failures route the captured stderr into a fresh AI chat with a typst-aware system prompt.
Features at a glance
Editor
- Typst syntax highlighting via tree-sitter-typst.
- Regex find / replace with same-line current-match highlighting.
- Split-edit with versioned snapshots — see two versions of a paragraph side by side, accept either.
- Word-aware navigation and deletion shortcuts.
- Vertical block selection (Alt+arrows) with rectangular copy.
- System-clipboard cut / copy / paste, plus per-doc undo / redo.
- Live "changes since last save" bolding; grammar-correction highlights
what changed after a
gapply.
Tree
- Multi-level folding (
←/→/Z/X). - Per-kind row colours (book / chapter / subchapter / paragraph / image)
- open-paragraph marker.
- Plain-letter shortcuts for add (
B/C/V/A/S/+/P), delete (D/-), reorder (U/J). - Document status badge column — one character per row colour-
coded to the workflow stage (
n/1/2/3/F/R). - Mouse: click to focus + select; scroll wheel scrolls.
AI pane
- Streaming markdown rendering — bold / italic / headings / code / lists.
- Six scope modes (cycled by
F9): None, Selection, Paragraph, Subchapter, Chapter, Book — each prepends the matching content to the next prompt. - Two inference modes (
F10): Local (use only supplied context) and Full (augment with general knowledge). Help inferences are pinned to Local automatically. - Persistent chat history with one-key clear (
Ctrl+B C). - Full-screen AI layout (
Ctrl+B K) — AI pane + scrollable chat history + AI prompt; persisted to.inkhaven-chat.jsonbetween sessions;Ctrl+Fsearches;Ctrl+Centers a turn-selection mode. - Lexicon RAG —
Ctrl+B P/C/G/Yin the editor sweep the selection throughPlaces/Characters/Notes/Artefactsand prepend the lookup to the next AI prompt. - F1 Help-manual floating query → grounded answer over the Help book.
inkhaven import-typst-helpseeds Help with a curated typst reference. - F7 Grammar check with deterministic correction extraction (
greplaces the buffer with just the corrected text, preserving Typst markup).
Storage and backup
- DuckDB metadata + Tantivy full-text + HNSW vectors via bdslib.
- Snapshots:
F5captures the buffer;F6opens the snapshot history picker. inkhaven backup --out <dir>zips the entire project.inkhaven restore <archive> --to <dir>puts it back.- Auto-backup on TUI exit when the last backup is older than
backup.max_age(humantime:7d,12h,30m, …) — splash screen with a progress bar. - Session persistence: cursor position, focus, tree-scroll, open paragraph all survive restarts. Per-paragraph cursor memory: switch around and every paragraph remembers where you were.
CLI tools
init— set up a fresh project (interactive confirmation if the directory exists).add/delete/mv/list— manage the hierarchy from a script.search "phrase"— semantic search from the shell.reindex— re-walk.typfiles into the database.export typst/export pdf— produce a single Typst manuscript or a built PDF.import-help --documents-directory <dir>— populate the Help book from a directory of markdown / text / typst files (wipes Help first).backup/restore— see above.ai "prompt"— one-shot inference from the shell (no TUI).
Configuration
A single inkhaven.hjson in each project root drives every knob:
embedding model, LLM providers, autosave cadence, sync interval, hierarchy
depth, language, snowball stemmers, the full visual theme (per-pane
backgrounds and foregrounds, all syntax colours, lexicon highlight
colours), key bindings, and backup policy.
Install
Inkhaven ships as a single static binary per platform. Three install paths:
1. cargo binstall (no compile)
If you already have cargo-binstall:
cargo-binstall reads [package.metadata.binstall] from Cargo.toml,
picks the right asset off GitHub Releases, and drops the binary into
~/.cargo/bin. Works on Linux (x86_64), macOS (Intel + Apple Silicon),
and Windows (x86_64).
2. GitHub Releases (direct download)
Grab the tarball for your platform from
Releases, unpack,
and put inkhaven somewhere on your PATH. Builds are produced by
the release.yml workflow on every
tag push.
3. cargo install --git (compile from source)
This works because every dependency (including bdslib and
tree-sitter-typst) is vendored under vendor/ — no separate registry
fetches, no GitHub auth needed. The first build takes ~10 minutes on a
modern laptop because of DuckDB + Tantivy + fastembed compilation; the
release binary above is the fast path.
Inkhaven is not published on crates.io. See
Cargo.toml'spublish = falseline and theDocumentation/notes for the rationale.
Quick start
# Build (if installing from source)
# Initialise a project (asks for confirmation if the directory exists)
# Build the hierarchy from the CLI…
# …or skip the CLI and add everything from the TUI
# Inside the TUI: B (book), C/V (chapter), A/S (subchapter), +/P (paragraph)
Use cases
- Long-form fiction. Hierarchy fits novels naturally (Book → Part → Chapter → Scene). Places / Characters / Research system books keep worldbuilding next to prose.
- Technical documentation. Each chapter is a
.typfile; the tree doubles as a table of contents. Semantic search makes "where did I document the retry policy?" a one-keystroke question. - Translation work. Multilingual embeddings + per-language Snowball stemmers let you keep source and target in two parallel books.
- Research notebooks. Snapshots track how a draft evolved; the AI pane can summarise a chapter when you come back after a week.
- Help and onboarding writing. Ship docs as a directory and let Inkhaven build a Help book your readers can query through F1.
Documentation
The full docs live under Documentation/.
Start here:
Documentation/README.md— entry point and table of contents.Documentation/FIRST_STEPS.md— compile, install, initialise.Documentation/Tutorials/— narrative walk-throughs, each focused on one workflow.
Reference:
Documentation/KEYBINDING.md— every keystroke the TUI recognises, organised by pane and overlay.Documentation/CONFIGURATION.md— the full HJSON reference.Documentation/MAINTENANCE.md— backup, restore, reindex, logs.Documentation/PROMPTS.md— the prompt library and the Prompts system book.Documentation/LOCATIONS.md— managing Places.Documentation/CHARACTERS.md— managing Characters.
Built with
- bdslib — DuckDB + Tantivy + fastembed + HNSW document store
- ratatui, tui-textarea
- tree-sitter + tree-sitter-typst
- genai — provider-neutral LLM streaming
- pulldown-cmark,
rust-stemmers,
zip,
humantime, and many others —
see
Cargo.toml.
Licence
Apache 2.0 — see LICENSE.