Claude SEO v2.3.1 is a patch release. Five judgment-heavy agents now run on Opus, Keywords Everywhere joins as a free backlinks fallback, setup failures show the failing stage's own output, every extension installer writes ~/.claude.json atomically and without a byte-order mark, and two scripts that v2.3.0 shipped unregistered are now reachable through the launcher. Windows, macOS, PowerShell 5.1, and pip-audit legs all passed on the release PR.
Added
- Keywords Everywhere (Open PageRank) as an optional, free-signup backlinks
fallback source: a single 0-10 domain rank metric used for the Profile
Overview section when Moz isn't configured. Wired through
backlinks_auth.py(newkeywordseverywhereservice) and a new
keywordseverywhere_api.pyclient, following the existing Moz/Bing auth
and source patterns. The outbound call goes through the shared
url_safety.safe_requests_getDNS-pinned helper, domains are normalized
and SSRF-checked before use, and requests are capped at 100 domains per
call.keywordseverywhere_api.pyis registered inruntime.py's
ALLOWED_CORE_SCRIPTS(a script invoked from a SKILL.md but missing from
that allowlist is refused byclaude-seo run; a new test in
tests/test_runtime.pyguards against that class of bug for every
script every SKILL.md/agent invokes). The live API path is unverified:
landing this required no Keywords Everywhere account, and none was
available to exercise the real endpoint end to end (#262).
Changed
- The five judgment-heavy agents (
seo-content,seo-geo,seo-sxo,seo-cluster,
seo-drift) declaremodel: opus; the other thirteen stay on Sonnet. README
documents the cost implication and how to override per agent (#268). - Applied the mechanical hunks from #196 ("ponytail cleanup") by hand: hoisted
three function-localfrom urllib.parse import urlparseimports to the top of
validate_backlink_report.py, and deletedcommoncrawl_graph.py's dead
_stream_gz_lineshelper (zero callers) along with thegzip/ioimports it
alone used. Left out thehashlib.file_digestrewrite (Python 3.11+ only;
pyproject.tomlrequires >=3.10) and narrowingdataforseo_normalize.py's
--modulechoices, a compatibility change rather than a cleanup. Credit:
pookNast (#196).
Fixed
metadata_template.py, added in v2.3.0, was not registered in the launcher's
ALLOWED_CORE_SCRIPTS, soclaude-seo run metadata_template.pywas refused for
/seo pageand/seo programmatic. Registered, with a test that every script an
instruction file invokes is allowlisted.- The dataforseo, ahrefs and firecrawl PowerShell installers created
mcpServersas
a hashtable, whichConvertTo-Jsonserialised as{}when~/.claude.jsonwas
missing or had nomcpServersyet, silently dropping the server entry; they now
create an object. They also wrote the file with a byte-order mark on Windows
PowerShell 5.1, which Node's JSON parser rejects; the write is BOM-free now. _run_checkeddiscarded a failing setup stage's stderr/stdout, so a broken
venv or pip install reported only "failed with exit code 1" with nothing
actionable. It now surfaces a bounded tail of the child's own output, pip is
bootstrapped as its own stage (venv --without-pip+ensurepip) so its
diagnostics are no longer swallowed byvenv, and home-directory redaction
covers repr-quoted and mixed-case forms child tracebacks print. Also fixed a
gap the same change opened: the non-fatal "Browser setup incomplete" warning
printed the raw exception instead of the redacted one, so a failing Chromium
install could leak the home directory through the one message that wasn't
routed through_redact(#300, Nordalux).extensions/dataforseo/install.ps1andextensions/ahrefs/install.ps1merged
their MCP server entry with an embedded Python heredoc (tempfile.mkstemp+
os.replace), andextensions/firecrawl/uninstall.ps1wrote
ConvertTo-Json -Depth 10straight to~/.claude.jsonwith no temp file. All
three now follow the nativeConvertTo-Json -Depth 100+ temp-file +
Move-Item -Forcepattern v2.3.0 established in
extensions/firecrawl/install.ps1;ahrefs/install.ps1no longer requires
Python as a result.- The
anthropic-aicrawler row v2.3.0 added toskills/seo-geo/SKILL.mdand
agents/seo-geo.md, marked unverified, still does not appear on Anthropic's
crawler support article (confirmed by re-fetching it: only ClaudeBot,
Claude-User, and Claude-SearchBot are documented), so the row is removed
rather than kept as an unverifiable guess.
Contributors
- Agrici Daniel
- John DeGeorge
- Tobi | Nordalux
Install
curl -fsSL https://raw.githubusercontent.com/AgriciDaniel/claude-seo/v2.3.1/install.sh | bash