--- title: "How the SEOAgent CLI works" description: "Install, init, the .seoagent/ workspace, sync, the inbox, cloud login, autopilot, scheduled runs, and the full command reference for @seoagent-official/seoagent." updated: "2026-09-12" url: "https://seoagent.com/docs/cli" --- # 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](/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 ` 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/` with `project.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 sync` runs 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](/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/.md` | Article briefs: outline, word counts, internal-link plan, role in the cluster | | `content/.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. 1. `seoagent doctor` at session start. It is the router: it prints which references and commands this workspace needs right now (`--json` to branch on it). 2. `seoagent sync` pulls the cloud's work into `.seoagent/inbox/` and `.seoagent/briefs/`. 3. Triage the inbox. Do the work in the repo. 4. If the inbox is empty and `content/` has no article yet, write the first article from the brief the sync named, then `seoagent content track `. 5. `seoagent ack ` for every action finished (`--failed --reason "…"` to decline). 6. `seoagent sync` again, then `seoagent summary` to 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 ` shows the cloud body, `--force ` 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/-.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 ` 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](/for/grok-bots) or the dashboard: `seoagent init --code ` or `seoagent login --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=:`. 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 ` 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 ` 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 `, `--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 ` | `on`, `off`, `status`, `auto-approve on \| off`, `draft-mode cloud \| agent` | | `gsc ` | `connect`, `status` | | `upgrade` | Open the pricing page | ### Environment variables | Variable | Effect | | --- | --- | | `SEOAGENT_AUTH` | `:`; 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](/pricing). ## Help `seoagent doctor` first. Then [support@seoagent.com](mailto:support@seoagent.com) with the `doctor` output, or the [community Slack](/join-slack?c=seoagent). Package page: [npm](https://www.npmjs.com/package/@seoagent-official/seoagent). More machine-readable entry points on [/developers](/developers) and in [/llms.txt](/llms.txt).