Skip to content

Contributing

Contributions are welcome. The canonical guide is CONTRIBUTING.md in the repo; this mirrors it.

Runs on Python 3.10+, tested on Linux · macOS · Windows.

Terminal window
git clone https://github.com/vikast908/WritingAgent.git
cd WritingAgent
python -m venv .venv
source .venv/bin/activate # macOS / Linux
# .venv\Scripts\Activate.ps1 # Windows (PowerShell)
pip install -e ".[dev]" # editable install + pytest + ruff

You 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 - the engine imports them lazily and degrades gracefully without them.

  • Deep-research fetch backend - pip install -e ".[deep]" (Scrapo + Playwright, Python 3.11+), then python -m playwright install chromium for the browser binary.
  • Firecrawl search - set FIRECRAWL_API_KEY in .env and search_provider: firecrawl to swap the default DuckDuckGo backend (a missing key falls back to DuckDuckGo).
Terminal window
pytest

The 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.

Terminal window
ruff check . # lint
ruff format . # format

A .pre-commit-config.yaml is provided - run pre-commit install to lint on commit.

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:

Terminal window
writing-agent web # http://127.0.0.1:8787, auto-opens the browser
writing-agent web --port 9000 --no-browser

It 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.

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.

  • plan.md is the architecture/spec source of truth; resume.md is the running dev journal (newest entry on top). Durable decisions go in plan.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.
  1. Branch off master.
  2. Make the change + add/adjust tests.
  3. ruff check . && pytest locally.
  4. Open a PR describing the change and linking any issue. CI must pass.

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 stable orchestrator/__init__.py facade.
  • nodes.py / prompts.py / schemas.py - the LLM nodes, their prompts (incl. the wrap_untrusted injection fence), and structured outputs.
  • llm.py - OpenRouter wrapper (retry/backoff, timeout, repair, token budget, cost tallies).
  • telemetry.py - per-call JSONL records + the /dashboard aggregation (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, behind shell/__init__.py), one-shot CLI, and the theme registry (incl. the colourblind-safe highcontrast; default editorial “ink & brass”).
  • export.py - pdf · epub · html · docx · txt · md renderers.

See also SECURITY.md and the Changelog.