The author profile is the core of StoryForge. Without a profile, the plugin won't write. By design β an author profile is what keeps your text from sounding like generic AI output.
An author profile is not a marketing persona. It is a set of parameters that determines how prose is built at sentence, paragraph, and dialog level. The quality of your book depends directly on the quality of your author profile.
Sprint 1 update: An author's
vocabulary.mdis no longer just a soft reference for the voice-checker β it is now read by the PostToolUse hook live during writing as a hard-block source. Every word in the### Forbidden ...sections blocks the write attempt withexit 2. See Hook Integration below.
Author-wide Don'ts: Beyond
vocabulary.md, the hook now also reads## Writing Discoveries / ### Don'tsfromprofile.md. Patterns you place there as backtick regex (`\bthe (room|silence) (received|held)\b`) or italicized example phrases (*The room received it.*) block the write for every book by this author. Themanuscript-checkerscans the same section plusvocabulary.mdβ author-level rules no longer need to be duplicated into each book'sCLAUDE.md.
AI models have a "default style": light elegance, abstract poetic nouns, low-variance sentences, dialog-beats instead of subtext. This default sounds the same everywhere β whether horror or romance. The voice-checker calls it "AI tells".
Author profiles are the countermeasure:
When chapter-writer runs, it loads the profile first, always. Every prompt context contains the profile parameters. When a Write is attempted, the PostToolUse hook additionally checks against vocabulary.md β banned words are hard-rejected.
Author profiles live outside the plugin directory so they survive plugin updates:
~/.storyforge/authors/{slug}/
βββ profile.md # Main profile (YAML frontmatter + prose)
βββ vocabulary.md # Forbidden sections (hook banlist) + Preferred + Signature
βββ studied-works/ # Analysis results from imported PDFs/EPUBs
β βββ my-novel-2023.md
β βββ short-story-collection.md
βββ examples/ # Manual sample texts (optional)
βββ voice-sample-1.md
---
name: "Maja Sundberg"
slug: "maja-sundberg"
created: "2026-04-24"
updated: "2026-04-24"
primary_genres: ["contemporary", "mystery", "literary-fiction"]
narrative_voice: "third-person-limited"
tense: "past"
tone: ["melancholic", "understated", "coastal"]
sentence_style: "varied-short-to-long"
vocabulary_level: "moderate-with-regional-terms"
dialog_style: "naturalistic-with-dialect-markers"
pacing: "slow-build-with-occasional-sharp-accelerations"
themes: ["memory", "loss", "the-sea-as-character"]
influences: ["Jon Fosse", "Siri Hustvedt", "Per Petterson"]
avoid:
- "purple-prose"
- "info-dumps"
- "deus-ex-machina"
- "therapist-speak"
- "epiphany-moments"
author_writing_mode: "outliner"
native_language: "sv" # ISO 639-1: author's mother tongue (for chapter-proofreader explanations)
preferred_writing_language: "sv" # ISO 639-1: fallback when no book_language is set
---
Required fields:
| Field | Values |
|---|---|
name |
Human name of the author/persona |
slug |
URL-safe slug (filesystem name) |
narrative_voice |
first-person, third-person-limited, third-person-omniscient, second-person |
tense |
past, present, mixed |
author_writing_mode |
outliner, plantser, discovery |
Important optional fields:
tone β array of descriptors (3-5 recommended)sentence_style β "varied", "short-terse", "long-flowing", "mixed"vocabulary_level β "sparse", "moderate", "rich", "dense"dialog_style β "naturalistic", "stylized", "minimal", "dialectal"pacing β "tension-driven", "meditative", "action-heavy", "slow-build"themes β central thematic obsessionsinfluences β literary modelsavoid β what this author never doesnative_language β author's mother tongue (ISO 639-1, e.g. de, fr, sv) β determines the explanation language in chapter-proofreaderpreferred_writing_language β default writing language (ISO 639-1) β fallback when no book_language is set in the book frontmatterAfter the frontmatter follow structured prose sections:
## Writing Style
Maja writes with the economy of a poet and the rhythm of a song.
Her sentences alternate between 6-word fragments and 40-word arcs.
She never describes an emotion directly β she shows it through objects,
landscape, body posture.
## Narrative Approach
- **POV:** Third-person limited, deeply anchored in the POV character
- **Tense:** Past, except in memories β then italic present-tense inserts
- **Sentence style:** Varied. Short staccato sentences in conflict moments.
Long compound-complex sentences in reflective passages.
- **Dialog approach:** Naturalistic with regional markers (North Sea dialect).
## Signature Techniques
- **Object-as-emotion:** Feelings are never named, made visible through
objects (the coffee goes cold, the key cuts into the hand).
- **Weather-as-chorus:** Weather comments on the scene, never just backdrop.
- **Silence-heavy dialog:** Long pauses in dialog, marked by "β" or
action between two lines.
## Tone & Atmosphere
Melancholic but not depressive. The sea is always present β as comfort,
threat, mirror. Humor only dry, never silly.
## Strengths
- Atmosphere through omission
- Dialog that shows more than it says
- Regional authenticity without pastiche
## Deliberate Imperfections
- Likes to repeat "later" and "again" β not stylistic mistakes but
rhythm markers
- Short sentences at paragraph end are common: "That was all."
- Fragments as a stylistic device: "A boat. Far out. No light."
## Influences & Comparable Authors
- Jon Fosse (Septology) β for repetition and slow tempo
- Siri Hustvedt β for intellectual depth without didactics
- Per Petterson β for Nordic coolness and landscape prose
## Anti-Patterns
- **No interior monologues** that explain what just happened
- **No therapy speak** ("I feel exposed")
- **No epiphany moments** β characters never suddenly understand "everything"
- **No rhetorical questions** in narrator text
- **No abstract nouns**: journey, tapestry, realm, essence
This is the operationally most important file. Concrete words are defined here that get blocked or preferred. Since Sprint 1 it is read by the PostToolUse hook live as a hard-block source.
For the hook to find the banned words, they must sit under exactly one of these four ### Forbidden ... subsections (within any ## Banned Words ... header):
# Vocabulary β Maja Sundberg
## Banned Words β AI Tells
### Absolutely Forbidden
- delve / delve into
- tapestry (metaphorical)
- nuanced
- vibrant
- pivotal
- realm
- testament
- journey (metaphorical)
### Forbidden Hedging Phrases
- it's worth noting that
- arguably
- broadly speaking
- one might say
- to put it simply
### Forbidden Emotional Tells
- her heart raced
- a wave of emotion
- he felt the weight of
- she felt safe
- held space
### Forbidden Structural Patterns
- in essence
- at its core
- this underscores the importance of
- a key takeaway is
- from a broader perspective
## Preferred Words
Words this author actively uses. Preferred at word-choice conflicts.
### Everyday
- mug (always, not cup)
- boat (never ship, when small)
- path (never way)
### Regional markers (North Sea)
- moin (greeting)
- Schiet (mild)
- bΓΌschen (a little)
## Signature Phrases
Turns of phrase typical of this author. Used at most 2x per book
(otherwise becomes mannered).
- "...and then it was quiet."
- "That was that."
- "Not today."
Important: Sections outside the four official
### Forbidden ...subheadings are not recognized as a banlist by the hook. A## Preferred Vocabularysection next to## Banned Wordsis safe β words there are not accidentally blocked.
The hook supports two conventions per bullet:
delve / delve into β split into two separate patterns (delve and delve into)tapestry (metaphorical) β stripped, the pattern is just tapestry### Don'ts and ### Recurring TicsTwo more subsections under ## Writing Discoveries in profile.md feed the hook and the manuscript-checker with author-wide banlists:
### Recurring TicsPhrases the skill /storyforge:harvest-author-rules extracted from finished books. Each bullet has a bold title with a quoted phrase as the scannable pattern:
## Writing Discoveries
### Recurring Tics
- **Vague-noun "thing" as a fallback** β "doing a thing with his hand"
or similar constructions: concretize on sight.
- **"count" as a time-marker tic** β *for a count of X*, *a long count* β
max 2-3 per chapter.
The hook extracts the phrase in double quotes (or falls back to the bold title text itself when no quotes are present). The /storyforge:harvest-author-rules skill writes automatically in this shape.
### Don'tsForbidden shapes that apply to every book by this author. Format convention:
### Don'ts
- **Never use word-count meta-commentary** β *Two words. He had not used them often.* /
*One word. The same way he texted.* The narrator must not count spoken syllables.
- **Never personify rooms or silences as receivers** β
`\bthe (room|silence|quiet) (received|held|carried|absorbed)\b`
Pattern sources per bullet (evaluation order):
| Form | When extracted | Example |
|---|---|---|
| Backtick regex | always | `\bthe room received\b` |
| Backtick literal | always | `Two words.` |
| Double quotes | only with a ban cue (Never, Avoid, ...) |
"totally landed" |
Italic (*...*) |
only with a ban cue | *The room received it.* |
Trailing sentence punctuation (., ,, !, ?, ;, :) is automatically stripped from italic patterns so *The room received it.* also matches The room received it without complaint.
Format tip: The anti-pattern catalog
reference/craft/anti-ai-patterns.md(Section 11 β Elegant Abstraction Register) ships ready-to-use backtick regexes for the five most common AI tells. Copy them straight into your### Don'tsand both hook and manuscript-checker enforce them for every book by this author.
| Source | Hook (write-block) | Manuscript-Checker (post-draft) |
|---|---|---|
vocabulary.md ### Forbidden ... |
yes, severity block |
yes, category author_vocab_violation |
profile.md ### Recurring Tics |
yes, severity block |
yes, category writing_discovery_violation |
profile.md ### Don'ts |
yes, severity block |
yes, category author_rule_violation |
profile.md ### Style Principles |
no (prose-level rule) | no (prose-level rule) |
Catalog anti-ai-patterns.md Section 11 (shape regex) |
yes, severity warn (auto, every author) |
yes, category global_shape_violation, severity medium |
Style Principles are intentionally not machine-scannable β they are narrative instructions for chapter-writer and chapter-reviewer, not phrase banlists.
Catalog shape bans: The five+1 elegant-abstraction shapes from
reference/craft/anti-ai-patterns.mdSection 11 (word-count meta, sentence-as-projectile, room-as-receiver, economic metaphor, near-miss body, body-part anthropomorphisation) are active for every author automatically β no copy into### Don'tsrequired. Severity iswarn(hook) / medium (manuscript report). To hard-block a shape (Writefails), copy the regex from Section 11 into### Don'tsβ it then counts as user-asserted and blocks for that author.
Write on chapters/22-the-night-before/draft.md- **Author:** Ethan Coleethan-cole~/.storyforge/authors/ethan-cole/:
vocabulary.md β all ### Forbidden ... sectionsprofile.md ## Writing Discoveries / ### Recurring Tics β bold-title bullets with quoted phrasesprofile.md ## Writing Discoveries / ### Don'ts β backtick regex and italicized phrases (under a ban cue) from each bulletFor the hook to find the right author, the book CLAUDE.md must have a ## Book Facts section:
## Book Facts
- **Author:** Ethan Cole (Eddings-humor with Twilight-stakes)
- **POV:** Theo Wilkons (third-person limited)
- **Tense:** Past
The hook regexes on - **Author:** <name> and slugifies the name. Examples:
| Display name | Slug |
|---|---|
| Ethan Cole | ethan-cole |
| Maja Sundberg | maja-sundberg |
| Henri Delacroix | henri-delacroix |
| Ursula K. Le Guin | ursula-k-le-guin |
The bracketed annotation after the name is ignored.
Single words (no spaces, no hyphens) automatically match inflections:
| Pattern | Matched in prose |
|---|---|
delve |
delve, delved, delving, delves |
embark |
embark, embarked, embarking, embarks, embarkment |
vibrant |
vibrant, vibrants, vibrantly |
Logic: Single words with silent e (delve, embrace) use the stem without e (delv, embrac) plus \w*. Other single words use pattern + \w*. Leading word boundary in both cases β redelve does not match the delve pattern.
Multi-word phrases match exactly:
| Pattern | Match? |
|---|---|
it's worth noting that |
only the full phrase |
her heart raced |
only the full phrase |
Theo writes in the draft She delved into the box.:
StoryForge linter blocked this write:
[BLOCK] draft.md line 8: Banned by author voice
(author-vocab (Absolutely Forbidden)): 'delve'
Fix the blocking issues and try again. Set `linter_mode: warn` in the
book's CLAUDE.md frontmatter to override.
The model receives this message in stderr and must replace delve before the next write is accepted.
When a vocabulary pattern is too aggressive for a specific book:
### Absolutely Forbidden and move it to a separate notes section (e.g. ## Soft Watch) β hook ignores itlinter_mode: warn in book CLAUDE.md frontmatter β all block-severity findings downgraded to soft warnings (not selectively per pattern, but globally)More details: Quality System β Pre-Save Hook.
The skill /storyforge:study-author imports own works (PDF, EPUB, DOCX) and extracts style parameters automatically.
Sentence-length distribution
Vocabulary register
Signature phrases
POV patterns
Dialog proportion
Paragraph structure
# Studied Work: The Island at Night (2023)
## Style Parameters Extracted
### Sentence Length
- Mean: 16.3 words
- Median: 14 words
- StdDev: 9.8 words (high β human-typical)
- Range: 2-47 words
### Vocabulary
- 8,423 unique content words over 82,000 total
- Top 5 content words: "sea" (184), "light" (142), "mother" (127),
"always" (118), "again" (112)
- Dialect markers: "moin" (23x), "Schiet" (8x), "bΓΌschen" (11x)
### Filter Word Usage (per 10,000 words)
- saw: 12 (low)
- heard: 8 (low)
- felt: 15 (low)
- β Very restrained filter-word usage
### Dialog Proportion
- 23% dialog, 77% narration
- Dialog tags: 78% "said", 15% no tag, 4% "asked", 3% other
### Signature Phrases (>3x)
- "and then it was quiet" (6x)
- "that was that" (14x β strong signature)
- "not today" (4x)
- "the sea was [X]" (11x)
## Update to profile.md
- Adding signature_phrases
- Setting sentence_style: "varied-high-variance"
- Setting vocabulary_level: "moderate"
- Adding regional markers to preferred words
- Adding "felt"/"saw"/"heard" soft-cap (max 10 per chapter)
The skill writes these findings automatically to profile.md and vocabulary.md.
A user can have any number of profiles:
~/.storyforge/authors/
βββ maja-sundberg/ # For literary/contemporary
βββ maja-sundberg-thriller/ # For thriller (different cadence)
βββ ghostwriter-1/ # For client work
βββ test-voice/ # Experimental profile
One author per book (author_slug in book frontmatter, plus **Author:** line in book CLAUDE.md for hook integration). Can be changed per new book.
The field author_writing_mode controls which workflow is suggested automatically:
| Value | Effect |
|---|---|
outliner |
new-book proposes the full outliner pipeline |
plantser |
plot-architect switches to MVO mode (6 beats) |
discovery |
new-book skips plot-architect, suggests rolling-planner |
The author profile can be overridden per book β e.g. an outliner author writes an experimental novella in discovery mode.
Two fields control the language logic for language-aware skills like chapter-proofreader:
| Field | Level | Purpose |
|---|---|---|
native_language |
Author | Mother tongue β determines the explanation language in the proofreader |
preferred_writing_language |
Author | Default writing language β fallback when no book_language is set per book |
book_language |
Book | Authoritative per book β overrides preferred_writing_language |
Resolution order for writing language:
book_language (book frontmatter)
β preferred_writing_language (author profile fallback)
β "en" (global fallback)
Example: Ethan Cole normally writes in English (preferred_writing_language: en) and has German as his mother tongue (native_language: de). The chapter-proofreader checks grammar against English rules and explains errors in German β without each book needing to set this information again.
native_languageandpreferred_writing_languageare collected during the/storyforge:create-authorworkflow Phase 1 and persisted via MCPupdate_author(). For existing profiles:update_author(slug, "native_language", "de").
Fictional author "Henri Delacroix" β Historical Mystery, France, 1920s.
---
name: "Henri Delacroix"
slug: "henri-delacroix"
created: "2026-04-24"
primary_genres: ["historical", "mystery"]
narrative_voice: "first-person"
tense: "past"
tone: ["wry", "world-weary", "ironic", "slightly-cynical"]
sentence_style: "long-flowing-with-sharp-short-punchlines"
vocabulary_level: "rich-period-appropriate"
dialog_style: "formal-with-class-markers"
pacing: "meditative-build-with-sudden-violence"
themes: ["lost-era", "class-tension", "self-deception"]
influences: ["Georges Simenon", "Graham Greene", "Patrick Modiano"]
avoid:
- "modern-slang"
- "anachronistic-references"
- "info-dumps-on-period"
- "first-person-present"
author_writing_mode: "outliner"
native_language: "fr" # ISO 639-1: mother tongue
preferred_writing_language: "fr" # ISO 639-1: writes in French
---
# Henri Delacroix
## Writing Style
First person, narrated retrospectively from a later time (usually 20 years
later). The narrator knows more than the character in the scene β but
holds it back until the right moment. Sentences can spread out like smoke
in a bistro and then end abruptly with a six-word observation.
## Narrative Approach
- **POV:** First person, strongly reflective
- **Tense:** Past, occasionally historical present in tension scenes
- **Dialog approach:** Formal, with clear class markers
(vouvoiement vs. tutoiement strictly observed)
## Signature Techniques
- **"I should have known..."-openings:** Retrospective narrator hints early
- **Object catalogs:** Scenes often begin with a list of 3-5 objects
in the room
- **Dialog-break:** Characters do not finish each other's sentences β they
suddenly throw in another topic
## Tone & Atmosphere
Wryness like an old cognac. Humor is there but dry. The world is
beautiful but unreliable. Violence comes suddenly but is not
celebrated β it is a cut, not an attraction.
## Deliberate Imperfections
- "I do not know why I..." as a phrase that occurs 2-3x per book
- Em-dashes (β) often for thought breaks
- Single-sentence paragraphs to close scenes, always 6-10 words
## Anti-Patterns
- NEVER modern psychology terms (trauma, triggered, boundaries)
- NEVER American idioms
- NEVER "it was the year 1924" (info-dump)
β Instead: weave in details from the year naturally (prices, brands,
newspapers)
Vocabulary for Henri Delacroix:
# Vocabulary β Henri Delacroix
## Banned Words β AI Tells
### Absolutely Forbidden
- trigger (as a verb)
- realm
- journey (metaphorical)
- cool (as adjective for calmness)
- processing (as mental processing)
### Forbidden Hedging Phrases
- arguably
- broadly speaking
- to put it simply
### Forbidden Emotional Tells
- "she was strong" β too modern
- felt safe (anachronistic)
- held space (anachronistic)
### Forbidden Structural Patterns
- in essence
- at its core
## Preferred Words
- coffee house (never cafΓ© when narrator looks back β period-typical)
- motor cab (never taxi)
- telephone exchange (for 1920s scenes)
## Signature Phrases (max 2x)
- "I should have known..."
- "The rain had already fallen by the time I..."
- "They used to say..."
StoryForge ships with a built-in anti-pattern catalog (reference/craft/anti-ai-patterns.md). The voice-checker compares every text against this list (soft, post-draft), the PostToolUse hook scans it as well β as warn severity (AI-tell '<word>' found).
Typical AI tells:
Promoting to hard-blocks: The global AI tells from
anti-ai-patterns.mdare surfaced by the hook as warn (not block). Two ways to promote them to hard-blocks:
- Vocabulary ban: Single words in
vocabulary.md ### Absolutely Forbiddenβ works with inflection matching (delveβdelved,delving).- Shape ban: Structural patterns (e.g. the five elegant-abstraction shapes from Section 11) in
profile.md ### Don'tsas backtick regex β works for whole phrase families via regex alternation.Both sources block the write and are visible to the
manuscript-checker. No more per-book duplication.
Specificity > Generality. "Melancholic tone" is weak. "Melancholic, Nordic-cool, focused on the sea as a third character" is strong.
Always fill ### Absolutely Forbidden. An empty vocabulary.md is as good as no profile β and the hook then has nothing to block.
Studied works are the booster. An author profile without studied works is like an actor without rehearsal. Import at least 1-2 of your own or stylistically related works.
Don't invent signature phrases β only use them when they actually occur in studied works. Artificial signature phrases become mannered.
One profile per genre. If you write horror and romance, make two profiles. Even if they map to you yourself β the writing style differs significantly.
Profiles live. After every book: update. New signature phrases? Preferred words that crept in? Add them. New banned words from beta feedback? Straight into ### Absolutely Forbidden.
Be careful with too-short banned patterns. One-word bans like like, thing, way have legitimate uses. If you put them in ### Absolutely Forbidden, the hook blocks every dialect-typical like β which gets annoying fast. Better to keep such words as soft patterns in the manuscript-checker (per-book CLAUDE.md with quote instead of backtick).
Symptom: Chapter-writer produces generic text with delve, tapestry etc. even though a profile exists.
Possible causes:
- **Author:** ... line β hook finds no slug~/.storyforge/authors/{slug}/vocabulary.md has no ### Absolutely Forbidden section (or other subheading name)Diagnose:
# Check slug resolution
~/.storyforge/venv/bin/python3 -c "
from pathlib import Path
import sys
sys.path.insert(0, '/home/<user>/projekte/storyforge')
from tools.banlist_loader import author_slug_from_book, load_author_vocab
book = Path('/path/to/book')
slug = author_slug_from_book(book)
print(f'Slug: {slug}')
patterns = load_author_vocab(slug) if slug else []
print(f'Patterns loaded: {len(patterns)}')
for p in patterns[:5]:
print(f' β {p.label!r}')
"
Fix per cause:
## Book Facts + - **Author:** <Name> to book CLAUDE.mdvocabulary.md section headings to ### Absolutely Forbidden etc./storyforge:setupSymptom: Write fails with Banned by author voice (...), but the phrase is part of the intended voice.
Fixes:
### Absolutely Forbidden## Soft Watch section (hook ignores)linter_mode: warn in book CLAUDE.md frontmatter (emergency override for the whole book)Symptom: Voice-checker reports high AI-tell density even though profile and hook are strong.
Cause: Scene-by-scene mode was off, user chose "full chapter". More slips through with long passages (hook only blocks pattern hits, voice-checker also checks structures).
Fix: