Skip to content

Latest commit

 

History

2,455 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

QUILL for All

Contributors

QUILL for All is an open-source, accessibility-focused editor from Community Access. It helps people write, edit, convert, compare, and publish documents in a screen-reader-friendly environment.

QUILL stands for Quality, Usable, Inclusive, Lightweight, Literate:

  • Quality -- dependable, polished, and serious enough for real work.
  • Usable -- built around practical keyboard, screen reader, and low-friction editing needs.
  • Inclusive -- designed from the beginning for blind users, screen reader users, keyboard users, and people with different skill levels.
  • Lightweight -- fast, focused, not bloated, and friendly to people who just want to write or edit.
  • Literate -- about words, code, Markdown, documents, learning, and thoughtful communication.

New to the repository? This README covers getting started; REPO-GUIDE.md is the complete map of every folder, and CHANGELOG.md is what shipped, release by release.

One repository, a family of apps

The current release line is QUILL 1.0.0. This repository builds the editor and a family of companion apps -- together, QuillVille:

App What it is
QUILL (the editor) The full writing and document environment, for Windows and macOS
Quill Radio Internet radio with a 60k-station offline catalog, recording, and weather
QUILL Cast An accessible podcast player with downloads, queue, and notes
QUILL Audio Studio Audiobook and audio production: chapters, captions, publishing
Quill Weather Forecasts, hourly detail, moon phases, US alert monitoring
Quill Inkwell Text expansion
Quill Beacon Encrypted sync beacon
QUILL Social Accessible social reading (RSS today; a NetworkAdapter contract for more)

The companion apps share one QuillVille Runtime -- a single Python runtime (about 294 MB) installed once at %LOCALAPPDATA%\QuillVille\Runtime\3.13 and reused by every app, so a person who installs three apps downloads the shared engine once. Media tools (ffmpeg, libmpv, about 304 MB) ride only with the apps that declare them: Radio, Cast, and Audio Studio. Everything an installer ships works offline the moment installation finishes; larger optional components (dictation engines, neural voices, extra spell-check languages) are offered in-app as consented, SHA-256-verified downloads. How the runtime got this small -- and the three silently broken speech engines found on the way -- is told in plain English in the runtime layering retrospective.

The Quillin Hub hosts community-created extensions (Quillins) -- from research tools to accessibility auditors -- verified for security and WCAG 2.2 AA compliance.

The editions: five ways to get one app

Each app ships in up to five flavors, so nobody pays for delivery they don't need:

Edition What it carries Who it is for
Setup The app plus the shared runtime and the app's declared media tools; works offline from first launch Most people
Portable The same, self-contained in a zip with its own data folder; travels on a stick No-install machines, USB workflows
Companion A ~1 MB runtime-less stick: launcher and docs, running off the machine's shared runtime Stick users on machines that have the runtime
Lite A 2-3 MB installer: just the native launcher and docs Machines that already have (or will share) the runtime
Offline Setup plus the app's on-demand components pre-bundled -- engines, models, dictionaries; zero downloads ever People the internet cannot reach

Which file do I want?

  • Installing an app the normal way? Take its Setup (named -Setup-Shared- for the shared-runtime apps). Run it, press Next, done. The app works offline the moment the installer finishes -- stations, media tools, docs, everything its core job needs is inside.
  • Already have a QuillVille app, adding another? Take the new app's Lite Setup if it has one. It is 2-3 MB because the shared engine is already on your machine from the first app -- the Lite installer finds it and installs in seconds.
  • No internet, or almost none? Take an Offline edition. QUILL's bundles every optional component; Audio Studio's bundles the dictation engine and a starter model -- and because the runtime is shared, installing it gives every QuillVille app on that machine offline dictation.
  • USB stick, no installation at all? Take a Portable zip. Unzip anywhere and run the exe inside; settings and downloads live in the data folder next to the app, so the whole thing travels. Already have the runtime installed? The Companion zip is the same stick at ~1 MB.

What actually happens when you run each one

