meain/dotfiles/esql
Claude Code and agent skill by meain/dotfiles
- community
Checking that the SKILL.md file is still in the repository.
Query Elasticsearch/Kibana using ES|QL via the Kibana async search API. Requires an initial curl command from the user to extract session credentials. Triggers: /esql, 'query elastic', 'search logs', 'check elastic logs', 'run esql', 'elasticsearch query', 'check kibana'
Install
npx vskill@latest install meain/dotfiles/esqlSKILL.md
ES|QL Query Skill
Query Elasticsearch via the Kibana ES|QL async search API. Run ES|QL queries directly against Kibana clusters without the user needing to copy-paste results.
Setup
Staging / Production — ,es-web CLI
The ,es-web CLI at /Users/meain/.local/bin/utils/,es-web handles Kibana ES|QL queries with automatic async polling, session management, and table output.
First-time setup for a cluster: open Kibana's ES|QL tab (use the URL with dataSource:(type:esql) so an esql_async request fires on load), open DevTools → Network, filter by esql_async, right-click the request → Copy as cURL, then run:
Check configured clusters:
Session cookies expire after a few hours. If you get a 401/session expired error, use reinit — it reopens Kibana and waits for a fresh curl on the clipboard itself, then tests & saves:
Run this with dangerouslyDisableSandbox: true since it needs to open the browser. It blocks until a valid curl shows up on the clipboard, so tell the user to copy one (DevTools → Network → filter esql_async → right-click → Copy as cURL) while it's waiting.
How to query with ,es-web
,es-web options
-c— Cluster alias (e.g.stg-us,prd-eu)-s—service.namefilter-t— Time window (e.g.30m,1h,2d). Defaults to4hif omitted (a warning is printed to stderr)-n— Max rows (default: 20)-q— Additional WHERE clause-f— Comma-separated fields for KEEP clause-i— Index pattern (default:logs-*)--json— Raw JSON output--debug— Print generated query to stderr
Important notes
,es-webswallows unknown-column errors — aKEEP/STATS BYon a non-existent field returns an empty "No results", not an error. Before concluding "no data", confirm the field exists (e.g.... | WHERE <field> IS NOT NULL | STATS COUNT(*)). Field names vary by dataset (e.g.apm.app.earnhas no HTTP path field;apm.app.nginxuseslabels.path).labels.statusis a keyword field — compare with strings, not integers (e.g.,labels.status >= "500")- When no
-fis specified, default fields are:@timestamp, service.name, message, labels.error, labels.error_message, labels.path, labels.status, trace.id - For raw ES|QL queries, pass the full query as a positional argument — no default KEEP is added
- LIKE queries on
messageacross many services can be slow — scope with service and tight time windows
EARN-specific reference
For EARN log fields, structured labels, message strings, query patterns, and metrics, read: .mdocs/reference/earn-kibana-esql-reference.md (relative to the control-plane-backend repo root).
That doc is authoritative for EARN. The quick summary of EARN-specific field names (these differ from other services):
labels.workload_tenant_id— workload tenant UUID (notlabels.workload_tenant.id)labels.event_type— EARN event type (notlabels.earn.event.type)labels.organization_id— org UUID in EARN contextlabels.operation— EARN operation name (e.g.get_workload_tenant_metadata)labels.clog_labels— structured log category (e.g.[earn_event_dropped])log.level— log level in EARN APM logs (notlevel)
Note: EARN logs appear twice in logs-* — once as APM-parsed (data_stream.dataset: apm.app.earn, has structured fields) and once as raw filebeat (data_stream.dataset: kubernetes.container_logs, has JSON in message). Filter to data_stream.dataset == "apm.app.earn" to avoid double-counting in STATS.
Known service names
These are the service.name values for control-plane-backend services:
| Service | service.name | |
|---|---|---|
| Workload Tenants | workload-tenants-svc | |
| Subscriptions | subscriptions-svc | |
| User Management | user-management | |
| Routing | routing | |
| EARN | earn | |
| EARN Telemetry | earn-telemetry | |
| Usage Reports | usage_reports | |
| Onboarding | onboarding | |
| Scheduler | scheduler |
The nginx ingress controller logs under service.name == "nginx".
Common log fields
Standard fields
@timestamp— event timestamp (ISO 8601)service.name— service identifier (see table above)service.environment—prod,prd,qa,devmessage— log message textlevel— log level (info,warn,error)trace.id— distributed trace ID for correlating across services
Label fields (keyword/string type)
labels.status— HTTP status code (string, not int)labels.path— request pathlabels.method— HTTP methodlabels.error/labels.error_message— error detailslabels.organization_id/labels.org_id— organization identifierlabels.organization.id— alternative org ID fieldlabels.workload_tenant_id— workload tenant identifier (EARN: same field, see EARN reference)labels.user.id/labels.principal.id— user/principal identifierslabels.operation— operation being performedlabels.handler— handler namelabels.event_type— EARN event type (uselabels.event_type, notlabels.earn.event.type)labels.earn.event.dedupe_key— EARN dedup keylabels.scheduler.event.id— scheduler event IDlabels.request.url— outgoing request URLlabels.http.router.request_id— request ID
Numeric label fields
numeric_labels.*— numeric values (latency, counts, etc.)
Overview labels (for filtering structured log categories)
These are set via clog.Label() and appear in a labels field:
http_server_overview,dispatcher_overview,queue_dispatcher_overviewearn_event_delivery,events_processorpanic_recovery,panic_recoveredazure_sdk_logging,secrets_handlingdeprecated_behavior_overview
Common query patterns
List services in a time window
Find 5xx errors from nginx
Find errors for a specific service
Search by org/tenant ID across all services
Search by workload tenant ID
Trace a request across services
Check latency metrics
Error rate by service (last hour)
Find panics
Dev / Personal Environments — ,es CLI
The ,es CLI at /Users/meain/.local/bin/utils/,es provides a simpler way to query Elasticsearch, but it only works for the dev environment. Do not use it for staging or production.
Common queries
Search by trace ID:
Filter for errors:
Broader service-level search (no trace ID):
,es CLI options
-q— Lucene query string-n— Number of results-f— Comma-separated fields to display-s— Sort field (e.g.@timestamp:desc)
Choosing the right approach
| Environment | Method | |
|---|---|---|
| Dev / personal | Use ,es CLI directly | |
| Staging / production | Use ,es-web -c <cluster> (requires session cookie from user) | |
| No session available | Fall back to clipboard mode (see below) |
Cluster naming convention: <env>-<region>, e.g. stg-us, stg-eu, prd-us, prd-eu, prd-apj (APJ, not apac).
When no ,es-web session is configured for the target cluster:
- Look up the Kibana URL on the Confluence Speed Dial page (
confluence page 405504500), open<kibana-base-url>/app/discover#/withopen <url>(withdangerouslyDisableSandbox: true), then ask the user to copy a curl from the network tab and run! pbpaste | ,es-web init <cluster> - If that's not possible, fall back to clipboard mode:
- Copy the ES|QL query to the user's clipboard with
pbcopy - Tell the user to open Kibana, run the query in Discover (ES|QL mode)
- Have them copy the response JSON from the network tab
Investigation workflow tips
- Start broad, narrow down. First identify which services are involved, then drill into specific errors.
- nginx → upstream. nginx logs show external-facing status codes; upstream service logs show root cause.
- Use trace.id to correlate requests across services when available.
- Error details live in
labels.errorandlabels.error_message. - Field types matter:
numeric_labels.*fields are numeric;labels.*fields are keywords (strings). - Time windows: Default is 4h when
-tis omitted. If a query times out, retry with a narrower window (e.g.,1h→30m). For very broad searches (e.g., no service filter), start at30mand expand only if needed. - Overview labels (like
http_server_overview,dispatcher_overview) are useful for filtering to structured log categories without needing to match on message text.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingagents/.agents/skills/esql/skill.md
Popularity
- Repository stars
- 279
- Repository forks
- 11
- 7-day trend score
- 33
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/meain/dotfiles/esql)