Turn one topic into a ready-to-post Instagram carousel, caption, and reel — in your brand's voice.
Generated by the command below from the topic “why your cold brew tastes bitter.”
git clone https://github.com/galak06/persona.git
cd persona
pip install -r app/requirements.txt
python cli.py demoThat's it. No API key, no account, no database — demo renders the full
pipeline offline and writes real files to ./out/.
When you're ready for real imagery and a written caption, add one key:
export GEMINI_API_KEY=... # https://aistudio.google.com/apikey
python cli.py generate --topic "why your cold brew tastes bitter"Every run writes a folder you can post from directly:
out/why-your-cold-brew-tastes-bitter/
├── slide-1.jpg hook slide, with your @handle badge
├── slide-2.jpg first key point
├── slide-3.jpg second key point
├── slide-4.jpg payoff slide, with your site CTA ribbon
├── caption.txt 80–140 words in your voice, ends on a question, 6–8 hashtags
└── reel.mp4 9:16 vertical reel, crossfaded (needs ffmpeg)
The model plans the slides; a deterministic renderer draws the text. That split matters — headlines land in the same place every time instead of wherever an image model felt like putting them.
Persona has no niche baked in. Everything it says about your brand comes from one config file:
cp app/config.example.json ~/my-brand/config.json
$EDITOR ~/my-brand/config.json
python cli.py generate --brand ~/my-brand --topic "your topic"The fields that shape the output:
| Field | What it does |
|---|---|
site.name |
Brand name used throughout |
site.niche |
What you write about — drives slide content |
site.target_audience |
Who the copy speaks to |
site.brand_persona |
The voice the caption is written in |
site.mascot_name |
Mentioned once, naturally, in the caption |
site.mascot_kind |
Optional. Leave blank and prompts say “the brand's mascot” — they never guess a species |
social_channels.instagram.ig_username |
The @handle on the hook slide |
See examples/demo-brand/config.json for a filled-in example.
Persona degrades instead of failing. Every provider is optional; the chain falls through to the next one.
| Capability | Provider | Env var | Without it |
|---|---|---|---|
| Slide + caption planning | Gemini | GEMINI_API_KEY |
Deterministic template plan |
| Slide imagery | Gemini image | GEMINI_API_KEY |
Falls through to Pexels |
| Stock imagery | Pexels | PEXELS_API_KEY |
Falls through to generated gradients |
| Reel composition | ffmpeg | (on PATH) | Slides + caption only, no MP4 |
On Linux, text rendering needs a font: apt-get install fonts-dejavu-core.
python cli.py demo # zero-config sample
python cli.py generate --topic "..." # your topic
--brand PATH brand dir or config.json (default: demo brand)
--out DIR output directory (default: ./out)
--offline skip all network calls
--no-reel skip MP4 composition
-v show progress
The studio above is the part that runs anywhere with one API key. The repository also contains a fuller platform — a FastAPI backend, a React dashboard, a WordPress publishing pipeline, scheduling, and outbound social engagement.
Those parts need real accounts and infrastructure (Postgres, Redis, a
Meta app), and they are not wired into cli.py. Setup lives in
app/SETUP.md.
A note on the engagement modules. Persona can drive a logged-in browser session to like and comment on Instagram and Facebook. That is against Meta's Terms of Service, and accounts doing it can be restricted.
Nothing in
cli.pyreaches them, and they can't run without the full platform — Postgres, a provisioned brand, and a browser session you have logged in yourself. But once you provision a brand through onboarding,ig-engageris in the default enabled flow set and will run on its schedule. Turn it off in Brand Settings, or pass a differentenabled_flows, if that isn't what you want.Understand the risk to your own account before leaving it on. The maintainers don't recommend pointing it at an account you can't afford to lose.
What works today, what's parked, and what's planned: ROADMAP.md.
Issues and pull requests are welcome — see CONTRIBUTING.md.
MIT — see LICENSE.


