Skip to main content
You do not need a database to run Causeloop locally. When DATABASE_URL is unset, the app uses a fast in-memory store that is seeded with demo data. Add an LLM key only if you want real AI responses; the offline mock works for everything else.
1

Clone the repository

git clone https://github.com/your-org/causeloop-backend.git
cd causeloop-backend
2

Create a virtualenv and install dependencies

python3 -m venv .venv
.venv/bin/pip install --upgrade pip
.venv/bin/pip install -r requirements.txt
Or use the make shortcut:
make install
3

Configure your environment

cp .env.example .env
Open .env. For local development the defaults are fine — you only need to change values if you want a real database or real LLM responses:
PORT=4000
JWT_SECRET=dev-secret-change-me   # OK for local only
CORS_ORIGINS=http://localhost:3000

# Optionally add a key for real AI responses:
# ANTHROPIC_API_KEY=sk-ant-...

# Optionally point at a local Postgres:
# DATABASE_URL=postgresql://localhost:5432/causeloop
# CAUSELOOP_MASTER_KEY=<base64-32-bytes>
4

Start the dev server

.venv/bin/uvicorn app.main:app --port 4000 --reload
Or with make:
make dev
The server starts on http://localhost:4000. Hot-reload is on by default with --reload.
5

Explore the API

Open the interactive docs in your browser:
  • Swagger UI: http://localhost:4000/docs
  • OpenAPI schema: http://localhost:4000/openapi.json
  • Health check: http://localhost:4000/health

Option B — Docker (no Python install required)

1

Build the image

docker build -t causeloop-backend .
2

Run the container

docker run -p 4000:4000 --env-file .env causeloop-backend
To run in mock LLM mode without an .env file:
make docker-run-mock
# equivalent to:
docker run --rm -p 4000:4000 \
  -e JWT_SECRET=dev-secret \
  -e USE_MOCK_LLM=true \
  -e CORS_ORIGINS=http://localhost:3000 \
  causeloop-backend:latest

Available make targets

Run make help to see all targets:
TargetDescription
make installCreate .venv and install requirements.txt
make devStart dev server with hot reload on $PORT (default 4000)
make dev-logDev server with JSON access logs enabled
make testRun pytest test suite
make lintLint with ruff
make typecheckType-check with mypy
make migrateApply forward-only SQL migrations (requires DATABASE_URL)
make docker-buildBuild the Docker image as causeloop-backend:latest
make docker-runRun the Docker image using .env
make docker-run-mockRun in mock LLM mode (no .env needed)
make cleanRemove .venv and cache directories

Dev seed accounts

When running with the in-memory store, the following accounts are pre-seeded and can be used in API requests:
User IDRoleNotes
usr_seed_adminadminFull access
usr_seed_analystanalystRead + write on analysis resources
usr_seed_viewerviewerRead-only
Use these IDs in the X-User-Id header (when auth is relaxed for local dev) or exchange a Clerk session token via POST /v1/auth/exchange.

Connecting a local database

If you want to run against a real Postgres instance during development:
1

Start Postgres

# macOS with Homebrew
brew services start postgresql@16

# or Docker
docker run -d -e POSTGRES_DB=causeloop -e POSTGRES_USER=causeloop \
  -e POSTGRES_PASSWORD=localpass -p 5432:5432 postgres:16-alpine
2

Set DATABASE_URL and master key

In your .env:
DATABASE_URL=postgresql://causeloop:localpass@localhost:5432/causeloop
CAUSELOOP_MASTER_KEY=<output of: python3 -c "import os,base64;print(base64.b64encode(os.urandom(32)).decode())">
3

Load the schema and reference data

psql "$DATABASE_URL" -f db/schema.sql
psql "$DATABASE_URL" -f db/seed_reference.sql
psql "$DATABASE_URL" -f db/onboard_client.sql
See Database setup for the full guide including migrations and RLS role requirements.
4

Apply migrations

make migrate