Markus Michalski FAQ

StoryForge Author Profiles - Anti-AI Engine

Author profiles in StoryForge: structure of profile.md, writing discoveries in the database, how banned phrases and tics are enforced by the prose hook, study-author, language fields and troubleshooting.

StoryForge Author Profiles

Deutsche Version

Back to StoryForge Main Page


Overview

The author profile is the core of StoryForge. The chapter-writer loads it after the chapter writing brief as mandatory context before it writes a word. There is no technical gate for this: if no author exists yet, new-book merely suggests running create-author first. Without a profile the prose falls back to the generic AI style. The profile is what keeps your text from sounding like that.

An author profile is not a marketing persona. It is a set of parameters that determines how prose is built at the sentence, paragraph and dialogue level. The quality of your book depends directly on the quality of your profile.

A profile has two parts:

vocabulary.md is reference only. The hook does not read this file. You add banned phrases with write_author_banned_phrase or add_vocabulary_entry, see Writing Discoveries.


Why Author Profiles?

AI models have a default style: smooth elegance, abstract poetic nouns, little sentence variation, dialogue beats instead of subtext. That default sounds the same in every genre. The voice checker calls these "AI tells".

Author profiles are the countermeasure:

  1. Style parameters override the defaults.
  2. Banned phrases and patterns are reported by the hook right after every write, with a demand to fix them, not only in a check at the end.
  3. Style principles describe positively what makes the voice.
  4. Studied works provide concrete examples from analyzed texts.

The chapter-writer loads the profile after the brief. When it or you write a draft.md, the PostToolUse hook checks the text against the author banlist. Hook details are on the Technical Details page.


Storage

Author profiles live outside the plugin directory and so survive plugin updates:

~/.storyforge/authors/{slug}/
β”œβ”€β”€ profile.md            # frontmatter and style description
β”œβ”€β”€ vocabulary.md         # reference: preferred words, signature phrases
β”œβ”€β”€ studied-works/        # analyses from study-author
β”‚   └── analysis-{book-slug}.md
└── examples/             # your own sample texts (optional)

~/.storyforge/db/authors.db   # writing discoveries (author_discoveries)

Profile.md: Structure

Frontmatter

/storyforge:create-author asks for the values and creates the file. An example:

---
name: "Maja Sundberg"
slug: "maja-sundberg"
created: "2026-04-24"
updated: "2026-04-24"
primary_genres: ["contemporary", "mystery", "literary-fiction"]
narrative_voice: "third-limited"
tense: "past"
tone: ["melancholic", "atmospheric", "terse"]
sentence_style: "varied"
vocabulary_level: "moderate"
dialog_style: "naturalistic"
pacing: "slow-burn"
themes: ["memory", "loss", "the-sea-as-character"]
influences: ["Jon Fosse", "Siri Hustvedt", "Per Petterson"]
avoid: ["purple-prose", "info-dumps", "deus-ex-machina"]
author_writing_mode: "outliner"
native_language: "sv"
preferred_writing_language: "sv"
---
Field Meaning
name, slug display name and directory name
primary_genres genres the author writes in
narrative_voice first-person, third-limited, third-omniscient or second-person
tense past or present (memoir authors may also use mixed)
tone two to four values from the create-author list: sarcastic, dark-humor, atmospheric, lyrical, terse, warm, cold, irreverent, earnest, melancholic, playful, intense, detached, intimate (memoir has its own list)
sentence_style short-punchy, long-flowing, varied or minimalist
vocabulary_level, dialog_style vocabulary level (simple, moderate, advanced, archaic) and dialogue style (naturalistic, stylized, minimal, heavy)
pacing slow-burn, tension-driven, breakneck or literary
themes, influences, avoid themes, literary influences, what this author never does
author_writing_mode outliner, plantser or discovery, see Writing Modes
native_language, preferred_writing_language see Language Fields

