Skip to content

CLI — cw-* Read Commands

CritterWatch ships a server-less command-line surface for an embedded CritterWatch console: four read commands that emit the same JSON the MCP read tools produce, without ASP.NET Core, the MCP HTTP transport, or even starting the application. They exist for AI agents and scripts that want a point-in-time snapshot of a system's health from the shell.

Paid tier

Like the whole MCP/AI surface, the cw-* commands are license-gated. Without a valid CritterWatch license the commands exit non-zero with an explanatory message.

Setup

No extra package. The cw-* commands ship inside CritterWatch.Services, which every console package already brings in — reference CritterWatch for a Marten / PostgreSQL host, CritterWatch.SqlServer for Polecat / SQL Server, or CritterWatch.Sqlite for Fisher / SQLite, exactly as you would to mount the console:

bash
dotnet add package CritterWatch

They also add nothing to your dependency closure: the commands are built on the same store-agnostic reporters the console already carries, and JasperFx.CommandLine arrives with Wolverine itself. No Marten or Polecat reference, no ASP.NET Core, no MCP SDK.

The commands are discovered by JasperFx's command runner — the same RunJasperFxCommands entry point a Wolverine application already uses:

cs
// The cw-* read commands ship with the CritterWatch console packages, and JasperFx's command
// runner discovers them automatically — no registration call. `dotnet run` with no arguments
// starts the host normally; `dotnet run -- cw-health` (etc.) runs the command against a
// BUILT-but-not-started host and exits — a point-in-time read of the last persisted state.
return await app.RunJasperFxCommands(args);

Nothing is started when a cw-* command runs: the host is built, not run, so the command reads the console's last persisted state and exits.

Commands

Every command supports --format json (the default — agent-first, stable shapes shared with the MCP tools) and --format text (human-readable).

--view is a closed set

Each command accepts a fixed list of --view values, given per command below. An unrecognised value is an error — the command prints the accepted set to stderr and exits non-zero rather than answering with some other report. Omitting --view is always fine: you get that command's documented default view.

This matters most for the audience these commands were built for. An agent that asks for degraded and silently receives a healthy-looking cluster summary has no way to tell it was misunderstood, so the surface fails closed instead.

cw-health

Accepted --view values: summary (default) · service · degraded

InvocationReturns
dotnet run -- cw-healthFleet-level health rollup (the default view)
dotnet run -- cw-health --view summaryFleet-level health rollup
dotnet run -- cw-health --view service --service <name>One service's health detail
dotnet run -- cw-health --view degradedOnly the services with problems

cw-performance

Accepted --view values: backlog (default) · hotspots · lag

InvocationReturns
dotnet run -- cw-performance --view backlogQueue/backlog pressure across endpoints
dotnet run -- cw-performance --view hotspotsThe slowest / busiest message types
dotnet run -- cw-performance --view lagProjection lag against the high-water marks

cw-alerts

Accepted --view values: list (default) · summary · get

InvocationReturns
dotnet run -- cw-alerts --view listActive alerts
dotnet run -- cw-alerts --view summaryAlert counts by severity/type
dotnet run -- cw-alerts --view get --id <alert-stream-id>One alert's full detail

cw-routing

cw-routing takes no --view — it has a single report, shaped by whether --message is supplied.

InvocationReturns
dotnet run -- cw-routing --service <name>The service's message-routing topology
dotnet run -- cw-routing --service <name> --message <type>How one message type routes

Reading the exit code

The commands separate "your invocation was wrong" from "there is nothing to report", because an agent has to branch on the difference:

SituationExit codeOutput
A successful read0The report on stdout
A lookup that found nothing (unknown service, unknown alert id)0A structured { "found": false, ... } payload on stdout
The console has never run (no data yet)0A structured { "error": "NoMonitoringData", ... } payload on stdout
An unknown --view, or a missing flag the chosen view requiresnon-zeroA message on stderr naming the accepted values
No valid CritterWatch license, or the host mounts no consolenon-zeroAn explanatory message on stderr

So the empty and not-found cases stay parseable on stdout — scripts branch on the payload without reading stderr — while a malformed invocation is a hard failure that cannot be mistaken for an answer.

Relationship to MCP

The commands reuse the exact reporters behind the CritterWatch.Mcp read tools and serialize through the same JsonSerializerOptions instance, so the JSON is identical to what an MCP client sees — by construction, not by two configurations happening to agree. Pick by transport: MCP for a connected AI session over HTTP, cw-* for shells, cron, and agents that exec commands. See MCP — Model Context Protocol.

Smoke coverage

Every command × view × format combination is exercised by the repo's SmokeTestCli build target against both console hosts (Marten and Polecat / SQL Server), with an anti-drift check that fails the build if a new cw-* command ships without matrix coverage.

Free for read-only monitoring. A commercial license is required for administrative actions and the MCP server.