inkhaven 1.2.15

Inkhaven — TUI literary work editor for Typst books
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
# 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](Documentation/Bund/README.md)
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](https://github.com/jeremychone/rust-genai) routes is
one HJSON line away.

![Inkhaven screenshot](screen.png)

## Latest release · 1.2.15 — Stability + self-healing + security hardening

Read the full notes: [`Documentation/RELEASE_NOTES/1.2.15.md`](Documentation/RELEASE_NOTES/1.2.15.md)

1.2.15 is a stability + security release.  The
goal is concrete: zero panics from the hot path,
zero data loss across crashes, every project-wide
inconsistency either auto-fixed or surfaced to
the user.  Four themes landed.

Tests 565 → 695 (+130).  Zero new dependencies.

### Survivable panics — `Ctrl+C` proof, `kill -9` proof

A custom panic hook (installed before any code
that might panic) catches every panic the editor
or the host throws.  On firing it:

1. Flushes every dirty editor buffer atomically
   to a side-by-side `<path>.inkhaven-rescue`
   companion file.
2. Writes `inkhaven-crash-<UTC>.hjson` to the
   launch cwd with the panic message + location,
   the project state at the moment of the
   crash, a ring buffer of the last 50 user
   actions, and an environment fingerprint.
3. Restores the terminal so anything that
   prints after is readable.

After the crash, `inkhaven recover <crash.hjson>`
walks the rescued-buffer manifest with `y` / `N`
/ `diff` per buffer.  Accepted rescues are
applied atomically, with the current on-disk
version snapshotted as `<original>.pre-recover-
<UTC>` so rollback is one `mv` away.  `--yes`
for scripted recovery; `--keep` to retain the
report files.

The dirty-buffer mirror runs at a 2 s debounce
in the main loop, so the worst-case unsaved-
typing window a panic can take down is bounded
at ~2 s.

### Stability sweep across the codebase

Five sub-phases catalogued and patched **62
panic sites** (the entire hot-path `unwrap()` /
`expect()` / `unreachable!()` surface in
`src/tui/app`, `src/store`, `src/cli`, and
helper modules) **+ 2 latent out-of-bounds
crashes + 5 non-atomic critical-data writes + 4
lock-poisoning sites**.

The flagship side-effect: every user-data save
path now goes through the new `crate::io_atomic`
module — temp + fsync + rename + parent-dir
fsync.  A power loss mid-save preserves either
the previous version or the new version, never a
half-written truncated file.  Applies to the
manuscript save path, the secondary-editor save,
comment sidecar writes, session state, and
directory imports.

### Background health monitor + project doctor

A tokio task running alongside the TUI
periodically checks project-root reachability
(90 s), backup freshness vs. `backup.max_age`
(5 min), and rescue file orphans older than 7
days (1 h).  Findings drive a status-bar chip
(`✓` clean / `✎` repaired / `⚠` warning / `✗`
error) and are appended to
`<project>/.inkhaven/health.log` (size-rotated
at 1 MB × 5 archives).  Per-class auto-repair
opt-in in HJSON (`health.auto_repair.*`).

The on-demand counterpart is the project
doctor.  `inkhaven doctor --scan` walks the
project for five problem classes:
zero-byte-file, orphan-paragraph-row, missing-
referenced-file, corrupt-comments-sidecar, and
the recoverable `bdslib-only` (disk file
missing but content preserved in bdslib).
`--autofix [--yes]` applies per-class repairs
(delete row + file, move corrupt sidecar to
`.bak`, rematerialize disk from bdslib).
`--json` for CI gates (exit 2 on any Warning+).
`Ctrl+B Shift+0` opens the same flow as a TUI
modal.

### Security hardening from a full audit

A 1.2.15 security audit catalogued four risk
classes; all patched before release:

* **Path-traversal in the recover CLI**  crafted crash reports with `paragraph_rel_path:
  "../../etc/passwd"` now rejected.
* **Path-traversal in HJSON config**  `prompts_file` and `artefacts_directory` `..`-
  escapes blocked.
* **`ink.fs.*` sandbox** — Bund scripts'
  filesystem read / write now confined to the
  project root by default.  `scripting.fs_
  unsandboxed: true` opt-out for power users.
* **Script auto-load trust gate** — opening a
  project no longer silently runs Bund scripts.
  `scripting.trust_decision: "ask"` (default)
  requires `<project>/.inkhaven/trust` with a
  `trust` marker line; `"trust"` / `"deny"`
  override.

New [`Documentation/SECURITY_WARNING.md`](Documentation/SECURITY_WARNING.md)
documents known + unknown risks and limitation
of liability.

Every prior release lives under
[`Documentation/RELEASE_NOTES/`](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]https://ratatui.rs/ and
  [tui-textarea]https://github.com/rhysd/tui-textarea.
- **Your manuscript is plain files.** A paragraph lives in a `.typ` file
  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` /
  `G` query each via RAG. `F1` answers questions about Inkhaven itself
  by RAG over `Help`. `Scripts` (added in 1.2) holds `.bund` source
  files auto-loaded into the embedded Bund scripting VM at project
  open — see [`Documentation/Bund/`]Documentation/Bund/README.md.
- **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 P` inside `#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 A` assembles your tree
  into a typst-compilable directory; `Ctrl+B B` compiles it; `Ctrl+B O`
  builds 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]https://github.com/uben0/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 `g` apply.