Further fields update_author may write: pen_name, bio, website, social_media, mood, voice and the four quantitative targets dialog_ratio_target, fragment_ratio_target, single_line_paragraph_ratio_target and avg_sentence_length_target. study-author sets the latter from the analyzed text, and author-check uses them instead of its general defaults. Memoir authors additionally have subject_position, relationship_to_material and off_limits.

update_author rejects any other field, so nobody can smuggle arbitrary keys into the frontmatter.

Writing mode

author_writing_mode controls which path new-book and book-conceptualizer suggest and how extensively plot-architect works. The mode can be overridden per book, but the override only takes effect in some places. Everything else is under Writing Modes.

For memoir authors, create-author asks with the terms Structured, Accumulative and Discovery instead of Outliner, Plantser and Discovery Writer. When saved through update_author, these terms are normalized case-insensitively to the canonical values: Structured becomes outliner, Accumulative becomes plantser, Discovery stays discovery. The profile then holds the canonical value that every other skill also recognizes. An input that is none of these terms is stored unchanged.

Prose sections

After the frontmatter comes free prose. The tool create_author creates three sections with placeholder text for it: ## Writing Style, ## Signature Techniques and ## Voice Notes. You fill them by hand or through study-author. Further sections such as ## Narrative Approach, ## Tone & Atmosphere, ## Strengths, ## Deliberate Imperfections or ## Influences & Comparable Authors are a recommendation (the file templates/author-profile.md in the plugin shows them) that you add yourself when needed. The more concrete the description, the better the output:

## Signature Techniques

- **Object-as-emotion:** feelings are never named, they show in objects
  (the coffee goes cold, the key cuts into the hand).
- **Weather-as-chorus:** the weather comments on the scene, never mere backdrop.

Writing Discoveries

An author's writing discoveries live in the author_discoveries table of the database authors.db. There are three types:

Type Content Effect
donts banned phrases and patterns the hook reports as block
recurring_tics recurring tics collected from finished books the hook reports as block or warn, depending on marking
style_principles positive style patterns, preferred words not scanned, loaded by chapter-writer and chapter-reviewer through get_author

get_author returns them under writing_discoveries. Entries created with write_author_discovery can carry an origin (book, date), genres, universal and an example.

Adding entries

Way Effect
write_author_banned_phrase(author_slug, phrase, reason) creates a donts entry of the form `phrase` β€” reason with no origin. The hook searches the phrase as a plain substring, see below.
add_vocabulary_entry(author_slug, entry_type, text, source) banned becomes donts (a flat entry, with inflection and word boundary), preferred and phrase become style_principles
write_author_discovery(author_slug, section, text, book_slug, ...) writes to recurring_tics, style_principles or donts; optionally with example, genres, universal; for a memoir book, without example and without the name of a person from the book
/storyforge:chapter-voice-harvest adopts confirmed voice patterns from your review corrections as style_principles with a genre scope; never as donts or recurring_tics
/storyforge:harvest-author-rules carries over findings from a finished book
/storyforge:study-author writes style patterns from analyzed texts

All ways are idempotent: an entry with identical text is not created twice.

add_vocabulary_entry stores the text unchanged. A full sentence yields a sentence-length pattern that practically never matches. Enter short phrases.

create_author also seeds 19 default words from the anti-pattern catalog (see Anti-Pattern Catalog) as donts immediately on creation; from that moment they take effect like any other flat phrase and count as author_vocab_violation in the manuscript checker. vocabulary.md no longer lists these words, only a reference to the database. If the database write fails, the author is still created; the response from create_author then carries a warning field instructing you to add the words via add_vocabulary_entry.

Entry format

Banned phrases (donts) can take four forms. How exactly the hook searches depends on the form, and thus on the way the entry was created:

