A roll of numbered paper raffle tickets unspooling in dim light

Build Note

SEO reports from the CLI, sized for AI agents

A reporting CLI that agents run over Bash: bounded JSON on stdout, a committed Search Console archive, and hard caps that keep 100k-token snapshots out of context.

Published August 20, 2026

A reporting tool an AI agent can actually use is a CLI, not a dashboard: agents run it over Bash and get bounded JSON back on stdout. This one pulls Search Console into a committed archive, ranks content opportunities, and enforces hard output caps — because the real constraint isn't the data, it's the agent's context window.

Why a CLI instead of a dashboard or an API?

Dashboards serve humans; this needed to serve an agent that plans content work. An agent consumes tools through the interfaces it already has, and the cheapest universal interface is a shell command with structured output. No server to keep alive, no auth handshake per session, and a human can run the identical command to audit what the agent saw. The tool's own README states the principle: agents run it over Bash and get bounded JSON back.

The command surface
pull      # GSC → raw/<property>/<shape>/<window>.json  (frozen)
stitch    # merge across a domain migration's properties
analyze   # detectors → runs/<date>/snapshot.json + digest.md
week      # the agent's entry point — summary on stdout
queue     # ranked opportunities, 10 by default, 50 max
evidence  # drill into ONE opportunity, bounded
doctor    # what can this credential actually see?

Everything downstream of pull works from local files, for the reasons covered in the Search Console API guide: frozen 28-day windows, several low-dimension shapes per window, and a committed archive because Google only retains 16 months. Reports are reproducible; re-running analyze on yesterday's data yields yesterday's answer.

How do you keep a 100k-token snapshot out of the context window?

The full analysis snapshot is a machine artifact — six figures of tokens. One careless cat and the agent's session is spent. The defenses are structural, not advisory:

Output discipline, from the queue command
// A day's snapshot is 100k+ tokens and must never enter an
// agent's context — so this prints one line-block per
// opportunity, defaults to 10, and there is deliberately no
// flag that dumps the file.
const DEFAULT_LIMIT = 10
const MAX_LIMIT = 50

// This is the command an agent runs, so its output goes to
// stdout rather than stderr — it is the payload, not progress.
  • Hard caps with no escape hatch. The queue prints ten ranked opportunities by default, fifty at most — and there is deliberately no flag that dumps the underlying file. A cap with a bypass is a suggestion.
  • Payload on stdout, progress on stderr. The command an agent runs treats its output as the interface, so logging never contaminates what gets parsed.
  • A narrowing funnel. Session shape is summary first (week), then at most three evidence drill-downs — each bounded to one opportunity.
  • Expensive verbs reserved for humans. pull spends API quota and analyze rewrites the current run, so the agent's operating contract excludes both. Agents read runs; people create them.

Where does a hosted dashboard fit alongside the CLI?

The same Google APIs also feed a human surface: a small Next.js admin app on Railway with the site's CRM, showing GA4 and Search Console side by side. It follows the inverse discipline — instead of bounding output, it bounds calls: the analytics page renders only a snapshot cached in Postgres, and Google is contacted exclusively when someone presses Refresh (the reasoning is in the GA4 Data API guide). Two consumers, two disciplines, one rule underneath: every read from Google is deliberate, and everything else reads a local copy.

Which of these rules transfer to any agent-facing tool?

  1. Budget output in tokens, not rows — decide what a command may cost before deciding what it prints.
  2. Make caps structural. If the unbounded path exists, it will be taken.
  3. stdout is the contract; stderr is the narration.
  4. Split verbs by cost: reads for agents, writes and quota-spends for humans.
  5. Ship a doctor command — the agent (and you) should configure from what the credential can actually see, never from memory. Kin to the checks in the service account guide.
  6. Keep the archive in version control when the source forgets — reproducibility is a feature of reports, same as it is of repos structured for agents.

Questions

Should a tool for AI agents be an MCP server or a CLI?

If the agent can run Bash, a CLI is the simpler contract: no server process, no protocol dependency, testable by a human typing the same command. MCP earns its place when you need typed schemas, discovery, or access from clients that can't shell out. Either way, the binding constraint is the same — bounded output.

Why commit analytics data files to git?

Because Search Console deletes everything older than 16 months. The API is a rolling window, not an archive; the repo is the archive. Raw responses are written once per closed window and never rewritten, so history accumulates and every report is reproducible from committed inputs.

Why limit how many times an agent can drill into the data?

Because an agent will otherwise explore its way through its own context budget. The operating contract allows a summary command first, then at most three evidence calls per session — enough to verify a finding, not enough to wander. The constraint lives in the agent's instructions and in the tool's caps, so neither side can drift alone.

Written by

Karol

Senior engineer and systems architect behind Tall Karol. Everything published here is grounded in real client work — no roundups, no tools that haven't run in production.

Why Tall KarolWork with Tall Karol

Related notes

More on ai integration

Related service: AI Integration

Want this kind of engineering on your project?

Tall Karol takes on fractional and project-based engagements for startups and agencies.

Book a working session