Thank you for your interest in contributing to DeepWork! This guide will help you set up your local development environment and understand the development workflow.
- Prerequisites
- Development Setup
- Installing DeepWork Locally
- Installing Pre-Release Versions
- Testing Your Local Installation
- Running Tests
- Code Quality
- Development Workflow
- Project Structure
- Submitting Changes
- Python 3.11 or higher - Required for running DeepWork
- Git - For version control
- Nix (optional but recommended) - For reproducible development environment
- Nix flakes enabled (add
experimental-features = nix-command flakesto~/.config/nix/nix.conf)
- Nix flakes enabled (add
- direnv (optional) - For automatic environment activation when using Nix flakes
- uv - Modern Python package installer (included in Nix environment)
- Homebrew (optional) - For easy installation on macOS/Linux via
brew install - Signed CLA - All contributors must sign the Contributor License Agreement (see below)
Before we can accept your contributions, you must sign our Contributor License Agreement (CLA). This is a one-time requirement for all contributors.
The CLA ensures that:
- You have the legal right to contribute your code
- The project can safely use and distribute your contributions
- Your contributions comply with the Business Source License 1.1 under which DeepWork is licensed
- Both you and the project are legally protected
For First-Time Contributors:
- Submit your pull request - When you open your first PR, the CLA Assistant bot will automatically comment on it
- Read the CLA - Review the Contributor License Agreement (CLA)
- Sign electronically - Comment on your PR with:
I have read the CLA Document and I hereby sign the CLA - Verification - The bot will verify your signature and update the PR status
The CLA Assistant will remember your signature for all future contributions.
For Corporate Contributors:
If you're contributing on behalf of your employer, your organization must sign a Corporate CLA. Please contact legal@unsupervised.com to obtain the Corporate CLA.
Our CLA:
- Grants the project a license to use your contributions
- Confirms you have the right to contribute the code
- Acknowledges the Business Source License 1.1 restrictions
- Is based on the Apache Software Foundation's CLA with modifications for BSL 1.1
For the full text, see CLA.md.
direnv automatically loads the Nix environment when you cd into the project directory:
# Install direnv (if not already installed)
# On macOS with Homebrew:
brew install direnv
# On Linux (Debian/Ubuntu):
apt-get install direnv
# On NixOS or with Nix:
nix-env -i direnv
# Add direnv hook to your shell
# For bash, add to ~/.bashrc:
eval "$(direnv hook bash)"
# For zsh, add to ~/.zshrc:
eval "$(direnv hook zsh)"
# For fish, add to ~/.config/fish/config.fish:
direnv hook fish | source
# Restart your shell or source your rc file
source ~/.bashrc # or ~/.zshrcOnce direnv is set up, the environment will activate automatically when you enter the directory.
The easiest way to get started is using Nix flakes, which provides a fully reproducible development environment with all dependencies pre-configured.
If you have direnv installed, the entire development environment activates automatically when you cd into the project:
# Clone the repository
git clone https://github.com/deepwork/deepwork.git
cd deepwork
# Allow direnv (first time only)
direnv allow
# That's it! Everything is ready:
deepwork --help # CLI works
pytest # Tests work
ruff check src/ # Linting worksThe .envrc file contains use flake, which tells direnv to load the Nix flake's development shell. This automatically:
- Provides Python 3.11 with all dependencies via Nix
- Installs deepwork as an editable uv tool (so
uvx deepworkuses local source) - Sets
DEEPWORK_DEV=1
Every time you cd into the directory, the environment is ready instantly.
If you don't use direnv, you can manually enter the development environment:
# Clone the repository
git clone https://github.com/deepwork/deepwork.git
cd deepwork
# Enter the Nix development environment
nix developThe Nix environment provides:
| Tool | Description |
|---|---|
deepwork |
CLI using your local source code (editable install) |
claude |
Claude Code CLI (built from source for version control) |
pytest |
Test runner with all plugins |
ruff |
Fast Python linter and formatter |
mypy |
Static type checker |
uv |
Python package manager |
python |
Python 3.11 interpreter |
update |
Updates claude-code and flake inputs |
For CI pipelines or scripts, use nix develop --command:
nix develop --command pytest
nix develop --command ruff check src/
nix develop --command mypy src/The Nix environment includes Claude Code built from source to ensure version control (the nixpkgs version can lag behind npm releases). Use the update command to keep dependencies current:
# In the dev shell - updates claude-code and flake inputs
updateTo manually update Claude Code:
./nix/claude-code/update.shThis fetches the latest version from npm, computes the necessary hashes using prefetch-npm-deps, and updates package.nix automatically.
A GitHub Action automatically checks for new Claude Code versions daily and creates PRs when updates are available.
If you prefer not to use Nix:
# Clone the repository
git clone https://github.com/deepwork/deepwork.git
cd deepwork
# Install uv if you don't have it (see https://docs.astral.sh/uv/getting-started/installation/)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create virtual environment and install all dependencies (including dev tools)
uv venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
uv sync --all-extras
# Set environment variables for development
export PYTHONPATH="$PWD/src:$PYTHONPATH"
export DEEPWORK_DEV=1The DeepWork plugin's MCP config uses uvx deepwork serve to start the MCP server. By default, uvx fetches from PyPI — not your local source. To make uvx deepwork resolve to your local code, install it as an editable uv tool:
The flake's shellHook runs uv tool install -e . automatically. Every time you enter the dev shell, uvx deepwork points to your local source. No manual steps needed.
# Install deepwork as an editable uv tool
uv tool install -e .This registers deepwork in uv's tool registry pointing at your local checkout. Now uvx deepwork serve (what the MCP config runs) uses your development code.
# Check that uv tool list shows deepwork pointing to your local path
uv tool list | grep deepwork
# Verify the CLI works
uvx deepwork --version
# Test the MCP server starts
uvx deepwork serve --path . --external-runner claudeDeepWork uses pre-release versions (e.g., 0.7.0a1) during development. By default, uv and pip skip pre-release versions, so you need to opt in explicitly.
# Install the latest pre-release from PyPI
uv pip install --prerelease=allow deepwork
# Or pin to a specific pre-release
uv pip install --prerelease=allow "deepwork==0.7.0a1"pip install --pre deepworkuv tool install --prerelease=allow deepwork# Should show deepwork with an editable path to your checkout
uv tool list | grep deepwork
# Should run your local version
uvx deepwork --versionThe MCP server is DeepWork's core runtime. Test it directly:
uvx deepwork serve --path . --external-runner claudeInstall the plugin in a test project and verify the MCP server connects:
# In a test project with the DeepWork plugin installed
claude # Start Claude Code
# The /deepwork skill should be available
/deepworkAny changes you make to src/deepwork/ are immediately reflected since the editable install points to your source tree.
You can test a feature branch directly from GitHub without cloning or modifying your local environment. This is useful for:
- Reviewing someone else's PR
- Testing a feature branch before merging
- Trying out experimental changes without affecting your setup
# Run DeepWork CLI directly from a feature branch
nix run github:Unsupervisedcom/deepwork/feature-branch-name -- --help
# Enter a development shell with a specific branch
nix develop github:Unsupervisedcom/deepwork/feature-branch-name
# Test against a specific commit
nix run github:Unsupervisedcom/deepwork/abc1234 -- --version
# Test against a PR from a fork
nix run github:pr-author/deepwork/feature-name -- --help
# Or if the PR is from a branch in this repository:
nix run github:Unsupervisedcom/deepwork/feature-name -- --helpFor example, to test a branch named feat/new-parser:
# Quick test of the CLI
nix run github:Unsupervisedcom/deepwork/feat/new-parser -- --version
# Or enter a full development shell to run tests
nix develop github:Unsupervisedcom/deepwork/feat/new-parser --command pytest tests/unit/core/test_parser.py -vNote: The first run will take longer as Nix fetches and builds the branch. Subsequent runs use the cached build.
DeepWork has a comprehensive test suite with 568+ tests.
# In Nix environment (interactive or CI)
pytest
# Or using nix develop --command (CI-friendly, no interactive shell)
nix develop --command pytest
# Using uv run (without Nix)
uv run pytest# Unit tests only
pytest tests/unit/ -v
# Integration tests only
pytest tests/integration/ -v
# Run a specific test file
pytest tests/unit/core/test_parser.py -v
# Run a specific test function
pytest tests/unit/core/test_parser.py::test_parse_valid_job -v# Generate coverage report
uv run pytest tests/ --cov=deepwork --cov-report=html
# View coverage in browser
open htmlcov/index.html # macOS
# or
xdg-open htmlcov/index.html # Linux# Install pytest-watch
uv pip install pytest-watch
# Run tests on file changes
ptwDeepWork maintains high code quality standards using automated tools.
# Check for linting issues
ruff check src/
# Check specific files
ruff check src/deepwork/cli/main.py
# Auto-fix linting issues
ruff check --fix src/# Format code
ruff format src/
# Check formatting without making changes
ruff format --check src/# Run mypy type checker
mypy src/
# Run mypy on specific module
mypy src/deepwork/core/# Before committing, run all checks
ruff check src/
ruff format --check src/
mypy src/
uv run pytestgit checkout -b feature/your-feature-name
# or
git checkout -b fix/your-bug-fix- Edit code in
src/deepwork/ - Add tests in
tests/unit/ortests/integration/ - Update documentation if needed
# Run relevant tests
uv run pytest tests/unit/core/test_yourmodule.py -v
# Run all tests
uv run pytest
# Check code quality
ruff check src/
mypy src/# Verify uvx deepwork uses your local source
uv tool list | grep deepwork
uvx deepwork serve --path ~/test-project --external-runner claudegit add .
git commit -m "feat: add new feature X"
# Or for bug fixes
git commit -m "fix: resolve issue with Y"Follow Conventional Commits format:
feat:- New featurefix:- Bug fixdocs:- Documentation changestest:- Test additions or changesrefactor:- Code refactoringchore:- Maintenance tasks
deepwork/
├── src/deepwork/ # Source code
│ ├── cli/ # CLI commands (serve, hook)
│ │ └── main.py # Main CLI entry point
│ ├── core/ # Core functionality
│ │ ├── parser.py # Job definition parsing
│ │ ├── jobs.py # Job loading and management
│ │ └── doc_spec_parser.py # Document spec parsing
│ ├── mcp/ # MCP server (core runtime)
│ ├── hooks/ # Hook scripts and wrappers
│ ├── standard_jobs/ # Built-in job definitions (auto-discovered)
│ ├── schemas/ # JSON schemas for validation
│ └── utils/ # Utility modules
│ ├── fs.py # File system operations
│ ├── yaml.py # YAML operations
│ ├── git.py # Git operations
│ └── validation.py # Validation utilities
├── platform/ # Shared platform-agnostic content
│ └── skill-body.md # Canonical skill body
├── plugins/
│ ├── claude/ # Claude Code plugin
│ │ ├── .claude-plugin/plugin.json
│ │ ├── skills/ # /deepwork skill
│ │ ├── hooks/ # hooks.json
│ │ └── .mcp.json # MCP server config
│ └── gemini/ # Gemini CLI extension
├── library/jobs/ # Reusable example jobs
├── tests/
│ ├── unit/ # Unit tests
│ ├── integration/ # Integration tests
│ └── fixtures/ # Test fixtures and sample data
├── doc/ # Documentation
│ └── architecture.md # Comprehensive architecture doc
├── flake.nix # Nix flake for development environment
├── pyproject.toml # Python project configuration
├── CLAUDE.md # Project context for Claude Code
└── README.md # Project overview
-
Ensure all tests pass:
uv run pytest
-
Ensure code quality checks pass:
ruff check src/ ruff format --check src/ mypy src/
-
Add tests for new features:
- Unit tests in
tests/unit/ - Integration tests in
tests/integration/if appropriate
- Unit tests in
-
Update documentation:
- Update
README.mdif adding user-facing features - Update
doc/architecture.mdif changing core design - Add docstrings to new functions/classes
- Update
-
Test in a real project:
- Verify
uvx deepwork serveuses your local version - Test the MCP server and plugin end-to-end
- Verify
-
Push your branch:
git push origin feature/your-feature-name
-
Create PR on GitHub:
- Go to https://github.com/deepwork/deepwork
- Click "Pull requests" → "New pull request"
- Select your branch
- Fill in the PR template:
- Description: What does this PR do?
- Motivation: Why is this change needed?
- Testing: How did you test this?
- Breaking Changes: Any breaking changes?
-
Respond to review feedback:
- Address reviewer comments
- Push additional commits to your branch
- Request re-review when ready
- Keep PRs focused: One feature/fix per PR
- Write clear commit messages: Follow conventional commits
- Add tests: All new code should have tests
- Update docs: Keep documentation in sync
- Pass CI checks: All automated checks must pass
- Documentation: See
doc/architecture.mdfor design details - Issues: Check existing issues or create a new one
- Discussions: Use GitHub Discussions for questions
- Code Style: Follow existing code patterns
# In one terminal: Enter Nix development environment
nix develop
# In Nix environment: Watch tests
uv run pytest tests/unit/ --watch
# In another terminal: Make changes to src/deepwork/
# Tests automatically re-run on save# Run tests with verbose output and stop on first failure
uv run pytest -vv -x
# Run tests with pdb debugger on failure
uv run pytest --pdb
# Add breakpoints in code
import pdb; pdb.set_trace()# Time test execution
time uv run pytest tests/unit/
# Profile test execution
uv run pytest --profileWith Nix: Re-enter the development environment:
nix develop
# or if using direnv
direnv reloadWithout Nix: Ensure venv is activated and dependencies synced:
source .venv/bin/activate
uv sync --all-extrasSolution: This usually means dependencies aren't installed. Re-sync:
uv sync --all-extrasSolution: Install as an editable uv tool:
uv tool install -e .
# Verify it points to your local path
uv tool list | grep deepworkSolution: Ensure Nix is installed with flakes enabled:
nix --version
# Add to ~/.config/nix/nix.conf if not already there:
# experimental-features = nix-command flakesSolution: Reinstall the editable tool:
uv tool uninstall deepwork
uv tool install -e .By contributing to DeepWork, you agree that your contributions will be licensed under the project's current license. The licensor (Unsupervised.com, Inc.) reserves the right to change the project license at any time at its sole discretion.
You must sign the Contributor License Agreement (CLA) before your contributions can be accepted. See the CLA section above for details.
Thank you for contributing to DeepWork! Your efforts help make AI-powered workflows accessible to everyone.