Clean Architecture¶
ModelDock follows Clean Architecture with SOLID principles. Dependencies point inward.
Dependency Direction¶
This is non-negotiable. Violating it breaks extensibility and testability.
The Layers¶
Interface Layer (modeldock/__init__.py + modeldock/cli)¶
The public surface. The SDK exposes functions like load(), list(), search(). The CLI translates argv → core service calls.
Rule: No business logic in CLI. CLI only calls core.
Application Layer (modeldock/core/)¶
Services that implement use cases by composing ports:
ModelManager— high-level facadeLifecycleOrchestrator— the brain behindload()RegistryService— search, info, categoriesDownloadService— orchestrates pullCacheService— smart cachingConfigService— settings
Rule: Depends on ports/ interfaces only, never on concrete adapters.
Domain Layer (modeldock/domain/)¶
Pure entities. No I/O, no framework imports, no references to Ollama/HTTP/filesystem.
Model,ModelSpec,ModelRefCapability,CategoryRuntimeBackendAlias, alias resolution rules- Domain exceptions
Rule: Validates invariants. Knows nothing about the outside world.
Port Layer (modeldock/ports/)¶
typing.Protocol interfaces defining what the system needs:
RuntimePort— runtime operationsRegistryPort— model catalogDownloaderPort— file transferCachePort— artifact trackingProgressPort— progress reportingEventPort— lifecycle hooks
Rule: No implementation. Just the contract.
Adapter Layer (modeldock/adapters/)¶
Concrete implementations of ports:
runtimes/ollama.py— Ollama runtime (shipped)runtimes/base.py— shared logic (BaseRuntime)registry/ollama_library.py— dynamic catalog from ollama.comregistry/bundled.py— offline fallbackdownloaders/ollama_pull.py— Ollama native pulldownloaders/http.py— generic HTTP downloadercache/filesystem.py— filesystem cache + manifestprogress/rich_progress.py,tqdm_progress.py,silent.py
Rule: Implements port interfaces. Registered via entry points.
Common Layer (modeldock/common/)¶
Cross-cutting utilities:
config.py— settings model + loaderslogging.py— logging setupplatform.py— OS detection, pathshttp.py— shared httpx client factoryerrors.py— base error hierarchy
Rule: No business logic. Pure utilities.
Why This Matters¶
- Testability — Core logic testable with fake adapters (no Ollama needed)
- Extensibility — New runtimes = one adapter class + one entry-point line
- Independence — Domain/ports have zero external dependencies
- Replaceability — Swap any adapter without touching core
Next Steps¶
- Runtime Adapters — adding new runtimes
- Port Interfaces — the contract