Asi scrivener

install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/asi/skills/scrivener" ~/.claude/skills/plurigrid-asi-scrivener && rm -rf "$T"
manifest: plugins/asi/skills/scrivener/SKILL.md
source content

Scrivener: Project Format, Data Model & Programmatic Access

Trit: -1 (MINUS - validator/extractor) Color: #E91A2F (Character Notes red)

When to use this skill

  • Parsing or inspecting
    .scriv
    project bundles (XML, RTF, metadata)
  • Querying a DuckDB export of Scrivener data (documents, content, labels)
  • Extracting manuscript text, character info, or synopses programmatically
  • Migrating projects across Scrivener versions or platforms (Windows ↔ macOS)
  • Building tools that read/write Scrivener project structures

File Format: .scriv Bundle

A

.scriv
project is a directory. On macOS it displays as a single file (document package); on Windows it's a regular folder.

MyProject.scriv/
├── Files/
│   ├── Data/
│   │   ├── <UUID>/
│   │   │   ├── content.rtf       # Document body (RTF format)
│   │   │   ├── notes.rtf         # Inspector notes (RTF)
│   │   │   ├── synopsis.txt      # Synopsis text
│   │   │   └── snapshot-*.rtf    # Version snapshots
│   │   └── docs.checksum         # Integrity checksums
│   ├── binder.autosave           # Auto-saved binder state
│   ├── binder.backup             # Binder backup
│   ├── search.indexes            # Full-text search index
│   ├── styles.xml                # Document styles
│   ├── version.txt               # Format version
│   └── writing.history           # Session word counts
├── <ProjectName>.scrivx           # Master XML: binder tree + metadata
├── Settings/
│   ├── recents.txt               # Recent documents
│   ├── ui-common.xml             # Cross-platform UI state
│   └── ui.ini                    # Platform-specific UI state
└── QuickLook/
    └── Preview.html              # Finder preview (macOS only)

Version History & Cross-Platform Migration

The ☼ project was created on Windows and has been migrated through multiple Scrivener versions:

VersionPlatformFormatNotes
Scrivener 1 (Win)WindowsXML
.scrivx
v1 + RTF
Original Windows port.
.scriv
is a visible folder.
Scrivener 1 (Mac)macOSBinary plist
.scrivproj
+ RTF
macOS only, different format entirely.
Scrivener 2 (Mac)macOSBinary plist → XMLTransitional. No Windows v2 existed.
Scrivener 3 (Win)WindowsXML
.scrivx
v2 + RTF
Current. Creator tag:
SCRWIN-3.x.x.x
Scrivener 3 (Mac)macOSXML
.scrivx
v2 + RTF
Current. Creator tag:
SCRMAC-3.x.x

Windows → macOS migration

  • .scriv
    folder on Windows is a regular directory; on macOS it becomes a document package (UTI:
    com.literatureandlatte.scrivener3.scriv
    )
  • Copy the entire
    .scriv
    folder to macOS and open with Scrivener 3 — it auto-upgrades
  • The
    Creator
    attribute in
    .scrivx
    preserves origin:
    SCRWIN-3.1.5.1
    means Windows Scrivener 3.1.5.1
  • ui.ini
    stores platform-specific UI state;
    ui-common.xml
    stores cross-platform state
  • QuickLook/ only generated on macOS
  • Line endings in RTF may differ (CRLF from Windows, LF on macOS) — both parse correctly

Version upgrade path

Windows v1 → Windows v3: Scrivener auto-converts on open. Creates backup of v1 project first. Binder structure, labels, statuses, and content preserved. Custom metadata fields may need manual re-setup.

.scrivx XML Schema

The

.scrivx
file is the master index:

