10月30日 11:16 檢查 · 分數為各平台在最後檢查時顯示的數值。我們不複製貼文內文與留言,原文刪除後此處也會移除。
A terminal writing desk for novels. Your manuscript is a folder of plain Markdown — no database, no lock-in, diffable in git. Rust + Ratatui.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
A writing desk for novels that lives in your terminal. It knows what a
manuscript is — pages, chapters, scenes, word targets — and it keeps every word
of it as plain files you could read with cat.
Every open-source novel tool makes one of two mistakes. It traps your
manuscript in a database, or it's a text editor with no idea what a manuscript
is.
Grimoire does neither. The directory tree is the outline. There is no index
file, so there is nothing central to conflict when you sync across machines.
Reordering is renaming. Backing up is copying a folder.檢視完整 README ↗grimoiretui.com · free classroom curriculum · Rust + Ratatui · MIT · macOS, Linux and Windows · made by Catfinity Studios, makers of Catfinity
Grimoire is a cozy little writing desk for your novel, and it lives right in
your terminal. It understands how a book comes together, from parts and
chapters down to scenes and word goals, and it keeps every word you write in
plain files you can open with anything, even cat.
Most novel apps make you pick. Some tuck your manuscript away in a database you can't open without them. Others are lovely text editors that have no idea what a chapter is.
Grimoire wanted both: an app that understands your book, and files that stay yours. So your folders are your outline. There's no hidden index, which means there's nothing for two computers to squabble over when your book syncs. Moving a scene is just renaming a file, and backing up is just copying a folder.
And if Grimoire ever disappears, your book doesn't. That promise came first, and everything else was built around it.
Windows — open PowerShell or Command Prompt and paste:
powershell -ExecutionPolicy Bypass -c "irm https://github.com/kelsierbot/GrimoireTUI/releases/latest/download/grimoire-tui-installer.ps1 | iex"
macOS and Linux — in a terminal:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/kelsierbot/GrimoireTUI/releases/latest/download/grimoire-tui-installer.sh | sh
Then open a new terminal (on Windows, Windows Terminal is best) and run
grimoire. Nothing else to install — no Rust, no build tools. The installer
puts grimoire in ~/.cargo/bin and adds that to your PATH. Builds are for
Windows x64, macOS (Apple Silicon and Intel) and Linux (x86_64 and ARM64);
every download is on the releases page.
With Homebrew (macOS or Linux):
brew tap kelsierbot/tap
brew trust kelsierbot/tap
brew install grimoire
brew upgrade then brings each new release.
Debian and Ubuntu — a package, handy for a school lab or anywhere IT installs things for everyone:
curl -LO https://github.com/kelsierbot/GrimoireTUI/releases/latest/download/grimoire_amd64.deb
sudo apt install ./grimoire_amd64.deb
Fedora (and other RPM systems):
sudo dnf install https://github.com/kelsierbot/GrimoireTUI/releases/latest/download/grimoire.x86_64.rpm
On ARM it's grimoire_arm64.deb and grimoire.aarch64.rpm. The same commands
again bring you up to date.
Settings live in ~/.config/grimoire (%USERPROFILE%\.config\grimoire on
Windows) and a first manuscript goes in Documents/Grimoire.
Linux needs two things every desktop distro already has: glibc 2.35 or
newer (Ubuntu 22.04, Debian 12, Fedora 36 and later), and ALSA's audio library.
Minimal installs, servers, containers and WSL can be missing the library, and
then grimoire stops with libasound.so.2: cannot open shared object file.
Install it and run grimoire again:
sudo apt install libasound2t64 # Ubuntu 24.04+, Debian 13+ (older: libasound2)
sudo dnf install alsa-lib # Fedora
sudo pacman -S alsa-lib # Arch
Requires Rust 1.85 or newer.
git clone https://github.com/kelsierbot/GrimoireTUI
cd GrimoireTUI
cargo install --path .
The crate is grimoire-tui; the binary it installs is grimoire. On Windows,
install Rust with rustup and let it add the Visual Studio
C++ build tools.
grimoire open your manuscript
grimoire ~/novels/the-archive open a specific one
grimoire new ~/novels/next-one start one (add --short-story or --blank)
grimoire import draft.docx bring in a draft you already have
grimoire music-setup install + connect YouTube Music
Already inside Grimoire? Esc › Start a new book… asks for a name and opens it
right there, and Esc › Open another book… hops between the ones you've had open.
A new book starts as a novel (three parts of nine chapters), a short story
(three chapters: a beginning, a middle and an end) or blank; Tab picks.
Got a draft already? Grimoire brings in a Word file (.docx), Markdown or
plain text and splits it into chapters and scenes for you: chapters at its
headings, scenes at its scene breaks (***, #), with italics and bold kept.
Anything before the first chapter, like a title page, lands in Notes, and every
word comes across. From Google Docs, download it as Word first. In the app it's
Esc › Open another book… › Bring in a draft…, or type the draft's path into
Start a new book….
With no arguments it opens the current directory if it's a manuscript,
otherwise the last one you had open, otherwise it creates one in
~/Documents/Grimoire.
Folders are containers, at any depth. Files are scenes. Order comes from the
name — a leading 01- sorts the file and is stripped for display.
the-archive/
├─ novel.toml title, author, word targets, part_label
├─ Novel-Format.md how the book is laid out
├─ manuscript/
│ ├─ 01-Part-One/
│ │ ├─ 01-Chapter-One/
│ │ │ ├─ 01-Scene-One.md a scene
│ │ │ ├─ 02-Scene-Two.md
│ │ │ └─ 03-Scene-Three.md
│ │ └─ 02-Chapter-Two/ …
│ ├─ 02-Part-Two/ …
│ └─ 03-Part-Three/ …
├─ characters/ the notebook: names here teach the
├─ places/ spellchecker and the codex
├─ front-matter/
│ ├─ 01-Manuscript-Format/ title page for a Word submission
│ ├─ 02-Paperback/ title, copyright, dedication
│ └─ 03-Ebook/ title, copyright, dedication
├─ back-matter/ acknowledgements, about the author, also by
├─ notes/
├─ research/
│ └─ 01-Sample-Output/
├─ template-sheets/ Character Sketch, Setting Sketch
└─ .grimoire/ session state, gitignored
└─ trash/ what you delete, still shown in the tree
The tree shows each of those as a section — Novel Format, Manuscript,
Characters, Places, Front Matter, Notes, Research, Template Sheets, Trash —
and every section and folder folds. A symbol beside each row is off to begin
with; turn tree icons on in Esc → Settings, or from the palette. The pane is headed
with the book's title and, when the window is tall enough to spare the rows,
an open spellbook with light rising from its spine.
A new book arrives with its shape already standing: three parts of nine
chapters, three scenes in each — twenty-seven chapters, eighty-one scenes, all
of them empty. The structure is a suggestion you rearrange; the writing is
never presumed. part_label in novel.toml is what this book calls its
largest division — Part to begin with, Act or Book if you prefer — and
the app says your word back everywhere it names one.
Front matter goes by edition. Pages in Manuscript Format go into the Word
export, pages in Ebook into the EPUB, and pages loose in front-matter/ into
both. The starter pages are compile: false until you set them to true.
Books from earlier versions are brought into this shape once, when they
open: Characters, Places and Research move out of notes/ into sections of
their own, missing sections are added, and [[links]] follow every move. Nothing
is deleted. A big book opens folded down to the first scene, so launching
shows you the shape rather than a hundred rows.
Scene metadata lives in YAML frontmatter:
---
title: Gravel
pov: Wren
status: draft
synopsis: Confronts the caretaker in the lot.
target: 1200
---
Frontmatter is round-tripped verbatim. Grimoire reads a few keys and never rewrites the block, so Obsidian and anything else can own fields it has never heard of.
Everything is one Esc away. The first screen is short, and the rest sits one
step down in a few small groups: This book, Writing tools, Settings and
Help & about. Whatever row you're on says what it does, in plain words, and
? opens the help page for it.
And every feature is explained inside: F1 (or ? outside the page) opens the
help on the topic for where you are, whether that's the outline, the page, the
Pomodoro or the export dialog. Type to search every topic. The menu, row by
row goes through every row, and Every key lists every key. About Grimoire…
(in Help & about) says which version you're running, and who made it
(grimoire --version from a terminal).
| Key | |
|---|---|
Esc | the menu, from anywhere: find anything, this book, the writing tools, export, a new book or another one, settings, help, and Quit Grimoire at the bottom. Esc again closes it; with a note or a scene open beside, the first Esc closes that |
F1 · ? | the help — every feature explained, opened on the topic for where you are. ? works wherever you aren't typing; on the page it's a question mark |
Ctrl-K | find anything — every action, scene, note and theme by name, with its key |
Tab / Shift-Tab | cycle panes — tree, editor, the open note, Pomodoro, music |
↑ ↓ · j k | move in the tree |
Enter · Space | fold or unfold a section or folder · open a scene |
→ l / ← h | expand / collapse, or jump to parent |
n | new scene — at the end of the selected chapter (a selected part's last chapter); in another section, a note, document or sheet there |
c | new chapter — named for you ("Chapter Two"), at the end of the part you're in |
p | new part — named for you ("Part Two", or "Act Two" if part_label says so), at the end of the manuscript |
N | new folder beside the selected one — outside the manuscript; in it, a chapter or part |
r | rename what's selected — the file is renamed to match and keeps its place |
d | delete what's selected — asks first, then moves it to .grimoire/trash |
Ctrl-Z Ctrl-Y (in the tree) | undo · redo a delete, rename, move or new item — a delete comes back from the trash to where it was |
Alt-↑ Alt-↓ · K J | move what's selected up or down — a scene or folder crosses chapters and parts at the ends, a section changes places with its neighbour; dragging a row in the tree does the same |
Ctrl-D) hides everything but the prose: centred, no
frame, a quiet status line. Esc still opens the menu.%% like this %% (Obsidian's comment
syntax, across lines if you like) and TK are dimmed as you write, left out
of every word count, compile and export, and kept on disk exactly as typed.
Ctrl-T lists them all.sprint 212/500 · 14:32. A scene's
target: shows as progress in the editor's title.Space pauses, ← → skip, Esc stops. It uses a
natural Piper voice if you have
one, or your computer's own (the Mac and Windows voices, Speech Dispatcher or
eSpeak on Linux). Nothing leaves your computer.v in the tree): another scene, read-only, next to the
one you're writing, for continuity.Changes made elsewhere are never overwritten. Grimoire looks at the book on disk every couple of seconds. An edit from Obsidian, a sync app or the phone is taken in; if you had unsaved words in that scene too, they're kept beside it as Scene (from this-computer, date) — a parked copy — and neither version is lost. Scenes added, moved or deleted elsewhere show up by themselves. A file that isn't UTF-8 opens read-only and is never rewritten.
Autosave. A scene is written two seconds after you stop typing, and
never sits unsaved longer than twenty. Every write goes through a temporary
file, so a crash mid-save can't tear a scene in half. Closing the terminal
window, logging out or kill saves first; so does quitting.
Recovery. If a save fails (a full disk, a file another program has
locked) or Grimoire crashes, the words go to .grimoire/recovery/ and the
next launch offers them back beside the saved version — chosen with the
arrows and Enter, never by a stray key; declining puts them in the trash.
Undo. A word at a time, per scene, kept when you switch scenes. Typing over a selection replaces it; a paste is one step; a replace across the whole book is one step too.
Moves can't strand anything. A move that can't finish (a locked folder, a sync app holding a file) puts everything back, and anything a crash left mid-move reappears when the book opens.
History. Every scene keeps dated copies as you work — at most every five
minutes, plus how it was before today's first change and before anything
drastic — in .grimoire/history/, as plain Markdown. H lists them with a
word diff against now and restores any version (itself undoable).
Ctrl-W, Ctrl-E).~/.config/grimoire/dictionary.txt). Words you add go in dictionary.txt at
the book's root. On unless turned off (palette).[[links]] in your notes that pointed at them.b) shows a part as index cards chapter by chapter:
POV (each character in its own colour), status, synopsis, words against
target. p filters to one POV; s, e and v edit the card, changing only
that line of the scene's frontmatter. n adds a card, r renames one, d
sends one to the Trash, and < > move a card to try a scene somewhere else.Names from your notebook — note titles, their aliases:, the distinctive
words of a longer title — show in the accent colour as you write. Ctrl-O on
one opens that note beside the scene, with Appears in: every scene that
mentions it. Nothing extra is stored; it's all read from the files.
Esc › Export…): a Word document in standard manuscript
format, the same pages as a PDF, a print-ready paperback, an EPUB for
phones and e-readers, and Markdown — the whole book, chosen parts, or the
sample an agent asked for (the first N chapters, chapters X–Y, or the first
N words) — into exports/. Also grimoire export [--docx] [--pdf] [--paperback [--trim 6x9]] [--epub] [--md] [--parts 1,3] [--chapters 1-3 | --words 10000].Export compiles a submission manuscript in William Shunn's modern standard manuscript format by default:
Esc › Settings), "about 82,000 words" top right
(rounded to the nearest 100 for a story, 500 for a novella, 1,000 for a
novel), the title halfway down as you typed it, and your byline under it.Surname / KEYWORD / page top right — numbered from 1 on the
first page of text.#, and the manuscript ends with END.-- to an em dash, ... to an ellipsis — in every format, never
on disk.%% notes %% are removed, and a
TK stays visible — export lists every one before it writes anything.Surname_Title_Manuscript.docx,
plus the sample (…_Chapters-1-3).Manuscript look… changes the rest, saved in novel.toml under
[manuscript]: Modern (Times New Roman) or Classic (Courier, with
underlines for italics and typewriter quotes — "Shunn Classic"), US Letter or
A4 (UK and European agents), double or 1.5 spacing, chapter headings
(Chapter One, CHAPTER ONE, Chapter 1, 1, or the chapter's title),
first paragraphs indented or flush, END / THE END / nothing, the header's
keyword, and whether a spaced hyphen becomes an em dash (US) or a spaced en
dash (UK). Always follow an agent's own guidelines where they differ.
PDF comes from LibreOffice (free), which converts the Word file page for
page — Grimoire finds it on your PATH, in the usual install places, or as the
Flatpak (flatpak install flathub org.libreoffice.LibreOffice). Without it,
the export dialog says so and writes everything else.
Every edition is compiled the same way as the manuscript — empty chapters left out, the same typography, TKs kept and warned about, a Prologue under its own name — and laid out for its readers:
← → for the trim, or
grimoire export --paperback --trim 6x9): a print-ready interior, a DOCX
for Word plus a PDF when LibreOffice is installed. Trim 5×8, 5.25×8,
5.5×8.5 or 6×9, mirrored margins with KDP's gutter for the page count,
running heads (author on the left page, title on the right, none on chapter
openers), each chapter on a right-hand page a third of the way down with a
small-caps lead-in or a drop cap, justified and hyphenated text, a centred
ornament between scenes. [paperback] in novel.toml sets the font, size,
ornament and drop caps; its front matter comes from front-matter/Paperback
(or a title and copyright page are made for it).cover.jpg (or .png) to the book, or name one in
[ebook] cover, and it's the cover; a contents page follows the front
matter, as the Kindle store asks; [ebook] fills in the language,
publisher, ISBN, description, subjects, rights, publication date, and series
and number. It passes EPUBCheck.back-matter/Paperback only in the paperback, in back-matter/Ebook
only in the EPUB, and loose ones in both. New books start with the three,
compile: false until they're written..grimoire/resume.md remembers the scene and paragraph you were
at, so opening the book on any computer the folder reaches lands you there.Vertical movement in the editor is visual, not logical — Down moves one screen row inside a wrapped paragraph rather than jumping the whole paragraph, which is the only behaviour that feels right for prose.
Grimoire accepts Ctrl or Cmd, and the status bar labels whichever your
terminal can actually deliver. Cmd only reaches a terminal application through
the Kitty keyboard protocol — Ghostty, Kitty, WezTerm and foot support it,
Apple Terminal cannot send it at all. Ctrl always works.
A book is a folder, so any sync service carries it — OneDrive and iCloud Drive too. What Grimoire does about the ways syncing goes wrong:
Advice: keep the book folder available offline ("Always keep on this device" / "Make available offline"); don't put one book in two sync services at once; and let a service finish syncing before opening the book on another device.
What each service calls its conflict copies (Grimoire recognises them all):
| Service | Conflict copy |
|---|---|
| Dropbox | Scene (Ann's conflicted copy 2026-09-25).md |
| Google Drive | Scene (1).md — only a copy when Scene.md is beside it |
| pCloud | Scene (conflicted).md, Scene [conflicted].md |
| Box | Scene (1).md, Scene ([email protected]).md |
| OneDrive | Scene-LAPTOP.md |
| iCloud Drive | Scene 2.md |
| Grimoire itself | Scene (from laptop, 2026-09-25 14-02).md |
F9 anywhere, or t from the tree. Nineteen presets — Grimoire, Gruvbox
Dark, Nord, Dracula, Solarized Dark, Catppuccin Mocha, Tokyo Night,
Everforest, Lost Forest, Rosé Pine, One Dark, Monokai, Kanagawa, Ayu
Mirage, Night Owl, Material Palenight, Synthwave '84, GitHub Dark and
Rainbow — each row showing a strip of its colours, and j/k previews
each one live as you move, so you pick by looking rather than by name.
Enter keeps it, Esc puts back what you had. All of them are dark themes:
Grimoire draws on your terminal's own background.
Pick one to see the whole desk in it — or switch
the website itself, with t:
Rainbow isn't a flat palette. Everything the others draw in their accent — the focused border, titles, the progress bar, the word count — is painted as a diagonal sweep of the spectrum that flows round the wheel once every twelve seconds; the Visualizer's bars climb from red to violet; and its Pomodoro is a rainbow over the hills.
Lost Forest is the one written for this app rather than borrowed. It is
green-led on purpose: accent drives focused borders, pane titles, the
open-scene marker and the progress bar, so a cyan accent would make the whole
interface read cyan. Cyan is kept for the two places it stays rare — the
break-time moon and the flowers — with a warm rust for warnings, since an
all-green palette otherwise hides its own alerts.
The last entry is Custom…, which opens a swatch editor: twelve named roles (accent, text, dim, border, selection, warning, then the six the forest uses), each showing its colour block and hex. Type six hex digits and it applies the moment the sixth lands. It starts from whichever theme you were previewing, so you can pick the closest preset and adjust from there.
Below the swatches, Custom mixes and matches: pomodoro and visualizer
each borrow any preset's — Kanagawa's great wave with Synthwave '84's neon
grid, say — cycled with ← → and previewed in the pane under the tree as
you go. Entering Custom from a preset starts from that preset's world and look.
Saved to ~/.config/grimoire/theme.toml. Presets store only their name, so
they follow any future refinements; Custom stores every swatch.
It's a TUI, but the mouse works. Click a chapter to fold it, a scene to open it, anywhere in the prose to put the caret there. Click the Pomodoro to start the timer, or the music pane to play and pause. The wheel scrolls whichever pane is under the pointer without stealing focus.
Drag to select. Click and drag in the prose to select across lines;
Ctrl-C copies it (via pbcopy, wl-copy, xclip or xsel, whichever the
machine has). Any keystroke collapses the selection — it deliberately does not
delete it, because there is no undo yet and a stray key must never eat text.
Mouse capture does suppress the terminal's own drag-to-select. Grimoire's is
the replacement inside the prose pane; hold Shift while dragging if you want
the terminal's version anywhere else.
Below the manuscript tree is a small world, and the world is the timer.
The sun's position is the clock. F2 starts it; it crosses the sky over a
twenty-five minute writing session, so you read the time remaining off the
light instead of watching a number count down, and the ground beneath fills
in behind it. Paused, the sun waits, dimmed. Break time is night: the moon
rises and the world's night things come out.
Every theme has its own world. Lost Forest's glade and its rabbits (above, and for any custom palette); a wizard's tower for Grimoire, its windows lit at night; an autumn farm with a turning windmill for Gruvbox; snowy peaks and the aurora for Nord; a castle and its bats for Dracula; a lighthouse sweeping the sea for Solarized; two cats on a fence for Catppuccin; a skyline and its night train for Tokyo Night; a lake in the woods for Everforest; a blossom tree and a stone lantern for Rosé Pine; a ringed planet for One Dark; the desert for Monokai; the great wave for Kanagawa; hot-air balloons for Ayu Mirage; an owl, asleep until dark, for Night Owl; a reef for Palenight; a neon horizon for Synthwave '84, where the striped sun itself is the clock; a campsite for GitHub Dark; and a rainbow of fine ribbons standing in two clouds for Rainbow. All of them move slowly, if at all — this sits beside someone writing.
←/→ switches the pane to the Visualizer, which listens to whatever the
computer is playing — on a Mac (macOS 14.6+, once your terminal is allowed
under Privacy & Security › Screen & System Audio Recording › System Audio
Recording Only), and on Linux through PipeWire's pw-record or PulseAudio's
parec (set GRIMOIRE_MONITOR=<sink> to hear an output other than the
default). It too is drawn in each theme's own style — meter segments for
Gruvbox, pastel beads for Catppuccin, dotted frost over snowdrifts for Nord, a
neon skyline for Tokyo Night, a rolling wave for Kanagawa, a synthwave grid, a
mirrored prism for Rainbow — and it always names the song that's playing, in
its title or written along the bottom, cut to fit.
Music is off until you turn it on — from the menu (Esc → Settings → Turn music on)
or the palette. Setting a source up turns it on too. Four sources, chosen from
the menu (Esc → Settings → Music source) and remembered.
| Source | How it works | Setup |
|---|---|---|
| YouTube Music | drives th-ch/youtube-music's API Server | grimoire music-setup youtube-music |
| Spotify | drives the desktop app — AppleScript on macOS, MPRIS on Linux (not Windows yet) | nothing to do |
| Jellyfin | Grimoire plays it — your files, your server | grimoire music-setup jellyfin |
| Plex | Grimoire plays it — your files, your server | grimoire music-setup plex |
F7 opens it from anywhere. The top shows what's playing with a real progress
bar; below it are three tabs, switched with Tab:
↑↓ to browse,
Enter to jump to any song.Enter replaces the queue with a
playlist and starts it; a queues the whole thing after the current song.
/ searches every public playlist on YouTube Music; Esc brings yours back./, type, Enter. Enter on a result plays it now; a plays
it next. Songs and videos only.Everywhere in the player — and on the music pane when it has focus: space
pause · ← → seek 10 s · [ ] previous / next · s shuffle · r repeat ·
+ - volume · l like · Esc close. The player shows repeat, shuffle,
volume and like under the progress bar, the pane shows ↻ (repeat all), ↻1,
⇄ and ♥ beside the time, and each key says what it did — "repeat: one",
"volume 70" — or why the player refused it.
How playlists work, since the API Server has no "play playlist" call: Grimoire reads the songs from YouTube Music's public web listing — so the playlist has to be public or unlisted, and a private one tells you so — then queues them in the app one at a time, first song first so the music starts straight away. Playlists past 300 songs are cut there. Queue browsing also works for Jellyfin and Plex; Spotify gets the controls but doesn't share its queue.
The split matters. There is no official YouTube Music API, and anything that extracts stream URLs both violates the terms and side-steps the subscription you already pay for — so for YouTube Music and Spotify, Grimoire never touches audio. It presses buttons on a player you already run.
Jellyfin and Plex are the opposite case: your own files on your own hardware, no terms to violate and no subscription to bypass. So Grimoire plays those itself and nothing else has to be running.
Spotify needs no setup at all. Its Web API would mean OAuth, a registered
application and a refresh-token dance for the privilege of pressing pause. Both
platforms already expose the running player locally, so there is nothing to
sign into and no token to store. On Linux it wants playerctl. Windows has
no equivalent Grimoire can use yet, so Spotify is macOS and Linux only.
YouTube Music setup installs the app for you on all three. On macOS and Linux it asks whether the machine is x86 or ARM (Enter takes what it detects); on Windows the installer picks the right build itself, so it doesn't ask.
Jellyfin signs in with the same username and password you use for the web
UI — no hunting through the dashboard for an API key. Plex needs an
X-Plex-Token, and the setup flow tells you where to find it.
Audio playback is a default cargo feature. On Linux it needs ALSA headers
(libasound2-dev); build with --no-default-features to drop it and keep the
remote-control sources.
v0.2 (unreleased). Everything above: autosave, recovery, undo and history; the palette; find and replace; spellcheck and name drift; moving scenes; the corkboard; the codex; export; resume and writing sessions.
Limits: spellcheck is English only, and Spotify isn't supported on Windows.
cargo build --release
cargo test --workspace # the book on disk, the desk frame by frame, every theme's world
cargo install --path .
crates/grimoire-core/ the book on disk: project, editor, history, export, search, sync
crates/grimoire-app/ services for the phone app over the same core
apps/mobile/ the Android app (Tauri)
src/main.rs entry, event loop, key and mouse routing
src/app.rs state, focus, per-pane input; src/app/overlays/ one file per dialog
src/ui.rs rendering
src/scene.rs the Pomodoro timer; src/scenery.rs every theme's world
src/visualizer.rs audio capture and the analyser; src/viz_view.rs every theme's look
src/theme.rs presets, custom palette, load/save
src/music/ one file per music source, plus setup
site/ the landing page
The screenshots in this README are drawn by Grimoire itself, from a sample book, then painted to PNG:
GRIMOIRE_SHOTS=/tmp/frames.json GRIMOIRE_SHOTS_BOOK=~/shots-book \
cargo test --locked shots -- --ignored
(cd ~/shots-book && grimoire export --docx --pdf --paperback) # PDFs need LibreOffice
python3 tools/screenshots.py /tmp/frames.json assets/screenshots ~/shots-book/exports
Pillow and fontTools paint the frames; pdftoppm renders the manuscript and
paperback pages.
Bump version in Cargo.toml, add a matching section to CHANGELOG.md,
commit, then tag and push the tag:
git tag v0.2.0 && git push origin v0.2.0
The Release workflow (dist)
builds every platform and publishes the GitHub release with both installers;
installer-check then installs it with the one-liners on Windows, macOS and
Linux and runs it. Nothing is published unless every build succeeds.
packages builds the .deb and .rpm for x86-64 and ARM, attaches them to
the release, and installs each on a clean Debian, Ubuntu and Fedora to run it.
Then tools/winget.py <version> sends the release to winget.
The moving demo at the top is drawn by Grimoire itself, frame by frame:
GRIMOIRE_DEMO=/tmp/demo.json cargo test --locked demo -- --ignored
python3 tools/demo.py /tmp/demo.json assets/readme/demo
Issues and pull requests welcome.
A Week with Grimoire is a free, five-day curriculum that takes a class from "what's a terminal?" to a finished short story in a real manuscript. It comes in two parts:
Every page prints neatly as a handout. It's free to use, print, copy and adapt for your classes, commercial use included, as long as the credit stays. You never have to pay for it; if it helps your students, a donation is appreciated.
Grimoire is free, and a donation is never required. It's always appreciated, though, and it all goes toward Grimoire's development.
The same is in the app: Esc › Help & about › Donate…, or d in About Grimoire….
Another way to help: Grimoire comes from Catfinity Studios,
and we also make Catfinity, a cozy idle
cat RPG. It's free on iPhone
and Android,
and in the app, c in About Grimoire… takes you there.
Grimoire is free and open source, under the MIT License. Here's what that means in plain words:
The same is in the app: l in About Grimoire…, or Ctrl-K › License.
Copyright (c) 2026 Josh King.
H | the scene's history — every kept version, what changed, restore any |
b | the corkboard |
/ | find in the whole book |
Ctrl-F | find in the scene (Ctrl-F again: the whole book) · Tab to replace · Ctrl-R replace all |
Ctrl-W · Ctrl-E (in find) | whole words ↔ inside words · exact case ↔ any case (Alt-W / Alt-C too) |
Ctrl-Z Ctrl-Y | undo · redo (Ctrl-Shift-Z too, where the terminal can send it) |
Ctrl-X Ctrl-C | cut · copy the selection |
Ctrl-O | open the note for the name under the cursor beside the scene — again to put it away |
v (in the tree) | show the selected scene beside, read-only — Esc closes it, Enter writes in it |
Ctrl-D | focus mode — just the prose; again to leave |
Ctrl-T | notes & TKs — every %% note %% and TK in the book; type to filter, Enter to go there |
F8 | spelling suggestions for this word, or the next misspelling |
Ctrl-S | save now — autosave already does, two seconds after you stop typing |
Ctrl-Q · q in the tree | quit, saving everything first |
F2 F3 | start or pause the timer · reset |
F9 · t | themes |
← → | in the Pomodoro pane: switch between the Pomodoro and the Visualizer |
F4 F5 F6 | previous · play-pause · next (with music on) |
| (music pane) | the player's keys: [ ] track · space pause · ← → seek · r repeat · s shuffle · + - volume · l like · Enter the player |
F7 | the music player — queue, your playlists, search, and every control (also in the menu, or Enter on the music pane) |