Skip to main content

v0.0.180

Released Nov 13, 2026


Release Notes

squirrel ci gates a deploy on the findings it adds, --target-url audits exactly the URLs you name, an audit that ran out of credits says so in every report, and [[ignore]] reasons now show up in all of them. The bundled agent skills move to squirrelscan 2.0 and audit-website 3.0.

Added

  • New rule content/voice-consistency. Flags pages whose reading level is far from the rest of the site: the page written by a different hand, text pasted in from elsewhere, or bulk-generated copy. The norm is the median Flesch Reading Ease score of the site's own pages; a page at least 25 points away (harder or easier) is reported with its score and the site norm. Legal, privacy and terms pages are never judged (counted in excludedLegalPages), and the rule skips a crawl under 10 pages, under 10 scorable pages, or with no clear norm. It is a normal local rule: no model, no account, no surcharge. The score is stored per page (page_features.reading_level, schema version 41) so the streaming and legacy paths give the same answer. (squirrelscan/repo#1384)
  • squirrel ci <url> --website <id> [--fail-on-new error|warning|info] audits a deployed URL in the cloud as one of your websites (a real cloud run, in the website's audit history), waits for it, and exits 2 when the audit has findings new since the previous completed audit at or above the severity. It lists each new and resolved finding, how many older findings could not be compared, the report link and the credits used. 0 passes (the first audit of a website prints that there is no baseline), 3 blocked, 5 unreachable, 1 an operational error or a comparison that could not be evaluated. Needs an org API key with audits:read and audits:write. The public API docs gain GET /v1/websites/{websiteId}/audits/compare and its AuditComparison and CompareGate schemas, and the CI guide a "Fail the build on new findings" section (#1776)
  • squirrel audit --target-url <url> (repeatable) audits exactly the URLs you name and nothing else (#1777): no sitemap, no discovery probes, no link following. Each URL goes through the normal scope, robots and length checks and --max-pages caps the list. Rules that judge the whole site skip with the reason targeted-run and report as not checked, never as a pass or a finding, so a targeted run cannot resolve a finding it did not check. A redirecting URL is recorded as a redirect and its destination is audited only when it is listed too. The report accounts for every URL given (requested, audited, and each one not audited with its reason): scanScope.targeted, and meta.targeted in the JSON report (schema 1.16). The engine option is targetUrls. A targeted run is not auto-published (it would replace the site's latest audit with a few pages; --publish publishes it, and publish.reason is targeted), checks no links, is cut at 1,000 URLs (the rest counted in overLimit), and is refused a --resume across a different list. See Targeted audits.
  • Locked and not-checked rules can carry the reason credits (#1792): the audit ran out of credits before the check ran. Every report groups and words it on its own ("ran out of credits: add credits, then re-run the audit"), never as a plan or an environment limit, and the Free account keeps its add-credits link. A reader from before this release treats the new value as no reason and keeps the generic wording.
  • A site page record can carry canonical, the page a query-string variant counts with. The cloud merge records a crawl's variants (report.canonicalVariantPages), counts them with their canonical page in coverage.knownPages (auditedPages stays as crawled), and returns the site's variant map so a server folds the merged report after scoring. generateReportFromStorage takes exportCanonicalVariants to list the variants without folding: the list is always sent when the page features could be read, an empty one included, and canonicalVariantsComplete: false marks a list clipped at 1000. A complete list is the whole truth for the crawled pages (a page it no longer names stops being recorded as a variant); a clipped one only adds. coverage.carriedPagesOutsideCrawl counts pages that carry a finding and are not in the run's crawl, only when the caller asks. A site with no variants reports exactly as before. #1350 #1031
  • Reports explain an overall score that sits below its section scores (squirrelscan/repo#3915): when the engine recorded a site-wide adjustment in healthScore.debug, the HTML, Markdown, text and LLM reports say "Overall 72: 95 before a 24% site-wide adjustment for issue density across the whole audit. Section scores use only their own checks." Shown only when the report has section scores and the adjustment is at least 1%. No score changes. scoreAdjustment and scoreAdjustmentNoteFor in @squirrelscan/report give the same numbers and wording to other surfaces.
  • A cloud report can say what became of the known pages that carry open findings (#1759): coverage.seedVerification counts the pages re-verified (gone with their 404 or 410 status, redirected with source, destination and status, or still live) and the pages left carried, split into skipped by the page budget, no longer linked and unverified. The console, text, Markdown, HTML and llm formats state it and the JSON report carries it, whenever a report has it; a local CLI audit does not seed pages, so its report is unchanged. summarizeSeedVerification is exported from @squirrelscan/core-contracts/seed-verification for the hosted merge, and runSmartAudits accepts the run's seedVerification (seeds and frontier) for a caller that seeds. What the merge resolves or carries is unchanged.

Fixed

  • core/h1 tells hidden H1s apart from visible ones. A page with one shown H1 and two alternatives under hidden or an inline display:none no longer reads Multiple H1 tags found (3) like a page with three shown H1s: it reads Multiple H1 tags found (1 exposed, 3 in the HTML; ...) and still warns, since crawlers that do not render the page read every H1. The details keep the raw count as rawCount beside exposedCount and hiddenCount. Two or more shown H1s warn on the exposed count, and an H1 a style may hide but squirrel cannot settle is reported on h1-unconfirmed. The messages say that an HTTP-only audit cannot resolve visibility set by external stylesheets or scripts. A page whose H1s are all shown reads as before. (#1636)
  • crawl/robots-txt no longer says every crawler is blocked when User-agent: * has Disallow: / but a Googlebot or Bingbot group allows the site. That file now gets a new warning, robots-txt-disallow-wildcard, which names the crawlers still allowed. robots-txt-disallow keeps its meaning: it fails only when every crawler is blocked. The two checks are never reported together. The rule now declares its checks (meta.checks).
  • squirrel ci prints the report's own address (https://<org>.squirrel.report/..., read from the API) on its Report: line and in --json, as squirrel audit does, instead of the id on the older reports.squirrelscan.com host; it falls back to that host, which redirects, only when the address cannot be read (#1730).
  • The rule cache and template fan-out now run together (#296). Before, a run with the cache did not fan out, which cost the cold rules phase about 7%. A cached page records its template cluster and the page whose template-shared verdicts it holds; when the first page of a cluster changes, the pages that inherited its verdict are checked again, so a fully replayed audit is byte-identical to a fresh one. Entries written by an earlier release replay only when fan-out is off (SQUIRREL_TEMPLATE_FANOUT=0), and are otherwise checked again once.
  • A capped (published) report keeps coverage-gap skip rows instead of cutting them like a "does not apply" skip (#1775). Per rule, up to 5 skipped rows whose outcome is a coverage gap, a timeout or an error (scan-truncated, unread-page, rule-timed-out, ...) are kept per page with their pageUrl, the rest fold into one class per skip reason, and each check's tally gains gaps (a count by reason), so a reader sees a gap even when no row survives. not-applicable, noindex, page-type and free-text skips are never marked as a gap.
  • [[ignore]] reasons and unmatched entries now reach every report (#1262): an entry with a reason that waived something prints its own line (Ignore entry 1 (security/cookie-flags), Shopify sets these: 3 findings waived.) in the console, text, Markdown and HTML reports, and the HTML report now lists the entries that matched nothing, as the other formats already did (an unmatched entry keeps its reason). The docs say which rules rewrite their message from the remaining items and which keep their text with an (N ignored) suffix.

Changed

  • Bundled agent skills updated: squirrelscan 2.0, audit-website 3.0 (served by both MCP servers).

Update to this version

squirrelscan will auto-update, or run this command to update now:

$

Downloads

macOS

Detected
Apple Silicon (M-series)
squirrel-0.0.180-darwin-arm64 · 102.3 MB
Download
SHA-256
Intel
squirrel-0.0.180-darwin-x64 · 110.9 MB
Download
SHA-256

Linux

x64
squirrel-0.0.180-linux-x64 · 121.2 MB
Download
SHA-256
ARM64
squirrel-0.0.180-linux-arm64 · 121.3 MB
Download
SHA-256
ARM64 (musl/Alpine)
squirrel-0.0.180-linux-arm64-musl · 114.1 MB
Download
SHA-256
x64 (musl/Alpine)
squirrel-0.0.180-linux-x64-musl · 115.1 MB
Download
SHA-256

Windows

x64 (Intel/AMD)
squirrel-0.0.180-windows-x64.exe · 127.1 MB
Download
SHA-256

Audit your site in one command

SEO, performance, security, accessibility and agent experience issues, with exact fixes for your coding agent.

Install
$

No account needed for the CLI. Cloud audits include free monthly credits.