# Contributing to ReqLLM
Thank you for your interest in contributing to ReqLLM! This guide outlines the expectations and requirements for different types of contributions.
## Table of Contents
- [Contributing to ReqLLM](#contributing-to-reqllm)
  - [Table of Contents](#table-of-contents)
  - [Core Principles](#core-principles)
  - [Types of Contributions](#types-of-contributions)
    - [Core Library Contributions](#core-library-contributions)
    - [New Provider Contributions](#new-provider-contributions)
    - [Provider Feature Extensions](#provider-feature-extensions)
  - [Development Setup](#development-setup)
  - [Testing Requirements](#testing-requirements)
    - [Running Tests](#running-tests)
    - [Fixture Generation](#fixture-generation)
  - [Pull Request Process](#pull-request-process)
  - [Code Quality Standards](#code-quality-standards)
    - [Formatting](#formatting)
    - [Compilation](#compilation)
    - [Static Analysis](#static-analysis)
    - [Linting](#linting)
    - [Combined Check](#combined-check)
    - [Code Style Conventions](#code-style-conventions)
  - [Questions?](#questions)
  - [License](#license)
## Core Principles
ReqLLM is built on two foundational commitments:
1. **Fixture-Based Reliability**: All functionality must be validated against cached fixtures. This ensures reproducible tests without hitting live APIs and maintains reliability across provider changes.
2. **Quality Over Speed**: Code must pass all quality checks (formatting, compilation, dialyzer, credo) before review.
These principles keep the project maintainable and the maintainers sane.
## Types of Contributions
### Core Library Contributions
Core library contributions modify the foundational components of ReqLLM including:
- Core modules (`ReqLLM`, `ReqLLM.Model`, `ReqLLM.Provider`, etc.)
- Data structures (`Context`, `Message`, `StreamChunk`, `Response`, etc.)
- Shared utilities and helpers
- Provider behavior and DSL
- Testing infrastructure
**Requirements:**
✅ **All existing tests must pass**
```bash
mix test
```
✅ **All model compatibility tests must pass**
```bash
mix mc "*:*"
```
✅ **All quality checks must pass**
```bash
mix quality
# Runs: format check, compile with warnings as errors, dialyzer, credo --strict
```
✅ **New functionality requires comprehensive tests**
- Unit tests for new modules/functions
- Integration tests with fixtures where appropriate
- Coverage tests if new API behavior is introduced
✅ **Documentation must be updated**
- Add `@moduledoc` and `@doc` annotations
- Update relevant guides in `guides/`
- Add examples to README if introducing user-facing features
**Pull Request Checklist:**
- [ ] All existing tests pass (`mix test`)
- [ ] All model compatibility tests pass (`mix mc "*:*"`)
- [ ] Quality checks pass (`mix quality`)
- [ ] New tests added for new functionality
- [ ] Documentation updated
- [ ] CHANGELOG.md updated with changes
### New Provider Contributions
Adding a new LLM provider requires implementing the `ReqLLM.Provider` behavior and ensuring comprehensive model coverage.
**Requirements:**
✅ **Provider implementation complete**
- Implement all required callbacks in `lib/req_llm/providers/your_provider.ex`
- Use `ReqLLM.Provider.DSL` for provider registration
- Follow existing provider patterns (see [Adding a Provider Guide](guides/adding_a_provider.md))
✅ **Model metadata configured**
- Provider registry in `priv/models_dev/your_provider.json` (synced via `mix req_llm.model_sync`)
- All models have proper metadata (capabilities, cost, context length, etc.)
✅ **Fixtures generated for all supported models**
```bash
# Generate fixtures for all provider models
mix mc "your_provider:*" --record
```
✅ **Model compatibility tests pass**
```bash
# Verify all models pass
mix mc "your_provider:*"
```
The output should show all models with ✓ status. This is **mandatory** before PR submission.
✅ **Provider-specific tests added**
- Add tests in `test/provider/your_provider_test.exs`
- Use mocked responses (no live API calls in provider tests)
- Cover edge cases, error handling, and provider-specific features
✅ **Quality checks pass**
```bash
mix quality
```
**Pull Request Checklist:**
- [ ] Provider module implemented with all callbacks
- [ ] Model metadata synced and present
- [ ] Fixtures generated for all models (`mix mc "your_provider:*" --record`)
- [ ] All model compatibility tests pass (`mix mc "your_provider:*"`)
- [ ] Provider-specific tests added with mocks
- [ ] Quality checks pass (`mix quality`)
- [ ] Documentation added (provider-specific guide if needed)
- [ ] README updated with provider in supported list
- [ ] CHANGELOG.md updated
**Note:** The responsibility is on the PR author to generate fixtures locally. Reviewers will verify by running `mix mc "your_provider:*"` and expect all models to pass.
### Provider Feature Extensions
Adding new features to existing providers (e.g., file uploads, PDF support, image inputs, text-to-speech, vision capabilities).
**Requirements:**
✅ **Feature implementation complete**
- Modify provider module to support new feature
- Update encoding/decoding logic as needed
- Add parameter validation and options
✅ **Fixtures generated for new feature**
```bash
# Generate fixtures for affected models
LIVE=true mix test --only "provider:your_provider" --only "category:relevant_category"
# Or regenerate specific model fixtures
mix mc "your_provider:specific-model" --record
```
✅ **Tests cover new feature**
- Add coverage tests in `test/coverage/` for high-level API
- Add provider tests in `test/provider/` with mocked responses
- Ensure fixtures demonstrate the new capability
✅ **Model compatibility maintained**
```bash
# Verify affected models still pass
mix mc "your_provider:*"
```
✅ **Quality checks pass**
```bash
mix quality
```
**Pull Request Checklist:**
- [ ] Feature implemented in provider module
- [ ] Fixtures generated for new feature
- [ ] Tests added covering new functionality
- [ ] All model compatibility tests pass for affected provider
- [ ] Quality checks pass (`mix quality`)
- [ ] Documentation updated (API reference, provider guide)
- [ ] Example usage added to README or guides
- [ ] CHANGELOG.md updated
## Development Setup
```bash
# Clone the repository
git clone https://github.com/agentjido/req_llm.git
cd req_llm
# Install dependencies
mix deps.get
# Set up API keys (copy and configure)
cp .env.example .env
# Edit .env with your API keys
# Verify setup
mix test
mix quality
```
## Testing Requirements
ReqLLM uses a three-tier testing architecture:
1. **Core Package Tests** (`test/req_llm/`): Unit tests with no API calls
2. **Provider Tests** (`test/provider/`): Mocked provider-specific tests
3. **Coverage Tests** (`test/coverage/`): Live API tests with fixture caching
### Running Tests
```bash
# Run all tests with cached fixtures
mix test
# Run tests against live APIs (regenerate fixtures)
LIVE=true mix test
# Run specific provider tests
mix test --only "provider:anthropic"
# Run specific category tests
mix test --only "category:core"
# Run model compatibility checks
mix mc                          # Show fixture status for all models
mix mc "*:*"                    # Run tests for all models
mix mc "anthropic:*"           # Run tests for all Anthropic models
mix mc "openai:gpt-4o"         # Run tests for specific model
mix mc --sample                # Run tests for sample subset
```
### Fixture Generation
Fixtures are the backbone of ReqLLM's reliability:
- **Cached by default**: Tests run against cached JSON fixtures
- **Generated with LIVE=true**: Set `LIVE=true` to hit real APIs and regenerate fixtures
- **Stored alongside tests**: Fixtures live in `test/.../fixtures/provider/test_name.json`
- **Required for all new features**: Every new capability must have fixture coverage
```bash
# Generate fixtures for a new test
LIVE=true mix test test/coverage/your_new_test.exs
# Regenerate all fixtures for a provider
mix mc "provider:*" --record
# Regenerate fixtures for a specific model
mix mc "provider:specific-model" --record
```
## Pull Request Process
1. **Fork and Branch**
   ```bash
   git checkout -b feature/your-feature-name
   ```
2. **Develop with Tests**
   - Write tests first (TDD encouraged)
   - Ensure tests pass with fixtures
   - Run quality checks frequently
3. **Generate/Update Fixtures**
   ```bash
   # For new features
   LIVE=true mix test test/path/to/your_test.exs
   
   # For new providers
   mix mc "your_provider:*" --record
   ```
4. **Verify Everything Passes**
   ```bash
   mix test                    # All tests
   mix mc "*:*"                # Model compatibility (or specific provider pattern)
   mix quality                 # Code quality
   ```
5. **Update Documentation**
   - Add/update module docs
   - Update guides if needed
   - Add CHANGELOG entry
6. **Submit Pull Request**
   - Use descriptive title
   - Reference related issues
   - Include checklist from relevant contribution type above
   - **Include output of `mix mc "*:*"` (or provider-specific pattern) showing passing models**
7. **Review Process**
   - Maintainer will run `mix mc "*:*"` (or provider-specific) to verify fixtures
   - Maintainer will review code quality and tests
   - Address feedback and update PR
## Code Quality Standards
All contributions must meet these standards:
### Formatting
```bash
mix format
mix format --check-formatted  # In CI
```
### Compilation
```bash
mix compile --warnings-as-errors
```
### Static Analysis
```bash
mix dialyzer
```
### Linting
```bash
mix credo --strict
```
### Combined Check
```bash
mix quality  # Runs all of the above
```
### Code Style Conventions
- **No inline comments in function bodies**: Code should be self-documenting through clear naming and structure
- **Use `@moduledoc` and `@doc`**: All public modules and functions must have documentation
- **TypedStruct for data structures**: Use TypedStruct with `@type` definitions
- **Splode for errors**: Return `{:ok, result}` or `{:error, %ReqLLM.Error{}}` tuples
- **NimbleOptions for validation**: Validate public API options with schemas
- **Pattern matching over conditionals**: Prefer pattern matching when possible
- **Explicit module calls**: Minimize imports, prefer `Module.function()` style
See [AGENTS.md](AGENTS.md) for complete style guide and architecture details.
## Questions?
- **Documentation**: Check [guides/](guides/) for detailed implementation guides
- **Issues**: Open an issue for questions or bug reports
- **Discussions**: Use GitHub Discussions for general questions
- **Examples**: Look at existing providers for implementation patterns
## License
By contributing to ReqLLM, you agree that your contributions will be licensed under the Apache License 2.0.
---
Thank you for helping make ReqLLM better! Your contributions make this library more reliable, feature-rich, and valuable for the Elixir community.