A Setup installer installs the tiny app itself -- a native launcher, an icon, docs -- and installs (or reuses) the shared QuillVille Runtime at %LOCALAPPDATA%\QuillVille\Runtime\3.13. One runtime serves every app; each app registers a reference to it, and the media tools an app declares ride inside the runtime's tools folder. Everything is per-user, so no elevation is ever needed. First launch just works, offline; bigger optional features appear in-app as consented, size-labelled, SHA-256-verified downloads that are yours forever once fetched.

A Lite installer installs the same tiny app, then checks for the shared runtime. Already there? Done in seconds. Missing? It downloads QuillVille-Runtime-Setup.exe from this repository's latest GitHub release -- through Inno Setup's built-in download page, a standard progress bar and status text that NVDA, JAWS and Narrator read -- and runs it. Decline, or lose the connection, and nothing breaks: the app itself offers the runtime download again on first launch. Lite and full installers share one AppId per app, so either upgrades the other, and an edition marker tells the updater which flavor to offer next time.

An Offline installer does everything the Setup does, with the app's on-demand components already in the box -- fetched at build time from the same pinned, SHA-256-verified vault the in-app downloads use, so offline and online users end up with byte-identical components. Nothing ever phones home.

A Portable zip involves no installer at all: the app, its runtime (or none, for the Companion), its declared media tools, and a data folder whose presence is the portable-mode switch. Delete the data folder and the app uses the computer's shared Quill data instead.

The runtime's own installer (QuillVille-Runtime-Setup.exe, built by standalone\runtime\build_runtime_installer.ps1) is what the Lite installers download; it ships the base runtime only -- no media tools, because a Weather user should never download 300 MB of them. Media apps' full installers carry their own copies, and a Lite install offers them as verified on-demand downloads.

The Offline flavor is built by an app's build_release.ps1 -Offline. Apps with no on-demand components (Weather, Inkwell, Beacon) need no separate Offline flavor: their Setup already is one. As of 2026-08-18 every companion app is on the shared-runtime layout, and all seven ship the full flavor set -- Setup-Shared, Portable, Lite, and Companion -- with Audio Studio adding the family's first per-app Offline Edition.

Running from source

You need Python 3.13 on Windows (the version releases are built and tested against; 3.12 is the floor) or macOS.

# 1. Clone, then install the editor with UI and dev tooling
pip install -e ".[ui,dev]"

# ...or the same install in seconds with uv (dev only; releases use pip)
uv pip install -e ".[ui,dev]"

# 2. Run the editor
python -m quill          # pythonw -m quill for no console window

# Companion apps run from the same checkout
python -m quill.apps.radio
python -m quill.apps.podcasts    # QUILL Cast
python -m quill.apps.studio
python -m quill.apps.weather

Notes for a working developer setup:

  • Optional extras are opt-in and named in pyproject.toml: ai (on-device llama.cpp assistant), spellcheck, speech, dictation, ocr, glow (document accessibility engine), and more. The everything set a release runtime ships is pip install -e ".[runtime,packaging]".
  • Vendored wheels: a few first-party dependencies (the GLOW engine, feedback-hub) are not yet on PyPI and live in vendor/wheels. Installs that need them take --find-links vendor/wheels.
  • Useful launch flags: --safe-mode (disables AI, watch folder, and extensions), --version, --diagnostics, --new-window, --line N --column M. Safe mode is also QUILL_SAFE_MODE=1.
  • Running from source uses your real %APPDATA%\Quill data folder unless a data\ folder with a portable marker sits next to the app; developers can point QUILL_DATA_DIR somewhere else (honoured only with QUILL_DEV_BUILD=1).

Repository structure

