This post is about the signaldiff CLI: how to install it, run a local sitemap crawl, and hand that to Cursor, Copilot, or Claude Code so the agent can spot SEO and crawl issues without opening a dashboard.
Signal Diff
is the product behind that command. It fetches the URLs in a sitemap, checks on-page SEO and crawl health (titles, meta descriptions, redirects, slow responses, and more), and can compare a run with a baseline—often the previous deploy—so you see what changed. I already use it on this blog after each Static Web Apps release via funkysi1701/signal-diff-action
. That Action is the unattended gate. The CLI is the same crawl, from a shell. (There is also a customer-hosted crawler; this post stays on the coding-agent path.)
A CLI is a good fit here because coding agents already have a terminal. They can install one binary, run a crawl, and read an HTML report. You do not need a browser session, and you do not need an MCP server. Local crawls need no account. Cloud commands are optional once an API key is already in the environment. The rest of this post walks through install, a capped crawl of this site, the prompt I give an agent, and the cloud commands worth using when a key is set.
CLI behaviour agents need
Once a key exists, the subcommands sites, runs, diff, findings, and scan call the Agent API
. Full command reference: signaldiff.dev/docs/cli
.
A few behaviours matter once an agent is the one typing:
signaldiffwith no arguments prints help and exits. It does not start a crawl.--jsonbelongs on cloud subcommands. Success JSON goes to stdout. A failure is one JSON object on stderr, with a status code and, on a rate limit, how many seconds to wait. Progress logs stay on stderr, so a pipe keeps the result.- A local
--sitemapcrawl refuses--jsonand still writes HTML.
Install, then crawl this blog
The installers are self-contained. You do not need the .NET SDK, and you do not need a clone of the repo. They verify SHA256 before putting signaldiff on your PATH. Prefer that path, or download a versioned zip from the CLI downloads page
and check the published .sha256 sidecar yourself. On Windows:
irm 'https://signaldiff.dev/install/cli.ps1' -OutFile "$env:TEMP\signaldiff-install-cli.ps1"
& "$env:TEMP\signaldiff-install-cli.ps1"
On Linux or macOS:
curl -fsSL 'https://signaldiff.dev/install/cli.sh' | bash
Open a new terminal so PATH picks up the binary (~/.local/bin on Linux and macOS). Then crawl a real sitemap, with a page cap so the first run stays small:
signaldiff --sitemap https://www.funkysi1701.com/sitemap.xml --max-pages 20 --output seo-report.html --quiet
--output creates missing folders before the crawl starts. --quiet keeps the summary short. The report path is on stdout. I point this at my own sitemap because that is the site I already monitor. Swap in yours.
signaldiff update replaces the install with the latest published build and checks the SHA256. signaldiff update --check tells you whether one is waiting, and leaves the current binary alone.
What I tell the agent
The API key stays in the environment. It stays out of the chat. Here is the prompt I give Cursor, Copilot, or Claude Code:
Install the Signal Diff CLI from https://signaldiff.dev/docs/cli . Then, in a new terminal, run
signaldiff --sitemap https://www.funkysi1701.com/sitemap.xml --max-pages 20 --output seo-report.html --quiet. Readseo-report.htmland list the SEO and crawl issues worth fixing, with the URL for each and a concrete change. Use cloud commands only ifSIGNALDIFF_API_KEYis already set. Leave the key out of the chat.
That is the loop. The agent installs if it must, runs a capped crawl, and works from the HTML. I still read the suggestions. A title that is two characters over the limit is a real fix. A rewrite of a post I care about is a suggestion until I agree with it.
On a recent crawl of this sitemap the report had no errors and a few hundred warnings. Even with --max-pages, a site-wide CSS finding still fans out across every page the crawl touched. The agent did not invent a title rewrite for every post. It collapsed them into one finding: Font Awesome’s CSS sits at the 100 KB file-size limit, repeated across pages. That is the shape of answer I want—site-wide root cause, not hundreds of identical notes.
This sits next to the split I described in how I use AI on side projects . ChatGPT when the question needs no repo. Cursor when the answer is in the files. The CLI when the question is about the live sitemap.
When a key is already set
Cloud commands need a paid key from the Signal Diff dashboard (Developers → API keys). Set it in the environment. Prefer that to --api-key, which shows up in the process list.
$env:SIGNALDIFF_API_KEY = "sck_…"
$env:SIGNALDIFF_API_BASE_URL = "https://signaldiff.dev/api"
The base URL includes /api. That is the easy one to get wrong. The GitHub Action uses a different variable, and the site origin with no /api suffix. Same secret value. Different names, different URL shape.
| Caller | Variable | Base URL |
|---|---|---|
| CLI and the Agent API | SIGNALDIFF_API_KEY | https://signaldiff.dev/api |
| GitHub Action | SIGNALDIFF_CI_API_KEY | https://signaldiff.dev |
These are the commands I want an agent to run once that is set:
| You want | Command |
|---|---|
| Sites you already monitor | signaldiff sites list |
| Recent runs for one site | signaldiff runs list --site example.com |
| A short brief for one run | signaldiff runs summary <runId> |
| Only the deploy diff | signaldiff diff get <runId> |
| Errors from that run | signaldiff findings list <runId> --severity Error --limit 50 |
| Machine-readable output | add --json |
runs list is how you get a runId. runs summary is the one I point agents at after that. It is a capped brief: headline counts, top regressions, top improvements, and fix hints. It leaves out the full page payload. diff get is there when the only question is what changed against the baseline.
Starting a cloud scan is a separate decision. signaldiff scan start queues work on the service, and signaldiff scan wait <scanId> --json polls until it finishes. I leave that out of the default prompt. A local HTML report answers “what is wrong on this sitemap right now”. A cloud scan spends quota and shows up in the dashboard, so I ask for it on purpose.
The Action still runs after deploy
The pipeline check stays. On this blog the Action still crawls after a Static Web Apps deploy, with the API key in GitHub secrets and a pinned signal-diff-action
version. The Action answers “did this deploy stay healthy?” when I am not looking. The CLI answers the same SEO questions while an agent and I are still in the change. A local --sitemap crawl is not a drop-in for that CI step: it does not attach a commit SHA, collect a code diff, or comment on a pull request.
Try it on a sitemap you care about
Install the CLI, cap a crawl with --max-pages, and have the agent read the HTML before it edits templates. If you already have a key, ask for runs summary on the latest run and see whether the brief is enough to act on.
I am curious how you give an agent this kind of check. A CLI it can run, an MCP server, or a dashboard you still open by hand? Tell me in the comments. Command reference, updates, and checksums are on the CLI docs .
Comments