<?xml version="1.0" encoding="UTF-8"?>
<ScrivenerProject Template="No" Version="2.0"
    Identifier="UUID" Creator="SCRWIN-3.1.5.1"
    Device="HOSTNAME" Modified="2025-03-14 22:15:28 -0600"
    ModID="UUID">
  <Binder>
    <BinderItem UUID="..." Type="DraftFolder" Created="..." Modified="...">
      <Title>Draft</Title>
      <MetaData>
        <IncludeInCompile>Yes</IncludeInCompile>
      </MetaData>
      <Children>
        <BinderItem UUID="..." Type="Text" Created="..." Modified="...">
          <Title>Chapter 1</Title>
          <MetaData>
            <LabelID>2</LabelID>
            <StatusID>-1</StatusID>
            <IncludeInCompile>Yes</IncludeInCompile>
            <SectionType>-1</SectionType>
          </MetaData>
        </BinderItem>
      </Children>
    </BinderItem>
  </Binder>
  <LabelSettings>
    <Labels>
      <Label ID="0" Color="0.993 0.227 0.172">Red</Label>
    </Labels>
  </LabelSettings>
  <StatusSettings>
    <StatusItems>
      <Status ID="1">To Do</Status>
      <Status ID="2">In Progress</Status>
      <Status ID="3">First Draft</Status>
    </StatusItems>
  </StatusSettings>
  <ProjectProperties>
    <ProjectTitle>My Novel</ProjectTitle>
    <FullName>Author Name</FullName>
  </ProjectProperties>
</ScrivenerProject>

BinderItem Types

TypeDescription
DraftFolder
Manuscript root (compile target)
ResearchFolder
Research materials container
TrashFolder
Deleted items
Folder
User-created folder
Text
Document (main content unit)
PDF
Imported PDF
Image
Imported image
WebArchive
Saved web page

Document Content Storage

Each document's UUID maps to

Files/Data/<UUID>/
:

  • content.rtf: Body text. Contains inline annotations via
    {\Scrv_fn=...}
    custom tags.
  • notes.rtf: Inspector notes pane.
  • synopsis.txt: Plain text synopsis (corkboard cards).
  • snapshot-YYYY-MM-DD-HH-MM-SS.rtf: Version snapshots.

Color Values

Colors in

.scrivx
are space-separated RGB floats (0.0–1.0):

# "0.952941 0.917647 0.329412" → #F3EB54
hex_color = f"#{int(r*255):02x}{int(g*255):02x}{int(b*255):02x}"

DuckDB Export Schema

When exported to DuckDB (via

build_sun_org.py
or similar):

documents

CREATE TABLE documents (
    project VARCHAR,          -- e.g. '☼'
    uuid VARCHAR PRIMARY KEY,
    title VARCHAR,
    parent_uuid VARCHAR,
    depth_int INT,            -- Nesting depth in binder
    item_type VARCHAR,        -- 'Text', 'Folder', etc.
    label_id INT,
    status_id INT,
    include_in_compile VARCHAR,
    binder_id VARCHAR,        -- Binder sort order
    section_type INT
);

content

CREATE TABLE content (
    project VARCHAR,
    uuid VARCHAR,             -- FK to documents
    body TEXT,                -- Full RTF body
    synopsis TEXT,
    notes TEXT,
    body_length INT,
    content_file_type VARCHAR
);

labels
,
statuses
,
comments

CREATE TABLE labels (project VARCHAR, label_id INT, name VARCHAR, color VARCHAR);
CREATE TABLE statuses (project VARCHAR, status_id INT, name VARCHAR);
CREATE TABLE comments (project VARCHAR, uuid VARCHAR, comment_text TEXT, position INT);

Additional tables:

collections
,
bookmarks
,
styles
,
section_types
,
projects
.

Common Queries

Manuscript text in binder order

SELECT d.uuid, d.title, c.body, c.synopsis
FROM documents d
JOIN content c ON d.uuid = c.uuid AND d.project = c.project
WHERE d.project = '☼'
  AND d.item_type = 'Text'
  AND d.include_in_compile = 'Yes'
  AND c.body IS NOT NULL
