The same gate, in your terminal. Score content, audit a blog, and wire the gate into CI - all from dokeo scan.
Install
The CLI ships as the dokeo package on PyPI. Requires Python 3.9+. Zero non-stdlib dependencies - works on any machine with the standard library.
# Install from PyPI
pip install dokeo
# Or install from the repo (for the latest dev version)
git clone https://github.com/rasulshaikh/dokeo.git
cd dokeo
pip install -e .Authenticate
Generate an API key from the admin panel or by calling POST /api/v1/admin/keys. Then either set it inline or save it for reuse.
# Save your API key to ~/.dokeo/config.json (one-time setup)
dokeo login dk_your_tenant_key_here
# Or pass it inline
export DOKEO_API_KEY="dk_..."
# Point at a self-hosted instance if you're running one
export DOKEO_API_URL="http://localhost:8000"Score a piece of content
The scan command accepts content three ways: inline (--content), from a file (--file), or by fetching a URL (--url).
# Scan inline content
dokeo scan --content "Most B2B event teams outgrow their first registration tool..."
# Scan a file
dokeo scan --file post.md --content-type blog --primary-keyword "event software"
# Scan a URL (server fetches + extracts)
dokeo scan --url https://yourblog.com/posts/foo --content-type blog
# Output raw JSON instead of the pretty report
dokeo scan --content "..." --formatSample output (pretty-printed by default):
VERDICT FAIL
SCORE 54/100
WORDS 152
SEO 65 AEO 60 GEO 38
CHECKS
FAIL structure
→ 152 words is below hard floor 800
→ only 1 H2 sections, expected >= 3
WARNING aeo
→ no FAQ section detected
PASS readability
PASS claims
ACTION ITEMS (5)
[critical] Add 650 more words to clear the structure hard floor
[recommended] Add an FAQ section with 3+ Q&A pairs
[recommended] Cite at least 2 authoritative sources
Scan a whole blog
dokeo batch <url> discovers URLs via RSS / Atom feed or sitemap.xml, fetches each post (SSRF-guarded), and scores them all. Returns a JSON object with {scanned, results[]}.
# Scan the first 25 posts on your blog
dokeo batch https://yourblog.com --limit 25
# Stream results as JSON
dokeo batch https://yourblog.com --limit 50 --formatInspect your account
whoami shows your tenant id, tier, and current credit balance. history lists your most recent scans. types shows the 17 supported content types.
# Show your tenant + credit balance
$ dokeo whoami
{
"tenant": "default",
"tier": "admin",
"credits_balance": 1000000000,
"credits_monthly": 1000000000
}Pipe into CI
dokeo scan itself never sets an exit code from the verdict -- use dokeo pre-commit, which exits 1 when any scanned file comes back FAIL or BLOCKER (the two severities that should block a merge). Wrap it in your CI:
# GitHub Actions example
- name: Content gate
run: dokeo pre-commit post.md
env:
DOKEO_API_KEY: $DOKEO_API_KEY