Contributing to CCProxy API¶
Thank you for your interest in contributing to CCProxy API! This guide will help you get started.
Development Setup¶
Prerequisites¶
Initial Setup¶
- Clone and setup the repository:
Note: Pre-commit hooks are automatically installed with
./Taskfile setup
Development Workflow¶
1. Create a Feature Branch¶
2. Make Changes¶
- Follow existing code patterns (see CONVENTIONS.md)
- Add tests for new functionality
- Update documentation as needed
3. Quality Checks (Required Before Commits)¶
# Recommended: Run comprehensive checks with auto-fixes
./Taskfile pre-commit
# Alternative: Run individual checks
./Taskfile format # Format code
./Taskfile lint # Check linting
./Taskfile typecheck # Check types
./Taskfile test-unit # Run fast tests
4. Commit Your Changes¶
Pre-commit hooks run automatically on commit:
git add specific/files.py # Never use git add .
git commit -m "feat: add new feature"
# If hooks modify files, stage and commit again:
git add .
git commit -m "feat: add new feature"
5. Full Validation¶
Before pushing:
6. Push and Create PR¶
Code Quality Standards¶
Quality Gates¶
All code must pass these checks before merging:
| Check | Command | Purpose | Auto-fix |
|---|---|---|---|
| Formatting | ./Taskfile format |
Code style consistency | ✅ |
| Linting | ./Taskfile lint |
Error detection | Partial (./Taskfile lint-fix) |
| Type Checking | ./Taskfile typecheck |
Type safety | ❌ |
| Tests | ./Taskfile test |
Functionality | ❌ |
| Pre-commit | ./Taskfile pre-commit |
All checks combined | ✅ |
Architecture: DI & Services¶
This project uses a container-first dependency injection (DI) pattern. Follow these rules when adding or refactoring code:
- Use the service container exclusively
- Access services via
app.state.service_containeror FastAPI dependencies. -
Never create new global singletons or module-level caches for services.
-
Register services in the factory
- Add new services to
ccproxy/services/factories.pyusingcontainer.register_service(...). -
Prefer constructor injection and small factory methods over service locators.
-
Hook system is required
HookManageris created at startup and registered in the container.-
FastAPI dep
HookManagerDepis required; do not make it optional. -
No deprecated globals
- Do not use
ccproxy.services.http_pool.get_pool_manager()or any global helpers. -
Always resolve
HTTPPoolManagerviacontainer.get_pool_manager(). -
Settings access
- Use
Settings.from_config(...)in CLI/tools and tests. The legacyget_settings()helper was removed.
Adding a New Service¶
1) Register in the factory:
# ccproxy/services/factories.py
self._container.register_service(MyService, factory=self.create_my_service)
def create_my_service(self) -> MyService:
settings = self._container.get_service(Settings)
return MyService(settings)
2) Resolve via container in runtime code:
container: ServiceContainer = request.app.state.service_container
svc = container.get_service(MyService)
3) For FastAPI dependencies, use the shared helper:
Streaming and Hooks¶
StreamingHandlermust be constructed with aHookManager(the factory enforces this).- Do not patch dependencies after construction; ensure ordering via DI.
Testing with the Container¶
- Prefer constructing a
ServiceContainer(Settings.from_config(...))in tests. - Override services by re-registering instances for the type under test:
This pattern keeps tests isolated and avoids cross-test state.
Running Tests¶
The CCProxy test suite uses a streamlined architecture with 606 focused tests organized by type:
# All tests with coverage (recommended)
./Taskfile test
# Fast unit tests only - isolated components, service boundary mocking
./Taskfile test-unit
# Integration tests - cross-component behavior, minimal mocking
./Taskfile test-integration
# Plugin tests - centralized plugin testing
./Taskfile test-plugins
# Coverage report with HTML output
./Taskfile test-coverage
# Specific patterns
./Taskfile test-file tests/unit/auth/test_auth.py
./Taskfile test-match authentication
Test Organization¶
- Unit tests (
tests/unit/): Fast, isolated tests with mocking at service boundaries only - Integration tests (
tests/integration/): Cross-component tests with minimal mocking - Plugin tests (
tests/plugins/): Centralized plugin testing by plugin name - Performance tests (
tests/performance/): Dedicated performance benchmarks
Test Architecture Principles¶
- Clean boundaries: Mock external services only, test real internal behavior
- Type safety: All tests require
-> Nonereturn annotations and proper typing - Fast execution: Unit tests run in milliseconds with no timing dependencies
- Modern patterns: Session-scoped fixtures, async factory patterns, streamlined fixtures
Plugin Development¶
Creating a New Plugin¶
-
Create plugin structure:
ccproxy/plugins/your_plugin/ ├── __init__.py ├── adapter.py # Main interface (required) ├── plugin.py # Plugin declaration (required) ├── routes.py # API routes (optional) ├── transformers/ # Request/response transformation │ ├── request.py │ └── response.py ├── detection_service.py # Capability detection (optional) ├── format_adapter.py # Protocol conversion (optional) └── auth/ # Authentication (optional) └── manager.py -
Implement the adapter (delegation pattern):
-
Register in pyproject.toml:
-
Add tests:
Commit Message Format¶
Follow Conventional Commits:
feat: add user authentication
fix: resolve connection pool timeout
docs: update API documentation
test: add streaming integration tests
refactor: extract pricing service
chore: update dependencies
CI/CD Pipeline¶
GitHub Actions Workflows¶
| Workflow | Trigger | Checks |
|---|---|---|
| CI | Push/PR to main, develop | Linting, types, tests (Python 3.11-3.13) |
| Build | Push to main | Docker image build and push |
| Release | Git tag/release | PyPI publish, Docker release |
| Docs | Push to main/dev | Documentation build and deploy |
Local CI Testing¶
Test the full CI pipeline locally:
Common Development Tasks¶
Running the Dev Server¶
Debugging Requests¶
# Enable verbose logging
CCPROXY_VERBOSE_API=true \
CCPROXY_REQUEST_LOG_DIR=/tmp/ccproxy/request \
./Taskfile dev
# View last request
scripts/show_request.sh
Building and Testing Docker¶
Documentation¶
Troubleshooting¶
Type Errors¶
Formatting Issues¶
Linting Errors¶
Test Failures¶
# Run specific failing test with verbose output
uv run pytest tests/test_file.py::test_function -vvs
# Debug with print statements
uv run pytest tests/test_file.py -s
Pre-commit Hook Failures¶
# Run manually to see all issues
./Taskfile pre-commit
# Skip hooks temporarily (not recommended)
git commit --no-verify -m "WIP: debugging"
Project Structure¶
ccproxy-api/
├── ccproxy/ # Core application
│ ├── api/ # FastAPI routes and middleware
│ ├── auth/ # Authentication system
│ ├── config/ # Configuration management
│ ├── core/ # Core utilities and interfaces
│ ├── models/ # Pydantic models
│ └── services/ # Business logic services
├── ccproxy/plugins/ # Provider plugins
│ ├── claude_api/ # Claude API plugin
│ ├── claude_sdk/ # Claude SDK plugin
│ ├── codex/ # OpenAI Codex plugin
│ └── ... # Other plugins
├── tests/ # Test suite
│ ├── unit/ # Unit tests
│ ├── integration/ # Integration tests
│ └── fixtures/ # Test fixtures
├── docs/ # Documentation
├── scripts/ # Utility scripts
└── Makefile # Development commands
Getting Help¶
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: See
docs/directory and inline code documentation
Code of Conduct¶
- Be respectful and inclusive
- Focus on constructive feedback
- Help others learn and grow
License¶
By contributing, you agree that your contributions will be licensed under the same license as the project (see LICENSE file).