Form (way) Effect in the hook
flat phrase without backticks and bold, for example delve / delve into (add_vocabulary_entry with banned, migration from vocabulary.md) split into aliases at /, parenthetical notes such as (metaphorical) are removed. Single words match inflections and start at a word boundary.
backtick entry, for example `delve` β€” reason (write_author_banned_phrase) or `` `\bthe (room silence) received\b` `` if the text contains regex characters it is treated as a regular expression, otherwise as a plain substring with no inflection and no word boundary, case-insensitive
italic example phrase, for example *The room received it.*, in an entry with a ban cue (Never, Avoid, nie, kein and similar) searched as text, but only within the window before a recommendation marker (Render, Replace, Instead:, β†’ and similar), trailing punctuation is stripped. This window applies in the hook just as it does in the manuscript checker.
bold-titled line with no backtick and no italic example phrase after a ban cue, for example **word** (note) if the bold sits at the very start of the line, the bold-title fallback turns the text between the asterisks into a literal, a single word with inflection and a word boundary just like a flat phrase, a multi-word phrase matched exactly with word boundaries; if the title contains phrases in quotation marks, only those are searched; anything after the bold markup, such as the parenthetical note in the example, is not part of the title and is left out

The bold-title fallback only kicks in when the line starts directly with the bold markup. If other text precedes it, for example Avoid **word** entirely, the fallback does not recognize it and the entry stays without effect. This also covers bullets that were migrated from a vocabulary.md and kept their bold: if the bold sits at the start, such a migrated entry now acts like a flat phrase; if it does not, it stays without effect. Check such entries with get_author and recreate them as a flat phrase or backtick entry if needed.

The difference between the first two rows matters:

All donts hits have severity block.

Recurring tics (recurring_tics) are bullets with a bold title that carries the scannable phrase in quotation marks:

- **Vague noun "thing" as fallback** β€” make "doing a thing with his hand" concrete on sight.
- **"count" as time-marker tic** β€” *for a count of X* β€” max 2-3 per chapter.

The hook takes the quoted phrases from the title, otherwise patterns from the bullet text. Default is block. If [warn] or [advisory] appears in the bullet, the finding is only reported. An addition such as Max 2 per chapter, Max 2–3 pro Kapitel or Max einmal pro Kapitel allows up to that many hits per chapter. The limit is scaled by the length of the current draft relative to the chapter's target word count, so a half-finished draft is allowed correspondingly fewer hits. The manuscript checker applies the same distinction: a [warn]-tagged tic gets weight medium there instead of high, and a chapter that does not exceed the allowed number of hits produces no finding. Unlike the hook, which scales the limit by the draft's length against the target word count, the checker evaluates the limit per whole chapter.

Style principles are not machine-checked. They are narrative instructions: for each scene chapter-writer picks three fitting principles, quotes their example and applies them. Entries with genres apply only in books that have at least one of those genres. Entries without genres apply everywhere, with universal always. Memoir books additionally recognize the genre tag memoir: entries carrying that tag take effect in the author's memoir books and not in their fiction books. Whether the principles really show up in the draft is checked by /storyforge:author-check.

Who scans what?

Source Prose hook Manuscript checker (category)
donts, plain phrases block author_vocab_violation
donts, bold at the start of the line with no backtick/italic (bold-title fallback) block author_vocab_violation
donts, backtick and italic block author_rule_violation
donts, quoted phrase with a ban cue no author_rule_violation (only before a recommendation marker)
recurring_tics block or warn, with a per-chapter limit writing_discovery_violation, weight high or medium with [warn], with a per-chapter limit
style_principles no no
Global shape bans (anti-ai-patterns.md, section 11, six regex patterns) warn, for every author global_shape_violation
Global AI-tell words (anti-ai-patterns.md, section 1) warn, for every author (category ai_tell) ai_tell_violation

Global patterns only warn (hook) or count as advisory (checker). If you want to block one hard, add it as a backtick regex to the author's donts.

