How the SEOAgent CLI works
SEOAgent is a command-line tool plus a Skill for coding agents (Claude Code, Cursor, Codex, Grok bots). The CLI lives in your repo's .seoagent/ folder and does the mechanical work: crawl the live site, keep the SEO workspace in sync with the cloud, queue and close out actions. Your coding agent does the thinking and the editing. SEOAgent never publishes to a CMS or pushes to your repo; every change lands as a file your agent wrote and you review.
This page is also served as plain Markdown at /docs/cli.md (or send Accept: text/markdown). If you are an agent, read that.
Install
npm install -g @seoagent-official/seoagent
seoagent init
npm install -g puts seoagent on your PATH so an agent can call it directly at full speed. npx -y @seoagent-official/seoagent <command> works without installing anything and pays an npm fetch per call. Node 20 or newer.
seoagent init is a one-shot scaffolder, not a runtime dependency. Run it in the main repo root, never in a git worktree or scratch clone (the CLI refuses a worktree; pass --allow-worktree only if you know why). It:
- creates
.seoagent/withproject.md(domain, site type, content and public dirs, blog path), - installs the Skill bundle into your agent's skills directory and prints where,
- scans the codebase for pages (Next.js app and pages routers, Astro, static HTML, a committed sitemap) and seeds
.seoagent/pages.md, - scaffolds the Open Knowledge Format bundle under
.seoagent/okf/, - installs a post-edit hook so
seoagent syncruns after your agent writes an artifact.
Headless: seoagent init --yes --domain example.com. With a one-time setup code from seoagent.com/for/grok-bots: seoagent init --code sa_… scaffolds and binds the project to your cloud account in the same command (see Cloud account below).
The .seoagent/ workspace
Everything the CLI and the Skill know about your site is Markdown in one folder, committed to your repo. There is no database on your side.
| Path | What it holds |
|---|---|
project.md |
Site identity and publishing config: domain, site_type, live_url (the crawl origin), content_dir, public_dir, blog_path, skill_version |
context.md |
Business context the agent drafts and you correct; the relevance judge for keywords reads it |
audit/evidence.md |
Live-crawl evidence: titles, metas, H1s, canonicals, JSON-LD types, image alt gaps, robots and sitemap counts, client-render detection |
audit/latest.md |
Audit findings as a checkbox list, each citing the evidence |
audit/indexing.md |
Google URL Inspection verdicts per sitemap URL (cloud, Search Console connected) |
keywords.md, strategy/ |
Keyword inventory, topic clusters, roadmap, migration plan |
briefs/<slug>.md |
Article briefs: outline, word counts, internal-link plan, role in the cluster |
content/<slug>.md |
Article drafts; also cloud-written drafts delivered by sync |
pages.md, internal-links.md, competitors.md |
Page inventory, orphan report, competitor notes |
okf/ and llms.md |
Sources for /.well-known/okf/ and /llms.txt; sync mirrors them into public_dir |
inbox/ |
Pending actions the cloud queued for your agent (cloud, see Inbox) |
changelog.md |
Append-only line per Skill action |
Anything else you drop in .seoagent/*.md syncs too, as a raw mirror.
The session loop
This is what the Skill runs every time your agent works on SEO. It is the same loop whether a human opened the agent or a schedule did.
seoagent doctorat session start. It is the router: it prints which references and commands this workspace needs right now (--jsonto branch on it).seoagent syncpulls the cloud's work into.seoagent/inbox/and.seoagent/briefs/.- Triage the inbox. Do the work in the repo.
- If the inbox is empty and
content/has no article yet, write the first article from the brief the sync named, thenseoagent content track <path>. seoagent ack <id>for every action finished (--failed --reason "…"to decline).seoagent syncagain, thenseoagent summaryto compose the hand-off from the corrected on-disk state.
Without a cloud account the loop is local: seoagent crawl for evidence, the Skill's audit, keyword strategy and briefs written locally, seoagent verify-recs and seoagent summary at the end. sync is a silent no-op when logged out, so the Skill always runs it.
Sync: push, then pull
seoagent sync is two passes over .seoagent/*.md.
- Push sends every changed artifact to the cloud as a lossless mirror, plus typed projections for the files the cloud understands (audit findings, briefs, keywords, pages, articles). Identical bytes are never resent.
- Pull brings back what changed on the cloud since your last sync: dashboard edits, chat edits, autopilot briefs, cloud-written drafts, and pending inbox actions. A conflict on a file you edited locally keeps your copy and tells you;
seoagent pull --print <path>shows the cloud body,--force <path>takes the cloud version for that one file.
Before the auth gate, sync also does local-only work that a logged-out user needs most: it re-scans the codebase for pages, regenerates llms.md, and mirrors the OKF bundle and llms.txt into your static dir (never overwriting a route you already serve, never publishing a placeholder). You still commit and deploy.
On every pull the cloud also hands the agent short instructions, printed as SEOAgent › … lines: Search Console not connected, briefs waiting and which to write next, all free briefs written, or Autopilot off and what it would queue. They come from the server, are throttled to once a day where they repeat, and are recorded per sync so they can be measured.
sync --silent is what the post-edit hook runs. --push-only and --pull-only split the passes; seoagent pull is --pull-only.
Inbox and ack
With a cloud account, the cloud queues work for your agent as files in .seoagent/inbox/<type>-<id>.md. Each file says what to do, why, and how risky it is. Types:
| Action | Meaning |
|---|---|
cli_technical_fix |
An open technical-SEO finding to fix in a page's source |
cli_new_content |
A brief with no article yet: write and place it |
cli_content_update |
An existing page to revise (declining clicks, low CTR, thin) |
cli_draft_ready |
The cloud wrote a full article into content/; review and place it |
cli_new_landing_page |
A high-value keyword with no page covering it |
cli_sitemap_update |
Search Console cannot fetch your sitemap; write or refresh it |
cli_ai_files_update |
The OKF bundle or llms.txt is missing, unmanaged, or stale |
cli_run_audit |
The audit is older than 28 days or never ran |
cli_draft_context |
Business context is missing; draft context.md |
cli_prune_pending |
An underperforming article should be removed. Destructive: confirm first |
cli_send_outreach_email |
A human-approved link-building email to send from your own account. Confirm first send |
cli_outreach_drafts_ready |
Drafts await review on the dashboard; tell the user, then ack |
seoagent inbox lists them (--json for scripts). seoagent ack <id> closes one as completed; --failed --reason "…" declines it. seoagent process runs the pending actions through the Claude Agent SDK for you, with a selection prompt (-y for CI).
Cloud account
A free account adds what the local Skill cannot: Search Console traffic and indexing verdicts, keyword volumes, the dashboard, managed sitemaps, chat. Paid Autopilot adds the cloud doing the research (keywords, clusters, briefs) and queueing every next step in the inbox, cloud-written drafts, and owner-approved outreach.
Login. seoagent login opens the browser and binds this project's site. Headless harnesses use a one-time setup code minted at /for/grok-bots or the dashboard: seoagent init --code <code> or seoagent login --code <code> (also read from SEOAGENT_SETUP_CODE). A code is sa_ plus 24 hex characters, is issued only by the server, and works exactly once. Never guess, invent, or retype one from memory; a made-up code fails with not recognized every time.
Credentials are stored per site in ~/.config/seoagent/auth.json (XDG_CONFIG_HOME honoured), never in the project. seoagent whoami shows the account, site, plan and API base; --json for scripts. seoagent logout removes them.
Scheduled runs on a fresh machine. A scheduled task (Grok task, routine, CI job) starts cold: no auth file, and the setup code is consumed. Give it a credential instead. On the bound machine run seoagent whoami --env; it prints one line, SEOAGENT_AUTH=<user_token>:<website_token>. Store that as the task's secret. Every scheduled run then installs the CLI, exports SEOAGENT_AUTH, and runs the session loop. The CLI reads that variable before the auth file and never writes it to disk. A scheduled run must never run init --code or login --code. Full recipe, per harness, in the Skill's references/recurring-runs.md.
Autopilot. seoagent autopilot on|off|status, autopilot auto-approve on|off, autopilot draft-mode cloud|agent. Paid; seoagent upgrade opens pricing.
Search Console. seoagent gsc connect opens Google sign-in and stores the connection in the cloud; seoagent gsc status shows it. Then seoagent indexing writes URL Inspection verdicts and seoagent keywords --seed adds the queries you already rank for.
Command reference
Every command prints --help. seoagent menu is an interactive picker.
Project
| Command | What it does |
|---|---|
init |
Create .seoagent/, install the Skill, scan pages, scaffold OKF. --yes --domain, --site-type, --code |
status |
Current project state |
doctor |
Session-start health check and router (--json) |
refresh |
Refresh the installed Skill and re-scan pages (--all for every project on this machine, --crawl to fill page status) |
update-cli |
Update to the latest npm version, then refresh every project |
uninstall |
Remove .seoagent/, the Skill bundle and the hook (--global also wipes ~/.config/seoagent) |
menu |
Interactive command picker |
Audit and evidence
| Command | What it does |
|---|---|
crawl |
Live-crawl the site into audit/evidence.md. The origin is explicit: --url wins and is saved as live_url, else project.md, else it errors. A loopback origin is labelled a source render, not live evidence |
indexing |
Search Console indexing coverage into audit/indexing.md (login + GSC) |
sitemap |
Validate the live sitemap: reachability, private-route leakage, freshness, missing public pages |
internal-links |
Orphan-page report into internal-links.md |
verify-recs [files…] |
Mechanically check authored recommendations against the crawl evidence and rewrite false claims. Mandatory last step of an audit |
summary [files…] |
Compose the session summary from the corrected on-disk state (runs verify-recs first) |
citations |
Track whether answer engines cite you, with history and share of voice, into citations/scorecard.md |
Strategy and content
| Command | What it does |
|---|---|
keywords |
Enrich keywords with volume, difficulty and opportunity (login). --peek <kw> free one-off lookup; --seed from Search Console; --discover and --competitors (paid); --purge |
migrate |
Plan the migration of legacy Search Console authority after a repositioning: harvest, redirect, sunset (--csv works without login) |
content track |
Register a published article so the dashboard sees it (--file, --slug, --url, --brief, --action) |
content reconcile |
Backfill every article in the content dir (--dir, --prune) |
generate-image, env-check |
Generate an article image with the provider you have a key for (OpenAI, fal, Replicate) |
AI-readable files
| Command | What it does |
|---|---|
okf validate | scaffold | publish |
Manage the Open Knowledge Format bundle; publish copies it into the static dir so /.well-known/okf/ is served |
llms |
Generate llms.md and publish llms.txt (also runs on every sync) |
Cloud
| Command | What it does |
|---|---|
login |
Browser login, or --code <code> headless |
logout |
Remove stored credentials (--all for every site) |
whoami |
Account, site, plan, API base. --json; --env prints the SEOAGENT_AUTH line for scheduled runs |
sync |
Push then pull. --silent, --push-only, --pull-only, --path, --force [path] |
pull |
Pull only. --print <path>, --force [path] |
inbox |
List pending actions (--json) |
ack [id] |
Close an action (--failed --reason) |
process |
Run pending actions through the Claude Agent SDK (-y, --model) |
autopilot <action> |
on, off, status, auto-approve on | off, draft-mode cloud | agent |
gsc <action> |
connect, status |
upgrade |
Open the pricing page |
Environment variables
| Variable | Effect |
|---|---|
SEOAGENT_AUTH |
<user_token>:<website_token>; logged in without an auth file. For scheduled runs |
SEOAGENT_SETUP_CODE |
One-time setup code, same as --code |
SEOAGENT_AGENT |
Name the harness driving this run (claude-code, cursor, codex, grok-bot) when it cannot be detected from the environment |
SEOAGENT_API_BASE |
Point the CLI at another server (default https://seoagent.com) |
SEOAGENT_DOMAIN, SEOAGENT_SITE_TYPE |
Non-interactive init values |
SEOAGENT_TELEMETRY=0 or DO_NOT_TRACK=1 |
Turn off the anonymous install and login pings |
What is free and what is paid
The Skill and every local command are free and work without an account: crawl, audit, keyword strategy, briefs, articles, OKF and llms.txt, sitemap checks. A free account adds Search Console data, the dashboard, and the first five briefs from the cloud's discovery run. Autopilot is the paid plan: the cloud researches, writes briefs and drafts, and queues the work; your agent applies it. See pricing.
Help
seoagent doctor first. Then [email protected] with the doctor output, or the community Slack. Package page: npm. More machine-readable entry points on /developers and in /llms.txt.