The anti-slop pSEO engine.
rankloop is a stateful, self-feeding loop built around one SQLite keyword backlog: real search data flows in, grounded writer briefs flow out, and a wall of publish laws blocks filler before it ships. It was extracted from a production engine that ran three sites, and it encodes the one thing that engine proved: nine-tenths of the value of programmatic SEO is the machinery around the writing, not the writing.
rankloop never writes a word of content and never calls an LLM. It makes whatever writes your content — an LLM CLI, a script, a person — grounded, honest, and measurable.
seeds ──► discover / suggest / harvest ──► score ──► SERP-ground ──► pick
│
GSC unserved-query harvest ◄── measure traffic ◄──┐ ▼
(refills the backlog) │ brief ──► YOUR WRITER
▲ │ │
└─────────── deploy ◄── wire ◄──┴── check (the laws)
Every arrow reads or writes a single SQLite file that lives next to your config (safe to commit — state travels with the repo). The loop closes at the bottom-left: queries Google already shows your site for, that have no page and no backlog row yet, get harvested straight back into the queue on every Search Console sync. That is the flywheel.
- Stdlib-only core. No required dependencies. Python 3.11+.
- Niche-agnostic. All niche knowledge (seeds, relevance regexes, taxonomy,
banned phrases) lives in one commented
rankloop.toml; all machinery lives in code. Swap the config and the same engine runs any site. - Writer-agnostic.
rankloop briefemits a grounded markdown brief on stdout. Pipe it into anything.
The fastest path. From your site's repo:
pipx install rankloop
rankloop setup | claude -p # or any agent CLI with file accesssetup prints a complete onboarding prompt. The agent studies your site --
its niche, voice, information architecture, even the CSS -- and writes your
entire configuration: rankloop.toml (relevance regexes, taxonomy, laws
calibrated so your existing posts pass), seeds.txt (50-100 clustered seed
phrases), writer-prompt.md (your voice + verified facts), a post template
matched to your design, and an OG-card palette derived from your real brand
colors. It finishes by printing the cron lines that automate the whole loop.
Then automation is three cron lines -- each routine prints its full operating playbook, so the agent that runs it needs zero prior context:
30 9 * * * cd /your/site && rankloop routine daily | claude -p
0 9 * * 1 cd /your/site && rankloop routine weekly | claude -p
0 8,14,20 * * * cd /your/site && rankloop routine news | claude -pThe daily routine has catch-up quota semantics: a missed day is owed, not
skipped (rankloop quota computes it from the calendar and the content
tree itself, capped so an outage never floods the site). Your laptop can
sleep; the plan doesn't drift.
pipx install rankloop # stdlib-only core, zero dependencies
cd your-site/
rankloop init # writes a commented rankloop.toml + seeds.txt
$EDITOR rankloop.toml # your niche lives here: regexes, taxonomy, laws
$EDITOR seeds.txt # 50-100 seed phrases in commented clusters
# fill the backlog — free path first
rankloop suggest # Google/Bing/DDG autocomplete long-tails ($0)
rankloop harvest # StackExchange + Reddit literal questions ($0)
# optional paid metrics (DataForSEO account required)
rankloop discover --dry-run # cost projection only — spends nothing
rankloop discover # volume + difficulty + SERP briefs, budget-capped
# write one post
rankloop pick # top-scored keywords + one fresh-question slot
rankloop brief "your keyword" | your-writer > website/blog/your-keyword/index.html
# ^ claude -p, a script, a human with a text editor
# gate + ship
rankloop check # the publish laws; any failure exits 1
rankloop wire # regenerate sitemap.xml, rss.xml, llms.txt
rankloop indexnow # ping Bing/DuckDuckGo/Yandex directly
git add -A && git commit -m "post" && git push # deploy however you deploy
# close the loop (weekly)
rankloop gsc setup # one-time Search Console OAuth (loopback, stdlib)
rankloop gsc sync --days 28 # pull real queries; unserved ones refill the backlog
rankloop status # backlog by status/source, spend, 28-day GSC summaryrankloop check is designed as a CI gate: it exits non-zero on any law
failure, so one sloppy post can never silently ship with the good ones.
Every post passes these before it ships. Thresholds are config
([laws] in rankloop.toml); defaults were calibrated on a real corpus.
| law | default | why |
|---|---|---|
| em dashes banned | on | the single most reliable LLM tell; colons and periods instead |
| word count | 850–4500 | below = thin page; above = should be two pages |
| H2 sections | ≥ 4 | scannable structure; each H2 is a potential snippet |
| FAQ entries | ≥ 3 | answer engines extract these verbatim |
| internal links | ≥ 2, must resolve | every link is checked against real slugs — no post ships a 404 |
| title length | ≤ 70 chars | SERP truncation |
| meta description | ≤ 165 chars | SERP truncation |
| keyword in body | required | you'd be surprised |
| keyword density | ≤ 2.5% | above this it reads like it was written for a robot, because it was |
| banned filler phrases | 15 defaults | "delve into", "game-changer", "in today's fast-paced world"… any hit fails |
| first-person present | on | a human voice, enforced mechanically |
| canonical URL | required (html mode) | must equal exactly site.url + blog_path + slug |
A second, tool-gated layer runs when the tools are installed and degrades to a
WARN + skip when they are not — automation is never blocked by a missing
dependency:
- vale — the same banned-phrase laws as prose lint, plus an AI-slop
watchlist and hedge-phrase warnings (styles ship in
rankloop/templates/vale/) - lychee — offline link checking across the whole content tree
- extruct — JSON-LD completeness, FAQ schema mirrored in visible text
- textstat — readability band (FK grade / reading ease)
pip install 'rankloop[lint]' # extruct + textstat
brew install vale lychee # or your package manager of choice| command | what it does |
|---|---|
rankloop init |
write a commented rankloop.toml + seeds.txt template |
rankloop suggest |
free autocomplete harvest (Google, Bing, DuckDuckGo; 8 question prefixes × a–z fan-out) |
rankloop harvest |
free literal-question harvest (StackExchange tag feeds, Reddit public RSS) |
rankloop discover |
paid keyword metrics via DataForSEO — cost-projected, budget-capped, every call logged to a spend ledger |
rankloop news |
poll trigger feeds, dedupe, print fresh items — news is a trigger for evergreen pages, never a content type |
rankloop pick |
the selector: highest-scored backlog rows + one fresh-question slot |
rankloop brief |
emit a grounded markdown writer brief (cached SERP + real People-Also-Ask + your laws) to stdout |
rankloop check |
enforce the laws; exit 1 on any failure |
rankloop linkfix |
strip dead internal links, keep the anchor text as prose |
rankloop wire |
regenerate sitemap.xml, rss.xml, llms.txt, llms-full.txt from the post manifest — idempotent, never touches your index or theme |
rankloop indexnow |
submit URLs to the IndexNow API (Bing/DuckDuckGo/Yandex) |
rankloop gsc setup / gsc sync |
Search Console OAuth + sync; unserved queries auto-refill the backlog |
rankloop status |
one screen: backlog by status/source, total spend, GSC 28-day summary |
The part that makes the engine self-feeding: rankloop gsc sync pulls your
real Search Console rows, then harvests unserved queries — search terms
Google already shows you for that have no page and no backlog row — straight
back into the keyword queue. It also surfaces opportunity pages (earning
impressions, CTR under 2%: your title/meta rewrite queue) and page-2
keywords (positions 5–20 with real impressions: the small-push targets).
Real traffic data refills the topic queue. No brainstorming meeting required.
Does rankloop write content? No. It has no LLM integration and makes no LLM API calls, ever. It produces briefs and enforces laws; the writing is your writer's job.
Does it track rankings? No. There is no rank tracker. What you get is your own Search Console data (impressions, clicks, average position), which is both free and more honest than scraped rank checks.
Does it do outreach or build backlinks? No. Nothing in rankloop contacts anyone, and nothing should. Outreach automation is how link profiles die.
Are the volume and difficulty numbers real? They are vendor estimates, and rankloop treats them that way: free long-tail keywords carry NULL volume and neutral prior scores by design, because "0 volume" from a keyword tool frequently means "real but too small to measure" — exactly the queries a young domain can win.
Will Google penalize this? The scaled-content-abuse policy targets thin mass pages, not automation. The laws exist to keep you on the right side of that line — unique substance, enforced voice, honest claims, a throttle. No tool can guarantee rankings, including this one.
More in docs/faq.md.
- docs/playbook.md — the full operating playbook: seed authoring, the relevance gate, source strategy, the flywheel, gotchas
- docs/config.md — every
rankloop.tomlkey - docs/routines.md — cron / launchd / GitHub Actions templates for the daily and weekly cadences
- docs/faq.md — the honest limits, in full
Running rankloop on a real site? Open a PR and add it here.
MIT.