From section 11, only the lines that begin exactly with **Banned shape:** are enforced by machine. There are six: count-and-editorialize fragments (11.1), sentence as projectile (11.2), room as receiver (11.3), economic metaphors (11.4), body-part agency (11.6) and backward-negation loops (11.7). The variants Banned shape (trust-split) and Banned shape (density), as well as 11.5, 11.8 and 11.11 to 11.13, have no loaded regex. The chapter-humanizer covers them in part with its own density rules and judgment review, see Quality System.

Adopting an existing vocabulary.md

For enforcement only the database counts, not vocabulary.md. If you have banned words in such a file, scripts/migrate_vocabulary_to_db.py copies the Banned Words sections into the database (preview without a flag, --execute writes, repeatable). See Technical Details.


Hook and Author

The hook first finds which author belongs to a book through the line - **Author:** Name in the book CLAUDE.md. The name is turned into a slug, and a parenthetical note after it is ignored:

Display name Slug
Ethan Cole ethan-cole
Ursula K. Le Guin ursula-k-le-guin

If this line or the file is missing, the loader falls back to the author: field in the book README.md frontmatter. That field already holds the slug itself, with no conversion. create_book_structure writes this field for every newly created book, even when no author was passed; in that case it stays empty and counts as a missing value.

No tool writes the CLAUDE.md line: the book CLAUDE.md template carries only POV, Tense, Genre and Writing Mode under Book Facts, and init_book_claudemd passes no author. You can still add it by hand, for example in the Book Facts section; the loader searches the whole file for it, not only there, and it takes precedence over the README field. If both sources are missing, there is no author banlist. If authors.db is missing or the query fails, the author also counts as having no entries; on a query failure the hook writes a note to stderr.

The hook runs as PostToolUse, that is, after the file has been written. A block finding leads to exit code 2 in strict mode: the message goes back to Claude, and Claude has to fix the finding before continuing. In warn mode (linter_mode: warn in the frontmatter of the book CLAUDE.md) blockers are only printed, for the whole book, not for individual patterns. More: Technical Details and Configuration.

If a pattern is too sharp for a single book, remove the entry from the author's writing discoveries rather than loosening the book's mode.


Study Author: Style Extraction

/storyforge:study-author <file> [author-slug] analyzes your own or other texts (PDF, EPUB, DOCX, TXT, MD) and carries style patterns into the profile. The skill rejects files over 50 MB. Texts over 200,000 words are not rejected: it then analyzes a sample from the beginning, middle and end. The skill refines an existing profile. If there is none yet, it first points to create-author, because a profile built from one foreign work would copy that author's signature too closely.

The flow in fiction mode:

  1. Input: file, author, source genres. If an analysis-{book-slug}.md already exists, the skill warns about duplicate discoveries.
  2. Checklist of positive markers: from the ## study-author: Positive Markers section of the author's genres and their tone values the skill assembles a checklist. The analysis starts only after you confirm it.
  3. Analysis: sentence length and variance, vocabulary, dialogue share and tags, paragraph structure, style markers such as metaphor frequency, filter words and adverbs.
  4. Analysis file under studied-works/analysis-{book-slug}.md.
  5. Update the profile: frontmatter fields and quantitative targets via update_author, found style patterns as style_principles, recurring habits as recurring_tics, patterns to avoid via write_author_banned_phrase. Deliberate idiosyncrasies from the "Deliberate Imperfections" section are stored as style_principles, explicitly not as recurring_tics, because tics get enforced. If a new finding contradicts an existing one, the skill asks.

In memoir mode the skill analyzes your own texts (journals, letters, old blog posts) to bring out the unguarded voice, and skips the profile gate.

For authors studied before the checklist existed, /storyforge:backfill-style-principles <author-slug> recovers positive patterns from the existing analysis files. The skill is idempotent. With /storyforge:migrate-source-genres you add missing genre tags.


Multiple Author Profiles

You can have as many profiles as you like:

~/.storyforge/authors/
β”œβ”€β”€ maja-sundberg/
β”œβ”€β”€ maja-sundberg-thriller/   # different rhythm for thrillers
└── test-voice/               # experimental profile

