███████╗██╗ ██╗ ██████╗██╗ ██╗
██╔════╝██║ ██║ ██╔════╝██║ ██║
███████╗██║ ██║ ██║ ██║ ██║
╚════██║╚██╗ ██╔╝ ██║ ██║ ██║
███████║ ╚████╔╝ ╚██████╗███████╗██║
╚══════╝ ╚═══╝ ╚═════╝╚══════╝╚═╝
Agentic SEO & GEO from the command line
SV CLI is an open-source command-line client for agentic SEO and GEO workflows using the SV API (SEO VENDOR API). It is designed as a definition-driven resolver layer: humans can use friendly commands, slugs, aliases, and presets, while scripts and AI agents can use strict enum IDs and raw JSON calls.
The CLI discovers available tools from the API root and fetches each tool's definitions endpoint at runtime. Definitions are cached locally for speed, refreshed automatically after 24 hours by default, and can be refreshed or cleared manually.
pip install sv-cliFor local development:
git clone https://github.com/seovendor/sv-cli.git
cd sv-cli
python -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
sv --helpAn API key is required for API calls. Resolution order:
--api-keyflagSV_API_KEYenvironment variable- Stored profile config from
sv auth set - Interactive prompt when allowed
SV_API_KEY is the current environment variable. SEOVENDOR_API_KEY is still accepted as a legacy fallback during migration.
Recommended setup:
sv auth set
sv auth statusCI setup:
export SV_API_KEY="your-key-here"
sv seogpt generate --type 18 --keyword "white label seo" --strict --format json --non-interactiveAvoid passing real keys with --api-key in shared shells because shell history may store the value. Debug output masks keys.
The package, repository, executable, Python package, and local state directory now use the SV brand:
- PyPI package:
sv-cli - Executable:
sv - Python package:
sv_cli - Default local state directory:
~/.sv - Preferred environment variables:
SV_API_KEYandSV_HOME
For migration safety, SEOVENDOR_API_KEY, SEOVENDOR_HOME, and an existing ~/.seovendor/config.json are still accepted as fallbacks. New saves are written to ~/.sv.
sv definitions refresh
sv definitions list
sv definitions show seogpt
sv definitions clearCache location:
~/.sv/cache/definitions.json
The old ~/.seovendor/config.json file is read as a migration fallback when ~/.sv/config.json does not exist. New writes go to ~/.sv.
Default behavior:
- Use local cache when present.
- Refresh automatically if the cache is older than 24 hours.
- Use stale cache with a warning if refresh fails.
- Error clearly if no cache exists and definitions cannot be fetched.
sv keywords research --keyword "white label seo"
sv seogpt generate --type 18 --keyword "white label seo" --url https://example.com
sv geo-audit create-task --url https://example.com --keyword "seo agency,white label seo" --wait
sv image generate --keyword "white label seo" --type blog-header-image
sv top-competitors analyze --keyword "white label seo"
sv marketplace-services search --search "seo audit" --price 500 --category SEO
sv content-quality analyze --keyword "white label seo" --url https://example.comPresets (shorthand commands for common seogpt operations):
sv meta --keyword "white label seo" --url https://example.com
sv title --keyword "white label seo" --url https://example.comNote:
sv keywords,sv audit, andsv imageare group aliases, not standalone commands. They require an action:sv keywords research --keyword "...",sv audit create-task --url "...",sv image generate --keyword "...".
| Friendly command | Aliases | API tool key |
|---|---|---|
better-keywords |
keywords |
better-keywords |
content-transformer |
transform |
content-transformer |
core-analysis |
core |
core-analysis |
geo-audit |
geogpt-audit, audit |
geogptaudit |
insight-igniter |
insights |
insight-igniter |
preliminary-audit |
prelim-audit |
preliminaryaudit |
ranklens |
ranklens |
|
seo-image |
image |
seo-image |
seogpt |
seo-gpt |
seogpt |
seogpt2 |
seo-gpt2 |
seogpt2 |
seogpt-compare |
compare |
seogptcompare |
seo-mapping |
mapping |
seogptmapping |
topical-authority |
topical |
topical-authority |
top-competitors |
competitors |
top-competitors |
marketplace-services |
marketplace, services |
marketplace-services |
content-quality |
quality, hcu-quality, eeat-quality |
content-quality |
The canonical API tool keys are discovered from the live API root; local aliases are only a human-friendly layer. For newly released tools, the CLI can also use adapter-provided endpoint hints until the API root advertises those tools. Root-discovered metadata still takes precedence.
For enum-heavy fields such as content type, content length, language, engine, image type, theme, background, color, and size, the CLI resolves values in this order:
- Numeric ID exact match
- Exact slug match
- Exact canonical API value
- Exact alias match
- Exact label match
- Normalized exact match
- Prefix match
- Contains match
- Fuzzy match with safe thresholds
Examples that all resolve to Meta Description (id 18):
--type 18
--type meta-description
--type "Meta Description"
--type "meta desc"--length/--contentlength (content length by ID, slug, or label — run sv TOOL lengths for valid values) resolves the same way:
sv seogpt generate --keyword "white label seo" --type 18 --length 300Note: Fuzzy matching is enabled by default. Use
--strict --no-fuzzyin scripts to require exact ID or slug and avoid unintended matches.
Agent-safe mode:
sv seogpt generate --type 18 --keyword "white label seo" --strict --no-fuzzy --non-interactive --format jsonsv options list
sv options seogpt
sv options seogpt type --search meta
sv options seogpt contenttype --search meta
sv seogpt types --search meta
sv seogpt languages
sv seogpt engines
sv image themes --search wild
sv image types --search blogRaw calls use live definitions only to find the selected tool endpoint. The payload is otherwise passed through unchanged except that k is injected when no API-key field already exists.
sv --format json call seogpt --json '{"action":"generate","kw":"white label seo","type":18}'
sv --format json call seogpt --file payload.json
cat payload.json | sv --format json call seogpt --stdinThe per-tool raw sub-command works the same way:
sv --format json seogpt raw --json '{"action":"generate","kw":"white label seo","type":18}'Note:
--formatmust be placed before the tool name for bothsv callandsv TOOL raw— it is a global flag owned by the rootsvcommand, not bycallorraw.
For tools that return task IDs:
sv geo-audit create-task --url https://example.com --keyword "seo agency,white label seo" --wait
sv task status TASK_ID --tool geo-audit
sv task result TASK_ID --tool geo-auditseogpt2 is another async tool. Its required field is Topic (a title or subject), mapped via --topic (--title is an alias for the same field). --keyword/--kw is a separate, optional field for additional keywords — it does not set the topic:
sv seogpt2 create-task --topic "White Label SEO for Agencies" --type on-page-blog-article --waitSee available types with sv seogpt2 types, lengths with sv seogpt2 lengths, engines with sv seogpt2 engines.
Manual 3-step flow (without --wait):
sv geo-audit create-task --url https://example.com --keyword "seo agency,white label seo"
sv geo-audit get-task-status --task-id TASK_ID
sv geo-audit get-result --task-id TASK_IDNote:
--formatis not available onsv task statusorsv task resultdirectly. Place it beforetaskas a global flag:sv --format json task status TASK_ID sv --format json task result TASK_ID
If a task is created through the CLI, its tool mapping is stored in ~/.sv/tasks.json, so --tool is usually optional later.
--format pretty # default rich terminal output
--format json # raw JSON (always works for any response)
--format table # column table (list responses only)
--format csv # CSV (list responses only)
--format markdown # Markdown
--format text # plain text (content/article responses)Which format to use:
| Response type | Recommended formats |
|---|---|
| List results (keywords, competitors, services) | table, csv |
| Content / articles / generated text | text, markdown |
| Audit / analysis / nested data | json, markdown |
| Async task ID responses | pretty (default) |
| Any response | json (always safe) |
Placement: For tool commands (sv seogpt generate, sv keywords research, etc.), --format can go anywhere. For sv call, sv options, and sv task, --format must come before the subcommand:
sv seogpt generate --keyword "white label seo" --type 18 --format json # works
sv --format json call seogpt --json '{"action":"generate","kw":"..."}' # must be before callExamples:
sv keywords research --keyword "white label seo" --format csv --output keywords.csv
sv geo-audit create-task --url https://example.com --keyword "seo agency,white label seo" --wait --format markdown --output audit.mdsv profile create agency-a
sv --profile agency-a auth set
sv profile use agency-a
sv profile list
sv profile delete agency-aProfile config is stored in ~/.sv/config.json, not in project folders.
pip install -e '.[dev]'
pytest
ruff check .
python -m buildLive tests should be opt-in only:
SV_API_KEY=... RUN_LIVE_TESTS=1 pytest -m liveNever commit API keys, .env, or ~/.sv/config.json. The repository .gitignore excludes common secret/config files. Report vulnerabilities using the process in SECURITY.md.