Build Sudowrite

KINDAback to the verdict

0%0 of 20 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

An editor over your own Markdown files with a story bible it builds from the text, retrieval that assembles relevant context instead of sending the whole manuscript, suggestions shown as a diff you accept or reject, and a per-request record of exactly what was sent and what it cost.

estimated effort weekendthe files for this build are in the project pack

RuntimeTypeScript with a desktop shellFilesPlain Markdown, one file per scene or chapterIndexSQLite with full text search over scenes and entitiesModelsAny provider behind one adapter, plus a local optionDiffsWord-level diff shown before anything is applied

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the build and the desktop shell.

    Get it nodejs.org, or nvm install 22. open ↗

    Verify node --version prints v22 or higher

  2. have readyfree

    Why Context assembly, extraction and retrieval are all trivial on a short story and revealing on a novel. The budget problem only exists at length.

    Get it Use your own work in progress, or a public domain novel split into scene files for testing.

    Verify The manuscript loads and its scene count and word count are reported

  3. API keypay per token; a paragraph rewrite is a fraction of a cent and a long session is more than you expect

    Why Suggestions need a model. Phases 1 to 3 work entirely without one, which is deliberate.

    Get it Create an account with a provider and set a spend limit when you create the key. Or install Ollama and pull a model to keep everything local.

    Verify A test request returns text and its cost is recorded

  4. decidefree

    Why This is the question the whole build is arranged around, and it is the writer's to answer rather than the tool's to assume.

    Get it Read your chosen provider's terms on training and retention before Phase 4. If the answer is no, use the local model path and accept lower quality.

    Verify The decision and the terms you read are recorded with a date

  5. decidefree

    Why These are plain files and this application writes to them. A backup is the safety net that atomic saves do not replace.

    Get it Version control the manuscript folder, which also gives you history, or ensure your ordinary backup covers it.

    Verify The folder is in a backup that has been restored from at least once

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- manuscripts(id, path, title, updated_at)
- scenes(id, manuscript_id, path, ordinal, title, word_count, content_hash)
- entities(id, manuscript_id, kind, name, description, first_seen_scene_id) · kind is character, place, object or thread
- mentions(entity_id, scene_id, count) · which scenes an entity appears in, which is how context is assembled
- requests(id, scene_id, at, purpose, model, prompt_tokens, completion_tokens, cost_usd, context_scene_ids)
- suggestions(id, request_id, original_text, suggested_text, state) · state is pending, accepted or rejected
- The requests table records which scenes were sent. A writer should always be able to answer what left their machine.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
MANUSCRIPT_PATHrequired~/Writing/NovelThe folder of Markdown files. Your data, in your backup.
INDEX_PATHrequired~/.local/share/write/index.dbSearch index and request log. Deliberately outside the manuscript folder so syncing cannot corrupt it.
MODEL_PROVIDERrequiredlocalWhich adapter is active. Local means nothing leaves the machine.
MODEL_API_KEYsecretoptionalsk-...Only needed for a hosted provider. Set a spend limit at the provider as well.
CONTEXT_TOKEN_BUDGETrequired8000Maximum assembled context. Exceeding it refuses rather than truncating.
SESSION_COST_WARN_USDrequired2Session spend at which a warning appears. Visible while writing rather than in settings.

The build, in order

  1. Editing your own files

    You can write comfortably, and the files stay ordinary Markdown.

    1. Scene order from a filename convention you document. Filesystem order is not stable and will reorder your book.

      Files src/manuscript.ts

    2. Temporary file plus rename. Test by killing the process mid-save.

      Files src/storage.ts

    3. Hash what you wrote and ignore your own events, so the watcher does not fight the editor.

      Files src/watcher.ts

    done when · tick each as it passes
    watch out
    • Writing directly over a file means a crash mid-save can truncate a chapter, and for a writer that is the worst possible failure. Write to a temporary file and rename over the target, which is atomic and cannot leave a half-written manuscript.
  2. A story bible built from the text

    The application knows who is in your book without you filling in a form.

    1. Proper nouns with frequency and first appearance. A model pass can improve it, but the deterministic pass is the baseline.

      Files src/bible/extract.ts

    2. Nothing enters the bible without the writer saying so. Manual entries are marked and never overwritten.

      Files src/bible/confirm.ts

    3. It travels with the manuscript and is readable without this application, which is the point.

      Files src/bible/write.ts

    done when · tick each as it passes
    watch out
    • Automatic extraction will confidently invent a character from a repeated phrase and miss one introduced only by a nickname. Present extraction as suggestions requiring confirmation rather than as facts, and make manual entry as fast as accepting a suggestion.
  3. Context assembled, not dumped

    A request carries what is relevant, and you can see exactly what was sent.

    1. Current and previous scene always, bible entries for present entities, then search results until the budget is reached.

      Files src/context.ts

    2. The actual assembled text, not a summary of it. A writer deciding whether to use a hosted model needs to see this.

      Files src/ui/ContextPreview.tsx

    3. Scene identifiers on the request row. This is the audit trail that makes the privacy claim checkable.

      Files src/requests.ts

    done when · tick each as it passes
    watch out
    • Sending the whole manuscript with every request is expensive, slow, and worse for quality than a focused selection, because the relevant paragraph is buried. It also means the entire book leaves the machine on every keystroke-triggered suggestion, which is a privacy decision made by accident.
  4. Suggestions as diffs

    Nothing changes your text without you seeing exactly what would change.

    1. Expand, rewrite, describe and continue. Each is a prompt template plus the assembled context.

      Files src/actions/

    2. Sentence-level diffs on prose are unreadable. Word level with sentence grouping is what a writer can actually judge.

      Files src/diff.ts

    3. On the suggestion row, so an accepted change stays reversible beyond the undo stack.

      Files src/suggestions.ts

    done when · tick each as it passes
    watch out
    • Applying a suggestion directly into the text and relying on undo loses the original as soon as anything else is typed, and a writer who accepts a rewrite and then dislikes it has no way back. Keep the original on the suggestion row, so accepted suggestions remain reversible for as long as the record exists.
  5. Cost, and the local option

    You know what each request cost, and you can choose to send nothing off the machine.

    1. Tokens in and out, priced by model. Aggregate by session and by manuscript.

      Files src/cost.ts

    2. Through a local endpoint. Quality will be lower and privacy absolute, which is a trade the writer should make knowingly.

      Files src/models/local.ts

    3. Persistently in the interface, with whether text leaves the machine stated plainly.

      Files src/ui/ModelBadge.tsx

    done when · tick each as it passes
    watch out
    • A per-request cost of a fraction of a cent feels free and adds up quickly during a writing session where you try twenty variations of a paragraph. Show the session total in the interface rather than only in a settings pane, because that number changes behaviour and a monthly bill does not.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more writing tools.