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.
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.
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 |
- 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
datafolder next to the app, so the whole thing travels. Already have the runtime installed? The Companion zip is the same stick at ~1 MB.
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.
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.weatherNotes 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 ispip 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 alsoQUILL_SAFE_MODE=1. - Running from source uses your real
%APPDATA%\Quilldata folder unless adata\folder with a portable marker sits next to the app; developers can pointQUILL_DATA_DIRsomewhere else (honoured only withQUILL_DEV_BUILD=1).
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/.epubsiblings, 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) plusstandalone/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.
Everything releasable lands under dist/ subtrees, and a local build is
laid out identically to a CI build.
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 orderThere 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.
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:
scripts/check_build_env.py-- the floor: everything[runtime]needs is installed.scripts/check_runtime_inventory.py-- the ceiling: nothing undeclared appeared and nothing declared vanished (baseline:standalone/runtime/runtime-inventory.json).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.
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 scorecardBeyond 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.
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.
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.
Community contributions are welcome.
- CONTRIBUTING.md -- setup, workflow, and PR expectations.
- CODE_OF_CONDUCT.md -- before participating.
- SECURITY.md -- private vulnerability reporting.
- PRIVACY.md -- data handling and retention.
- RESPONSIBLE_AI_USE.md -- ethical and accountable AI use.
- GOVERNANCE.md and MAINTAINERS.md -- how decisions get made.
- Release process and branch policy: RELEASE.md.
MIT. See LICENSE.
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.