Local Development Setup
Complete guide to running Martha locally from a fresh clone.
Prerequisites
- Docker Desktop (with Compose v2)
- Python 3.11+
- Node 20+
- Git
1. Clone and initialize submodules
git clone git@github.com:westeuropeco/martha.git
cd martha
git submodule update --init --recursive2. Start common infrastructure
Martha depends on shared services (PostgreSQL, Redis, Temporal, Keycloak) from the common-infra stack.
cd common-infra
./setup.sh
cd ..This creates the common-infra-network, starts all infrastructure services, and imports the Keycloak frank realm with test users.
Verify:
docker exec postgres pg_isready -U postgres
docker exec redis redis-cli ping
curl -s http://localhost:8180/realms/frank/.well-known/openid-configuration | head -13. Configure environment
deployment/.env.dev contains dev-friendly defaults. You need to add API keys for LLM providers:
# Edit and add your API keys
vim deployment/.env.devRequired keys (at minimum one LLM provider):
| Key | Purpose |
|---|---|
ANTHROPIC_API_KEY | Claude models |
OPENAI_API_KEY | OpenAI models |
Optional keys are documented in the file.
4. Set up Keycloak client for Martha Admin
The admin panel requires an OAuth2 confidential client in Keycloak. This is automated:
bash deployment/setup-dev-keycloak.shCopy the output AUTH_KEYCLOAK_SECRET=... value into deployment/.env.dev:
echo 'AUTH_KEYCLOAK_SECRET=<paste-secret-here>' >> deployment/.env.dev!!! note On a fresh Keycloak (clean DB), the client is auto-imported from frank-realm.json with a dev secret: martha-admin-dev-secret-change-in-prod. The script is for existing environments where the realm import was already applied without this client.
5. Start Martha services
docker-compose -f deployment/docker-compose.dev.yml up -dServices start in dependency order:
martha-postgres-dev+martha-redis-dev(infrastructure)martha-api-dev(waits for postgres healthy)martha-worker-dev+martha-ingestion-worker-dev(wait for API healthy)martha-admin-svelte-dev+slo-pwa-dev(wait for API healthy)martha-rerank-dev(TEI cross-encoder reranker — see below)
Verify:
docker-compose -f deployment/docker-compose.dev.yml ps
curl -s http://localhost:8080/health
curl -s http://localhost:8088/health # rerank container (may take 30-60s on first start)Reranker (#231 C2-3a)
The martha-rerank container runs Hugging Face TEI loaded with Alibaba-NLP/gte-multilingual-reranker-base. Recall calls TEI's /rerank endpoint to reorder hybrid-search candidates by cross-encoder score.
- Add
MARTHA_RERANKER_URL=http://martha-rerank-dev:80to your localdeployment/.env.devso api/worker can reach the container. The variable is non-secret so it can be hardcoded in dev. (.env.devis gitignored — each developer manages their own.) - First start downloads ~600MB from HF Hub (30-60s). Subsequent starts read from the
rerank-model-cachenamed volume (~10-15s). - Healthcheck has
start_period: 120sto absorb the cold-start window. - Fail-open contract: if the container is down or unreachable, recall returns merge-order results plus a structured WARN log. Never blocks chat.
- Disable rerank for a session: unset
MARTHA_RERANKER_URLindeployment/.env.devand restartmartha-api-dev+martha-worker-dev. - Swap the model: edit the
command:indeployment/docker-compose.dev.ymland restartmartha-rerank-dev. Common alternatives:BAAI/bge-reranker-v2-m3— XLM-RoBERTa, 568M, slightly higher quality multilingual at 2x cost.Alibaba-NLP/gte-reranker-modernbert-base— ModernBERT, 149M, English-only, ~2x faster.
- Verify rerank is firing: in the logs of
martha-api-dev, look formemory.recall.rerank: success url=... candidates=...debug lines, or check the Prometheus countermartha_rerank_calls_total{outcome="success"}.
6. Run database migrations and seeds
Migrations run automatically on API startup. Seed scripts populate initial data:
docker-compose -f deployment/docker-compose.dev.yml exec martha-api \
python scripts/seed_platform_functions.py
docker-compose -f deployment/docker-compose.dev.yml exec martha-api \
python scripts/seed_node_types.py7. Access the applications
| Application | URL | Auth |
|---|---|---|
| Martha Admin | http://localhost:5174 | Keycloak login (admin / admin123) |
| SLO PWA | http://localhost:5173 | API key (preconfigured) |
| Martha API | http://localhost:8080 | JWT or API key |
| API Docs | http://localhost:8080/docs | None |
| Temporal UI | http://localhost:8088 | None |
| Keycloak Console | http://localhost:8180 | admin / (from common-infra/.env) |
Test users (Keycloak realm frank)
| Username | Password | Roles | Tenant ID |
|---|---|---|---|
| admin | admin123 | admin, user | 550e8400-e29b-41d4-a716-446655440000 |
| testuser | testpass | user | 550e8400-e29b-41d4-a716-446655440001 |
Development workflow
Live reload
All services mount source code as volumes. Changes to Python files (API, core, services) trigger FastAPI auto-reload. Changes to Svelte files trigger Vite HMR.
Running tests
# Python virtual env (for running tests outside Docker)
python -m venv myenv && source myenv/bin/activate
pip install -r requirements.txt
# Unit tests (no Docker needed)
pytest tests/unit/ -v
# Integration tests (needs Docker DB)
pytest tests/integration/ -v
# Frontend
cd martha-admin-svelte && npm run check && npm run buildDatabase access
docker exec -it martha-postgres-dev psql -U martha -d marthaLogs
# All services
docker-compose -f deployment/docker-compose.dev.yml logs -f
# Single service
docker-compose -f deployment/docker-compose.dev.yml logs -f martha-apiTeardown
# Stop Martha services (preserves data)
docker-compose -f deployment/docker-compose.dev.yml down
# Stop everything including common-infra
docker-compose -f deployment/docker-compose.dev.yml down
cd common-infra && docker-compose down
# Nuclear option: remove all data
docker-compose -f deployment/docker-compose.dev.yml down -v
cd common-infra && docker-compose down -vTroubleshooting
Martha Admin shows 500 Internal Error : Keycloak client not configured. Run bash deployment/setup-dev-keycloak.sh and add the secret to .env.dev.
Martha Admin shows "redirect_uri_mismatch" : Keycloak client redirect URIs don't include http://localhost:5174/*. Re-run the setup script.
API can't connect to Temporal : Ensure common-infra is running: docker exec temporal temporal operator cluster health
"common-infra-network not found" : Run cd common-infra && ./setup.sh first. The external network must exist before Martha services start.