Guide for contributors and AI coding agents setting up, building, testing, and
extending ModelDock. For product intent read PROJECT.MD; for
the design contract read Architecture.md; for agent
rules read AGENT.md.
- Python 3.9–3.12 (tested on the CI matrix: 3.9, 3.10, 3.11, 3.12)
- A local Ollama install for integration tests (unit/contract tests need none)
git, and a virtual environment tool of choice (venv,conda,uv)
# Clone
git clone https://github.com/OpenAgentHQ/modeldock.git
cd modeldock
# Create & activate a virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# Install in editable mode with dev + ollama extras
pip install -e ".[dev,ollama]"pyproject.toml declares these extras:
ollama— optional runtime-native SDK (ollamaPython client)dev—pytest,pytest-cov,pytest-mock,ruff,mypy,bandit,pre-commit
src/modeldock/ # package source (src/ layout)
tests/ # unit / integration / e2e
.opencode/ # agent + tooling config (not shipped)
PROJECT.MD # product intent
Architecture.md # design contract
AGENT.md # agent/contributor rules
QUICKSTART.md # user quickstart
Development.md # this file
pyproject.toml # build, deps, tooling, entry points
ModelDock uses a standard pyproject.toml (PEP 621) with a src/ layout. No
build backend magic required beyond pip/build.
# Build sdist + wheel
python -m build
# Or install editable (see §2)
pip install -e .Entry point (console script):
[project.scripts]
modeldock = "modeldock.cli.app:main"Runtime plugins are discovered via:
[project.entry-points."modeldock.runtimes"]
ollama = "modeldock.adapters.runtimes.ollama:OllamaRuntime"# Lint + format (ruff)
ruff check src tests
ruff format src tests
# Type checking (strict)
mypy src
# Security scan
bandit -r src -c pyproject.toml
# All-in-one via pre-commit
pre-commit run --all-filesPre-commit is configured to run ruff, mypy, and bandit on every commit.
# Everything (unit + contract + e2e); integration skipped if no Ollama
pytest
# Unit only (fast, no network/runtime)
pytest tests/unit
# Port-contract suite (parameterized over all adapters)
pytest tests/unit -k contract
# Integration (requires Ollama running)
pytest tests/integration -m integration
# E2E (CLI via subprocess / CliRunner)
pytest tests/e2e
# Coverage (target ≥80%)
pytest --cov=modeldock --cov-report=term-missingTest layers:
| Layer | Needs | Markers |
|---|---|---|
| Unit | nothing | (default) |
| Port-contract | fake ports (fixtures) | -k contract |
| Integration | real/containerized Ollama | -m integration |
| E2E | CLI entry point | -m e2e |
Integration tests auto-skip when Ollama is unavailable, so CI stays green
without a runtime. Use fake RuntimePort/RegistryPort/CachePort fixtures
(tests/conftest.py) so core logic is testable without any runtime installed.
# As installed console script
modeldock --help
modeldock list
modeldock install llama3
# Or via module (no install needed in editable mode)
python -m modeldock --helpConfig precedence (low → high): built-in defaults → dynamic catalog (ollama.com) →
system config → user config (~/.config/modeldock/config.toml or
%APPDATA%\modeldock\config.toml) → env vars (MODELDOCK_*) → runtime overrides.
modeldock config show
modeldock config set log_level DEBUGUseful env vars:
MODELDOCK_LOG_LEVEL—DEBUG/INFO/WARNING/ERRORMODELDOCK_DEFAULT_BACKEND—ollamaMODELDOCK_AUTO_INSTALL—true/falseMODELDOCK_CACHE_DIR— override cache location
Follow the Open/Closed rule — no core edits.
- Create
src/modeldock/adapters/runtimes/<name>.py. - Implement
RuntimePort(seeArchitecture.md§4). SubclassBaseRuntimefor shared logic (alias resolution, availability caching, error normalization). - Add an entry point in
pyproject.toml:[project.entry-points."modeldock.runtimes"] <name> = "modeldock.adapters.runtimes.<name>:<Name>Runtime"
- Add/extend the port-contract tests; ensure they pass.
- Document backend-specific install/host/capability notes.
- Do not modify
core/,cli/, or the public API inmodeldock/__init__.py.
See AGENT.md → "Extension Checklist" for the full list.
Model discovery is dynamic — scraped live from ollama.com/library.
New models appear automatically after catalog refresh (24h TTL cache).
To add a model to the bundled fallback, edit src/modeldock/data/catalog.json
(no code change). Each entry:
{
"name": "llama3",
"aliases": ["llama3", "llama-3"],
"category": "chat",
"capabilities": ["chat", "completion"],
"default_tag": "latest",
"variants": [
{ "tag": "8b", "params": "8B", "size_bytes": 4660000000, "min_ram": "8GB" }
],
"description": "Meta Llama 3 instruction model.",
"backend_hints": ["ollama"]
}Optional RemoteRegistry can refresh the catalog from a URL without a release.
- Enable
DEBUGlogging:modeldock --log-level DEBUG ...orMODELDOCK_LOG_LEVEL=DEBUG. An unrecognized--log-levelvalue is coerced toINFO(never crashes) — seeArchitecture.md§12. - Inspect cache state:
modeldock cache status/modeldock cache path. - Verify a runtime is detected:
python -c "import modeldock; print(md.installed())". - For download issues, check checksum mismatch errors — they raise
DownloadErrorwith a retry suggestion; never install corrupt weights. - Use fake adapters in tests to isolate core logic from network/runtime.
Matrix: Windows / macOS / Linux × Python 3.9–3.12.
Steps per job:
- Setup Python (matrix version)
pip install -e ".[dev,ollama]"ruff check+ruff format --checkmypy srcbandit -r srcpytest(integration auto-skips without Ollama)- Upload coverage
- Bump version in
pyproject.toml -
ruff+mypy+banditclean -
pytestgreen (all layers) - Docs current:
PROJECT.MD,Architecture.md,AGENT.md,QUICKSTART.md -
python -m buildproduces sdist + wheel - Tag release, publish to PyPI (
twine upload dist/*) - Verify
pip install modeldockin a clean venv
Keep this file in sync with Architecture.md and AGENT.md. When conflicts
arise, Architecture.md is authoritative for design.