Thank you for your interest in contributing to ClaudeBox! This document provides guidelines and instructions for contributing.
By participating in this project, you agree to maintain a respectful and inclusive environment for all contributors.
There are many ways to contribute to ClaudeBox:
- Code: Fix bugs, add features, improve performance
- Documentation: Improve docs, write tutorials, fix typos
- Examples: Create new example files demonstrating features
- Issues: Report bugs, suggest features, ask questions
- Reviews: Review pull requests, provide feedback
- Skills: Contribute new built-in skills
- Testing: Write tests, improve test coverage
- Python 3.9 or higher
- Docker installed and running
- BoxLite micro-VM runtime
- Git
# Clone the repository
git clone https://github.com/boxlite-labs/claudebox.git
cd claudebox
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install in development mode with dev dependencies
pip install -e ".[dev]"
# Install pre-commit hooks (optional but recommended)
pip install pre-commit
pre-commit install# Set your Claude Code OAuth token
export CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-...# Run all tests
pytest tests/ -v
# Run with coverage
pytest tests/ --cov=src/claudebox --cov-report=html
# Run specific test file
pytest tests/test_skills.py -v
# Skip real integration tests (faster)
pytest tests/ -v -m "not real"# Run linter (ruff)
ruff check src/ tests/
# Auto-fix linting issues
ruff check --fix src/ tests/
# Run type checker (mypy)
mypy src/claudebox/
# Format code
ruff format src/ tests/# Create a feature branch
git checkout -b feature/your-feature-name
# Or for bug fixes
git checkout -b fix/bug-description- Write clean, readable code
- Add type hints to all functions
- Include docstrings for public API
- Write tests for new functionality
- Update documentation as needed
# Ensure all tests pass
pytest tests/ -v
# Check code quality
ruff check src/ tests/
mypy src/claudebox/
# Verify examples still work
python examples/01_basic_usage.pyWe follow Conventional Commits:
# Good commit messages
git commit -m "feat: Add support for custom templates"
git commit -m "fix: Resolve session cleanup race condition"
git commit -m "docs: Add RL training tutorial"
git commit -m "test: Add integration tests for skills"
# Commit types
# feat: New feature
# fix: Bug fix
# docs: Documentation only
# test: Adding or updating tests
# refactor: Code change that neither fixes a bug nor adds a feature
# perf: Performance improvement
# chore: Changes to build process or auxiliary tools# Push your branch
git push origin feature/your-feature-name
# Go to GitHub and create a Pull Request
# Fill out the PR template with:
# - Description of changes
# - Related issue number (if applicable)
# - Testing performed
# - Screenshots (if UI changes)- Respond to review feedback promptly
- Make requested changes in new commits
- Don't force-push after review has started
- Mark conversations as resolved when addressed
Once approved and CI passes:
- Maintainer will merge your PR
- Your contribution will be in the next release!
- Follow PEP 8
- Use
rufffor linting (configured inpyproject.toml) - Use
mypyfor type checking - Maximum line length: 100 characters
All public functions must have type hints:
# Good
def create_session(session_id: str, workspace_dir: str | None = None) -> SessionWorkspace:
"""Create a new session workspace."""
...
# Bad
def create_session(session_id, workspace_dir=None):
...Use Google-style docstrings:
def code(self, prompt: str, timeout: int = 120) -> CodeResult:
"""
Execute Claude Code CLI with the given prompt.
Args:
prompt: Natural language instruction for Claude Code
timeout: Maximum execution time in seconds
Returns:
CodeResult containing response, success status, and metadata
Raises:
TimeoutError: If execution exceeds timeout
RuntimeError: If box is not initialized
Example:
>>> async with ClaudeBox() as box:
... result = await box.code("Create a hello world script")
... print(result.response)
"""- Group imports: stdlib, third-party, local
- Use
from __future__ import annotationsfor forward references - Import
Callablefromcollections.abc, nottyping - Sort imports with
ruff
from __future__ import annotations
import os
import uuid
from collections.abc import Callable
from boxlite import Boxlite, BoxOptions
from claudebox.results import CodeResult
from claudebox.session import SessionManager- Maintain >80% code coverage
- Write unit tests for new functions
- Write integration tests for new features
- Add examples demonstrating new features
import pytest
from claudebox import ClaudeBox, Skill
def test_feature_basic():
"""Test basic functionality."""
# Arrange
skill = Skill(name="test", description="Test skill")
# Act
result = skill.validate()
# Assert
assert result is True
@pytest.mark.asyncio
async def test_feature_async():
"""Test async functionality."""
async with ClaudeBox() as box:
result = await box.code("test")
assert result.success# Run tests for a specific module
pytest tests/test_skills.py -v
# Run a specific test
pytest tests/test_skills.py::test_skill_creation -v
# Run tests matching a pattern
pytest tests/ -k "skill" -v- Be clear and concise - Get to the point quickly
- Show examples - Include runnable code examples
- Link related docs - Help users discover related features
- Keep it updated - Update docs when code changes
- Guides: Explain how to do something (imperative)
- API Reference: Describe what something does (descriptive)
- Architecture: Explain why/how things work internally
# Sessions Guide
Learn how to use persistent and ephemeral sessions in ClaudeBox.
## Ephemeral Sessions
Ephemeral sessions auto-cleanup after use:
```python
async with ClaudeBox() as box:
result = await box.code("Create hello.txt")
# Session is automatically cleaned up
```
## Persistent Sessions
Persistent sessions survive across multiple runs:
```python
# Create session
async with ClaudeBox(session_id="my-project") as box:
await box.code("npm install")
# Reconnect later
async with ClaudeBox.reconnect("my-project") as box:
await box.code("npm test")
```Skills extend ClaudeBox capabilities. To contribute a new skill:
from claudebox import Skill
NOTIFICATION_SKILL = Skill(
name="notification",
description="Send notifications via Slack, Discord, email",
install_cmd="pip3 install slack-sdk discord-webhook",
requirements=["slack-sdk", "discord-webhook"],
env_vars={
"SLACK_TOKEN": "",
"DISCORD_WEBHOOK_URL": "",
},
)import pytest
from claudebox import ClaudeBox, NOTIFICATION_SKILL
@pytest.mark.asyncio
async def test_notification_skill():
async with ClaudeBox(skills=[NOTIFICATION_SKILL]) as box:
result = await box.code("Send test notification to Slack")
assert result.successCreate docs/skills/notification.md:
# Notification Skill
Send notifications to Slack, Discord, or email.
## Usage
```python
from claudebox import ClaudeBox, NOTIFICATION_SKILL
async with ClaudeBox(skills=[NOTIFICATION_SKILL]) as box:
await box.code("Send 'Build completed' to #engineering on Slack")
```
## Environment Variables
- `SLACK_TOKEN` - Slack API token
- `DISCORD_WEBHOOK_URL` - Discord webhook URLSubmit your skill as a PR with:
- Skill definition in
src/claudebox/skills.py - Test in
tests/test_real_skills.py - Documentation in
docs/skills/ - Example in
examples/02_skills.py
(For maintainers)
# Update version in pyproject.toml
# Update CHANGELOG.md
# Commit
git add pyproject.toml CHANGELOG.md
git commit -m "chore: Bump version to X.Y.Z"
# Tag
git tag -a vX.Y.Z -m "Release X.Y.Z"
git push origin main --tagsGitHub Actions automatically publishes to PyPI when a new tag is pushed.
- GitHub Issues: Report bugs or request features
- GitHub Discussions: Ask questions, share ideas
- Documentation: Check the docs/ directory
- Examples: Browse examples/ for code samples
Contributors are recognized in:
- Git commit history
- CHANGELOG.md release notes
- GitHub contributors page
Thank you for contributing to ClaudeBox! 🎉