
Docs Validate Code Samples
- 57 installs
- 71 repo stars
- Updated July 31, 2026
- elastic/elastic-docs-skills
docs-validate-code-samples is an Elastic documentation skill for code sample validation.
About
The docs-validate-code-samples skill supports Elastic technical writers and contributors. code sample validation. Validates code samples in Elastic docs for syntax, runnable correctness, and version alignment. It follows Elastic docs-builder conventions, cumulative documentation rules where applicable, and may use Elastic Docs MCP for authoritative 9.x references. Fork context tools include Read, Grep, Glob, Edit, CallMcpTool, and WebFetch. Use when writing, reviewing, or fixing Elastic documentation pages that need code sample validation.
- Code sample syntax validation.
- Runnable example verification.
- Version alignment with 9.x baseline.
Docs Validate Code Samples by the numbers
- 57 all-time installs (skills.sh)
- Ranked #782 of 1,879 Documentation skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
docs-validate-code-samples capabilities & compatibility
- Capabilities
- code sample syntax validation. · runnable example verification. · version alignment with 9.x baseline.
- Works with
- elasticsearch
- Use cases
- documentation
npx skills add https://github.com/elastic/elastic-docs-skills --skill docs-validate-code-samplesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 57 |
|---|---|
| repo stars | ★ 71 |
| Last updated | July 31, 2026 |
| Repository | elastic/elastic-docs-skills ↗ |
How do I code sample validation in Elastic docs?
code sample validation
Who is it for?
Elastic documentation authors and reviewers.
Skip if: Skip for non-Elastic documentation repositories.
When should I use this skill?
User needs Elastic docs help with code sample validation.
What you get
Documentation updated per docs-validate-code-samples skill rules.
Files
<!-- Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Elasticsearch B.V. licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -->
You are a code sample validator for Elastic documentation. Check every code block in one or more markdown files against the docs-builder style rules and report all violations.
Never modify documentation source files. Only analyze and report.
---
Step 1: Resolve files
Parse $ARGUMENTS for an optional --output <path> flag (strip it before continuing). Resolve the target:
- Single `.md` file — analyze that file only.
- Directory — find all
.mdfiles recursively withfind <dir> -name "*.md" -type f | sort. - Glob — expand with
bash -O globstar -c 'printf "%s\n" <glob>'. - No argument — ask: "Please provide a file path, directory, or glob pattern."
---
Step 2: Extract code blocks
For each file, use Grep with pattern ` ^` to find fence line numbers, then Read the file to extract blocks. Also search for indented fences ( ^\s+` `) to catch blocks inside list items.
- Skip blocks inside HTML comments (
<!-- ... -->). - Skip MyST directive blocks where the info string starts and ends with
{}(e.g., ``{note}`).
For each block capture: opening line number, fence info string, language identifier (first word), attributes (remaining tokens), and body.
---
Step 3: Run checks A through H
Check A — Missing or wrong language identifier
Flag any block with an empty fence info string. Also flag blocks where the language identifier is clearly wrong for the content (e.g., js used for a JSON-only response, console used for response-only data with no HTTP method line).
Common valid identifiers: bash, sh, console, console-result, json, yaml, python, javascript, js, typescript, java, go, ruby, sql, esql, eql, painless, kql, kuery, txt, text, xml, toml, ini, diff.
Infer the correct identifier from content: HTTP method line → console; starts with {/[ → json; key: value lines → yaml; curl/apt-get → bash; import/def/print( → python; public class → java; const/let/=> → javascript.
Check B — Variable substitution missing subs=true
Walk up from the target file to find docset.yml and parse its subs: section for valid variable names. Stop at the git root (presence of .git/) or after 6 directory levels, whichever comes first. Flag any block containing {{var}} where var is a defined substitution key but the fence info lacks subs=true. Also flag the inverse: subs=true on a block with no {{...}} patterns.
If no docset.yml is found, flag any {{word}} pattern (single identifier) as a potential substitution variable.
Check C — Inline comments that should be callouts
For blocks with language bash, sh, shell, console, yaml, python, javascript, js, typescript, java, go, or ruby: flag lines where # or // appears after code on the same line and the comment reads as a reader-facing explanation.
Exemptions: shebang lines, standalone comment lines (no code on the same line), # inside strings, lines already using callout markers (<1>).
Suggestion: replace with explicit callout markers (<N>) and a numbered list after the block.
Check D — JSON validation in console and console-result blocks
console blocks are API requests (customers copy-paste them); console-result blocks are responses (display only). Each console block contains one or more API calls: an HTTP method+path line, followed by an optional JSON body, repeated for multiple calls.
Flag `...` in `console` blocks — never acceptable; replace with realistic values. ... in console-result is fine.
Pre-process both block types before JSON parsing: 1. Strip callout markers (<N>) and their preceding ///# from line ends. 2. Replace {{var}} / {{{var}}} template variables with a placeholder string. 3. Skip standalone # or // comment lines when building the JSON body. 4. Replace triple-quoted Painless strings ("""...""") with a placeholder using a multiline perl substitution. 5. For console-result only: normalize ... ellipsis — replace [...] with [], {...} with {}, : ... with : null, strip standalone ... lines. 6. Detect and flag trailing commas before } or ] (do not silently fix).
NDJSON (`_bulk`): if the method line contains _bulk, validate each non-empty line as a separate JSON object. Otherwise validate the full body with jq.
Do NOT flag: Painless scripts (replaced before parsing), EQL/ES|QL string values, callout markers and template variables (already stripped).
Check E — Non-reserved domain names
Flag URLs or hostnames in code blocks that use invented placeholder domains with real TLDs (e.g., mycompany.com, mycluster.io).
Safe — do not flag: example.com/net/org, any subdomain thereof, .example/.test/.localhost/.invalid TLDs, localhost, loopback (127.x.x.x), RFC 5737 doc IPs (192.0.2.x, 198.51.100.x, 203.0.113.x), private ranges, and known legitimate domains: elastic.co, amazonaws.com, azure.com, googleapis.com, docker.com, github.com, pypi.org, npmjs.com, and similar well-known registries and cloud providers.
Suggestion: replace with example.com or a subdomain like my-cluster.example.com.
Check F — API validation for console blocks
Collect all unique METHOD /path values across all files first. For each unique endpoint (skip any already validated earlier in this run), call mcp__elastic-docs__search_docs with query "request body fields <endpoint> elasticsearch API" (product: elasticsearch, section: api) to find the matching API reference page (URL starting with /docs/api/doc/elasticsearch/operation/). Fetch it with mcp__elastic-docs__get_document_by_url (include_body: true).
- No matching page found: flag the endpoint as potentially removed or renamed.
- Deprecated field: if a top-level request body key appears alongside "deprecated" in the docs, flag it with the replacement.
- Unrecognized field (advisory): if a top-level key doesn't appear in the docs body at all, note it for verification.
Do NOT flag: _-prefixed metadata fields, nested object keys, standard Search DSL fields (query, aggs, sort, size, from, highlight, knn, retriever, script).
Always include the API docs URL in the issue detail.
Check G — ES|QL syntax validation
G-1 — Source command: the first non-blank, non-comment line must be FROM, ROW, SHOW INFO, or METRICS. Flag blocks that start with a processing command (missing source), or with SELECT (SQL syntax).
G-2 — Pipe command names: every line beginning with | must use a recognized command: CHANGE_POINT, COMPLETION, DISSECT, DROP, ENRICH, EVAL, FORK, FUSE, GROK, INLINESTATS, KEEP, LIMIT, LOOKUP JOIN, METRICS_INFO, MMR, MV_EXPAND, REGISTERED_DOMAIN, RENAME, RERANK, SAMPLE, SORT, STATS, TS_COLLAPSE, TS_INFO, URI_PARTS, USER_AGENT, WHERE. Flag unrecognized names.
G-2a — Incomplete pipe commands: recognizing the command name is not enough — flag any pipe command that is present but has no arguments following it on the same line. Required arguments:
| Command | Requires |
|---|---|
KEEP, DROP | at least one field name |
WHERE | a condition expression |
SORT | at least one field |
EVAL, STATS | at least one expression |
RENAME | at least one old AS new pair |
DISSECT, GROK | an input field and a pattern |
ENRICH | a policy name |
LOOKUP JOIN | a lookup index name and ON <field> |
G-3 — SQL-isms: flag SELECT at line start, GROUP BY, raw JOIN (without LOOKUP), and ORDER BY — all SQL syntax invalid in ES|QL.
G-4 — Do not flag: // comment lines, WHERE after a pipe, FROM inside a string, blocks with only comments or blank lines.
Check H — Painless script validation
Painless appears in two places: standalone ` `painless blocks, and triple-quoted """...""" strings inside console blocks. Extract inline Painless from console` blocks using a multiline perl match (via Bash) before Check D replaces them with placeholders.
Run these checks on each Painless source:
H-1 — Balanced delimiters: count {} [] () pairs. Flag any imbalance. Do not count delimiters inside string literals.
H-2 — Deprecated `.getValue()` API: .getValue() on doc fields is deprecated — flag any usage and suggest .value instead (e.g., doc['field'].value).
H-3 — Unavailable APIs: flag use of System.out, System.err, System.exit, Thread.sleep, Runtime.getRuntime, or ProcessBuilder — none are available in the Painless sandbox. Suggest using the Painless execute API (POST /_scripts/painless/_execute) for debugging instead.
H-4 — Do not flag: // comment lines, delimiters inside quoted strings, single-expression scripts with no delimiters, empty or comment-only blocks.
---
Step 4: Generate the report
Output two sections. Omit any table where no files have issues.
Section 1 — Summary tables:
## Code Sample Validation Report
**Target:** <path>
**Files checked:** N
**Issues found:** N
### Summary
#### All blocks (Checks A, B, C, E)
| File | Missing/wrong lang | subs=true | Callout | Domain | Total |
|------|--------------------|-----------|---------|--------|-------|
#### Console / console-result blocks (Checks D, F)
| File | Ellipsis | JSON errors | API Validation | Total |
|------|----------|-------------|----------------|-------|
#### ES|QL blocks (Check G)
| File | Source cmd | Pipe cmd | SQL-ism | Total |
|------|------------|----------|---------|-------|
#### Painless blocks (Check H)
| File | Unbalanced delimiters | Deprecated API | Unavailable API | Total |
|------|-----------------------|----------------|-----------------|-------|Section 2 — Issue details, one subsection per file:
````
path/to/file.md — Line N — Check X — Short title
Issue: description
Suggestion: fix
context lines around the error
^````
For JSON errors include the jq error message and up to 2 lines of context around the offending line with a ^ pointer. For Painless inline scripts, note whether the issue is from a standalone block or an embedded triple-quoted string.
If no issues are found: print "No issues found across all checked files." in place of Section 2.
Output mode: print to console unless --output <path> was given, in which case write the report as a markdown file and confirm the path.
---
Guidelines
- Report the line number of the opening fence for every flagged block.
- Do not flag false positives — skip ambiguous inline comments, and apply H-1 only when imbalance is unambiguous.
- Skip non-markdown files silently. Note unreadable files and continue.
{
"skill_name": "validate-code-samples",
"evals": [
{
"id": 1,
"prompt": "Check ~/docs/bbq-example.md for code sample issues. The file contains:\n```console\nPUT bbq_disk-index/_mapping\n{\n \"index_options\": {\n \"type\": \"bbq_disk\"\n \"bits\": 2\n }\n}\n```",
"expected_output": "Flags a JSONDecodeError for the console block — missing comma between 'type': 'bbq_disk' and 'bits': 2 — and shows a ^ pointer at the error location",
"expectations": [
"Identifies the console block",
"Flags a JSONDecodeError with a message about a missing ',' delimiter",
"Shows a code snippet with a ^ pointer indicating the error line",
"Reports the file path and line number in the output",
"Does NOT modify the source file"
]
},
{
"id": 2,
"prompt": "Check ~/docs/callout-example.md for code sample issues. The file contains:\n```console\nPUT /my-index\n{ // <1>\n \"settings\": { // <2>\n \"number_of_shards\": 1\n }\n}\n```",
"expected_output": "Does NOT flag a JSON error — the // <1> and // <2> callout markers are stripped before JSON parsing, leaving valid JSON",
"expectations": [
"Identifies the console block with // <1> callout marker syntax",
"Strips the // <1> and // <2> callout markers before JSON parsing",
"Does NOT flag a false positive JSON error for the callout syntax",
"Reports zero JSON errors for this file"
]
},
{
"id": 3,
"prompt": "Check ~/elastic-repos/docs-content/raw-migrated-files/elasticsearch/elasticsearch-reference/subs-example.md for code sample issues. The file contains:\n```bash\nwget https://artifacts.elastic.co/downloads/elasticsearch-{{version}}.tar.gz\n```\nand also:\n```bash subs=true\necho 'no variables here'\n```",
"expected_output": "Flags the bash block with {{version}} as missing subs=true, and the bash block with subs=true but no variables as having an unnecessary attribute",
"expectations": [
"Flags the block containing {{version}} for missing subs=true",
"Flags the block with subs=true but no {{...}} patterns as having unnecessary subs=true",
"Reports both issues with line numbers",
"Does NOT flag valid code blocks without substitution issues"
]
},
{
"id": 4,
"prompt": "Check ~/docs/painless-example.md for code sample issues. The file contains:\n```console\nPOST /my-index/_update/1\n{\n \"script\": {\n \"source\": \"\"\"ctx._source.counter += params.count\"\"\",\n \"lang\": \"painless\",\n \"params\": { \"count\": 4 }\n }\n}\n```\nand:\n```console-result\n{\n \"_index\": \"my-index\",\n \"_id\": \"1\",\n \"result\": \"updated\",\n \"_shards\": ...\n}\n```",
"expected_output": "Reports no JSON errors — the Painless triple-quoted string is replaced before parsing, and the console-result ellipsis is normalized",
"expectations": [
"Correctly handles the Painless triple-quoted string in the console block without a JSON error",
"Correctly handles the ... ellipsis in the console-result block without a JSON error",
"Does NOT generate false positive JSON errors for either block",
"Produces a report with zero JSON errors"
]
},
{
"id": 5,
"prompt": "Check ~/docs/clean-example.md for code issues. The file has:\n```console\nGET /my-index/_search\n{\n \"query\": { \"match_all\": {} }\n}\n```\nand:\n```bash\n#!/bin/bash\ncurl -X GET localhost:9200/_cat/indices\n```",
"expected_output": "Reports no issues — the console block has valid JSON, the bash block has a shebang (not a callout candidate), and all code blocks have language identifiers",
"expectations": [
"Does NOT flag the console block (valid JSON, no issues)",
"Does NOT flag the shebang line as an inline comment that should be a callout",
"Does NOT flag any missing language identifiers (both blocks have them)",
"Reports zero issues or 'No issues found' for the file"
]
},
{
"id": 6,
"note": "The prompt references a file path but supplies the file content inline. The skill should use the inline content as the file body — no file system access is needed. This pattern works in CI without external repos and is the recommended approach for Check F evals.",
"prompt": "Check ~/docs/reindex-example.md for code sample issues. The file contains:\n```console\nPOST _reindex\n{\n \"source\": { \"index\": \"old-index\" },\n \"dest\": { \"index\": \"new-index\" },\n \"conflicts\": \"proceed\"\n}\n```",
"expected_output": "Uses the elastic-docs MCP server to look up the reindex API, confirms the endpoint exists, and does not flag 'source', 'dest', or 'conflicts' as errors — all are valid documented request body fields",
"expectations": [
"Calls SemanticSearch or GetDocumentByUrl to look up the POST _reindex API reference",
"Confirms the endpoint exists in current Elastic documentation",
"Does NOT flag 'source', 'dest', or 'conflicts' as errors (all are valid documented fields)",
"Includes the API docs URL in the API Validation section",
"Reports no issues for this file",
"Treats the inline file content in the prompt as the file to validate — no external file access required"
]
}
]
}
Related skills
FAQ
What does docs-validate-code-samples do?
docs-validate-code-samples is an Elastic documentation skill for code sample validation.
When should I use docs-validate-code-samples?
User needs Elastic docs help with code sample validation.
Is this skill safe to install?
Review the Security Audits panel on this page before installing in production.