One author is chosen per book: the slug in the book frontmatter's author field, which create_book_structure always writes, or the line - **Author:** that you add to the book CLAUDE.md when needed and which takes precedence over the frontmatter field. You can remove an author together with their writing discoveries with /storyforge:delete-author. The skill refuses while books still reference the author, unless you force it.


Language Fields

Field Level Purpose
native_language author mother tongue (ISO 639-1), sets the language of explanations in chapter-proofreader
preferred_writing_language author default writing language, fallback when the book has none
language book the book's writing language, takes precedence

Example: Ethan Cole usually writes in English (preferred_writing_language: en), his mother tongue is German (native_language: de). The proofreader checks by English rules and explains errors in German. For existing profiles you set the fields with update_author(slug, "native_language", "de").


Anti-Pattern Catalog

StoryForge ships a catalog of typical AI tells at reference/craft/anti-ai-patterns.md. It serves three purposes:

The catalog only applies to books written in English (language from the language field in the book's README frontmatter); for any other language the catalog hits do not apply.

Typical tells: abstract emotion nouns ("tapestry of feelings"), journey metaphors, hedging ("it's worth noting"), repeated sentence openers, therapy speak ("held space"), symphony metaphors, strikingly eloquent teenagers, beats without function and scene endings that are too tidy.


Tips for Strong Profiles

  1. Specific over generic. The lists for tone and the other style fields are coarse. Precision comes from the prose sections: "melancholic, Nordic cool, the sea as a third character" beats a bare melancholic.
  2. Maintain the bans. Without entries in donts, the hook only has the global catalog. Start with the phrases that bother you in your drafts.
  3. Use studied works. A profile without analyzed works is an actor without rehearsals. Analyze one or two of your own or related works.
  4. Do not invent signature phrases. Add them only when they really occur in analyzed texts, otherwise they feel mannered.
  5. One profile per genre. If you write horror and romance, create two profiles.
  6. Profiles live. chapter-voice-harvest already learns from your corrections while you write; after each book also run harvest-author-rules so findings are enforced in the next book.
  7. Be careful with short bans. One-word bans like like, thing or way have legitimate uses. As a backtick entry `thing` even hits in the middle of something. Better create them as a tic with [warn] and a per-chapter limit, or as a regex with a word boundary (`\bthing\b`).
  8. Check the effect. /storyforge:author-check shows whether the positive style patterns arrive in the draft.

Troubleshooting

The profile has no effect while writing

The chapter writer produces generic text with words like delve or tapestry although a profile exists.

Possible causes:

  1. Neither the book CLAUDE.md nor the README.md yields a slug: the - **Author:** ... line is missing (no tool writes it automatically) and the author: field in the README frontmatter is empty or missing.
  2. The slug derived from the name does not match the directory ~/.storyforge/authors/{slug}/.
  3. The words are only in vocabulary.md, not in the writing discoveries. The file is not read. Migrate it or enter the phrases with write_author_banned_phrase.
  4. The database ~/.storyforge/db/authors.db is missing or unreadable.
  5. The hook is not running (setup not done, plugin not active). Check with /hooks.
  6. A backtick entry does not hit the inflection (`delve` does not find delving). Create a regex or a flat entry.
  7. A migrated entry with bold has neither a backtick nor an italic example phrase, and the bold does not sit at the start of the line β€” the bold-title fallback then does not recognize it.

With get_author(slug) you can see which writing_discoveries are actually stored.

The hook reports unexpectedly

The message reads something like Banned by author voice, but the phrase belongs to the intended voice. Remove the entry from the writing discoveries, or set linter_mode: warn for the book as an emergency override.

The voice check reports many AI tells despite the profile

More slips through in long passages. The hook only reports pattern hits, while the voice-checker also scores structures. Write scene by scene, and run the voice-checker or the chapter-humanizer after each scene if needed.


← Back to StoryForge Main Page