{"id":50674065,"url":"https://github.com/delebash/justwrite-app","last_synced_at":"2026-06-08T14:30:48.811Z","repository":{"id":362561875,"uuid":"1251284169","full_name":"delebash/justwrite-app","owner":"delebash","description":"novel writing software writen by ai with ai features","archived":false,"fork":false,"pushed_at":"2026-06-04T21:50:17.000Z","size":26941,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-04T22:07:47.454Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/delebash.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-27T12:30:42.000Z","updated_at":"2026-06-04T21:50:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/delebash/justwrite-app","commit_stats":null,"previous_names":["delebash/justwrite-app"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/delebash/justwrite-app","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delebash%2Fjustwrite-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delebash%2Fjustwrite-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delebash%2Fjustwrite-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delebash%2Fjustwrite-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/delebash","download_url":"https://codeload.github.com/delebash/justwrite-app/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delebash%2Fjustwrite-app/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34067347,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-08T14:30:47.849Z","updated_at":"2026-06-08T14:30:48.805Z","avatar_url":"https://github.com/delebash.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JustWrite\n\nA desktop writing app for novels, with an audio studio that connects to any **OpenAI-compatible** AI provider — Ollama, LM Studio, OpenAI, or anything else that speaks the standard.\n\nBuilt with **Tauri 2 + Vite + Vue 3 + Pinia** (JavaScript renderer, Rust backend).\n\nUser docs live in `docs/`. The marketing site at \u003chttps://delebash.github.io/justwrite-website/\u003e mirrors them for each release.\n\n---\n\n## Quick start\n\n```bash\nnpm install            # JS deps\nnpm run dev            # Vite HMR + a native Tauri window\nnpm run build          # Packaged app for the current OS\n```\n\nThe app opens on a seed project (\"The Cartographer's Daughter\") so you can click through every screen immediately.\n\n\u003e **First run is slow.** Tauri compiles the Rust crate the first time. Subsequent dev launches are fast.\n\n---\n\n## Features\n\nEight rooms, one house — organised by what part of the work you're in.\n\n### ✶ Manuscript — the desk where you write\n\n- **TipTap-based rich-text editor.** Bold, italic, headings, lists, links, tables, images.\n- **Parts → Chapters → Scenes.** Write inside scenes; chapters and parts are containers.\n- **Three view modes per chapter.** Edit (single scene), Card view (scenes as a corkboard), Read (continuous prose, no scene titles).\n- **Continuous mode.** Stitch every scene in the chapter into one editable document with visible scene breaks.\n- **Whole-book mode.** Read or revise the entire manuscript as one continuous page.\n- **Focus mode.** Hide everything but the prose.\n- **Two page layouts.** Full-bleed or a traditional sheet with running head and folio.\n- **Markers.** Drop pins in the prose while drafting — fix-later, verify, weak passage, loose thread, TODO, idea — collected on their own manuscript-wide page with one-click jumps back.\n- **Resume briefings + end-of-session recaps.** Walk back into a chapter with a summary of where you left off and what's next.\n- **Find and replace** across the whole project, with snippet preview and one-click jump (⌘F).\n- **Smart quotes, em-dashes, smart ellipses** on the fly.\n- **Drag-to-reorder** for scenes, chapters, parts.\n- **`@`-mentions.** Type `@` to link characters, locations, objects, groups, or strands directly into the prose.\n\n### ✶ Story world — the world around the book\n\n- **Characters** with wants, needs, the lie they tell, the truth they deny, a three-act arc, voice + dialect notes, and an image.\n- **Character consistency audit.** AI flags contradictions between the profile and what the prose actually does.\n- **Relationship arc tracker.** How each pair-bond evolves chapter by chapter.\n- **Locations** with kind, status, tags, and \"appears in scenes\" backlinks.\n- **Objects** for significant props (relics, letters, instruments, heirlooms).\n- **Groups** that bundle characters / locations / objects / strands into factions, families, crews.\n- **Architecture documents.** Three permanent slots — **Premise** (one paragraph), **Fabula** (cause-and-effect chronology), **Setting** (world + time-period context).\n- **Worldbuilding wiki.** Free-form articles in six categories (Geography, History, Cultures, Languages, Factions, Lore \u0026 myth), tagged and cross-referenced.\n- **Notes** for anything that doesn't fit a structured surface.\n- **Per-entity event timelines** that link back to scenes.\n- **Relations graph.** A force-directed map of who is in what with whom — edges drawn automatically from shared scenes, groups, and mentions.\n- **Find-new-entities sweep.** AI surfaces characters and places the prose mentions but the Story Bible hasn't met.\n\n### ✶ Plot — the bones of the story\n\n- **Narrative strands** tracked across multi-beat arcs.\n- **Plot Board.** Strands × chapters grid. Drag beats, click empty cells to add, links back to scenes.\n- **Plot templates.** Three-Act, Save the Cat, Hero's Journey, Story Circle — scaffolded with one click.\n- **Beat-sheet overlay.** Map your existing chapters onto any chosen structural framework.\n- **Plot-hole audit.** AI walks the manuscript looking for setups without payoffs, character actions out of profile, and optional world-rule breaks.\n- **Dangling-thread tracker.** Lists foreshadowing the book never came back to.\n- **Scene-level linking** to characters, places, objects, and strands.\n- **Per-scene status** (To do · Draft · Revise · Done) surfaced everywhere as colour-coded donuts.\n\n### ✶ AI — models, on your terms\n\n- **Any OpenAI-compatible endpoint.** Add OpenAI, Ollama, LM Studio, llama.cpp, vLLM, Claude (via Anthropic's OpenAI-compatible API), or your own server.\n- **Per-feature model picker.** Use one model for chat, another for critique, another for entity sweeps.\n- **Ask-the-book chat.** Hybrid BM25 + vector retrieval with citations back to the chapters the answer came from.\n- **Talk to a character.** Converse with anyone in your cast in their own voice, with story-world knowledge.\n- **In-editor bubble actions.** Rewrite, expand, tighten, continue from cursor — or generate three alternatives side by side.\n- **Guided continue.** Continue the prose with a specific brief.\n- **Voice canon.** A \"match my style\" fingerprint sampled from chapters you choose, injected into every generation.\n- **Unstuck — five ways out.** A stuck-on-this-chapter diagnostic that offers five distinct ways forward.\n- **Brainstorm pane.** Names, titles, plot twists, next beats — fifteen-to-twenty options per click, thumbs-up to steer.\n- **Marketing pack.** Logline, blurbs, synopsis, pitch, comp titles — generated in one pass from the same chapter digest.\n- **Multi-reader panel.** Four reader personas (genre reader / literary critic / agent intern / book-club reader) react to a chapter in parallel.\n- **AI-tells scanner.** Deterministic — flags stock verbs, body-language clichés, hedges. No LLM call, no token spend.\n- **Sensory research pack.** Smell, sound, touch, taste, period detail — fifteen specific phrases in twenty seconds.\n- **Writer Lab.** Every prompt and parsed result exposed for inspection.\n- **Usage ledger.** Per-feature token + cost estimates.\n\n### ✶ Studio — from cast list to finished audiobook\n\n- **Voice cast.** Map each character — and the narrator — to a voice from any TTS provider.\n- **Smart-cast.** LLM-suggested pairings based on character profile + voice metadata.\n- **Speaker analysis.** Per-chapter, line-by-line, cached.\n- **Render queue.** Per-chapter TTS render with timed silences at speaker changes.\n- **WAV → M4B mux.** Final audiobook with ID3 chapter markers, cover art, and metadata. Plays in Audible, Apple Books, Plex.\n- **Voice cloning.** Drop reference WAV/MP3 files into a Chatterbox server's `./voices/` folder; they appear in the cast picker by filename.\n\n### ✶ Reflection — two views of the work\n\n- **Home dashboard.** Today's session, streak, fortnight, cadence — and a button that drops you back into the chapter you were last in.\n- **Analysis dashboard.** Project KPIs, 30-day pace chart, 53-week writing-year heatmap, milestones, status donuts, narrative-strand distribution, character-presence heatmap, dialogue vs. narration vs. interior-monologue split.\n- **Story-tension timeline.** AI scores the rise and fall across chapters.\n- **Voice-drift report.** Flags chapters reading off-style, with per-chapter Explain.\n- **Reverse outline (StorySnap).** Summarises what each chapter actually does versus what you remember it doing.\n- **Reader-knowledge map.** Where the reader sits relative to the POV character — aligned, ahead (dramatic irony), behind (reader confused), or neutral — chapter by chapter. For mystery, thriller, and unreliable-narrator work.\n\n### ✶ Import \u0026 export — what goes in, what comes out\n\n- **Import** DOCX, EPUB, ODT, Markdown, plain text. Chapter auto-detection, image extraction, smart-quote normalisation.\n- **Import as audiobook.** Drop a file straight into Studio for narration.\n- **Import as notes.** Bring research into the Notes section instead of the manuscript.\n- **Entity sweep on import** (optional) to surface new characters and places.\n- **Export PDF.** TOC, part covers, optional cover image.\n- **Export DOCX.** Live auto-refreshing table of contents.\n- **Export EPUB 3.** Nav doc, OPF spine, cover xhtml, JSZip-packaged.\n- **Export M4B audiobook.** Built from rendered chapter audio.\n- **Strip scene markers on export** when you prefer.\n\n### ✶ Appearance — the room, set up your way\n\n- **Five theme presets.** Studio (Geist + teal), Fine Press (Fraunces + oxblood), Ivory Press (cream paper, italic headings), Calm Modern (clean defaults), Editorial (Newsreader + indigo).\n- **Light, dark, or follow the system.**\n- **Four font pairings** with per-surface overrides.\n- **Accent and gold hue sliders.** Tune the colour without leaving the app.\n- **Surface tints, paper tints, ink palettes** (warm / cool / sepia / auto).\n- **Button knobs.** Radius (sharp · standard · rounded · pill), density (compact · comfy), label-case (sentence · uppercase).\n- **UI scale.**\n- **Save your mix as a custom preset.**\n\n### ✶ Cross-cutting\n\n- **Local first.** Your manuscript is a file on your computer. No account, no upload, no server lock-in.\n- **Soft delete + Trash.** Every deletion is undoable; Trash holds items indefinitely until you empty it.\n- **Project-wide undo / redo.** 100 steps in-memory, last 10 persisted. ⌘Z / ⌘⇧Z.\n- **Autosave.** Every change flushes to IndexedDB instantly and to disk within ~10 seconds.\n- **Backups.** Export the whole project as a single JSON snapshot at any time; restore from one with a click.\n- **i18n-ready.** All UI strings flow through vue-i18n; locale-aware number formatting.\n\n---\n\n## Setup\n\n### Prerequisites\n\n| Tool | Purpose | Install |\n|---|---|---|\n| **Node 24+** | Renderer build + scripts | \u003chttps://nodejs.org/\u003e |\n| **Rust (stable)** | Tauri backend compilation | \u003chttps://www.rust-lang.org/tools/install\u003e |\n| **Tauri CLI** | Drives `tauri dev` / `tauri build` | Pulled in as a `devDependency`; `npx tauri` works out of the box. Optional global: `cargo install tauri-cli --version \"^2.0\"`. |\n| **gh CLI** | Triggering the release workflow only | \u003chttps://cli.github.com/\u003e + `gh auth login` |\n| **Platform deps** | Tauri runtime libs | Linux: `libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf`. macOS: Xcode CLT. Windows: WebView2 runtime (preinstalled on Win11). |\n\n### One-time\n\n```bash\nnpm install            # also: cd e2e \u0026\u0026 npm install (if you'll run screenshots/smoke tests)\n```\n\nThe e2e harness has its own `package.json` and its `postinstall` fetches the right `msedgedriver.exe` for your installed Edge version (Windows only).\n\n---\n\n## NPM scripts\n\nRun from the repo root unless noted.\n\n| Script | What it does |\n|---|---|\n| `npm run dev` | Tauri dev — launches the Rust crate **and** a Vite dev server, opens the native window. First run is slow (compiles Rust); subsequent runs cache. |\n| `npm run build` | Packaged app for the current OS. Outputs to `src-tauri/target/release/bundle/`. |\n| `npm run dev:vite` | Renderer only, in a plain browser tab at `http://localhost:1420` — no Tauri APIs. Falls back to IndexedDB / data-URLs. Useful for fast iteration on UI that doesn't need filesystem. |\n| `npm run build:vite` | Renderer build only. Tauri invokes this via `beforeBuildCommand`. |\n| `npm run preview:vite` | Serves the built renderer over Vite preview — handy for sanity-checking the bundle. |\n| `npm run tauri \u003ccmd\u003e` | Pass-through to the Tauri CLI (`npm run tauri icon source.png`, etc.). |\n| `npm run bump \u003cversion\u003e` | Updates `package.json`, `src-tauri/Cargo.toml`, `src-tauri/tauri.conf.json` to the same version. **Does not commit or tag** — you do. See [Release process](#release-process). |\n| `npm run release [version]` | Triggers the GitHub Actions release build via `gh workflow run`. Requires the tag to already exist on origin. Interactive `[y/N]` confirm. |\n| `npm run release:windows` · `:macos` · `:linux` | Same as `release` but builds a single platform. |\n| `npm run screenshots` | Runs the e2e screenshot capture (same as `cd e2e \u0026\u0026 npm run capture`). Drives the prod binary, writes PNGs to `../justwrite-website/public/screenshots/`. Requires `npm run build` first. |\n| `npm test` | Runs the e2e smoke suite (delegates to `npm test --prefix e2e`). Drives the prod binary through every major route and asserts each surface renders. Requires `npm run build` first. |\n\n\u003e No linter or formatter is wired into the dev loop on purpose — writing prose is the priority. Reach for the audit tools below when imports/locals drift, not on every commit.\n\n---\n\n## E2E harness (smoke tests + screenshots)\n\nLives in `e2e/`. WebDriver-driven automation against the real Tauri build via [`tauri-driver`](https://github.com/tauri-apps/tauri/tree/dev/tooling/webdriver) + `msedgedriver` (Windows / WebView2) — see [`e2e/README.md`](e2e/README.md) for the full story.\n\n### Prereqs (one-time)\n\n```bash\ncargo install --locked tauri-driver\ncd e2e \u0026\u0026 npm install        # postinstall fetches msedgedriver for your Edge version\nnpm run fetch-driver         # rerun manually after a major Edge update\n```\n\n### Smoke tests\n\n```bash\ncd e2e \u0026\u0026 npm test\n```\n\nSpins up the prod binary, runs `tests/*.test.mjs`, asserts the major routes render. Used as the green-light gate before a release.\n\n### Screenshots\n\n```bash\nnpm run screenshots          # from repo root\n# or:\ncd e2e \u0026\u0026 npm run capture\n```\n\nDrives `src-tauri/target/release/justwrite.exe` through a fixed list of routes (`TARGETS` in `e2e/capture-direct.mjs`) and writes PNGs straight into the marketing site's `public/screenshots/` folder. Rebuild first with `npm run build` if the renderer has drifted.\n\n#### Re-capture with a different theme\n\n`capture-direct.mjs` clicks the named preset tile in Settings → Appearance before the capture loop runs, so every shot reflects a chosen theme. Default is **Fine Press**.\n\n```bash\nJW_THEME=\"Fine Press\"   npm run screenshots   # default\nJW_THEME=\"Studio\"       npm run screenshots\nJW_THEME=\"Ivory Press\"  npm run screenshots\nJW_THEME=\"Calm Modern\"  npm run screenshots\nJW_THEME=\"Editorial\"    npm run screenshots\n```\n\nThe theme name has to match the preset's visible `\u003cb\u003e` label exactly. The change persists into IDB, so subsequent app launches keep that look until you switch again.\n\n#### Capture gotchas\n\n- **The release binary is whatever was last built.** Run `npm run build` before capturing if you've changed renderer code.\n- **Don't have JustWrite open** while capturing — both instances share AppData and IndexedDB; concurrent autosaves race.\n- **Orphan `tauri-driver.exe`** after a force-kill needs `taskkill /F /IM tauri-driver.exe` (Windows) before re-running.\n\n---\n\n## Release process\n\nManual release, triggered by `gh workflow run`. Pushes and tags do **not** build by themselves.\n\n```bash\n# 1. Bump version across the three manifests\nnpm run bump 1.2.0\n\n# 2. Commit, tag, push (the bump script does NOT do this)\ngit add package.json src-tauri/Cargo.toml src-tauri/tauri.conf.json\ngit commit -m \"release: v1.2.0\"\ngit tag v1.2.0\ngit push \u0026\u0026 git push --tags\n\n# 3. Dispatch the build\nnpm run release              # all platforms\nnpm run release:windows      # or one\n```\n\nWhat the workflow does (see `.github/workflows/release.yml`):\n\n1. Builds .dmg (macOS universal), .exe + .msi (Windows), .AppImage + .deb + .rpm (Linux) on per-platform runners.\n2. Creates / updates GitHub Release `v\u003cversion\u003e` with the binaries attached.\n3. Packs `docs/` into `docs.tar.gz` and attaches it to the release.\n4. Fires a `repository_dispatch` at the marketing-site repo so it rebuilds with the new docs.\n\nWatch with `gh run watch` or open the workflow runs page. A full all-platform build is roughly 9-15 min wall time.\n\n\u003e **`WEBSITE_DISPATCH_TOKEN`** secret in repo settings drives step 4. Without it, the workflow logs a skip and the marketing site won't refresh automatically — push a no-op commit to the marketing repo to trigger it manually.\n\n---\n\n## Project structure\n\n```\njustwrite-app/\n├── CLAUDE.md                  ← instructions for Claude Code (project context, conventions)\n├── README.md\n├── docs/                      ← user-facing docs, bundled into docs.tar.gz on release\n├── biome.json\n├── package.json\n├── vite.config.js\n├── scripts/\n│   ├── bump.mjs               ← version bumper (3 manifests)\n│   └── release.mjs            ← wraps gh workflow run\n├── e2e/                       ← screenshot capture + smoke tests\n│   ├── capture-direct.mjs\n│   ├── lib/driver.mjs\n│   └── tests/smoke.test.mjs\n├── src/\n│   └── renderer/\n│       ├── index.html\n│       └── src/\n│           ├── main.js                ← Vue entry; imports the Tauri bridge\n│           ├── App.vue\n│           ├── router/index.js\n│           ├── assets/styles/tokens.css\n│           ├── domain/seed.js         ← demo project \"The Cartographer's Daughter\"\n│           ├── stores/                ← project, ui, ai, studio, sessions\n│           ├── services/\n│           │   ├── tauri-bridge.js    ← exposes window.justwrite\n│           │   ├── openai-compat.js   ← unified HTTP client for every LLM/TTS\n│           │   ├── llm.js, tts.js, render.js, webSpeech.js\n│           │   ├── search.js, analysis.js\n│           │   ├── imageStore.js\n│           │   ├── m4b.js\n│           │   └── export/{manuscript,pdf,docx,epub}.js\n│           ├── components/\n│           └── views/\n└── src-tauri/\n    ├── Cargo.toml\n    ├── tauri.conf.json\n    ├── build.rs\n    ├── capabilities/default.json      ← plugin permissions\n    └── src/\n        ├── main.rs                    ← `fn main()` -\u003e justwrite_lib::run()\n        └── lib.rs                     ← #[tauri::command]s + Builder\n```\n\n---\n\n## How the IPC bridge works\n\nThe renderer never calls `invoke()` directly. `src/renderer/src/services/tauri-bridge.js` is a side-effect import in `main.js`. When running inside Tauri it populates `window.justwrite`:\n\n```js\nwindow.justwrite = {\n  project: { save, open, saveTo },\n  images:  { save, read, delete },\n};\n```\n\nThe Rust commands live in `src-tauri/src/lib.rs` and mirror the JS contract one-for-one (`project_save`, `images_save`, …). Outside Tauri (e.g. plain `npm run dev:vite` in a browser tab), `window.justwrite` stays undefined and the renderer falls back to its IndexedDB / data-URL paths.\n\nWhen adding a new Tauri command:\n\n1. Add the `#[tauri::command]` fn in `src-tauri/src/lib.rs` and register it in `invoke_handler![]`.\n2. Add a matching method on `window.justwrite.*` in `tauri-bridge.js`.\n3. If it needs a new plugin permission, edit `src-tauri/capabilities/default.json` (currently grants `core:default`, `dialog:default`, `fs:default`).\n\n---\n\n## AI providers\n\nJustWrite uses one client class for everything: **`OpenAICompatClient`** (`src/renderer/src/services/openai-compat.js`).\n\nPre-configured presets in Settings → **AI \u0026 Audio engines**:\n\n| Preset                        | Base URL                            | Notes                                                                                                                |\n| ----------------------------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------- |\n| OpenAI-compatible (local)     | `http://localhost:11434/v1`         | Generic LLM endpoint. Point at Ollama, LM Studio, llama.cpp, etc. — change the URL to whatever local server you run. |\n| OpenAI                        | `https://api.openai.com/v1`         | LLM + TTS. Add your API key.                                                                                         |\n| Claude (Anthropic)            | `https://api.anthropic.com/v1`      | LLM only, via Anthropic's OpenAI-compatible endpoint. Add your `sk-ant-...` key. Default model: `claude-haiku-4-5`.   |\n| Kokoro (local TTS)            | `http://localhost:8880/v1`          | Small, fast local TTS via Kokoro-FastAPI.                                                                            |\n| Chatterbox                    | `http://localhost:8004/v1`          | Local TTS + voice cloning (devnen/Chatterbox-TTS-Server). Drop reference WAV or MP3 files into the server's `./voices/` folder; they appear in JustWrite's cast picker by filename. |\n\nAdd any other OpenAI-style provider — including local TTS servers — via **Add provider**.\n\n---\n\n## Working with Claude Code\n\nThis repo is set up to be developed with [Claude Code](https://claude.com/claude-code), Anthropic's CLI. The same flow works for the [Claude Code GitHub Action](https://github.com/anthropics/claude-code-action) and for human contributors who want a sense of the conventions.\n\n### Project context\n\n- **`CLAUDE.md`** at the repo root is the agent's project brief. It captures: active work, the renderer/Rust split, the IPC bridge contract, the Pinia store invariants (snapshot-based undo, soft delete via `state.trash`, coalesced keystroke actions), the OpenAI-compat client, the audio pipeline, the export adapters, the Jw* UI component layer's design contract, and a \"Don't\" list (no PrimeVue, no `.btn-*` classes, no bypassing `window.justwrite`). Read it before changing renderer code.\n- **`docs/`** is user-facing reference, mirrored to the marketing site. When you ship a feature, update the relevant doc in the same commit (this is enforced by repo convention, not by hooks).\n\n### Recommended workflow\n\n```bash\n# Start a session in the repo\nclaude\n\n# Or with the Claude Code extension in VS Code / JetBrains —\n# it picks up CLAUDE.md automatically.\n```\n\nA few patterns that work well here:\n\n| Task | How to ask |\n|---|---|\n| **Add a new view** | Sketch what it should show. Claude will scaffold the Vue file, wire the route, add a sidebar entry, and update `docs/` if it's a user-facing surface. |\n| **Add a new AI feature** | Mention which provider/feature key in `ai.featureRouting` it routes through. The AI-call pattern is `runAiStream` from `services/aiStream.js` — don't roll a new stream loop. |\n| **Refresh screenshots after a UI change** | `Re-run npm run screenshots after rebuilding, then commit the diffs to ../justwrite-website.` Optionally pass `JW_THEME=\u003cpreset\u003e` to capture in a different look. |\n| **Deep audit / refactor pass** | `Use a workflow for a deep audit refactor.` The keyword *workflow* opts in to multi-agent orchestration — runs Biome / depcheck / jscpd / madge in parallel, triages findings against the actual code, applies safe fixes, hands back a punch list. |\n| **Cut a release** | `Smoke test, bump to 1.2.0, full release.` Triggers `e2e/npm test`, the bump script, the commit/tag/push, and `npm run release` end-to-end. |\n| **Update the marketing site** | The sibling repo `justwrite-website/` (Astro + GitHub Pages) consumes `docs.tar.gz` from each release and renders `src/components/Inside.astro` + `Screenshots.astro` for feature copy and gallery. Claude knows to commit screenshots there, not here. |\n\n### Code conventions Claude follows\n\n- **Plain JS, not TypeScript.** No `tsconfig.json`, no migration to TS unless explicitly asked.\n- **`window.justwrite`, not `invoke()`.** The browser-only dev path breaks if you bypass the bridge.\n- **`Jw*` components, not raw HTML.** Exceptions exist (title inputs, sidebar chrome, `.tb-btn` family, DateTimePicker internals) and are listed in `CLAUDE.md`.\n- **`confirmDialog` only for irreversible actions.** Undoable mutations show a toast naming what changed and lean on the undo history.\n- **Real screenshots, not invented mockups.** Use the e2e harness for visuals.\n\n### What Claude *won't* do without being asked\n\n- Run `git commit`. Commits stay manual.\n- Run tests or drive the app in a browser to verify. A clean compile check is fine; behaviour verification is the human's job.\n- Add new linters, formatters, test runners, or TS configs.\n\n---\n\n## Code audit \u0026 refactor\n\nFour dev-only tools are wired into devDependencies for periodic cleanup. None run automatically.\n\n| Tool | What it finds | When to reach for it |\n|---|---|---|\n| **Biome** | Unused imports, dead variables, suspicious patterns. Auto-fixes most of what it flags. | After heavy iteration when imports and locals drift out of sync. |\n| **depcheck** | `package.json` deps that nothing imports — and the reverse (imports of packages not declared). | Before a release, or after ripping out a feature. |\n| **jscpd** | Copy-paste detector. Surfaces duplicated blocks with file:line citations. | When you suspect a helper should be extracted but don't know where the copies live. |\n| **madge** | Circular dependencies and orphan files in the renderer. | When import errors get weird, or when untangling a module. |\n\n### Light audit — run by hand\n\n```bash\nnpx biome check src/renderer/src/        # lint findings (add --apply for safe auto-fixes)\nnpx depcheck                              # unused / missing deps\nnpx jscpd src/renderer/src/               # writes a report to ./report/\nnpx madge --circular src/renderer/src/    # circular deps only\nnpx madge --orphans src/renderer/src/     # files not imported anywhere\n```\n\nRead the output, fix what's obvious, skip what isn't. Biome's `--apply` is safe to run blind; the other three are read-only.\n\n### Deep audit — hand it to Claude Code\n\nFor a full pass — run all four tools, triage findings against the actual code (catches false positives like dynamic imports), apply the safe fixes, and produce a punch list of judgment calls — ask Claude Code to **\"use a workflow for a deep audit refactor\"**. The keyword *workflow* opts in to multi-agent orchestration: the audit fans out across parallel subagents instead of one agent reading every report end-to-end. Expect a few minutes wall-time and substantial token use; you get a structured report back instead of triaging hundreds of raw findings yourself.\n\n---\n\n## License\n\nYour code, your terms. Voices, models, and APIs are subject to their providers' terms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdelebash%2Fjustwrite-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdelebash%2Fjustwrite-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdelebash%2Fjustwrite-app/lists"}