Local development setup
Last Updated: 2026-05-23 Status: Alpha This is the end-to-end walkthrough for getting Poindexter running on your own machine. If you only want “one command to a working pipeline,” runpoindexter setup --auto — read
Quick Start in the README first.
This document covers the longer form: what the setup wizard does
under the hood, how to verify each layer, and how to troubleshoot
when something doesn’t come up.
Minimum hardware
| Tier | GPU VRAM | What it unlocks |
|---|---|---|
| Minimum | 8 GB | Runs smaller Ollama models only; writer model will be constrained to 7B range |
| Recommended | 16 GB | Supports Q4 quantized 7B–14B models at full quality |
| Optimal | 24 GB+ | Q4_K_M 32B writer models; comfortable headroom for image-gen + Ollama simultaneously |
| CPU-only | no GPU | Fallback available via pipeline_writer_model=ollama/gemma2:2b-instruct-q4_K_M but output quality will be noticeably poor |
1. Prerequisites
| Tool | Version | Purpose | Required? |
|---|---|---|---|
| Docker | 20.10+ | Runs the entire backend stack | Yes |
| Ollama | 0.1.40+ | Local LLM inference | Yes |
| Node.js | 22+ | Frontend (Next.js) and lint-staged hooks | Yes |
| Git + Git Bash | any | start-stack.sh uses bash | Yes |
| Python | 3.13+ | CLI + running worker outside Docker | Yes |
| GPU | 8GB VRAM | Ollama inference is far faster with CUDA | Recommended |
cmd.exe and PowerShell do not work with the start scripts.
Docker Desktop must be configured to use WSL2 backend.
Linux note. Stock Docker Engine on Linux does not automatically
resolve host.docker.internal — this is a Docker Desktop feature.
The compose files add extra_hosts: ["host.docker.internal:host-gateway"]
to every service that calls a host-side endpoint (Ollama, image-gen, voice
bridge). host-gateway is a Docker built-in alias that resolves to the
host’s IP and is supported on Docker Engine 20.10+. No manual
configuration is needed; the extra_hosts entries are already present in
both docker-compose.yml and docker-compose.local.yml.
GPU note. You can run Poindexter on CPU, but content generation
that takes 30 seconds on an RTX 4090 can take 10+ minutes on CPU.
Not practical for daily use.
2. Clone and setup
- Prompts for a database URL (or auto-provisions a local Docker
Postgres with
--auto). - Tests the database connection and reports success/failure.
- Runs migrations against the target database. Safe to re-run — migrations are idempotent.
- Generates secrets — creates random
local_postgres_password,grafana_password, andpgadmin_password. - Writes
~/.poindexter/bootstrap.tomlwith the database URL + generated secrets. This is the only config file on disk. - Provisions the initial CLI OAuth client — registers a row in
oauth_clients, encrypts the credentials intoapp_settings.cli_oauth_client_id/cli_oauth_client_secret, and prints the plaintext secret once for capture. (Worker auth uses OAuth 2.1 only as of Glad-Labs/poindexter#249.)
.env file is created. All secrets live in bootstrap.toml
(safe permissions, never committed to git).
3. Pull AI models
4. Bring up the full stack
~/.poindexter/bootstrap.toml, exports the values as env
vars, and runs docker compose -f docker-compose.local.yml up -d.
No .env file needed.
This starts the core containers (cross-referenced against the CLAUDE.md Quick-Links table for ports + purposes):
| Container | Purpose | Port |
|---|---|---|
poindexter-worker | FastAPI backend, content pipeline | 8002 |
poindexter-brain-daemon | Health probes + self-healing loop | — |
poindexter-postgres-local | PostgreSQL 16 + pgvector | 5433 |
poindexter-grafana | Monitoring dashboards | 3000 |
poindexter-prometheus | Metric scraper | 9091 |
poindexter-image-gen-server | image-gen image generation (GPU) | 9836 |
poindexter-pgadmin | Database GUI | 18443 |
poindexter-langfuse | LLM trace explorer + prompt UI (UnifiedPromptManager edits land here) | 3010 |
poindexter-glitchtip | Self-hosted Sentry — runtime errors from worker / brain / voice agent | 8080 |
poindexter-prefect | Orchestration UI for the Prefect server (flow runs, schedules) | 4200 |
poindexter-pyroscope | Continuous profiler — flame graphs from worker / brain / voice | 4040 |
poindexter-loki | Log storage (consumed via Grafana Explore — Loki datasource) | 3100 |
poindexter-tempo | Trace storage (consumed via Grafana Explore — Tempo datasource) | 3200 |
poindexter-alertmanager | Alert-routing UI | 9093 |
poindexter-livekit | Local LiveKit server (Tailscale Serve fronts /voice/join, tailnet-only) | 7880 |
5. Verify
pending → in_progress → awaiting_approval
within a few minutes. Follow along via:
6. Frontend (optional for backend dev)
If you’re only iterating on the backend, skip the frontend — the worker’s API and the Grafana dashboards are all you need. If you do want the Next.js public site running locally:7. Run the tests
The unit suite runs lean — the cross-encoder reranker (Expected: the full unit suite passes (several thousand cases). Some tests that depend on thesentence-transformers
torch) is an opt-inrerankextra that CI deliberately skips, and the tests that touch itimportorskip. Addpoetry install --extras rerankonly if you want to exercise the reranker locally.
brain module or sentry-sdk are skipped when running
inside Docker (these pass on the host where all modules are available).
8. What to do when something breaks
See troubleshooting.md.Configuration
All runtime configuration lives in theapp_settings Postgres
table, not env vars. After setup, change settings with: