Thank you for your interest in contributing to Quorum! This document provides guidelines and instructions for contributing.
By participating in this project, you agree to abide by our Code of Conduct.
If you find a bug, please open an issue with:
- A clear, descriptive title
- Steps to reproduce the issue
- Expected vs actual behavior
- Your environment (OS, Python version, Quorum version)
We welcome feature suggestions! Please open a feature request with:
- A clear description of the problem you're trying to solve
- Your proposed solution
- Any alternatives you've considered
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests (
pytest) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Clone your fork
git clone https://github.com/YOUR_USERNAME/quorum-cli.git
cd quorum-cli
# Run the install script
./install.sh
# Create .env with your API keys (for live testing)
cp .env.example .env
# Edit .env with your keys
# Run tests
pytest # Unit tests (no API keys needed)
pytest tests/test_live.py -v # Live tests (requires API keys)- We use ruff for linting
- Run
uvx ruff check src/before submitting PRs (oruvx ruff check src/ --fixto auto-fix) - Follow existing code patterns and naming conventions
- Add type hints where possible
- Write docstrings for public functions
- Write tests for new functionality
- Ensure all tests pass before submitting PR
- Unit tests should not require API keys (use mocking)
- Live/integration tests should be marked with
@pytest.mark.live
# Run all unit tests (no API keys needed)
pytest tests/ -v -m "not live"
# Run specific test file
pytest tests/test_agents.py -v
# Run live tests (requires API keys)
pytest tests/test_live.py -vquorum-cli/
├── src/quorum/ # Main source code
│ ├── clients/ # Direct SDK clients (OpenAI, Anthropic)
│ │ ├── types.py # Message dataclasses, ChatClient protocol
│ │ ├── openai_client.py # OpenAI-compatible client
│ │ └── anthropic_client.py # Anthropic client
│ ├── methods/ # Discussion method orchestrators
│ │ ├── base.py # BaseMethodOrchestrator, message types
│ │ ├── standard.py # StandardMethod
│ │ ├── oxford.py # OxfordMethod
│ │ └── ... # Other methods
│ ├── agents.py # Prompt templates and method logic
│ ├── config.py # Settings and configuration
│ ├── constants.py # Version, limits, timeouts
│ ├── ipc.py # JSON-RPC communication
│ ├── models.py # Model client factory, connection pooling
│ ├── providers.py # Provider detection
│ └── team.py # Main orchestration
├── frontend/ # React/Ink terminal UI
│ ├── src/
│ │ ├── components/ # UI components
│ │ ├── ipc/ # IPC client and protocol types
│ │ └── store/ # Zustand state management
├── tests/ # Test suite
├── docs/ # Documentation
│ └── api/ # API specifications
└── examples/ # Integration examples
Quorum uses a split architecture with a Python backend and React/Ink frontend communicating via JSON-RPC over stdin/stdout.
┌─────────────────────────────────────────────────────────────────┐
│ Frontend (React/Ink) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ UI │ → │ Store │ → │ IPC │ → │ stdin │ │
│ │Components│ ← │ (Zustand)│ ← │ Client │ ← │ stdout │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
↕ JSON-RPC (NDJSON)
┌─────────────────────────────────────────────────────────────────┐
│ Backend (Python) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ IPC │ → │ Team │ → │ Models │ → │ AI │ │
│ │ Handler │ ← │Orchestr. │ ← │ Client │ ← │ APIs │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
| Component | Responsibility |
|---|---|
clients/ |
Direct SDK clients (OpenAI, Anthropic) with unified ChatClient protocol |
methods/ |
Discussion method orchestrators (Standard, Oxford, Socratic, etc.) |
ipc.py |
JSON-RPC request handling, event emission, input validation |
team.py |
Discussion orchestration, phase management, lazy method loading |
agents.py |
Prompt templates, method requirements, role assignments |
models.py |
Model client factory, connection pooling, validation |
providers.py |
Provider detection, Ollama auto-discovery |
config.py |
Settings from .env, user preferences, cache management |
constants.py |
Version info, protocol version, limits, timeouts |
| Component | Responsibility |
|---|---|
ipc/client.ts |
Spawns backend, handles JSON-RPC communication |
ipc/protocol.ts |
TypeScript types for IPC messages |
store/index.ts |
Zustand state management |
components/*.tsx |
React/Ink UI components |
The backend emits typed messages during discussion:
| Message Type | Description |
|---|---|
PhaseMarker |
Phase transitions |
IndependentAnswer |
Phase 1 responses |
CritiqueResponse |
Phase 2 structured critiques |
TeamTextMessage |
Discussion messages with role/round metadata |
FinalPosition |
Phase 4 positions with confidence |
SynthesisResult |
Final synthesis with consensus status |
ThinkingIndicator |
Model is generating response |
1. Frontend sends run_discussion request
2. Backend creates FourPhaseConsensusTeam
3. Team.run_stream() yields messages:
├── PhaseMarker (phase 1)
├── IndependentAnswer (each model)
├── PhaseMarker (phase 2)
├── CritiqueResponse (each model)
├── ... (method-specific phases)
└── SynthesisResult
4. IPC handler converts to events
5. Frontend updates UI via store
- Add detection pattern in
providers.py - Add client factory case in
models.py - Add settings in
config.py - Update
.env.example
See docs/tutorials/ADDING_A_METHOD.md
- Add handler in
ipc.pyhandler_map - Add TypeScript types in
protocol.ts - Add client method in
client.ts - Update
docs/api/IPC_PROTOCOL.md
The IPC protocol uses semantic versioning. When making changes:
- PATCH: Bug fixes, documentation
- MINOR: New methods/events (backward compatible)
- MAJOR: Breaking changes to existing methods/events
Update PROTOCOL_VERSION in both:
src/quorum/constants.pyfrontend/src/ipc/protocol.ts
- Use clear, descriptive commit messages
- Start with a verb (Add, Fix, Update, Remove, etc.)
- Reference issues when applicable (
Fixes #123)
Feel free to open a Discussion for questions or ideas that don't fit into issues.
By contributing, you agree that your contributions will be licensed under the project's Business Source License 1.1.