ORDER BY d.binder_id;

Find documents mentioning a character

SELECT d.uuid, d.title, d.binder_id, length(c.body) AS bodylen
FROM documents d
JOIN content c ON d.uuid = c.uuid AND d.project = c.project
WHERE d.project = '☼' AND c.body ILIKE '%edith%'
ORDER BY d.binder_id;

Strip Scrivener RTF tags

import re
clean = re.sub(r'\{\\Scrv_fn=.*?\\end_Scrv_fn\}', '', body)

RTF Content Notes

  • Inline annotations:
    {\Scrv_fn=footnote ...text... \end_Scrv_fn}
  • Comments: Stored in
    comments
    table with position offsets
  • Styles: Referenced by name from
    styles.xml
  • Images: Embedded as RTF
    \pict
    objects or referenced externally
  • Links: Internal links use
    scrivener://
    protocol with UUID targets

Character Data Extraction

Scrivener fiction templates include a Characters folder with sketch documents (Role, Occupation, Physical Description, etc.) — but these are plain RTF, not structured data. In the ☼ project, the Characters folder contains only a blank template.

Characters must be detected from prose:

import duckdb

con = duckdb.connect('scrivener.duckdb', read_only=True)

def character_chunks(char_name: str) -> list:
    return con.execute("""
        SELECT d.title, left(c.body, 500) as preview, d.binder_id
        FROM documents d
        JOIN content c ON d.uuid = c.uuid AND d.project = c.project
        WHERE d.project = '☼'
          AND c.body ILIKE ?
          AND length(c.body) > 50
        ORDER BY d.binder_id
    """, [f'%{char_name}%']).fetchall()

# ☼ characters: she, narrator, ack, edith, deb, rad, glen, will, hub

macOS vs Windows Differences

AspectmacOSWindows
.scriv
appearance
Document package (single file)Regular folder
Browse internalsRight-click → Show Package ContentsOpen folder normally
UTI
com.literatureandlatte.scrivener3.scriv
N/A
QuickLook previewGenerated automaticallyNot available
Spotlight indexingVia
mdls
metadata
Windows Search indexes RTF
Line endings in RTFLFCRLF
Creator tag
SCRMAC-3.x.x
SCRWIN-3.x.x.x

Verify it worked

After parsing a

.scriv
project:

  1. Check that the
    .scrivx
    XML parses and contains
    <Binder>
    with at least one
    <BinderItem>
  2. Verify UUID directories exist under
    Files/Data/
    for documents listed in the binder
  3. Confirm
    content.rtf
    files are valid RTF (start with
    {\rtf1
    )
  4. If using DuckDB export:
    SELECT count(*) FROM documents
    should match binder item count

What not to do

  • Don't modify
    .scriv
    files while Scrivener has the project open — it uses file locks
  • Don't assume synopsis or notes fields are populated — many projects leave them empty
  • Don't parse RTF with regex for anything beyond stripping Scrivener tags — use a real RTF parser for styled content
  • Don't assume macOS package structure on Windows —
    .scriv
    is just a folder there
  • Don't delete
    docs.checksum
    — Scrivener uses it for integrity verification on open

☼ Project Specifics

  • 949 documents: 900 Text, 42 Folders, 2 PDF, 2 Image
  • 432 manuscript chunks with body > 50 chars
  • Labels: Idea (#F3EB54), Chapter (#48B300), Scene (#468EFF), Notes (#E48738), Character Notes (#E91A2F)
  • Characters folder: Only a blank template (unfilled)
  • No synopsis metadata (1 boilerplate entry on Title Page)
  • 2 inline comments: Both authorial reminders
  • Origin: Created on Windows Scrivener, migrated through version updates

References

GF(3) Triads

scrivener (-1) + catcolab-schemas (+1) + database-design (0) = 0
scrivener (-1) + build-sun-org (+1) + duckdb-ies (0) = 0