https://github.com/glad-labs/poindexter
Poindexter — open-source AI content pipeline that researches, writes, reviews, and publishes autonomously. Self-hosted on your machine. Built by Glad Labs LLC.
https://github.com/glad-labs/poindexter
ai ai-content apache2 automation blog-engine content-pipeline fastapi grafana headless-cms llm ollama pgvector postgresql self-hosted
Last synced: 22 days ago
JSON representation
Poindexter — open-source AI content pipeline that researches, writes, reviews, and publishes autonomously. Self-hosted on your machine. Built by Glad Labs LLC.
- Host: GitHub
- URL: https://github.com/glad-labs/poindexter
- Owner: Glad-Labs
- License: apache-2.0
- Created: 2026-04-10T02:25:55.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-05-31T07:42:15.000Z (25 days ago)
- Last Synced: 2026-05-31T09:22:19.088Z (25 days ago)
- Topics: ai, ai-content, apache2, automation, blog-engine, content-pipeline, fastapi, grafana, headless-cms, llm, ollama, pgvector, postgresql, self-hosted
- Language: Python
- Homepage: https://www.gladlabs.io
- Size: 131 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 62
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
- Support: SUPPORT.md
Awesome Lists containing this project
README
# Poindexter
**A plug-and-play AI/ML content creation OSS stack.** Your PC is the factory: Poindexter researches, writes, reviews, and publishes — autonomously. Local-first, Ollama-powered, zero API costs. Built by [Glad Labs LLC](https://www.gladlabs.io).
[](LICENSE)
[]()
[]()
[](https://www.gladlabs.io)
## Who this is for
If you've ever thought _"I could publish good content at scale if I had a system that didn't just spam mediocre AI text,"_ — Poindexter is that system.
It's built for:
- **Solo operators** who want to run a content business from one machine, with their own GPU, without paying per-token API fees
- **Indie publishers** who need automation but refuse to ship hallucinated text
- **AI/ML engineers** who want a working content stack to fork, extend, and learn from — every layer is OSS, every layer is swappable
It is _not_ for: marketing teams who want a one-click web app (use Jasper / Copy.ai), or anyone unwilling to run Docker on their machine.
The pitch is "plug and play": `poindexter setup --auto` takes you from a fresh clone to a healthy local stack in one command — Postgres provisioned, OAuth client minted, migrations run, models pulled, services up. After that, every component is swappable through `app_settings` or plugins.
## What it does
One engine, eight jobs:
1. **Discovers** trending topics from HackerNews, Dev.to, and your niche feeds
2. **Researches** each topic with deep web search and source verification
3. **Writes** long-form posts using local LLMs (Ollama) — or cloud models via the optional LiteLLM provider plugin
4. **Reviews** every draft with multi-model adversarial QA on 7 quality dimensions
5. **Validates** against hallucinations — catches fake people, stats, quotes, impossible claims
6. **Publishes** to any frontend via static JSON export (push-only headless CMS)
7. **Generates** podcast episodes, AI images, and short text-to-video clips (Wan 2.1 T2V — alpha, opt-in)
8. **Monitors** itself with Grafana dashboards, auto-heals via brain daemon, alerts on Telegram/Discord
Run it on your machine. Own your data. No cloud lock-in.
**Not a spam cannon.** ~50% of generated drafts are rejected by QA. Multi-model adversarial review, deterministic anti-hallucination validation, and research-backed content. Speed comes from generating more candidates and filtering aggressively — not from lowering the bar.
## Quick start
> **Windows users:** run from Git Bash or WSL. The setup script needs `bash`.
```bash
# 1. Clone
git clone https://github.com/Glad-Labs/poindexter.git
cd poindexter
# 2. Setup — generates secrets, tests DB, writes ~/.poindexter/bootstrap.toml
pip install -e src/cofounder_agent
poindexter setup --auto # spins up local Postgres automatically
# 3. Pull AI models
ollama pull gemma3:27b && ollama pull qwen3:8b && ollama pull nomic-embed-text
# 4. Start the full stack
bash scripts/start-stack.sh
# 5. Generate your first post
poindexter content create "Why Docker changed everything" --category technology
```
The pipeline runs automatically. Watch progress at `http://localhost:3000` (Grafana).
### Prerequisites
- **Docker Desktop** — [docker.com](https://docker.com)
- **Ollama** — [ollama.com](https://ollama.com)
- **Node.js 22+** — [nodejs.org](https://nodejs.org) (for the optional Next.js public site)
- **GPU** — RTX 3060+ (8 GB VRAM minimum). Works on CPU, just slowly.
### Required models
`poindexter setup --auto` doesn't pull these — Ollama does, but you trigger it. With these three, the full pipeline runs end-to-end on any 8 GB+ GPU:
| Model | Size | Role |
| ------------------ | ------ | ----------------------------------------------------- |
| `qwen3:8b` | 5 GB | Fast tasks — SEO, image decisions, summaries, routing |
| `gemma3:27b` | 16 GB | QA critic + writer fallback |
| `nomic-embed-text` | 274 MB | Embeddings for semantic search + memory retrieval |
### Writer model — configurable
The writer is the one model worth upgrading. Set `pipeline_writer_model` in `app_settings` (or via `poindexter settings set`) to any Ollama model you have. Trade-offs:
```bash
ollama pull qwen3:30b # 18 GB — best speed/quality balance publicly available
ollama pull qwen3.5:35b # 23 GB — stronger prose, slower
ollama pull llama3.3:70b # 42 GB — highest quality, needs 48 GB+ VRAM or CPU offload
ollama pull glm-4.7:9b # 6 GB — lighter fallback for <16 GB VRAM
```
Glad Labs production runs a custom RTX 5090 fine-tune (`glm-4.7-5090`, 19 GB) not on the public registry; any of the above work fine.
Every model routing decision (writer / critic / research / summarizer / embedder) lives in `app_settings` and can be swapped at runtime — no restart, no redeploy.
## Architecture
Poindexter is decomposed by analogy to brain anatomy. Each region is independent and communicates only through PostgreSQL — no inter-service imports.
```
Brainstem (brain/) — standalone daemon, monitors, self-heals
Cerebrum (src/cofounder_agent/) — FastAPI backend, content pipeline, REST + MCP
Cerebellum — anticipation engine + QA registry (learned patterns)
Limbic (brain_knowledge) — knowledge graph, memory retrieval, revenue feedback
Thalamus — process composer, routes inputs to the right pipeline
Hypothalamus (settings_service) — homeostasis: budget, cost guard, runtime config
Spinal Cord (PostgreSQL+pgvector) — shared substrate, all components talk through it
Any frontend reads static JSON from CDN — Next.js, Hugo, Astro, or a single HTML file.
```
The brainstem can crash and restart without taking down the cerebrum. The cerebrum can be replaced with a different pipeline implementation as long as it writes the same tables. The architecture is designed to be poked at one region at a time.
Full diagram and design rationale in [`docs/architecture/`](docs/architecture/).
## Key features
| Feature | Description |
| ---------------------------- | ------------------------------------------------------------------------------------------- |
| **Local AI by default** | Ollama for inference. Your GPU, your data, zero API costs. |
| **Cloud opt-in** | LiteLLM provider plugin routes to Anthropic, OpenAI, Groq, OpenRouter — gated by cost guard |
| **Anti-hallucination** | 3 independent layers: prompts, multi-model QA, deterministic validator |
| **DB-as-config** | 800+ settings (60 secret) in PostgreSQL. Change with SQL or REST. No deploys. |
| **Langfuse-managed prompts** | Edit prompts in a UI; runtime falls back to YAML defaults if Langfuse is offline |
| **LangGraph pipelines** | `template_runner.py` runs declarative DAGs with checkpointing |
| **Multi-modal output** | Markdown posts, AI images (SDXL / Flux), podcast audio, text-to-video (Wan 2.1 — alpha) |
| **Push-only output** | Static JSON + RSS + JSON Feed 1.1 to any S3-compatible storage |
| **Multi-site** | One daemon manages N sites. Each site = config row + storage bucket. |
| **Self-healing** | Brain daemon monitors all services, restarts failures, alerts via Telegram/Discord |
| **Production observability** | Grafana, Prometheus, Loki, Pyroscope (CPU profiling), Sentry/GlitchTip |
| **OAuth 2.1 throughout** | Every consumer (CLI, MCP, brain, scripts) mints scoped JWTs. No static API keys. |
| **8,400+ tests** | Unit coverage across all services, smoke tests on migrations, link-rot CI |
## Stack
- **Backend:** Python 3.13 / FastAPI / asyncpg
- **LLM (default):** [Ollama](https://ollama.com) — local inference, your GPU
- **LLM (optional):** [LiteLLM](https://github.com/BerriAI/litellm) provider plugin — Anthropic, OpenAI, Groq, OpenRouter, Bedrock, Vertex (gated by `cost_guard`)
- **Orchestration:** [LangGraph](https://github.com/langchain-ai/langgraph) (declarative pipelines via `template_runner`)
- **Prompt management:** [Langfuse](https://langfuse.com) (UI-editable, runtime fallback to YAML)
- **Embeddings:** `nomic-embed-text` via Ollama → pgvector
- **Database:** PostgreSQL 16 + pgvector
- **Auth:** OAuth 2.1 Client Credentials Grant (per-consumer JWTs)
- **Observability:** Grafana + Prometheus + Loki + [Pyroscope](https://pyroscope.io) + Sentry-compatible (GlitchTip)
- **Voice (optional):** LiveKit + Whisper (STT) + Kokoro (TTS)
- **Storage:** any S3-compatible (Cloudflare R2, AWS S3, Backblaze B2, MinIO)
- **CI/CD:** GitHub Actions
- **Infrastructure:** Docker Compose (~32 containers including the full observability + voice + image-gen sidecars; a minimal worker-only deploy needs ~8)
## Configuration
Everything tunable lives in the `app_settings` database table — not environment variables. The only file you write to disk is `~/.poindexter/bootstrap.toml`, created by `poindexter setup`. It contains the database URL plus a small number of pre-DB-reachable secrets (Postgres password, OAuth signing key, optional Telegram/Discord operator alerts).
After that, every config knob is managed via API, SQL, or the CLI:
```bash
# View all settings
poindexter settings list
# Change a setting at runtime
poindexter settings set auto_publish_threshold 80
# Rotate via REST (with OAuth-issued JWT)
curl -X PUT http://localhost:8002/api/settings/auto_publish_threshold \
-H "Authorization: Bearer $(poindexter auth token)" \
-d '{"value": "80"}'
```
No restart required for most settings. See [`docs/operations/environment-variables.md`](docs/operations/environment-variables.md).
## Plugins
Poindexter is built on a small extension framework. Eighteen plugin types let you customize the system without touching core code — the most commonly extended ones:
| Type | Role |
| ------------------ | -------------------------------------------------------------------------------------- |
| **Tap** | Pulls data into the system (RSS, Slack, social feeds, etc.) |
| **Probe** | Reports state to the brain (health checks, business metrics) |
| **Job** | Scheduled work (cron-like, lives in the worker) |
| **Stage** | A step in the content pipeline (research, draft, QA, etc.) |
| **TopicSource** | Discovers candidate topics (HackerNews, dev.to, web search, etc.) |
| **LLMProvider** | Inference backend (Ollama is default; LiteLLM, OpenAI-compat, etc.) |
| **ImageProvider** | Featured + inline images (SDXL, Flux, Pexels, etc.) |
| **PublishAdapter** | Where finished posts go (S3-compatible, Discord, custom CMS, etc.) |
| **Module** | Bundles the above + migrations + routes into a versioned business function (Module v1) |
The full set also includes Reviewers, Adapters, Packs, AudioGenProviders, VideoProviders, TTSProviders, CaptionProviders, and MediaCompositors. See `plugins/registry.py::ENTRY_POINT_GROUPS` for the canonical list.
Each plugin lives in its own pip package and registers via setuptools `entry_points`.
### Using a plugin
```bash
pip install poindexter-tap-slack
poindexter settings set plugin.tap.slack '{"enabled": true, "config": {"workspace": "myteam"}}'
```
Next worker restart picks it up. No core code changes.
### Authoring a plugin
A package needs three things — a class implementing the relevant Protocol, an `entry_points` registration, and per-install config docs. Example Tap:
```python
# my_package/slack_tap.py
from poindexter.plugins import Tap, Document
class SlackTap:
name = "slack"
interval_seconds = 3600
async def extract(self, pool, config):
async for msg in fetch_slack_messages(config):
yield Document(
source_id=f"slack/{msg.ts}",
source_table="slack",
text=msg.text,
metadata={"channel": msg.channel, "user": msg.user},
writer="poindexter-tap-slack",
)
```
```toml
# pyproject.toml
[project.entry-points."poindexter.taps"]
slack = "my_package.slack_tap:SlackTap"
```
The shipping samples (`HelloTap`, `DatabaseProbe`, `NoopJob`) live in `src/cofounder_agent/plugins/samples/`. The first real plugin in production is the `LiteLLMProvider` — Glad Labs eats its own dog food. Full design in [`docs/architecture/plugin-architecture.md`](docs/architecture/plugin-architecture.md).
## Project status
Poindexter is in **alpha**. Honest snapshot:
**What works today**
- Full content pipeline end-to-end on the author's daily-driver setup (RTX 5090, 64 GB RAM, Windows 11). Single-operator content business publishing daily.
- 78 live posts on [gladlabs.io](https://www.gladlabs.io) (222 total drafts, 1,626 pipeline runs).
- 8,400+ unit tests passing in CI on every push, plus migrations smoke test and link-rot CI.
- `poindexter setup` takes a fresh clone to a healthy local stack — generates secrets, tests DB, runs migrations, writes bootstrap.toml. No `.env` file required.
- Live in-place upgrades — schema changes, container renames, env var migrations applied to a running instance with zero data loss and no in-flight task downtime.
- Multi-model QA scoring with deterministic validators, an LLM critic chain, and a programmatic anti-hallucination layer.
- Push-only static export to any S3-compatible storage. Frontend is decoupled — Next.js, Hugo, Astro, or a static HTML file.
- OAuth 2.1 throughout (per-consumer scoped JWTs, no static API keys).
**Known rough edges**
- No managed/hosted Poindexter offering yet. Self-host only.
- No multi-tenant deployment recipe. One operator, one machine.
- Native Windows cmd / PowerShell not supported. Use Git Bash or WSL.
- Database schema is not yet stable across releases. Read the CHANGELOG before upgrading.
- Plugin framework is real (LiteLLMProvider runs in production), but the community ecosystem is nascent — you may be writing the second-ever third-party plugin.
- **Text-to-video is alpha.** The Wan 2.1 T2V provider plugin and `wan-server` Docker sidecar exist and pass smoke tests, but it's an opt-in path (not in the default content pipeline) and the inference server needs ~28 GB VRAM headroom on a 32 GB+ card. Track Glad-Labs/poindexter#124 for production-readiness.
If any of those would block your use case, that's worth knowing before you start. PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING).
## Pricing
The engine is free and open-source under Apache 2.0. **Pro** is a subscription for operators who want production-grade output without tuning from scratch.
| Tier | Price | What you get |
| -------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Free** | $0 | Full pipeline engine, baseline prompts, 1 Grafana dashboard (Pipeline Operations), GitHub issues support |
| **Pro** | $9/mo or $89/year (save ~17%)
**7-day free trial** | Production-tuned prompts (anti-hallucination, SEO, QA, research), additional Grafana dashboards, prompt updates as Matt tunes them, private VIP Discord, the Poindexter book |
Pro exists for the obvious case: you've installed the OSS, you've seen output that's _almost_ there, and you want the version that's actually shipping content on gladlabs.io daily. Pro gives you the months of prompt tuning in a single install.
- **[Start your 7-day Pro trial — $9/mo](https://gladlabs.lemonsqueezy.com/checkout/buy/a5713f22-3c57-47ae-b1ee-5fee3a0b43b9)**
- [Subscribe annually — $89/year](https://gladlabs.lemonsqueezy.com/checkout/buy/a5713f22-3c57-47ae-b1ee-5fee3a0b43b9)
- [Compare tiers on gladlabs.io/product](https://www.gladlabs.io/product)
## Documentation
Full technical docs live under [`docs/`](docs/welcome). Recommended path:
- **[Architecture overview](docs/architecture/overview)** — how the regions fit together
- **[Multi-agent pipeline](docs/architecture/multi-agent-pipeline)** — the content pipeline + cross-model QA
- **[Database schema](docs/architecture/database-schema)** — every table + migration system
- **[CLI reference](docs/operations/cli-reference)** — every `poindexter` subcommand
- **[Plugin authoring](docs/operations/extending-poindexter)** — write Stages, Reviewers, Adapters, Taps, Jobs, Probes
- **[Local development setup](docs/operations/local-development-setup)** — end-to-end walkthrough
- **[Troubleshooting](docs/operations/troubleshooting)** — production issues we've hit
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING). Issues and PRs welcome.
## Security & SBOM
- Report vulnerabilities to **security@gladlabs.io** ([SECURITY.md](SECURITY))
- Every push to `main` runs gitleaks (secrets), Trivy (CVEs), and syft+grype (SBOM + CVE scan)
- A CycloneDX-JSON **SBOM** is published as a workflow artifact on every release; enterprise buyers can request one directly
## License
[Apache License 2.0](LICENSE) — Copyright 2025-2026 Glad Labs LLC
Relicensed from AGPL-3.0 to Apache 2.0 on 2026-04-29 — see [CHANGELOG](CHANGELOG.md).