Contributing
Contributions are welcome. The canonical guide is
CONTRIBUTING.md
in the repo; this mirrors it.
Development setup
Section titled “Development setup”Runs on Python 3.10+, tested on Linux · macOS · Windows.
git clone https://github.com/vikast908/WritingAgent.gitcd WritingAgent
python -m venv .venvsource .venv/bin/activate # macOS / Linux# .venv\Scripts\Activate.ps1 # Windows (PowerShell)
pip install -e ".[dev]" # editable install + pytest + ruffYou do not need an API key to develop or run the tests - see fake mode below. Add one
(cp .env.example .env, set OPENROUTER_API_KEY) only for real runs.
Optional extras
Section titled “Optional extras”Optional - the engine imports them lazily and degrades gracefully without them.
- Deep-research fetch backend -
pip install -e ".[deep]"(Scrapo + Playwright, Python 3.11+), thenpython -m playwright install chromiumfor the browser binary. - Firecrawl search - set
FIRECRAWL_API_KEYin.envandsearch_provider: firecrawlto swap the default DuckDuckGo backend (a missing key falls back to DuckDuckGo).
Running tests
Section titled “Running tests”pytestThe suite runs fully offline. Pipeline tests use fake mode (WRITINGAGENT_FAKE=1), where
every LLM node returns deterministic placeholder output - no network, no key. Brain and
index isolation is autouse, so tests never touch your real telemetry or projects.
Linting & formatting
Section titled “Linting & formatting”ruff check . # lintruff format . # formatA .pre-commit-config.yaml is provided - run pre-commit install to lint on commit.
Running the web dashboard
Section titled “Running the web dashboard”The browser UI lives in src/writingagent/webui/ - a pure-stdlib ThreadingHTTPServer + SSE
backend (server.py) and a single-page app under static/. There is no build step and no
bundler; just run:
writing-agent web # http://127.0.0.1:8787, auto-opens the browserwriting-agent web --port 9000 --no-browserIt binds 127.0.0.1 only with no auth and runs one job at a time - see the
HTTP API for the endpoints. webui/server.py calls the same engine facade the
TUI does, so a change to the pipeline shows up in both without extra wiring.
Design system
Section titled “Design system”Both the web dashboard and the TUI follow the editorial design system spec’d in design.md
at the repo root (ink on warm paper, one accent - manuscript red #a3341f - the Fraunces display
serif, the pilcrow ¶ mark, WCAG-AA verified). Values are tokens: port them 1:1 to CSS vars for
the web app or to a ui.THEMES palette for the TUI. Named themes recolor but never restructure -
match design.md rather than hand-picking colors.
Conventions
Section titled “Conventions”plan.mdis the architecture/spec source of truth;resume.mdis the running dev journal (newest entry on top). Durable decisions go inplan.md.- Keep nodes deterministic LLM calls (see
plan.md§4) - don’t add free-roaming agentic behavior; the orchestrator decides the sequence. - Network/IO is best-effort: degrade gracefully, never crash the pipeline on a fetch error.
- All numeric thresholds are tunable config (
config/settings.yaml), not hard-coded. - Cross-platform: use
pathlib, avoid shelling out, don’t assume a POSIX or Windows path layout. CI runs the suite on all three OSes across Python 3.10–3.13 - keep it green.
Submitting changes
Section titled “Submitting changes”- Branch off
master. - Make the change + add/adjust tests.
ruff check . && pytestlocally.- Open a PR describing the change and linking any issue. CI must pass.
Architecture tour
Section titled “Architecture tour”A 60-second map (full detail in Architecture and plan.md):
orchestrator/- durable on-disk state machine (the brain is the checkpoint); a package (common · book · article · export · manage · review) behind a stableorchestrator/__init__.pyfacade.nodes.py/prompts.py/schemas.py- the LLM nodes, their prompts (incl. thewrap_untrustedinjection fence), and structured outputs.llm.py- OpenRouter wrapper (retry/backoff, timeout, repair, token budget, cost tallies).telemetry.py- per-call JSONL records + the/dashboardaggregation (per-node / per-unit cost attribution behind the Telemetry / Cost views).brain.py/store.py- markdown filesystem layout + SQLite/FTS canon & graph.search.py/deep_research.py/images.py/cache.py- the optional research stack (search_provider: DuckDuckGo default, Firecrawl opt-in).seo.py/promote.py- the local promotion layer: on-page SEO audit + keyword pack, and platform variants / headline variants / restyle. Both write local artifacts only.webui/- the local web dashboard (server.py+static/); see above.shell//cli//ui.py- Rich TUI (a package:branding · help · commands · dashboard · chat · dispatch · slash · session · repl, behindshell/__init__.py), one-shot CLI, and the theme registry (incl. the colourblind-safehighcontrast; defaulteditorial“ink & brass”).export.py- pdf · epub · html · docx · txt · md renderers.
See also SECURITY.md
and the Changelog.