A step-by-step guide to setting up the Docman development environment from scratch on a brand-new Apple Silicon Mac (M1, M2, M3, M4 — any model).
No prior developer experience is assumed. If you already have some of these tools installed, skip those steps.
- Python 3.13 — the programming language everything runs on
- uv — fast Python package manager (replaces pip and venv)
- Git — version control for downloading and contributing to the code
- OrbStack — lightweight container runtime (runs NATS message broker and Valkey)
- Ollama — runs AI models locally on your Mac
- Heddle — the orchestration framework
- Docman — the document processing pipeline you'll be testing
Total time: roughly 30–45 minutes (depending on your internet speed).
Terminal is the command-line application built into every Mac.
- Press Cmd + Space to open Spotlight
- Type Terminal and press Enter
You'll see a window with a blinking cursor. This is where you'll type all the commands in this guide.
Tip: Keep Terminal open for the entire setup. You can paste commands by pressing Cmd + V.
Homebrew is the standard package manager for macOS. It installs developer tools with simple commands.
Paste this into Terminal and press Enter:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"It will ask for your Mac password (the one you use to log in). Type it — you won't see characters appear, that's normal — and press Enter.
When it finishes, it will show instructions to add Homebrew to your PATH. Run the commands it displays. They will look something like:
echo >> ~/.zprofile
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"Verify it worked:
brew --versionYou should see something like Homebrew 4.x.x.
brew install python@3.13 git uvVerify both installed:
python3 --version
git --versionYou should see Python 3.13.x and git version 2.x.x.
OrbStack is a fast, lightweight alternative to Docker Desktop, optimized for Apple Silicon.
brew install orbstackAfter installation, open OrbStack once to complete its setup:
open -a OrbStackA window will appear. Follow the on-screen prompts (it takes about a minute). Once OrbStack is running, you'll see its icon in the menu bar at the top of your screen.
Verify Docker commands work:
docker --versionOllama runs AI models locally on your Mac.
brew install ollamaStart the Ollama service:
ollama serve &Note:
ollama serve &runs Ollama in the background. Alternatively, you can download the Ollama desktop app from ollama.com which starts automatically.
Download the AI model we'll use for testing:
ollama pull command-r7b:latestThis downloads about 5 GB. Wait for it to complete.
Verify it works:
ollama listYou should see command-r7b:latest in the list.
Docman needs two services running: NATS (a message broker) and Valkey (a data store).
docker run -d --name heddle-nats -p 4222:4222 nats:2.10-alpine
docker run -d --name heddle-valkey -p 6379:6379 valkey/valkey:8-alpineVerify they're running:
docker psYou should see two containers: heddle-nats and heddle-valkey.
Note: These containers will stop if you restart your Mac. To start them again later:
docker start heddle-nats heddle-valkey
Choose a directory where you want to keep the project. This example uses your home directory:
cd ~
mkdir -p Developer/IranTransitionProject
cd Developer/IranTransitionProjectClone all three repositories:
git clone https://github.com/getheddle/heddle.git
git clone https://github.com/IranTransitionProject/docman.git
git clone https://github.com/IranTransitionProject/baseline.gitNote: If these are private repositories, you'll need to authenticate with GitHub first. The simplest way:
brew install gh gh auth loginFollow the prompts to log in with your GitHub account.
uv manages virtual environments and dependencies automatically — no manual venv activation needed.
# Install Heddle (the framework) with all extras
cd ~/Developer/getheddle/heddle
uv sync --all-extras
# Install Docman (the test project) with dev tools
# This also resolves Heddle from the sibling directory automatically
cd ~/Developer/IranTransitionProject/docman
uv sync --extra devThis will download and install many packages (including PyTorch for document processing). It may take 5–10 minutes.
Verify installation:
uv run heddle --helpYou should see a list of Heddle commands: worker, processor, pipeline, orchestrator, scheduler, router, submit, mcp.
Docling uses AI models for document layout detection. Pre-download them so they're ready when you need them:
uv run docling-tools models downloadThis downloads a few hundred MB of models. They're cached at ~/.cache/docling/models/.
Let's verify everything is installed correctly:
# Test Heddle
cd ~/Developer/getheddle/heddle
uv run pytest tests/ -v --ignore=tests/test_integration.py
# Test Docman
cd ~/Developer/IranTransitionProject/docman
uv run pytest tests/ -vAll tests should pass (green). The Heddle integration test is excluded because it needs the full pipeline running.
Now let's run the complete document processing pipeline.
cd ~/Developer/IranTransitionProject/docman
source .envThis sets NATS_URL, OLLAMA_URL, and OLLAMA_MODEL.
mkdir -p /tmp/docman-workspaceIf you have a PDF you'd like to test with, copy it there:
cp ~/Downloads/your-document.pdf /tmp/docman-workspace/./scripts/dev-start.shThis starts the pipeline components in the background: router, extractor, classifier, summarizer, ingest, and pipeline orchestrator.
./scripts/dev-start.sh submit test_report.pdftail -f .dev-pids/*.logPress Ctrl + C to stop watching logs.
./scripts/dev-start.sh stopWorkers are defined by YAML configuration files. To create a new one:
-
Copy an existing worker config:
cp configs/workers/doc_classifier.yaml configs/workers/my_new_worker.yaml
-
Edit the file to define your worker's system prompt, input/output schemas, and behavior
-
Start it:
uv run heddle worker --config configs/workers/my_new_worker.yaml --tier local --nats-url nats://localhost:4222
See heddle/configs/workers/_template.yaml for a blank template with documentation.
Processing backends handle non-LLM tasks (like document extraction). To create one:
-
Create a new Python file in
docman/src/docman/backends/ -
Implement the
ProcessingBackendinterface from Heddle -
Reference it in a worker config:
processing_backend: "docman.backends.my_backend.MyBackend"
See docman/src/docman/backends/docling_backend.py for an example.
Pipeline stages are defined in configs/orchestrators/doc_pipeline_local.yaml. You can:
- Reorder stages
- Add new stages that reference your workers
- Change input mappings to pass data between stages
# See available models
ollama list
# Pull a new model
ollama pull llama3.2:3b
# Set it as the active model
export OLLAMA_MODEL=llama3.2:3b
# Restart the pipeline
./scripts/dev-start.sh stop
./scripts/dev-start.shRun the PATH setup commands from Step 2 again, or close and reopen Terminal.
Make sure Homebrew's Python is installed: brew install python@3.13
Use uv run heddle instead of bare heddle, or activate the venv: source .venv/bin/activate
docker start heddle-nats heddle-valkeyIf they don't exist yet, re-run the docker run commands from Step 6.
Some larger models need more RAM than your Mac has available. Stick with models 8B parameters or smaller (like command-r7b:latest or llama3.2:3b). Close memory-heavy applications if needed.
Make sure you ran uv sync in both repos (Step 8). Use uv run pytest to ensure the correct environment is used.
The first time Docling processes a document, it may take longer while PyTorch compiles operations for your GPU. Subsequent runs will be faster.
For those who want to understand how the pieces fit together:
You submit a document (PDF/DOCX)
│
▼
┌──────────────┐ NATS message bus
│ Pipeline │◄──────────────────────► Coordinates the 4 stages
│ Orchestrator │
└──────┬───────┘
│ Stage 1: extract
▼
┌──────────────┐
│ Extractor │ DoclingBackend reads PDF → extracts text, tables, structure
│ (Processor) │ Writes extracted JSON to workspace
└──────┬───────┘
│ Stage 2: classify
▼
┌──────────────┐
│ Classifier │ LLM (Ollama) classifies document type from extracted text
│ (LLM Worker)│ Returns: document_type, confidence, reasoning
└──────┬───────┘
│ Stage 3: summarize
▼
┌──────────────┐
│ Summarizer │ LLM (Ollama) produces structured summary
│ (LLM Worker)│ Returns: summary, key_points, word_count
└──────┬───────┘
│ Stage 4: ingest
▼
┌──────────────┐
│ Ingest │ DuckDBIngestBackend persists all results to DuckDB
│ (Processor) │ Returns: document_id, status
└──────────────┘
All communication happens through NATS messages. Workers are stateless — they process one task at a time and reset. The router determines which worker handles each task based on deterministic rules (no AI involved in routing).