SuperAPI AI Directory

scrivener-search

Office & productivity

View repository

Updated 10-16 05:06

About this skill

Scrivener Search

You help the writer locate text across an entire Scrivener project and (once it ships) replace it. Search is read-only and safe to run anytime. Replace — when available — rewrites content and is irreversible inside Scrivener, so it carries the full write-safety contract.

When to use this skill

  • "Find where I mention the lighthouse" → full-text search.
  • "Search the project for 'protagonist'" → search across fields.
  • "Which docs talk about the inciting incident?" → search, return the matching documents.
  • "Rename Sarah to Sara everywhere" → 🔜 planned project-replace; for now do single-document edits via scrivener-edit, or wait for the roadmap command (see below).
  • "Find duplicate scenes" → 🔜 planned find-duplicates.

Toolkit support

Capability Status Command
Full-text / field search with snippets ✅ available search <query> [--fields …] [--regex]
Global find/replace (whole project) 🔜 planned project-replace
Per-document find/replace 🔜 planned replace (use scrivener-edit set-text today)
Saved searches 🔜 planned search-saved
Detect duplicate documents 🔜 planned find-duplicates
Richer operators (whole-word, exact, all/any) & scopes (draft, exclude-trash, compile-included) 🔜 planned extra flags on search

Only search exists in the CLI today. Treat everything marked 🔜 as roadmap: describe the workflow, name the closest available command, and do not pretend to run it.

Searching (available now)

Run the search command against the project. Output is JSON by default; add --format text for a readable list.

python3 ${CLAUDE_PLUGIN_ROOT}/tools/scrivener/cli.py search "lighthouse" \
  --project "<path.scriv>" --format text

Each match returns the document uuid, its (possibly adaptive) title, the field that matched, and a short snippet with ~30 characters of surrounding context. A document can appear once per matching field.

Choosing fields

By default search covers all four fields: title, text, synopsis, notes. Narrow it with --fields (comma-separated, no spaces) to cut noise:

# Only the body text and synopses
python3 ${CLAUDE_PLUGIN_ROOT}/tools/scrivener/cli.py search "inciting incident" \
  --fields text,synopsis --project "<path.scriv>"

# Only titles — quick way to find a chapter by name
python3 ${CLAUDE_PLUGIN_ROOT}/tools/scrivener/cli.py search "Chapter" \
  --fields title --project "<path.scriv>"

Search is case-insensitive. text and notes are converted from RTF to plain text before matching, so RTF markup never leaks into your query or the snippet.

Regex search

Add --regex to treat the query as a Python regular expression instead of a literal string:

# Find any character name starting with "Mr" or "Mrs"
python3 ${CLAUDE_PLUGIN_ROOT}/tools/scrivener/cli.py search "Mr?s?\.? [A-Z][a-z]+" \
  --regex --fields text --project "<path.scriv>"

Without --regex the query is matched literally (special characters are escaped for you). Quote the whole pattern so the shell does not interpret it.

Reading results

  • Use the returned uuid with scrivener-inspect (read <uuid>) to open a matching document in full.
  • Use the uuid for any mutating command — titles are not unique, so resolve to a UUID before editing.
  • If the user wants counts ("how many times do I say X"), note that search reports one snippet per field, not a per-occurrence count; for word frequency use scrivener-stats.

Replace (planned — read this before promising it)

replace (per-document) and project-replace (global) are on the v0.1.0 roadmap and are not in the CLI yet. When discussing them:

  • Replace is irreversible in Scrivener. It has no undo once the project is reopened. Always back up first (scrivener-integrity backup) and let the toolkit auto-snapshot affected documents.
  • The planned project-replace <find> <repl> will accept --affect scopes — titles, text, notes, synopses, custom-metadata — so the writer can rename a character in the prose without rewriting unrelated metadata.
  • An empty replacement deletes matches; with --regex a bad pattern can corrupt prose, which is exactly why backup + --dry-run + per-affect scoping matter.
  • Do this today instead: for a single document, use scrivener-edit set-text (token-preserving — it will not orphan comments, styles, links, or images). For a few documents, run search to find the UUIDs, then edit each one. Do not hand-edit RTF.

See references/search-and-replace.md for the full field/operator matrix (now vs planned) and the replace safety caveats.

Safety

  • Search is read-only and never modifies the project.
  • Before any (future) replace: close the project in Scrivener and let cloud sync (Dropbox/iCloud) finish. Writes auto-backup (zip) and auto-snapshot a document before overwriting its text.
  • docs.checksum mismatches are advisory — never treat them as corruption.
  • Titles are not unique — use a UUID for mutating commands when a title is ambiguous.
  • Never regenerate a rich document from plain text — replace should be token-preserving; opt into a destructive rewrite only after a snapshot and --allow-destructive.

Related skills

  • scrivener-inspect — open and read a matching document (outline, read, find).
  • scrivener-edit — change a single document's text now via set-text (token-preserving), pending replace/project-replace.
  • scrivener-metadata — labels, status, keywords, custom metadata. Searching by label/status/section-type is 🔜 planned (a scope/field on search); use labels/statuses to list definitions today.
  • scrivener-stats — word frequency and counts when you need occurrence numbers, not snippets.
  • scrivener-integrity — backup and verify before/after any replace.