Skip to main content
This walkthrough takes a clean machine to a running Poindexter pipeline with a first post in the approval queue. It is the README’s quick start, step for step. A CI job (quickstart-e2e) runs that exact sequence on a clean GitHub runner every week and on every change to it, and fails unless the queued post reaches awaiting_approval, and, once approved and published, can be read at /site/. (A runner has no GPU, so the job stands one tiny model in for the three large ones and zeroes the quality bar; every command is yours, verbatim.) For what each step does under the hood, see operations/local-development-setup.
Poindexter runs on Linux (Docker Engine), Windows (Git Bash or WSL2 with Docker Desktop) and macOS (Docker Desktop). Linux needs one extra Ollama setting, covered in step 3.
The default models (about 31 GB) download once and the stack’s images build once (about 13 GB). The default writer and critic are 27B and 14B models: on a GPU with less VRAM than they need, Ollama runs part of each model on the CPU and a post takes much longer. CPU-only works, slowly.

Prerequisites

Steps

1

Clone and install the CLI

Install the poindexter CLI into a Python 3.13 virtualenv inside the clone.
On Windows Git Bash, create the virtualenv with py -3.13 -m venv .venv and activate it with source .venv/Scripts/activate.
2

Bootstrap

--auto generates the stack’s secrets into ~/.poindexter/bootstrap.toml (the only config file on disk), starts the stack’s own Postgres (the postgres-local service of the compose file the next steps launch), runs the migrations, and provisions the CLI’s OAuth client. The CLI and every container share that one database. Re-running with --force keeps the secrets the file already holds.
To run the worker outside Docker against a Postgres you manage, use poindexter setup --db-url postgresql://... instead. The Docker stack always uses its own postgres-local.
3

Pull the models

These are the models the default pipeline calls. The pulls happen once.
That is about 31 GB: gemma3:27b (17 GB) is the writer, phi4:14b (9 GB) is the critic that hard-gates every draft, llama3:latest (4.7 GB) drafts the podcast and video scripts, and nomic-embed-text (274 MB) does the embeddings. Nothing pulls a model on demand: a model Ollama does not have fails the call that names it, so poindexter setup --auto prints this same command from your database’s own model settings.Pull these only when you switch the feature on: qwen3-vl:30b-a3b-instruct (image QA and captions, about 20 GB, called only when a post has images), qwen2.5:32b (fallback critic), granite4.2:3b (the brain’s alert triage) and qwen2.5:7b (console chat and the voice agent).Linux only: the containers call Ollama at host.docker.internal:11434, which on Linux is the Docker bridge gateway, and a default Ollama install listens on loopback only. Make it listen on every interface once:
Firewall port 11434 if the machine sits on a network you don’t trust. Docker Desktop on Windows and macOS needs none of this.
4

Start the stack

start-stack.sh exports bootstrap.toml as the environment the compose file needs and launches docker-compose.consumer.yml: Postgres, the worker API, the brain daemon, Prefect (server, services and worker), Grafana, Prometheus, AlertManager and the backup jobs. The first run builds the images, so allow several minutes. On its first start the Prefect worker registers the content-generation deployment that turns a queued task into a pipeline run.
5

Queue a first post

--niche names the niche the post belongs to; a fresh install seeds starter-blog, and poindexter topics niche list shows yours. A post can only be published once its task has one.The command waits for the worker to finish booting (about a minute after the stack starts). Prefect then picks the task up within two minutes and runs it pending → in_progress → awaiting_approval. Follow along in Prefect at http://localhost:4200, in Grafana at http://localhost:3000 (the Pipeline dashboard), or with docker logs -f poindexter-prefect-worker.When the draft lands, it waits for you with its QA scores attached:
Then read it at http://localhost:8002/site/. A fresh install publishes to a local folder that the worker serves there, so no bucket, account or frontend is needed.
If the task never leaves pending, check docker logs poindexter-prefect-worker first: it should log the content-generation deployment on startup. Then see operations/troubleshooting.
If the task ends rejected instead of awaiting_approval, the auto-curator turned the draft away: a finished draft scoring under min_curation_score (seeded at 75) never reaches the queue, and a writer smaller than the default can land there. poindexter tasks list --status rejected shows its Q: score; operations/troubleshooting shows how to read the verdict and lower the bar (poindexter settings set min_curation_score 50; 0 turns the auto-curator off).

Next

Architecture overview

The kernel/module/capability structure, the LangGraph pipeline, the six QA rails — how the parts fit.

Operations runbooks

Day-2 work: troubleshooting, incident response, backups, secret rotation.

CLI reference

Every poindexter subcommand with flags and examples.

Extend with plugins

Add a Stage, Reviewer, Publishing Adapter, Tap, or Module.