HyperDX Log Querying
MANDATORY: Always use
hdx_query.shto query logs and traces. Do not use curl, raw API calls, or any other method — even if it seems simpler. If the script fails, fix the script — do not work around it.
Three failures are environment, not bugs — do not edit the script for these:
| What you see | What it means |
|---|---|
Missing required command: <x> (exit 127) |
A dependency is absent. Tell the user to install it. The script is fine. |
command not found: hdx_query.sh |
The skill's bin/ is not on PATH — the plugin is disabled, or the session started before it was installed. Ask the user to enable it and run /reload-plugins, or restart. Do not substitute an absolute path. |
| A permission prompt on every call | The allowlist is not installed. That is setup, not failure — see Permissions below. |
Anything else that fails is a real defect: fix the script rather than working around it.
hdx_query.sh ships in this skill's bin/ directory, which is on the Bash
tool's PATH whenever the skill is installed. Invoke it by bare name — never
by an absolute path. The bare form is the only spelling that works on both
install routes, and it is what the permission rule matches.
The script supports two modes: cloud (HyperDX REST API) and local (ClickHouse via docker exec into a local HyperDX container).
Per-Project Configuration (.agent.env)
Each project should have the following in its .agent.env file at the project
root:
HYPERDX_MODE: local # or: cloud
OTEL_SERVICE_NAME: your-service-name
HYPERDX_LOCAL_API_KEY: your-personal-api-key
HYPERDX_CONTAINER: hdx-local
HYPERDX_LOCAL_API_KEYis the Personal API Key from HyperDX account settings — not the Ingestion API Key.HYPERDX_CONTAINERis the Docker container name for local mode (default:hdx-local). Omit if using cloud mode only.OTEL_SERVICE_NAMEis the default service to filter on. Multi-service projects (e.g. a pipeline + an API) instead define one key per service —OTEL_SERVICE_NAME_<SERVICE>(e.g.OTEL_SERVICE_NAME_PIPELINE,OTEL_SERVICE_NAME_API). When those are present, pick the key matching what you're querying and pass it as-s; omit-sto sweep all services. Treat the bareOTEL_SERVICE_NAMEas optional in that case.
If a required value (mode, API key, container) is missing from
.agent.env, ask the user to add it before proceeding. The service name is
optional — without one, query without -s (all services).
Mode Detection (read this before every query)
Before running the script, read .agent.env and apply this logic:
if HYPERDX_MODE == "local"
→ add --local --container <HYPERDX_CONTAINER>
→ do NOT pass --api-key or --url
else (HYPERDX_MODE == "cloud" or not set)
→ pass --api-key <HYPERDX_LOCAL_API_KEY>
→ do NOT pass --local
Never guess the mode — always derive it from HYPERDX_MODE in .agent.env.
If HYPERDX_MODE is missing, ask the user to add it before proceeding.
Permissions
This script is meant to be pre-approved, via this rule:
Bash(hdx_query.sh:*)
That rule is not installed by either install route — it lives in the
toolkit's project-files/.claude/settings.json template and the user merges it
into a project's .claude/settings.json (or their user settings) themselves. So:
- If the rule is present, run the script directly and do not ask for approval.
- If every call prompts, the rule is simply absent. Say so once and continue — that is unfinished setup, not a malfunctioning skill, and not a reason to reach for curl.
Note the rule approves the command name. It matches whatever PATH resolves
hdx_query.sh to, which is why the name is unusual enough not to collide.
Dependencies: curl and jq (both standard on most dev machines).
Local mode also requires docker.
Arguments
| Flag | Short | Default | Description |
|---|---|---|---|
--query |
-q |
(required) | Lucene query term. Repeat for multiple terms — they are OR'd together. Never use shell-escaped quotes inside a single value. |
--service |
-s |
OTEL_SERVICE_NAME to filter by | |
--api-key |
-k |
HyperDX Personal API key (cloud mode, read from .agent.env) | |
--minutes |
-t |
5 |
How many minutes to look back |
--limit |
-l |
10 |
Max log lines to return |
--url |
https://api.hyperdx.io |
HyperDX base URL (cloud mode) | |
--local |
off | Query local ClickHouse instead of cloud API | |
--container |
hdx-local |
Docker container name (local mode) | |
--table |
logs |
logs or traces (local mode only) |
Multi-term Queries
Pass each search term as its own --query flag. The script OR's them together
automatically — no shell quote escaping needed:
# DO THIS
hdx_query.sh --query "request completed" --query "job finished" --query "status:500"
# NOT THIS — triggers shell obfuscation warning in Claude Code
hdx_query.sh --query "\"request completed\" OR \"job finished\""
Lucene Field Reference
| Lucene field | Cloud (HyperDX) | Local logs | Local traces |
|---|---|---|---|
level:error |
✓ | → SeverityText |
— |
service:name |
✓ | → ServiceName |
→ ServiceName |
TraceId:xxx |
✓ | → TraceId |
→ TraceId |
SpanName:xxx |
✓ | — | → SpanName |
"free text" |
✓ | → Body ILIKE |
→ SpanName ILIKE |
field:value |
✓ | → LogAttributes map |
→ SpanAttributes map |
Local mode matches field:value exactly and case-sensitively (it builds
col = 'value'). SeverityText is stored lowercase, so use level:warn /
level:error / level:info — level:WARN matches nothing. When unsure of a
field's stored values, drop the filter and grep Body with free text instead.
Workflow
- Read
.agent.env— extract the service name(s) (OTEL_SERVICE_NAME, or per-serviceOTEL_SERVICE_NAME_<SERVICE>keys),HYPERDX_LOCAL_API_KEY, andHYPERDX_CONTAINER. For a multi-service project, pick the key matching what you're querying; omit-sto sweep all services. - Determine mode — use
--localif the user is debugging a local run; use cloud (default) for deployed services. - Construct the query — use one
--queryflag per term, never escape quotes inside a single flag value. - Run the script — default to
--minutes 5 --limit 10for quick checks. - Interpret output — summarize patterns, highlight repeated errors, suggest next steps.
- Iterate — broaden query or increase
--minutes/--limitif needed.
Common Patterns
Cloud — quick error check:
hdx_query.sh \
-k "your-key" -s "your-service" -q "level:error"
Cloud — multi-term OR search:
hdx_query.sh \
-k "your-key" -s "your-service" \
--query "request completed" \
--query "job finished" \
-t 30 -l 50
Local — recent logs:
hdx_query.sh \
--local --container hdx-local -s "your-service" \
-q "level:error" -t 10 -l 20
Local — trace lookup:
hdx_query.sh \
--local --table traces -s "your-service" \
-q "TraceId:abc123"
Local — self-hosted URL:
hdx_query.sh \
-k "your-key" -q "level:error" --url http://localhost:8080
Error Handling
| Error | Likely cause | Fix |
|---|---|---|
No API key found |
Missing from .agent.env | Add HYPERDX_LOCAL_API_KEY |
Error: Unauthorized |
Wrong key type (Ingestion vs Personal) | Use Personal API Key from account settings |
ClickHouse error: docker exec failed |
Container not running or wrong name | Check docker ps and HYPERDX_CONTAINER in .agent.env |
No logs found matching... |
Query too narrow or wrong time window | Broaden query or increase --minutes |
HTTP Error: ... |
API-side issue | Check HyperDX status / try again |