The short version (the full map is REPO-GUIDE.md):

  • quill/ -- the application package, layered with strict import boundaries: core/ (pure domain logic, no wx, strict-typed), io/ (format readers/writers, no wx, strict-typed), ui/ (the wxPython shell), platform/ (Windows and macOS bridges), stability/ (crash reporting, safe subprocess, safe mode), tools/ (the shipped CI gates), apps/ (the companion apps' source), quillins_bundled/ (built-in extensions).
  • tests/ -- unit, stability, integration, UIA, and repository-structure suites; tests/unit/ mirrors the package layout.
  • docs/ -- all documentation: the PRD, user guides, release runbooks, QA books, planning, the published site. Every Markdown file has generated .html/.epub siblings, and CI enforces that parity.
  • scripts/ -- build and release tooling (see the next section).
  • standalone/ -- per-app build wrappers (installer scripts, specs, icons, app docs) plus standalone/runtime/, the shared QuillVille Runtime build.
  • installer/ -- QUILL's own Inno Setup sources (generated; edit the generator).
  • vendor/wheels/ -- vendored wheels for dependencies not yet published.
  • packages/, examples/ -- the Node Quillin runtime API and example extensions.
  • build.ps1, build.cmd, build-<product>.cmd -- the build commands, described in the next section.

Anything else you see at the root after building (dist/, build/, local/, data/) is gitignored output and safe to delete.

The build process

Everything releasable lands under dist/ subtrees, and a local build is laid out identically to a CI build.

One command per product

The root of the checkout carries a build command for every product, so nothing has to be remembered about where a build script lives, what interpreter it wants, or which flags it takes:

build-radio                  # Quill Radio: portable, Companion, Setup, Lite
build-runtime                # the shared QuillVille Runtime
build-runtime-installer      # QuillVille-Runtime-Setup.exe
build-quill                  # QUILL itself
build-all                    # every product, in the right order

There is one build-<product>.cmd per product -- runtime, runtime-installer, quill, radio, cast, weather, studio, inkwell, beacon, social, and all. Each is a shim over build.ps1, which is where the logic lives, so build.ps1 radio and build.cmd radio do exactly the same thing; build.ps1 list prints the roster with a one-line description apiece. (converter, player, and radio-mac have no build shell yet, and list says so rather than leaving you guessing.)

Nothing needs a path. The interpreter, ISCC, ffmpeg, libmpv, and the bundled feedback token are all resolved by scripts\BuildEnv.ps1, so the same command works on any machine and from any drive letter.

Options pass straight through to the real build script, so anything it accepts still works -- -SkipSharedRuntime (reuse the runtime already in standalone\runtime\dist, saving roughly ten minutes), -Offline (Audio Studio's Offline Edition), -SkipCatalog, -SkipToken, -Iscc <path>, -Python <exe>. -Sign is understood by every product, including QUILL's own Python build, where it sets the QUILL_SIGN the signer reads (docs/code-signing.md). Two options belong to the wrapper itself: -NoLog streams the build to the terminal instead of teeing it to a file, and -NoCopy leaves the artifacts in the product's dist.

Output is teed, not dumped. A PyInstaller run prints hundreds of thousands of lines, which is worth keeping and unbearable to read. Each build writes local\build-logs\<product>-<timestamp>.log and leaves the terminal holding the summary: which script ran, where its log is, what was copied, and how long it took.

Finished artifacts are collected in \installs. That path is deliberately written with no drive letter, so it resolves against the root of whatever drive the checkout is on: a build from S:\QUILL collects into S:\installs, and a clone on another drive collects there instead, with nothing to configure. Only files the current run produced are copied, matched on modification time -- a product's dist keeps older versions around, and without that filter every build would quietly refill \installs with releases nobody asked for.

Order matters, and build-all encodes it: the runtime first, then the runtime installer, then the apps. A media app stages the tools it declares (ffmpeg and libmpv, 306 MB) into the shared runtime dist after the runtime is built, and nothing unstages them; QuillVille-Runtime-Setup.exe is compiled from whatever is sitting in that dist and is meant to carry the base runtime only. Compiling it straight after a fresh runtime build is the one moment that dist is clean. The same rule applies when you run build-runtime-installer by hand: build it on a runtime no app has touched yet.

A failing product in build-all is recorded rather than fatal. The remaining products still build, the failures are named together at the end, and the run exits non-zero.

What runs underneath

The shared runtime. standalone\runtime\build_runtime.ps1 (no arguments) builds the QuillVille Runtime with PyInstaller from quillville-runtime.spec. What ships is declared, not inherited from whatever the build machine has installed, and three gates hold that promise:

  1. scripts/check_build_env.py -- the floor: everything [runtime] needs is installed.
  2. scripts/check_runtime_inventory.py -- the ceiling: nothing undeclared appeared and nothing declared vanished (baseline: standalone/runtime/runtime-inventory.json).
  3. scripts/check_runtime_imports.py -- the proof: runs the finished bundle and imports every optional piece, so present-but-broken can never ship silently.

Per-app installers. Each app's standalone\<app>\scripts\build_release.ps1 builds the runtime (or reuses it with -SkipSharedRuntime), stages exactly the media tools the app declares in its REQUIRED_COMPONENTS (via scripts\StageMediaTools.ps1, from pinned SHA-256-verified assets -- never from PATH), renders the app's docs, and compiles the Inno Setup installer plus a portable zip. Code signing is opt-in (-Sign, see docs/code-signing.md); a plain build is unchanged.

QUILL's own installers. python scripts/build_windows_distribution.py builds the editor's portable bundle and installer into dist/windows/; --bundle-offline builds the Offline Edition into dist/windows-offline/ -- everything bundled, zero downloads ever, for machines the internet cannot reach.

When two build machines disagree, python scripts/build_fingerprint.py capture records what a machine really is (interpreter, every package, staged-binary hashes, artifact sizes) and compare --fail-on-drift names exactly what differs. The procedure is docs/build-machine-sync.md.

Tests and quality gates

pytest -m smoke -q               # high-signal core checks, seconds
pytest -q                        # the full suite (~9 minutes)
pytest -q -n 8 --dist loadgroup  # parallel (~5.5 minutes)

ruff check .                     # lint
ruff format --check .            # formatting
mypy quill\core quill\io         # type-check (always scoped)

python -m quill.tools.platform_report   # every gate, one scorecard

Beyond the usual suite, the repository enforces its own rules with internal gates: module size budgets (a ratchet -- budgets only decrease), a banned-pattern gate, a dialog inventory and keyboard contract, menu accelerator checks (every enabled menu item shows a keyboard route; no duplicate keys), a network egress audit (every outbound call site is inventoried and consented), and error-code discipline (every custom exception carries a QUILL-* code). CLAUDE.md is the shortest accurate summary of these invariants; python -m quill.tools.platform_report runs them all and exits non-zero on any failure.

Documentation workflow

Every docs/**/*.md ships with rendered .html and .epub siblings, built deterministically (pinned epoch, stable EPUB identifiers, an accessible HTML template with lang, a skip link, and a main landmark). Render through the project's tooling -- python scripts/release_readiness.py rebuilds the docs/ tree as part of the release flow -- rather than calling pandoc by hand, and scripts/check_docs_artifacts.py fails any commit that changes a Markdown source without its regenerated siblings.

Support and issue reporting

Use Help -> Report a Bug inside any of the apps: it generates a diagnostics bundle (secrets scrubbed), previews the report, and submits it -- with a clipboard-and-browser fallback for users with no GitHub setup. On GitHub, use Discussions for questions and ideas, Issues for confirmed bugs and scoped requests.

Contributing

Community contributions are welcome.

License

MIT. See LICENSE.

Legal and Trademark Notices

QUILL for All is an independent open-source project by Community Access. It is not affiliated with, sponsored by, or endorsed by Quill.js, QuillBot, Quill.org, or any other similarly named product, project, company, or organisation. All trademarks are the property of their respective owners.

See TRADEMARKS.md, NOTICE, and THIRD_PARTY_NOTICES.md for more information.

About

Screen-reader-first writing, review, and document-intelligence environment for Windows with guided diagnostics and format workflows

Resources

Code of conduct

Contributing

Security policy

Stars

43 stars

Watchers

6 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages