Repository navigation
Releases: integrallis/rankcli
Release list
v0.0.58: five findings from dogfooding, fixed
v0.0.58: five findings from dogfooding, fixed
Found by auditing a plain static site with 0.0.56 and 0.0.57 and reading the source behind each finding.
- An inline
<style>is not a render-blocking resource (#19).RENDER_BLOCKING_RESOURCESrecommended inlining critical CSS and then counted the inline block, so a page with any CSS at all was flagged for good. An inline style costs no network round-trip before first paint; it is no longer counted, and the recommendation names the actual remedies. - A 401, 403, 405 or 429 is not a broken external link (#21). HEAD is refused by many hosts and a 403 or 429 is bot protection or a rate limit; Medium answers 403 to every crawler and every link to it was "broken". Those statuses are retried once with a browser-like GET and, if still refused, treated as indeterminate, like a timeout. A definite 4xx or 5xx on either request still counts.
/index.htmlis the homepage (#23). A site whose brand link points atindex.htmlhad its homepage keyed two ways, the link graph looked up the one the crawl had not stored, andNAV_NOT_IN_HTMLreported zero links over ten static ones.canonicalPageUrlfolds/index.htmlinto/, the graph falls back to the first audited page when the entry URL is not among the keys, and a page's link to itself is not a link to another page.- Two recommendations now say what the checks accept (#24).
FAQ_SCHEMA_MISSINGasks forFAQPageonly where each question heading is followed by its answer; a question mark is not evidence of a FAQ, and Google restricts the markup to real FAQ content.PLAINTEXT_EMAILrecommends amailto:link with descriptive text instead ofname[at]domain.com, which breaks the link for readers and screen readers. - The auto-fixer's structured-data fix states only what the page states (#20). It wrote a
SoftwareApplicationwith a freeOfferinto every page that lacked schema. It now writes aWebSitefor the site root and aWebPageelsewhere, named from the page's own title with its meta description, and never anOffer. - A lazy-loaded image's origin does not need a preconnect.
MISSING_PRECONNECTno longer counts an origin used only by an image withloading="lazy"orfetchpriority="low", which the browser fetches after the critical path.
Packages: @rankcli/cli 0.0.58, @rankcli/agent-runtime 0.0.46, @rankcli/mcp-server 0.0.31.
Install
npm install -g @rankcli/cli # or: brew install integrallis/tap/rankcliStandalone binaries for macOS, Linux and Windows and the Claude Desktop extension (.mcpb) are attached below.
v0.0.57: the second pass over the always-on findings
v0.0.57: the second pass over the always-on findings
0.0.55 removed the 25 findings the npm corpus showed on nearly every site, which took the audit from 56 codes per site to 42 on the same 367 sites. This release takes the next tier: ten findings on a third to two thirds of sites, each a heuristic with no evidence behind it.
| Gone | Share of the corpus | Why |
|---|---|---|
NO_AGENT_EXPERIENCE_SURFACE |
64% | "none of the emerging conventions found" (llms-full.txt, SKILL.md, an MCP server, OpenAPI); the llms.txt finding already says what the evidence says about that family |
AI_NO_TESTIMONIALS, AI_NO_REVIEW_PLATFORMS, AI_WEAK_REVIEW_ECOSYSTEM, AI_NO_REVIEW_INTEGRATION |
59% | "AI looks for social proof" has no source, and a library's documentation site has no testimonials to add |
LOW_AI_CITATION_READINESS |
53% | a composite of the freshness findings the check already reports one by one |
POPUP_BOUNCE_RISK |
51% | a dialog element in the HTML, called an intrusive interstitial; documentation sites have search dialogs |
LOW_CTR_POTENTIAL (was a warning) |
47% | a click-through estimate from the title and the description, next to the title and description findings themselves |
GSC_VERIFICATION_MISSING |
44% | Search Console verifies through DNS on the apex, a file, Analytics or Tag Manager; a missing meta tag proves nothing, as with Bing in 0.0.55 |
AI_NO_USP |
40% | "no unique selling proposition detected" |
NO_HIGH_PRIORITY_PLATFORMS |
35% | "no links to YouTube, TikTok, Twitter/X, LinkedIn or Reddit" |
What stays from that tier, on purpose: the security headers, DMARC and SPF, SCHEMA_MISSING, the performance findings Lighthouse also reports (render-blocking resources, preconnect, image dimensions, hero preload), LLMS_TXT_MISSING as framed in 0.0.54, NO_SOCIAL_PROOF (a conversion notice) and BOFU_NO_SOCIAL_PROOF (only on a bottom-of-funnel page), and AI_NO_REVIEW_SCHEMA, which only fires on a page that has testimonials.
The analyzers keep computing their data; only the findings go. Removed codes drop out of a 0.0.56 baseline silently; LOW_CTR_POTENTIAL was a warning, so a gate on warnings may pass where it failed.
Packages: @rankcli/cli 0.0.57, @rankcli/agent-runtime 0.0.45, @rankcli/mcp-server 0.0.30.
Install
npm install -g @rankcli/cli # or: brew install integrallis/tap/rankcliStandalone binaries for macOS, Linux and Windows and the Claude Desktop extension (.mcpb) are attached below.
v0.0.56: a disallowed training crawler is policy, not a critical finding
v0.0.56: a disallowed training crawler is policy, not a critical finding
A fix to rankcli geo and the MCP server's seo_geo_check, left over from the one bot table in 0.0.55. The geo analyzer took its crawler list from the audit's table but still treated every disallowed crawler the same way: GEO_AI_CRAWLERS_BLOCKED (critical) for any of them, ten GEO points off per crawler, "URGENT: Unblock AI crawlers", and a fix that told the site to allow Claude-Web. A site that disallows the training crawlers, which OpenAI and Anthropic document as costing no visibility, lost fifty points and got a critical finding for it.
By class now, the same way the audit reports it:
| Disallowed | Finding | GEO score |
|---|---|---|
| search, AI search (Googlebot, bingbot, OAI-SearchBot, Claude-SearchBot, PerplexityBot, YouBot) | GEO_AI_CRAWLERS_BLOCKED, critical, with the Allow group for those crawlers as the fix |
-10 each |
| user-triggered fetchers (ChatGPT-User, Claude-User, Perplexity-User) | GEO_AI_USER_FETCH_BLOCKED, warning (new) |
-5 each |
| training (GPTBot, ClaudeBot, CCBot, Google-Extended, Bytespider, Applebot-Extended, meta-externalagent, Amazonbot, cohere-ai) | listed, with a line saying it costs no visibility | none |
In the JSON, aiCrawlerAccess.byClass carries the split and robotsTxtAllowsAI is true when nothing that costs visibility or a user's fetch is disallowed; blockedCrawlers and allowedCrawlers keep their shape. The geo command and the MCP tool print the three disallowed rows by class. The audit (rankcli audit, the GitHub Action) is unchanged: it already reported crawler access by class.
Packages: @rankcli/cli 0.0.56, @rankcli/agent-runtime 0.0.44, @rankcli/mcp-server 0.0.29.
Install
npm install -g @rankcli/cli # or: brew install integrallis/tap/rankcliStandalone binaries for macOS, Linux and Windows and the Claude Desktop extension (.mcpb) are attached below.
v0.0.55: a finding that fires on nearly every site is a default, not a finding
v0.0.55: a finding that fires on nearly every site is a default, not a finding
The first run of the npm corpus (the homepages of the 400 most popular npm packages, 367 audited with 0.0.54, published at https://rankcli.dev/data/npm-sites) counted 56 codes per site on average, and 30 of them fired on 60 percent or more of the best-built documentation sites on the web. A notice every site gets carries no information and costs the credibility of the ones that do.
Gone, with the share of the corpus each fired on: AI_INCOMPLETE_BRAND_COVERAGE (95%), NO_SNIPPET_BAIT_HEADERS (92%), BING_VERIFICATION_MISSING, BING_NOT_VERIFIED and BING_PLACES_MISSING (92%), NO_RELATED_CONTENT (89%), INVERTED_PYRAMID_MISSING (88%), AI_LOW_CITATION_QUALITY (88%), AI_NO_ORIGINAL_DATA (87%), GTM_MISSING (86%), NO_EXPERIENCE_SIGNALS and AI_NO_EXPERIENCE_SIGNALS (81%), RAG_CHUNK_SIZE_MISMATCH (80%), NO_ENTITY_IDENTIFIED and NO_ENTITY_DEFINITION (79%), AI_NO_BRAND_DEFINITION and AI_LOW_BRAND_SCORE (78%), LOW_DWELL_TIME_SIGNALS (78%), GA4_MISSING (76%), AI_LOW_CITATION_WORTHINESS (71%), NO_ENGAGEMENT_TRIGGERS (69%), HIGH_BOUNCE_RISK (62%), plus REVIEW_NO_VIDEO, COMMERCIAL_NO_CTA and NEW_SITE_STRATEGY, which fired regardless of content. Not using Google's tag manager or Bing's webmaster tools is a choice; the rest were heuristics with no evidence behind them. The analyzers keep computing their data (brand, entity, chunk and engagement scores stay in the report's data); only the findings go.
Conditioned: NO_BREADCRUMBS (98%) never fires on the homepage, which has nothing to lead back to. INDEXNOW_NOT_IMPLEMENTED (100%) is dropped when the site has no sitemap, since Bing's advice is an accurate lastmod paired with IndexNow.
What stays from the high end of the table: the security-header notices, DMARC and SPF, the Apple touch icon. Each describes something a standard asks for and a site can add in a line.
One bot table. The analyzer behind rankcli geo, the MCP server's seo_robots_ai, seo_generate_robots and seo_ai_crawlers, and the robots.txt the auto-fix writes kept a second crawler list from before the bot classes: it still called Anthropic's crawler Claude-Web, told a site that disallowing GPTBot meant its content would not appear in ChatGPT answers (OpenAI documents the opposite), and generated a robots.txt that allowed "all AI crawlers" as one undivided group. All of it now derives from the audit's table: the robots analysis reports by class (search, AI search, user-triggered, training) with the advice worded for what blocking each class costs, and the generated robots.txt writes one group per class, training allowed but marked as the group to turn into Disallow when that is the policy. The table gains the robots-only tokens the old list knew (Applebot-Extended, meta-externalagent, Amazonbot and cohere-ai as training; YouBot as AI search), so AI_TRAINING_BOTS_DISALLOWED and AI_SEARCH_BOTS_DISALLOWED name them too.
Removed codes drop out of a 0.0.54 baseline silently; AI Readiness scores rise by the notices a site no longer gets.
Packages: @rankcli/cli 0.0.55, @rankcli/agent-runtime 0.0.43, @rankcli/mcp-server 0.0.28.
Install
npm install -g @rankcli/cli # or: brew install integrallis/tap/rankcliStandalone binaries for macOS, Linux and Windows and the Claude Desktop extension (.mcpb) are attached below.
v0.0.54: the AI checks say what the evidence says
v0.0.54: the AI checks say what the evidence says
The AI-readiness checks now follow what the crawler operators document and what the citation studies measure, and the audit reads two things a browser never shows: the metadata in the initial HTML, and the link graph before any script runs.
AI crawler access by bot class. OpenAI documents GPTBot as training-only and says a site opted out of OAI-SearchBot "will not be shown in ChatGPT search answers"; Anthropic documents the same split (ClaudeBot, Claude-SearchBot) plus Claude-User, which fetches one page because a user asked. The checks group bots that way and word each finding for its consequence, from robots.txt and from a live fetch as each bot:
| Class | Bots | robots.txt disallowed | Refused at the edge |
|---|---|---|---|
| search | Googlebot, bingbot | crawlability checks | SEARCH_CRAWLER_BLOCKED_AT_EDGE error |
| AI search | OAI-SearchBot, Claude-SearchBot, PerplexityBot | AI_SEARCH_BOTS_DISALLOWED warning |
AI_SEARCH_CRAWLER_BLOCKED_AT_EDGE warning |
| user-triggered | ChatGPT-User, Claude-User, Perplexity-User | AI_USER_FETCH_DISALLOWED warning |
AI_USER_FETCH_BLOCKED_AT_EDGE warning |
| training | GPTBot, ClaudeBot, CCBot, Google-Extended, Bytespider | AI_TRAINING_BOTS_DISALLOWED notice |
AI_TRAINING_CRAWLER_BLOCKED_AT_EDGE notice |
A challenge interstitial counts as a refusal even when it answers 200; the live fetch asks once per origin per run. Gone: AI_CRAWLER_BLOCKED_AT_EDGE, AI_BOT_GPTBOT_BLOCKED, AI_BOT_CLAUDEBOT_BLOCKED, AI_BOT_PERPLEXITY_BLOCKED, AI_BOT_GOOGLE_EXTENDED_BLOCKED.
Metadata placement. A fetch as Googlebot tells Next.js streaming metadata (METADATA_STREAMED_FOR_BOTS: the title, description and canonical reach Googlebot but arrive later, inside the body, for everyone else, including the AI search crawlers) from metadata rendered into the body for everyone (METADATA_OUTSIDE_HEAD). The fix names htmlLimitedBots.
The link graph without JavaScript. Each page's HTML links build a graph: linkGraph in the JSON report (homepage links, depth per page, unreachable pages, orphans, coverage) and depth on every page summary. NAV_NOT_IN_HTML (warning) when the homepage's HTML links to two pages or fewer on a site with ten or more; ORPHAN_PAGES and DEEP_PAGES only once every sitemap page was audited, so a five-page audit of a four-hundred-page site claims nothing it cannot see.
Content findings with their evidence. The comparison-table, direct-answer and uncited-statistics findings cite the studies behind them (tables +69 percent odds of citation; 23 versus 14 percent of pages opening with a direct answer; statistics with sources +29 percent, quotations +40 percent); the freshness findings cite Ahrefs and SE Ranking in place of an unsourced percentage. Gone: AI_NO_QA_FORMAT, AI_NO_DEFINITIONS, AI_QUESTIONS_NO_DIRECT_ANSWERS, AI_STOCK_IMAGE_HEAVY. Now notices, never a failed build: AI_LOW_STRUCTURE_SCORE, AI_LOW_CONCISENESS, AI_NO_REPUTABLE_CITATIONS, AI_NO_EXTERNAL_CITATIONS. Fixed: the table finding fired on any page containing "vs" as a substring. New: SITEMAP_LASTMOD_UNIFORM, when every URL carries the build time as its date.
llms.txt, as the evidence has it. A convention for coding agents and documentation sites, audited by Lighthouse, read by no search or answer engine. Missing stays a notice, framed for docs sites; invalid is a notice.
Structured data counts in the on-page score, at a third of the weight of the on-page essentials. Measured on six reference sites: 0 to 1 overall point.
The AI Readiness score, stated for what it is. It measures hygiene on the levers the citation evidence supports and does not predict citations; no published score does. The JSON report says so under notes.aiReadiness, the console under the score, the README in its own section.
Also fixed: a footer image is never reported as a lazy-loaded hero.
Codes that changed name show as new against a 0.0.53 baseline once; removed codes drop out of it silently.
Packages: @rankcli/cli 0.0.54, @rankcli/agent-runtime 0.0.42, @rankcli/mcp-server 0.0.27.
Install
npm install -g @rankcli/cli # or: brew install integrallis/tap/rankcliStandalone binaries for macOS, Linux and Windows and the Claude Desktop extension (.mcpb) are attached below.
v0.0.53: the audit as a CI gate
v0.0.53: the audit as a CI gate
One rule syntax for the gate, in the CLI, in a config file and in the GitHub Action, with baselines so an existing site can adopt it without first fixing every old finding, SARIF and JUnit output, build-directory audits and protected previews.
One rule syntax. --fail-on takes rules: error, warning or notice fails on any issue at or above that severity; score<80 on the overall score; score:aiReadiness<70 on a category (crawlability, indexability, onPage, content, links, performance, security, aiReadiness, social, localSeo, accessibility). Rules combine, comma-separated or with the flag repeated. --min-score 80 is the same as score<80 and still works. The exit codes have not changed: 0 completed, 1 a gate tripped, 2 bad invocation or an invalid config or baseline file, 3 no real audit (unreachable site, error status).
Baselines. Save a report once and commit it; the severity rule then counts only findings that are not in it. Old findings stay listed but do not fail the build until you fix them. Score rules stay absolute.
rankcli audit -o json > .rankcli/baseline.json # once; commit the file
rankcli audit --fail-on error --baseline .rankcli/baseline.jsonA finding is identified by its code and the page's path. The console and the JSON report list what is new since the baseline, what was fixed and what stayed. rankcli diff before.json after.json compares any two saved reports, with --fail-on and -o json.
SARIF and JUnit. -o sarif writes SARIF 2.1.0 for GitHub Code Scanning (github/codeql-action/upload-sarif) and other SARIF readers: one rule per code, one result per page, baselineState when a baseline is given, file locations with --dir. -o junit writes JUnit XML for test reporters. Every machine format is one document on stdout, on failure too.
Audit the build before deploying. rankcli audit --dir dist --url https://example.com --fail-on error serves the directory locally the way a static host would and audits it as the named site, so canonical and sitemap checks compare against the real origin. Host checks (TLS, security and caching headers, redirects, crawler access, canonical domain) are skipped. With -o sarif, findings point at the files.
Protected previews. --header "Name: value" and --cookie "name=value", both repeatable, go with every request to the audited site and to no other host.
Project config. rankcli.config.json (rankcli init writes it with the url) now carries the CI settings, read the same way by audit and the Action: maxPages, checkLinks, failOn, minScore, budgets (minimum category scores), baseline, ignore (by code, by page glob, or both, with a reason; ignored findings are counted and listed, never dropped silently), headers (values may use ${ENV_VAR}) and dir. Flags win over the file. An invalid file is exit 2, never ignored. --config <file> names another file.
Page discovery. The sitemap seeds the page list and homepage links fill the rest (default 5 pages); the JSON report says where each page came from (discovery) and adds ignored, baseline and gate.
The GitHub Action, v1.2.0 (integrallis/rankcli-action@v1), takes the same rules in fail-on, plus baseline, config, dir, max-pages (default 5), headers, report-file and annotations (findings annotated on the run, with file locations when dir is used). comment-on-pr is now regressions (the default: only when the gate fails or there are new findings against the baseline), always or never; the Action keeps one comment and updates it in place. New outputs: new-issues-count, fixed-issues-count, report-file. fail-on-error, fail-on-errors and score-threshold keep working. rankcli setup --github-action --url https://yoursite.com [--sync] writes a workflow that uses the Action.
Packages: @rankcli/cli 0.0.53, @rankcli/agent-runtime 0.0.41 (the gate, baselines, SARIF, JUnit, the config loader and auditSite() live in the engine), @rankcli/mcp-server 0.0.26 (the same engine).
Install
npm install -g @rankcli/cli # or: brew install integrallis/tap/rankcliStandalone binaries for macOS, Linux and Windows and the Claude Desktop extension (.mcpb) are attached below.
v0.0.52: the source is published
v0.0.52: the source is published
The source of the CLI, the audit engine, the MCP server, the GitHub Action and the framework plugins now lives here, with its history since January. Build it with Node and pnpm; there is no Rust toolchain or build key any more.
License. The engine, the CLI, the MCP server and the Action are under the Functional Source License, Version 1.1, MIT Future License (FSL-1.1-MIT): read it, run it, change it, redistribute it, embed it in your own tools and pipelines, all free; the one thing it does not permit is building a product or service that competes with RankCLI. Each version becomes MIT two years after its release. The three framework plugins are MIT. Versions published before this one stay MIT.
The 21 checks that were encrypted into the CLI are ordinary engine code. They lived in a private package, were bundled into a WASM binary and decrypted at run time with a passphrase that shipped in the same tarball. Every plan runs every check, so @rankcli/agent-runtime 0.0.40 exports them (premiumChecks) and runFullAudit runs them by default. The GitHub Action, which used to leave them out, now runs the same audit as rankcli audit and gives the same score.
The JSON report says when, which version, and page by page. -o json carries timestamp, cliVersion, checksRun, checksPassed and pages (one entry per audited page with its url, score and error, warning and notice counts).
No account box under a gate. The "keep this site audited" box after a console audit no longer prints under --fail-on or --min-score, or when CI is set.
Every published package links its source. The npm pages for @rankcli/cli, @rankcli/agent-runtime, @rankcli/mcp-server, @rankcli/github-action, astro-rankcli, next-rankcli and vite-plugin-rankcli point at this repository, as does the MCP registry entry.
Packages: @rankcli/cli 0.0.52, @rankcli/agent-runtime 0.0.40, @rankcli/mcp-server 0.0.25.
Install
npm install -g @rankcli/cli # or: brew install integrallis/tap/rankcliStandalone binaries for macOS, Linux and Windows and the Claude Desktop extension (.mcpb) are attached below.