All thresholds are tunable config, never hard-coded. Change any of them live with
/set <key> <value> (persisted), or edit config/settings.yaml.
| Key | Default | Does |
|---|
mode | article | What new creates: book or article |
autonomous | true | Never pause for review; commit the best-judged draft, auto-repair contradictions |
num_chapters | 8 | Default book length |
num_sections | 6 | Default article length |
max_revisions | 2 | Revision rounds per unit before escalating (manual) or committing best (autonomous) |
consolidate_every | 5 | Chapters between canon consolidation passes |
escalate_below_confidence | 0.5 | Manual mode pauses for review when the critic’s confidence drops below this |
escalate_on_contradiction | true | Manual mode pauses when consolidation finds a contradiction (autonomous auto-repairs) |
max_run_tokens | 0 | Run budget kill-switch: a hard ceiling that pauses cleanly when total tokens cross this. 0 = unlimited, and in budget mode lets the auto-scaled per-unit budget apply; an explicit value always wins |
cost_mode | budget | budget pins the spend-heavy knobs lean and routes the judgment nodes to a cheaper flash model to target ≤100k tokens/article; standard is the old unpinned behavior (see Cost) |
budget_tokens_per_unit | 20000 | Budget mode only: the session token budget auto-scales as ~this × unit count + a fixed overhead, so a full piece finishes rather than pausing mid-run |
| Key | Default | Does |
|---|
humanize | true | Surgical AI-tell removal on every committed unit |
divergent_drafts | 2 | First-draft variants sampled at different temperatures; the best is refined |
divergent_skeletons | false | Draft the variants SHORT, judge, then expand only the winner - cuts discarded-draft tokens ~60% (opt-in; a skeleton reveals less than a full draft) |
tournament_judge | true | Pick the best divergent draft by reading them side by side (vs. scalar self-scores) |
min_insight | 3 | Approval requires critic insight ≥ this (1–5); generic-but-correct drafts get a sharpening note |
verify_claims | true | Check each [N]-cited claim against its source; unsupported = blocking under deep research, a nit otherwise |
article_cohesion | true | Whole-article smoothing pass before References (guarded against content loss) |
book_cohesion | true | Book: a deterministic cross-chapter repetition report after assembly (a detector that feeds a targeted revise, not a rewriter) |
table_read | true | Automatic skeptical cold read after a run finishes (report only) |
table_read_revise | false | Autonomous: apply the reader’s single top fix as one bounded revision |
rank_references | true | Build one end ## References list ranked by influence (0–100): weighted cite count + title overlap with the thesis/headings, dated |
strip_inline_citations | true | After scoring, strip inline [N] markers from the body so prose reads clean and all sourcing lives in the end list |
skill_duels | false | A/B-test a learned skill by writing one extra draft with the candidate skill held out and letting the critic judge the lift - the causal efficacy signal. Opt-in (adds a draft while a skill is undecided) |
skill_distill | false | After learning, retire near-duplicate skills (keep the best-scoring one) so retrieval stays sharp. Non-destructive |
watch_blocking | true | Watch-list violations block only the CLEAR, CONCRETE ones (borderline/stylistic → nit); false makes them fully advisory |
| Key | Default | Does |
|---|
use_researcher | true | Web research per unit; off = uncited stats become blocking |
search_provider | duckduckgo | Web search backend: duckduckgo (free, default) or firecrawl (needs FIRECRAWL_API_KEY; also switches deep-research page scraping to Firecrawl). A missing key degrades back to duckduckgo |
deep_research | false | Multi-query fan-out + full page-text fetch + cross-source synthesis (layers on use_researcher) |
verify_excerpt_chars | 6000 | Per-source characters the claim verifier reads (the full fetched page). Verifying against a shorter excerpt can flag true claims as fabrication, so this must cover the whole page; 0 = no cap |
use_images | true | Generated SVG diagram per unit (Wikimedia Commons first for illustrated topics) |
diagram_engine | auto | Diagram layout: auto/builtin use the zero-dependency built-in engine (the default - it measures text and lays figures out compactly); d2 opts into D2 + ELK (needs the d2 binary; tends to render wide) |
use_embeddings | false | Semantic skill retrieval via sentence-transformers (lexical otherwise) |
The promotion layer (see the seo and promote commands).
Everything here produces local files only - a report, keywords.json, and promo/*.md drafts;
nothing is ever posted or scheduled anywhere.
| Key | Default | Does |
|---|
seo_keyword | “ (infer) | Pin the primary keyword to target from the start - it’s threaded into the writer/critic so the piece is written for it (title, opening, headings), and applied again post-validation. Empty = infer after writing |
auto_promote | true | After a finished write, automatically run the SEO audit + keyword pack and generate the promo pack. Local artifacts only - it never edits the manuscript body and never posts anything |
The craft engine (plan §22) and the compositor (plan §23). All clamped to their known sets;
leave them empty and the agent infers sensible defaults (the historical “researcher voice”
nonfiction default is preserved byte-for-byte).
| Key | Default | Does |
|---|
register | “ (infer) | Pin a genre register - one of 11 (nonfiction, technical, literary-fiction, genre-fiction, academic, journalism, copywriting, business, poetry, screenplay, children); it inverts the anti-slop rules, structure, and citation style per genre. Empty = infer from the topic/angle |
field | “ (register default) | Pin a structural field template within the register |
citation_style | “ (register default) | influence · numeric · apa · mla · chicago · ap · none |
craft_passes | true | Run the surgical show-don’t-tell / de-passive passes on each committed unit |
persona | “ (none) | A voice manner layered over the register - one of 46: 18 archetypes (e.g. wry-skeptic, warm-mentor, hard-boiled-minimalist, lyrical-maximalist, deadpan-technical, firebrand-essayist) + 28 public-domain manners (e.g. shakespearean, austen-ironic, twain-vernacular, wildean, dickensian, whitmanesque). Dropped + logged if it clashes with the register |
emotion | “ (none) | A per-run emotional target - one of 12 (fear, anger, grief, joy, love, shame, tension, hope, disgust, surprise, jealousy, pride); wires an anti-cliché deny-list into the detector + a show-don’t-name cue |
Off by default - when off, behavior is byte-identical to the fixed pipeline, which stays the fallback.
| Key | Default | Does |
|---|
agentic | false | Drive each unit through the controller (it may gather research / read canon before drafting) instead of the fixed order |
agentic_policy | default | Who chooses the next move: default (always draft - same as the fixed pipeline) · llm (an LLM controller decides) · trace (a policy learned from your own past runs; abstains until it has ≥3 labelled units per arm) |
agentic_controller_model | judge | Model-routing key for the llm policy’s controller |
agentic_max_unit_steps | 3 | Max research / read-canon gathering steps before a unit must be drafted |
agentic_inline_tools | false | Let the writer call research / canon-lookup tools mid-draft (in-generation tool use) |
agentic_critique_panel | false | A diverse-lens majority critique before approving a unit |
agentic_factcheck_panel | false | A multi-agent majority-vote fact-check panel (plan §21.10) |
| Key | Default | Does |
|---|
provider | openrouter | Model host: openrouter (default) or deepseek direct; switch live with /provider |
openrouter_providers | “ (empty) | Pin the OpenRouter upstream order. Default is unpinned ("" = OpenRouter’s default load-balancing, no upstream pinned). Recommended opt-in: set DeepSeek to engage the DeepSeek prompt cache (~80% of the prefix cached at ~3.5× lower cost) - not 100% reliable over OpenRouter’s load-balancing; for guaranteed caching use provider=deepseek direct |
max_context_chars | 24000 | Priority budget for the assembled canon + summaries + excerpts block, so a long book can’t silently overflow the model window (0 = unbounded; budget mode tightens this to 12000) |
request_timeout | 60.0 | Per-LLM-request timeout in seconds |
export_dir | “ (empty) | Where exported files are written (empty = the project folder); set with /path or /set export_dir |
theme | editorial | TUI theme |
default_user | default | The brain tenant |
| Variable | Does |
|---|
OPENROUTER_API_KEY | Required for real runs (.env) |
FIRECRAWL_API_KEY | Optional (.env) - enables search_provider: firecrawl for search + deep-research page scraping; without it, research falls back to DuckDuckGo |
WRITINGAGENT_FAKE=1 | Offline fake mode - whole pipeline, canned outputs, no API |
WRITINGAGENT_PROVIDER | Pick the model host at launch (syncs the saved provider setting) |
WRITINGAGENT_A11Y=1 | Accessibility line-mode: no live redraw, append-only full-sentence status (screen readers) |
WRITINGAGENT_REDUCED_MOTION=1 | Static run stages, no spinner animation |
WRITINGAGENT_HOME | Relocate brain + index off synced folders |
WRITINGAGENT_LIVE=1 | Enable the opt-in live network test in the suite |
WRITINGAGENT_NO_SCRAPO=1 | Force the stdlib research fetcher |
WRITINGAGENT_IGNORE_ROBOTS=1 | Skip robots.txt checks in the deep fetcher |
WRITINGAGENT_D2 | Path to the d2 binary (otherwise found on PATH) for the D2 diagram backend |
WRITINGAGENT_FAKE=1 | Fake mode: canned model output, no API calls (offline/CI) |
NO_COLOR / --plain | Plain-text TUI |