Scrivener Compile
You help the writer turn a .scriv project into a single finished document —
the Compile step, where the Draft's documents are assembled in binder order
into a manuscript. Compile is read-only for the project: it reads the binder
and writes a new output file; it never mutates the .scriv.
This is the place to get a structured manuscript: titles become headings, the documents flow in order, and items flagged out of the compile are skipped. For the raw words of one document (no structure), route to scrivener-extract.
When to use this skill
- "Compile the draft to Markdown."
- "Produce the manuscript as one file."
- "Export the book as docx / epub / pdf." (planned — engine-gated)
- "Compile just the first act / this folder."
- "Compile to Fountain." (planned)
- "Build a table of contents / front matter into the compile." (planned)
Compiling to Markdown or plain text (available now)
compile assembles the Draft (the DraftFolder, whatever it is renamed to) in
binder order. It turns each item's title into a heading by its depth (a
top-level item → #, its child → ##, and so on) and honors
IncludeInCompile — items flagged out are skipped.
# Compile the whole Draft to Markdown (default)
python3 ${CLAUDE_PLUGIN_ROOT}/tools/scrivener/cli.py compile \
--to md --project "<path.scriv>"
# Compile to plain text
python3 ${CLAUDE_PLUGIN_ROOT}/tools/scrivener/cli.py compile \
--to txt --project "<path.scriv>"
# Compile only one container (e.g. a single Part/folder) by UUID
python3 ${CLAUDE_PLUGIN_ROOT}/tools/scrivener/cli.py compile \
--to md --group <uuid> --project "<path.scriv>"
Output is JSON by default (the assembled document plus a manifest of which items
were included or skipped). Add --format text for the assembled document alone.
Items with no body text (folders, empty documents, Image items) contribute their
title heading but no paragraph text; that is normal, not an error.
Titles are not unique. When the user names the group to compile, run find
(see scrivener-inspect) first and pass the UUID to --group if more than one
item matches.
The compile model is bounded — say so
Scrivener's real Compile binds each document's section type to a section
layout (from a chosen compile Format), and the layout is what controls
title prefixes/suffixes, numbering (Chapter <$n>), separators, page breaks, and
heading levels. Those layout definitions do not live inside the .scriv —
Settings/compile.xml stores only the section-type → layout-ID mapping; the
actual definitions live in app-level stock Formats / .scrformat files outside
the project.
Be honest with the writer: because the definitions are external, a faithful
compile is bounded and approximate. The v0.1.0 compile:
- assembles in binder order, honors Include-in-Compile, and maps title → ATX heading by binder depth — a sensible, predictable approximation;
- does not yet read
compile.xml, apply section-type → layout, add title prefixes/numbering, insert separators, or run compile-time replacements.
If the user expects the exact output of a specific Scrivener compile Format, tell
them this toolkit approximates it rather than reproducing the external layout
definitions. See references/compile-model.md for the full inputs and the
bounded-approximation note.
Rich formats are engine-gated (planned)
Markdown, plain text (and, planned, HTML) are produced with the Python standard library — always available. Richer outputs require an external engine and are planned, gated, and degrade gracefully when the engine is absent:
| Output | Engine | Status |
|---|---|---|
--to md / --to txt |
stdlib | ✅ available now |
--to html |
stdlib | 🔜 planned |
--to docx / --to odt / --to epub |
pandoc | 🔜 planned (needs pandoc) |
--to pdf |
LaTeX (pdflatex) or native print | 🔜 planned (engine-gated) |
--to fountain |
stdlib (scripts) | 🔜 planned |
When asked for a planned format, say it isn't in the CLI yet and offer the closest path: compile to Markdown now, then convert with pandoc/LaTeX yourself, or wait for the gated engine support. Never claim a docx/epub/pdf compile succeeded when the engine isn't wired up.
Section-type → layout is on the roadmap
Mapping section types to layouts (compile-format list|show|assign-layout),
choosing a Format, and per-type title/numbering/separator behavior are
planned, not in the CLI yet. The primary end-to-end workflow — set section
types, then compile — is two skills today: assign section types with
scrivener-metadata, then run compile --to md here. The section types are
read and reported, but the v0.1.0 compile does not yet vary layout by type.
Safety
Compile is read-only — it writes a new output file and never modifies the
.scriv, so no backup or snapshot is taken. Even so, remind the writer to
close the project in Scrivener and let cloud sync (Dropbox/iCloud) finish
before compiling a live project, so you read a consistent on-disk state.
docs.checksum mismatches are advisory and never block a compile.
Toolkit support
| Capability | Status |
|---|---|
compile [--to md|txt] [--group <uuid>] (binder order; titles → headings by depth; honors IncludeInCompile) |
✅ available now |
compile --to html (stdlib) |
🔜 planned |
compile --to docx|odt|epub (pandoc) |
🔜 planned |
compile --to pdf (LaTeX / native print) |
🔜 planned |
compile --to fountain (scripts) |
🔜 planned |
Read compile.xml; section-type → layout mapping |
🔜 planned |
compile-format list|show|assign-layout (read/select/assign Formats) |
🔜 planned |
| Separators (before/between/after) | 🔜 planned |
Title prefix/suffix + numbering (Chapter <$n>) |
🔜 planned |
| Front / back matter | 🔜 planned |
| Compile-time replacements (incl. regex) | 🔜 planned |
Placeholder substitution (<$projecttitle>, <$author>, <$n>…) |
🔜 planned |
Table-of-contents generation (<$toc>) |
🔜 planned |
| Filtering by label / status / collection | 🔜 planned |
Authoring new Formats/Layouts in a WYSIWYG designer is out of scope — the toolkit reads/selects/assigns existing Formats; it does not reproduce the visual Format Designer.
Related skills
- scrivener-metadata — assign section types (the input the planned section-type → layout mapping will key on); do this before compiling.
- scrivener-extract — raw per-document text (one doc, subtree, all) with no binder structure; use it when you want words, not a manuscript.
- scrivener-styles — named Styles that compile as markup (prefix/suffix); what gets emitted around styled ranges on compile.
- scrivener-inspect —
outline,read,find; usefindto resolve an ambiguous group title to the UUID you pass to--group. - scrivener-scriptwriting — script mode + Fountain I/O, the home of the
planned
compile --to fountain. - scrivener-format — the
.scrivpackage +compile.xmlreference these notes cite.