From asi
Parse Scrivener .scriv bundles, query DuckDB exports, extract RTF manuscript text and synopses, handle cross-platform migrations.
npx claudepluginhub plurigrid/asi --plugin asiThis skill uses the workspace's default tool permissions.
**Trit**: -1 (MINUS - validator/extractor)
Searches and navigates PDFs/DOCX/PPTX/Markdown documents, extracts tables/figures, builds wiki knowledge bases using retrieval, deep reading, and ingestion tools.
Creates, reads, edits, and analyzes .docx files using docx-js (JS), Python unpack/edit scripts, pandoc extraction, and LibreOffice conversions. Handles tracked changes and validation.
Creates, reads, edits, and analyzes .docx files using docx-js for generation, pandoc/Python for extraction, XML editing, tracked changes, and LibreOffice conversions.
Share bugs, ideas, or general feedback.
Trit: -1 (MINUS - validator/extractor) Color: #E91A2F (Character Notes red)
.scriv project bundles (XML, RTF, metadata)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)
The ☼ project was created on Windows and has been migrated through multiple Scrivener versions:
| Version | Platform | Format | Notes |
|---|---|---|---|
| Scrivener 1 (Win) | Windows | XML .scrivx v1 + RTF | Original Windows port. .scriv is a visible folder. |
| Scrivener 1 (Mac) | macOS | Binary plist .scrivproj + RTF | macOS only, different format entirely. |
| Scrivener 2 (Mac) | macOS | Binary plist → XML | Transitional. No Windows v2 existed. |
| Scrivener 3 (Win) | Windows | XML .scrivx v2 + RTF | Current. Creator tag: SCRWIN-3.x.x.x |
| Scrivener 3 (Mac) | macOS | XML .scrivx v2 + RTF | Current. Creator tag: SCRMAC-3.x.x |
.scriv folder on Windows is a regular directory; on macOS it becomes a document package (UTI: com.literatureandlatte.scrivener3.scriv).scriv folder to macOS and open with Scrivener 3 — it auto-upgradesCreator attribute in .scrivx preserves origin: SCRWIN-3.1.5.1 means Windows Scrivener 3.1.5.1ui.ini stores platform-specific UI state; ui-common.xml stores cross-platform stateWindows 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.
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>
| Type | Description |
|---|---|
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 |
Each document's UUID maps to Files/Data/<UUID>/:
{\Scrv_fn=...} custom tags.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}"
When exported to DuckDB (via build_sun_org.py or similar):
documentsCREATE 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
);
contentCREATE 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, commentsCREATE 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.
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;
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;
import re
clean = re.sub(r'\{\\Scrv_fn=.*?\\end_Scrv_fn\}', '', body)
{\Scrv_fn=footnote ...text... \end_Scrv_fn}comments table with position offsetsstyles.xml\pict objects or referenced externallyscrivener:// protocol with UUID targetsScrivener 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
| Aspect | macOS | Windows |
|---|---|---|
.scriv appearance | Document package (single file) | Regular folder |
| Browse internals | Right-click → Show Package Contents | Open folder normally |
| UTI | com.literatureandlatte.scrivener3.scriv | N/A |
| QuickLook preview | Generated automatically | Not available |
| Spotlight indexing | Via mdls metadata | Windows Search indexes RTF |
| Line endings in RTF | LF | CRLF |
| Creator tag | SCRMAC-3.x.x | SCRWIN-3.x.x.x |
After parsing a .scriv project:
.scrivx XML parses and contains <Binder> with at least one <BinderItem>Files/Data/ for documents listed in the bindercontent.rtf files are valid RTF (start with {\rtf1)SELECT count(*) FROM documents should match binder item count.scriv files while Scrivener has the project open — it uses file locks.scriv is just a folder theredocs.checksum — Scrivener uses it for integrity verification on openscrivener (-1) + catcolab-schemas (+1) + database-design (0) = 0
scrivener (-1) + build-sun-org (+1) + duckdb-ies (0) = 0