### 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.json` between
  sessions; `Ctrl+F` searches; `Ctrl+C` enters a turn-selection mode.
- **Lexicon RAG**`Ctrl+B P` / `C` / `G` / `Y` in the editor sweep
  the selection through `Places` / `Characters` / `Notes` / `Artefacts`
  and prepend the lookup to the next AI prompt.
- **F1 Help-manual** floating query → grounded answer over the Help book.
  `inkhaven import-typst-help` seeds Help with a curated typst reference.
- **F7 Grammar check** with deterministic correction extraction (`g`
  replaces the buffer with just the corrected text, preserving Typst
  markup).

### Storage and backup
- DuckDB metadata + Tantivy full-text + HNSW vectors via
  [bdslib]https://github.com/vulogov/bdslib.
- Snapshots: `F5` captures the buffer; `F6` opens 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 `.typ` files 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`](https://github.com/cargo-bins/cargo-binstall):

```bash
cargo binstall inkhaven
```

`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](https://github.com/vulogov/blackInkhaven/releases), unpack,
and put `inkhaven` somewhere on your `PATH`. Builds are produced by
the [`release.yml`](.github/workflows/release.yml) workflow on every
tag push.

### 3. `cargo install inkhaven` (compile from crates.io)

```bash
cargo install inkhaven
```

Inkhaven is published on crates.io — every release tag pushes a
new version (latest: 1.2.14).  The first build takes ~10 minutes on
a modern laptop because of DuckDB + Tantivy + fastembed compilation;
`cargo binstall` above is the fast path.

### 4. `cargo install --git` (compile from a specific tag)

```bash
cargo install --git https://github.com/vulogov/blackInkhaven --tag v1.2.14
```

Useful when you want a specific tag, a pre-release branch, or a
local fork.

## Quick start

```bash
# Build (if installing from source)
cargo build --release

# Initialise a project (asks for confirmation if the directory exists)
./target/release/inkhaven init ~/Books/my-novel

# Build the hierarchy from the CLI…
./target/release/inkhaven --project ~/Books/my-novel add book "My Novel"
./target/release/inkhaven --project ~/Books/my-novel \
    add chapter "The Beginning" --parent my-novel
./target/release/inkhaven --project ~/Books/my-novel \
    add paragraph "Opening Scene" --parent my-novel/the-beginning

# …or skip the CLI and add everything from the TUI
./target/release/inkhaven --project ~/Books/my-novel
# 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 `.typ` file; 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/`](Documentation/).

Start here:

- [`Documentation/README.md`]Documentation/README.md — entry point and
  table of contents.
- [`Documentation/FIRST_STEPS.md`]Documentation/FIRST_STEPS.md — compile,
  install, initialise.
- [`Documentation/Tutorials/`]Documentation/Tutorials/ — narrative
  walk-throughs, each focused on one workflow.

Reference:

- [`Documentation/KEYBINDING.md`]Documentation/KEYBINDING.md — every
  keystroke the TUI recognises, organised by pane and overlay.
- [`Documentation/CONFIGURATION.md`]Documentation/CONFIGURATION.md  the full HJSON reference.
- [`Documentation/MAINTENANCE.md`]Documentation/MAINTENANCE.md — backup,
  restore, reindex, logs.
- [`Documentation/PROMPTS.md`]Documentation/PROMPTS.md — the prompt
  library and the Prompts system book.
- [`Documentation/LOCATIONS.md`]Documentation/LOCATIONS.md — managing
  Places.
- [`Documentation/CHARACTERS.md`]Documentation/CHARACTERS.md — managing
  Characters.

## Built with

- [bdslib]https://github.com/vulogov/bdslib — DuckDB + Tantivy +
  fastembed + HNSW document store
- [ratatui]https://ratatui.rs/, [tui-textarea]https://github.com/rhysd/tui-textarea
- [tree-sitter]https://tree-sitter.github.io/ +
  [tree-sitter-typst]https://github.com/uben0/tree-sitter-typst
- [genai]https://github.com/jeremychone/rust-genai — provider-neutral
  LLM streaming
- [pulldown-cmark]https://github.com/raphlinus/pulldown-cmark,
  [rust-stemmers]https://github.com/CurrySoftware/rust-stemmers,
  [zip]https://github.com/zip-rs/zip2,
  [humantime]https://github.com/tailhook/humantime, and many others —
  see [`Cargo.toml`]Cargo.toml.

## Licence

Apache 2.0 — see [`LICENSE`](LICENSE).

## Security Warning and Disclaimer

Inkhaven is provided **"AS IS"** with no warranty.  The author
cannot be held liable for personal, business, or financial
damage arising from its use.  Use is voluntary and **at your
own risk**.

Before opening a project file you did not author — and before
relying on Inkhaven for work you cannot afford to lose —
please read **[`Documentation/SECURITY_WARNING.md`](Documentation/SECURITY_WARNING.md)**.
It enumerates the security issues catalogued in the 1.2.15
audit (both fixed and pending), the design properties that
are inherent rather than bugs, the unknown-risk classes that
no audit can fully eliminate, and the limitation-of-liability
terms under which Inkhaven is distributed.