Query
Run one read-only Cypher statement from the terminal, bind parameters with --param, and read the same JSON envelope the HTTP API returns.
On this page (4)
Query Documentation
whisper query sends one Cypher statement to WhisperGraph and prints the answer. It goes to the same endpoint the HTTP API documents and gets the same reply back. The CLI only saves the typing.
Sign in first. Then:
whisper query "CALL whisper.identify(['api.openai.com'])"
host vendor_id canonical_name is_canonical confidence category roles band host_class
api.openai.com cloudflare Cloudflare true 0.8 cdn ["ORIGIN_AS","CDN"] DERIVED unknown
1 row(s)
Anything the Cypher chapter describes runs here: MATCH traversals, the procedures, CALL db.schema(). Writes are refused by the graph before they run, so there is nothing to be careful about.
Parameters
Never paste an indicator into the query string. Bind it with --param and refer to it as $name:
whisper query 'CALL whisper.assess([$v])' --param v=8.8.8.8
The value is parsed as JSON when it parses (numbers, booleans, lists, objects) and taken as a string otherwise. 8.8.8.8 is not valid JSON, so it arrives as the string the procedure expects. A list works the same way:
whisper query 'CALL whisper.assess($hosts)' --param 'hosts=["example.com","8.8.8.8"]'
host label band coverage
example.com benign-allowlisted NONE known-clean
8.8.8.8 benign-allowlisted INFO known-clean
2 row(s)
--param repeats, one per parameter.
JSON output
--json prints the reply exactly as the graph sent it: columns, rows and statistics.
whisper query 'CALL whisper.assess([$v])' --param v=8.8.8.8 --json
{
"columns": ["host", "label", "band", "sub_labels", "signals", "coverage", "evidence", "verdictScore", "isThreat", "threatSources"],
"rows": [
{
"host": "8.8.8.8",
"label": "benign-allowlisted",
"band": "INFO",
"coverage": "known-clean",
"verdictScore": 0.0,
"isThreat": false
}
],
"statistics": {"rowCount": 1, "executionTimeMs": 0}
}
That is the envelope from POST /api/query, so anything you already pipe API output into reads this too:
whisper query 'CALL whisper.assess([$v])' --param v=8.8.8.8 --json | jq -r '.rows[0].band'
Read coverage before band. INFO on a known-clean address and NONE on an address nobody has ever looked at print the same colour in a terminal, and only one of them is reassuring. Coverage explains the difference.
When something goes wrong
Errors print as one line beginning whisper: and the command exits with status 1. A write is refused the same way:
whisper query 'CREATE (n:X) RETURN n'
whisper: read_only
No key, a syntax error and an unreachable graph all arrive in that shape, so a script can test the exit code and read the line. Zero rows is not an error: it means the query matched nothing, and the Best Practices page has the usual reasons why.
Where next
- Recipes from the terminal: the common questions, already written, one name each.
- Cheat Sheet: edge directions, procedure columns and the query rules on one page.