Thank you for helping improve QUILL.
QUILL is a screen-reader-first Windows writing environment. Contributions should preserve that core direction: practical keyboard workflows, stable editing, accessible defaults, and clear user control.
- Read the product expectations and full architecture in
docs/QUILL-PRD.md(the single source of truth), and the architecture overview below. - Review project conduct rules in
CODE_OF_CONDUCT.md. - Check existing issues and pull requests before starting overlapping work.
- Review project decision process in
GOVERNANCE.md.
QUILL is a layered desktop application with strict boundaries that exist to
preserve accessibility behavior and testability. The canonical, detailed
specification lives in docs/QUILL-PRD.md; this section is the short version
contributors need day to day.
quill/core— pure domain logic: documents, command registry, settings, keymap, recent files, history, metrics, and storage primitives. Nowximports and no direct UI ownership; strict-typed and gated in CI.quill/io— format readers/writers and detection. The contract isread(path) -> Document, optionalwrite(doc, path), optionaloutline(doc); also strict-typed.quill/ui— wxPython shell, editor surface, menus, status bar, dialogs, and command palette. UI composescore+ioand owns widget lifecycle (gradual typing).quill/platform/windows— Windows-specific bridges (screen-reader announcements, DPAPI secrets, shell integration, single-instance, TTS).quill/plugins— plugin-facing API surfaces and manifest model.quill/tools— internal CLIs and gates (a11y audit, diagnostics, characterization and registry checks).
A user action enters through quill/ui/main_frame.py (MainFrame), dispatches
to core.commands.CommandRegistry, reads/writes a core.document.Document,
persists through io or core.storage, and surfaces the outcome through status
updates and platform.windows.sr_announce.announce.
coreandionever importwx; keepwxconfined toquill/uiandquill/platform/windows.uidoes not perform raw persistence; it callscorehelpers (settings, keymap, recent) andiofor document I/O.- Persistent writes are atomic via
core.storage.write_json_atomic(temp file +os.replace), with schema validation and.bak/recovery. - The single UI thread owns all widgets; background I/O and heavier compute run
off-thread, network/AI runs async behind explicit consent, and all cross-thread
UI updates marshal through
wx.CallAfter/wx.CallLater. core.events.CancelTokenis the shared cancellation primitive; long-running tasks accept and check it at safe boundaries.- No silent network calls: every cloud/AI action is explicit, per-action opt-in with visible progress and outcome.
- Install Python 3.12.
- Install dependencies:
pip install -e ".[ui,dev]"
- Run QUILL locally:
python -m quill- Or use a run-from-source launcher, which syncs dependencies and opens
Quill in one step:
run-from-source.bat(Windows),run-from-source.sh(any shell), andrun-from-source.command(macOS — double-click in Finder, which runs.commandfiles in Terminal the way.shfiles will not; #923). On macOS the first run may be blocked by Gatekeeper quarantine; right-click and choose Open once to trust it.
- Create a feature branch from
main. - Keep changes focused and small enough to review.
- Error-specificity review rule: a new user-visible error must name the
specific condition ("The [APIKey] section is missing from Access.ini",
not "could not read the file") and, where a next action exists, say it
(a menu path, a setting, a command). Coded errors get their what-to-do
sentence from
USER_HINTSinquill/core/error_codes.py(or a classuser_hint); surfaces display exceptions throughuser_facing_message. A blind user cannot open the failing file to see what went wrong — the message must carry the whole diagnosis and the next step.
- Error-specificity review rule: a new user-visible error must name the
specific condition ("The [APIKey] section is missing from Access.ini",
not "could not read the file") and, where a next action exists, say it
(a menu path, a setting, a command). Coded errors get their what-to-do
sentence from
- Follow the current module boundaries:
quill/core: nowximportsquill/ui: UI behavior and dialogsquill/io: format readers/writersquill/platform/windows: Windows-specific integration
- Prefer existing helpers and patterns over introducing parallel paths.
- Keep user-facing text clear and accessibility-friendly.
Run these before opening a pull request:
- Lint:
ruff check . - Format check:
ruff format --check . - Scoped strict type-check:
mypy quill\core quill\io - Tests:
pytest tests/unit/ tests/stability/ -q --ignore=tests/unit/core/test_net_tls.py --ignore=tests/unit/core/test_thesaurus.py - Docs artifact parity (if docs changed):
python scripts/check_docs_artifacts.py
Type-checking is intentionally scoped to quill\core and quill\io. These
layers are strict-typed and gated in CI. Do not run an unscoped whole-tree
mypy scan: quill\ui is excluded (gradual typing) in pyproject.toml, so a
whole-tree run is both slower and noisier without adding signal. Always use the
scoped command above.
To catch formatting, lint, and undefined-name problems on changed files before they reach CI, install the hooks once:
pip install pre-commit
pre-commit installThe hooks run ruff format, ruff check, and an undefined-name check on the
files you are committing. Commits that fail are blocked locally.
If your change updates docs/*.md, regenerate matching artifacts:
pandoc docs\\<name>.md -f gfm -t html5 -s -o docs\\<name>.htmlpandoc docs\\<name>.md -f gfm -t epub3 -o docs\\<name>.epub
A strong PR includes:
- A clear summary of what changed and why.
- Notes on accessibility impact, if any.
- Notes on risk or migration impact, if any.
- Evidence of the checks you ran.
Please avoid mixing unrelated refactors with feature or bug-fix work.
Quillins are small, sandboxed extensions that add commands, snippets, menus, and hotkeys to QUILL. Contributing one has its own dedicated path:
- Tutorial —
docs/quillins.md: a hands-on, build-it-from-scratch walkthrough (Layer 1 snippet → Layer 2 handler → lint → test → submit). - Submission guide —
docs/quillins.md: the process, directory layout, review criteria, and acceptance checklist. - Author Covenant —
docs/quillins.md: the code of conduct for Quillin code (accessibility, capability honesty, no silent network, security). Every submission attests to it. - Self-lint —
python -m quill.tools.quillin_lint <dir> --strictmust be green; theQuillin VerifyCI gate runs it on every submission. - Start a submission — open the Quillin submission issue (it scaffolds
the
manifest.json), then open a PR with the Quillin submission PR template.
Quill is built on open-source foundations and integrates best practices from the accessibility community:
-
AccessibleApps — Christopher Toth and contributors (https://github.com/accessibleapps/) contribute several libraries that are essential to Quill's accessibility and cross-platform reliability:
app_updater(MIT) — cross-platform incremental update delivery and automatic installer bootstrapper. Vendored atquill/_vendor/autoupdate/.smart_list(MIT) — accessible, model-based list view for large outlines and datasets.accessible_output2(MIT) — optional fallback for speech and braille output when Prism is unavailable.html_to_text(MIT) — converts HTML from clipboard pastes to clean, structured plain text. Used inquill/ui/html_paste_cleaner.py.app_elements,platform_utils,keyboard_handler— small cross-platform utilities for dialogs, clipboard, and hotkeys.
Full license text is reproduced in
docs/legal/THIRD_PARTY_NOTICES.md. -
liblouis 3.38.0 (https://github.com/liblouis/liblouis, LGPL-2.1-or-later) — open-source braille translation and back-translation library that powers the QUILL Braille Pack. Provides UEB Grade 1 and Grade 2, Standard American English, and dozens of international language tables through its
lou_translateruntime. The Braille Pack is an optional installer component; liblouis is only present when it is selected. Full license text is shipped alongside the pack asCOPYINGandCOPYING.LESSER. -
Prism (NVIDIA) — modern screen-reader backend for announcements and accessibility bridging.
Contributors who integrate third-party libraries from AccessibleApps or other open-source projects should document the license, purpose, and API contract in the relevant module docstring, and update this section when adding a new external dependency.
- For product/support issues, users can use in-app
Help -> Report a Bug. - For repository work, open a GitHub issue with:
- expected behavior
- actual behavior
- reproduction steps
- environment details
- Use the most specific issue template available (accessibility, AI, intake, snippets, dictation, performance, Quillin submission, or general bug/feature).
- Use GitHub Discussions for Q&A and early design exploration.
Do not open public issues for vulnerabilities. Follow SECURITY.md for private
reporting.
Before opening a PR, quickly sanity-check security posture:
- No secrets or credentials in code, tests, fixtures, or docs.
- No user document content added to logs/diagnostics paths.
- New network calls are explicit and user-controlled.
- New file/command paths are validated and not shell-interpolated.
Localization contributors should follow:
docs/translating.md
The following people have contributed code, tests, accessibility feedback, or documentation to QUILL. Thank you.
- Taylor Arndt (@taylorarndt)
- Michael Doise (@mikedoise)
- Doug Langley (@douglangley)
- Becky K (@BeckyK102125)
- Kelly Ford (@kellylford) — Vision Prompt Library (#195, #248): 12 IDT-evaluated image description styles, pre-describe picker, retry-in-dialog, VisionPromptManagerDialog, and AI Hub integration; HEIC/HEIF image support (#164, #165). Kelly is also the author of the Image Description Toolkit, a set of experimental tools for accessible image interaction that informed the prompt styles shipped here. His other accessibility-first projects include QuickMail (accessible IMAP client), RSSQuick (accessible WPF RSS reader), and ChatViewer (GitHub Copilot Chat viewer).
Releases are cut from main. Hotfixes may use short-lived release/x.y.z branches when needed.
Before tagging a release:
ruff check .pytest -qpython scripts/check_docs_artifacts.py- Windows packaging workflow readiness (
.github/workflows/windows-release.yml)
Documentation follows the per-app rule (see standalone/README.md): a change to a companion app (Radio, Cast, Weather, Converter, Audio Studio, Beacon, Social) is documented in that app's own standalone/<app>/CHANGELOG.md and docs/ files; a change to QUILL proper is documented in the repo-root files below; a shared change (announcement service, QuillVille menu, tray hotkeys, updater, dialog conventions) is documented in QUILL's files and mirrored into every affected app's changelog, so an app's user can learn everything about their app from that app's own docs.
Release notes are prepared in a release notes file with the version as a part of its naming convention ('release0.7.0.md'). The file is then converted to epub and html file formats for distribution by Pandoc. CHANGELOG.md carries the same content in abbreviated form. All three files should be
updated and committed before tagging.
Versioning follows semantic intent for user-visible behavior:
- Patch: bug fixes and low-risk changes
- Minor: additive features and workflow improvements
- Major: breaking changes or large platform shifts
main is branch-protected with required checks and pull-request reviews. Admin bypass remains
enabled for emergency direct commits; these must be followed by a post-merge explanation and
follow-up remediation if needed.
By contributing, you agree that your contributions are licensed under the repository's MIT license.