Thank you for your interest in contributing to Patter!
cd libraries/python
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest tests/ -vNote: the legacy
[local]extra is now an empty alias kept only for backwards compatibility —[dev]is sufficient.
cd libraries/typescript
npm install
npm test
npm run build- Fork the repository
- Create a feature branch:
git checkout -b feat/my-feature - Write tests first (TDD)
- Implement the feature
- Ensure all tests pass:
pytest tests/ -v/npm test - Commit with conventional commits:
feat:,fix:,docs: - Validate locally:
bash scripts/pr-validate.sh(see below) - Open a Pull Request against
main
These are the things CI (and reviewers) will block on. Catch them locally:
- Both SDKs. Every user-visible feature ships in Python AND
TypeScript in the same PR — same API shape and defaults,
snake_case↔camelCase. There is no "Python-only" / "TS-only" public surface. -
CHANGELOG.md. Add an entry under## Unreleased(### Added/### Changed/### Fixed/ …) for any user-visible change. Pure refactors, test-only, and docs-only diffs are exempt. -
bash scripts/pr-validate.shis green (mirrors the PR-blocking CI). - No external license headers / "ported from " provenance comments in source. Naming a provider/carrier you integrate (Twilio, Telnyx, Plivo, OpenAI, …) is fine; copying a competitor's lineage is not.
AI agents (Claude Code, Cursor, Codex, …): see
AGENTS.mdfor the same checklist in a machine-readable form.
Run every PR-blocking CI check locally before opening the PR:
bash scripts/pr-validate.sh # default: ~3-5 min
bash scripts/pr-validate.sh --quick # pre-commit + lint (~30s)
bash scripts/pr-validate.sh --full # default + e2e + all-extras (~10 min)The script mirrors .github/workflows/test.yml so a green local run lines up
with green CI. Selective skips: --skip-py, --skip-ts, --no-stop.
First-time setup:
pip install pre-commit==3.8.0 # required
brew install gitleaks # optional — system fallbackIf pre-commit's bundled tools don't work on your machine (hardened macOS, Go OOM during gitleaks build), use the documented escape hatches:
PR_VALIDATE_SKIP_GITLEAKS=1 PR_VALIDATE_SKIP_NBSTRIPOUT=1 bash scripts/pr-validate.shCI always runs the full unaltered suite, so these only affect local runs.
- Follow PEP 8
- Use type hints on all public methods
- Use
logging.getLogger("getpatter")— neverprint() - Frozen dataclasses for models
- Async everywhere — no blocking I/O
- Strict TypeScript — no
any - Use
WebSocket.OPENnot magic numbers - Export all public types from
index.ts xmlEscape()for all TwiML strings
Patter uses an instance-based class pattern (post-0.5.0). To add a new STT, TTS, or LLM provider:
- Create the provider class:
- Python:
libraries/python/getpatter/stt/<name>.py,libraries/python/getpatter/tts/<name>.py, orlibraries/python/getpatter/llm/<name>.pyexporting a class namedSTT,TTS, orLLM. - TypeScript:
libraries/typescript/src/stt/<name>.ts,libraries/typescript/src/tts/<name>.ts, orlibraries/typescript/src/llm/<name>.tsexportingSTT,TTS, orLLM.
- Python:
- Read credentials from the standard env var (e.g.
<NAME>_API_KEY) when noapi_key/apiKeyis passed; throw a clear error when both are missing. - Re-export a flat alias from the package barrel (
getpatter/__init__.pyfor Python,libraries/typescript/src/index.tsfor TypeScript) — for exampleSTT as DeepgramSTT. - Wire the new class into the pipeline dispatch (stream handler) for end-to-end audio flow.
- Add a default pricing entry under
DEFAULT_PRICINGso users see real cost numbers in the dashboard. - Add unit + integration tests; aim for 80%+ coverage on the new module.
- Update the docs:
docs/{python,typescript}-sdk/{stt,tts,llm}.mdxand the per-provider page underdocs/{python,typescript}-sdk/providers/<name>.mdxif applicable.
- Use the issue templates
- Include SDK version, Node/Python version, OS
- Enable debug logging:
logging.getLogger("getpatter").setLevel(logging.DEBUG)