Painless (Elasticsearch)
English | Español
English
Syntax highlighting support for the Elasticsearch Painless scripting language,
focused on ingest pipelines.
Features
- Syntax highlighting for Painless scripts
- Keywords (
def, if, for, return, etc.)
- Functions and method calls
- Types (
String, Map, List, etc.)
- Comments and Javadoc
- Code folding for function definitions
- Automatic language detection for
.painless files
- Run Painless Simulation - Execute scripts against Elasticsearch using the
_ingest/pipeline/_simulate API

Usage
Syntax Highlighting
Just open any file with the .painless extension and the language mode will be automatically set to Painless.
Run Painless Simulation
- Right-click on a
.painless file
- Select "Run Painless Simulation"
- The extension will execute your script against Elasticsearch
- Results are saved to
.painless/request.json and .painless/response.json
- The
response.json file will open automatically showing the execution results

Requirements: You must create a .painless/ directory with configuration files (see Setup below).
Output Files
Every time you run a simulation, two files are created/updated in the .painless/ directory:
Example response.json (success):
{
"timestamp": "2025-12-28T19:30:45.456Z",
"painlessFile": "c:\\path\\to\\script.painless",
"http": {
"statusCode": 200,
"statusText": "OK"
},
"success": true,
"data": {
"docs": [...]
}
}
Example response.json (error):
{
"timestamp": "2025-12-28T19:30:45.456Z",
"painlessFile": "c:\\path\\to\\script.painless",
"http": {
"statusCode": 400,
"statusText": "Bad Request"
},
"success": false,
"error": {
"message": "Elasticsearch returned error",
"body": {
"error": {
"type": "...",
"reason": "..."
}
}
}
}
Setup for Simulation
To run Painless simulations, create a .painless/ directory in the same location as your .painless script file.
Directory Structure
my-project/
├── transform.painless # Your Painless script
└── .painless/ # Configuration directory
├── .env # Elasticsearch credentials (required)
├── params.json # Script parameters (optional)
├── docs.json # Test documents (required)
├── request.json # Last request details (auto-generated)
└── response.json # Last response (auto-generated)
Required Files
.painless/.env
Contains your Elasticsearch connection details:
ELASTIC_URL=http://localhost:9200
ELASTIC_API_KEY=base64_encoded_api_key
.painless/params.json (optional)
Parameters that will be available in your Painless script via params:
{
"delimiter": "-",
"position": 1
}
.painless/docs.json
Array of test documents to process with your script:
[
{
"_source": {
"env": "es01-prod"
}
}
]
Example
If you have a script at ~/projects/my-script/transform.painless, create:
~/projects/my-script/.painless/.env
~/projects/my-script/.painless/params.json
~/projects/my-script/.painless/docs.json
Then right-click on transform.painless and select "Run Painless Simulation".
Development
This section is for contributors who want to modify or build the extension.
Quick start? See the Quick Start for Development section above for the fastest way to get started.
Project Structure
painless/
├── package.json # Extension manifest (published configuration)
├── README.md
├── syntaxes/ # TextMate grammar
├── icons/ # File icons
└── painless/ # TypeScript source code
├── package.json # Development configuration
├── src/
│ ├── extension.ts # Extension entry point
│ └── simulate/ # Simulation logic
└── out/ # Compiled JavaScript (generated)
Why two package.json files?
- package.json (root): Extension manifest for VS Code marketplace. Contains metadata, activation events, and runtime dependencies like
node-fetch needed for packaging.
- painless/package.json: Development configuration with TypeScript, ESLint, and build scripts.
Getting Started
Clone the repository
Install dependencies in BOTH locations:
# Install dependencies in root (required for vsce package)
npm install
# Install development dependencies
cd painless
npm install
Compile in watch mode:
npm run watch
Press F5 in VS Code to launch the Extension Development Host with hot-reload
Compilation
From the painless/painless directory:
npm run compile
This generates JavaScript files in the out/ directory.
Prerequisites for Packaging
Before running vsce package, ensure the development package.json has the required activation events:
File: painless/painless/package.json
"activationEvents": [
"onCommand:painless.runSimulation"
],
"contributes": {
"commands": [
{
"command": "painless.runSimulation",
"title": "Run Painless Simulation"
}
]
}
Note: The VS Code template creates an empty activationEvents array by default, which works during development but fails when packaging.
Packaging
From the root painless/ directory:
vsce package
This generates painless-X.X.X.vsix
Local Installation
code --install-extension painless-0.0.1.vsix --force
Then reload VS Code: Ctrl+Shift+P → "Developer: Reload Window"
Complete Development Workflow
# 1. Make changes in src/
cd painless/painless
npm run compile
# 2. Verify package.json has activationEvents configured
# (See "Prerequisites for Packaging" section above)
# 3. Package the extension
cd ..
vsce package
# 4. Install locally
code --install-extension painless-0.0.1.vsix --force
# 5. Reload VS Code
# Ctrl+Shift+P → "Developer: Reload Window"
Recommended: Watch Mode
For active development:
cd painless/painless
npm run watch
Then press F5 in VS Code to open the Extension Development Host. Changes will be recompiled automatically.
Troubleshooting
vsce package fails with "npm error missing: node-fetch"
Error completo:
ERROR Command failed: npm list --production --parseable --depth=99999
npm error missing: node-fetch@^2.7.0, required by painless@0.0.6
Causa: Las dependencias del package.json raíz no están instaladas.
Solución:
# Desde el directorio raíz del proyecto
npm install
Luego puedes ejecutar vsce package sin problemas.
vsce package fails with "Manifest needs the 'activationEvents' property"
Solution: Add activation events to painless/painless/package.json:
"activationEvents": [
"onCommand:painless.runSimulation"
]
This is required for packaging, even though the extension works in development mode without it.
Two package.json files?
painless/package.json: Extension manifest for VS Code marketplace (published configuration)
painless/painless/package.json: Development configuration with build scripts and dependencies
During packaging, files are copied and merged appropriately.
Complete Usage Example
Let's walk through a complete example of using this extension:
Step 1: Create Your Project Structure
mkdir my-painless-project
cd my-painless-project
mkdir .painless
Step 2: Create Configuration Files
File: .painless/.env
ELASTIC_URL=http://localhost:9200
ELASTIC_API_KEY=your_base64_encoded_api_key_here
File: .painless/docs.json (test documents to process)
[
{
"_source": {
"message": "Server es01-prod is running",
"timestamp": "2025-12-28T10:30:00Z"
}
},
{
"_source": {
"message": "Database es02-staging connection failed",
"timestamp": "2025-12-28T10:31:00Z"
}
}
]
File: .painless/params.json (optional - parameters for your script)
{
"delimiter": "-",
"position": 0
}
Step 3: Create Your Painless Script
File: transform.painless (in the same directory as .painless/)
// Extract environment from server name
// Example: "es01-prod" -> environment = "prod"
def message = ctx.message;
def parts = message.splitOnToken(params.delimiter);
if (parts.length > params.position) {
def serverPart = parts[params.position];
def envParts = serverPart.splitOnToken('-');
if (envParts.length > 1) {
ctx.environment = envParts[1];
}
}
Your project structure should look like:
my-painless-project/
├── transform.painless
└── .painless/
├── .env
├── params.json
└── docs.json
Step 4: Execute the Script
- Open
transform.painless in VS Code
- Right-click anywhere in the file (or right-click the file in the Explorer sidebar)
- Select "Run Painless Simulation"
- The extension will:
- Execute your script against Elasticsearch
- Save request details to
.painless/request.json
- Save response to
.painless/response.json
- Automatically open
response.json showing the results
Step 5: Check the Results
.painless/response.json will contain:
{
"timestamp": "2025-12-28T22:45:12.345Z",
"painlessFile": "C:\\Users\\you\\my-painless-project\\transform.painless",
"http": {
"statusCode": 200,
"statusText": "OK"
},
"success": true,
"data": {
"docs": [
{
"doc": {
"_source": {
"message": "Server es01-prod is running",
"timestamp": "2025-12-28T10:30:00Z",
"environment": "prod"
}
}
},
{
"doc": {
"_source": {
"message": "Database es02-staging connection failed",
"timestamp": "2025-12-28T10:31:00Z",
"environment": "staging"
}
}
}
]
}
}
Notice how the script added the environment field to each document!
If There's a Syntax Error
If your Painless script has a syntax error, response.json will show:
{
"timestamp": "2025-12-28T22:50:00.123Z",
"painlessFile": "C:\\Users\\you\\my-painless-project\\transform.painless",
"http": {
"statusCode": 400,
"statusText": "Bad Request"
},
"success": false,
"error": {
"message": "Elasticsearch returned error",
"body": {
"error": {
"type": "script_exception",
"reason": "compile error",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "invalid syntax on line 5..."
}
}
}
}
}
What This Extension Does (and Doesn't Do)
✅ What it DOES
- Syntax highlighting - Color-codes your Painless code (keywords, functions, types, comments)
- Execute against Elasticsearch - Runs your script using the
_ingest/pipeline/_simulate API
- Capture logs - Saves request/response details for debugging
- Visualize results - Opens formatted response automatically
❌ What it DOES NOT do
- Syntax validation before execution - Won't check syntax until you run it
- Error prevention - Errors only appear after Elasticsearch processes the script
- Autocomplete - No IntelliSense or code suggestions
- Go to definition - Can't navigate to function/variable definitions
- Type checking - No static type analysis
Important: This is a viewer and executor, not a code analyzer. It helps you:
- Write scripts with syntax highlighting (easier to read)
- Execute them against Elasticsearch
- See results or errors
Syntax errors are caught by Elasticsearch during execution, not beforehand.
Quick Start for Development
Want to contribute or modify the extension? Follow these steps:
Clone the repository
Install dependencies in BOTH locations:
# Root directory
npm install
# Source code directory
cd painless
npm install
Start development:
npm run watch
Press F5 in VS Code to launch Extension Development Host
Make your changes - they'll recompile automatically
To package:
# From root directory
npm run package
Why install in two places? The root package.json contains dependencies needed for packaging (like node-fetch), while painless/package.json contains the development toolchain (TypeScript, ESLint, etc.).
Changelog
0.1.1
- README Improvements: Added screenshots showing syntax highlighting and execution flow
- Better Documentation: Complete usage examples in English and Spanish with step-by-step instructions
- Optimized Package: Reduced extension size from 13MB to 2.14MB (84% reduction)
- Marketplace Ready: Added keywords, license, and metadata for VS Code Marketplace publication
0.1.0
- Request/Response Logging: All executions now save complete request and response details to
.painless/request.json and .painless/response.json
- Enhanced Error Handling: Errors now include HTTP status codes and full Elasticsearch error responses
- API Key Security: API keys are sanitized in request logs (showing only last 4 characters)
- Automatic File Opening:
response.json opens automatically after each execution
- Better Debugging: Complete audit trail of all requests with timestamps and metadata
0.0.7
- Added context menu option in file explorer for "Run Painless Simulation"
- Now you can right-click on
.painless files directly from the explorer sidebar
0.0.5
- Added Painless simulation feature (run scripts against Elasticsearch)
- Added context menu command "Run Painless Simulation"
0.0.2
- Added file icon for .painless files
- Improved syntax highlighting
License
MIT
Español
Soporte de resaltado de sintaxis para el lenguaje de scripting Painless de Elasticsearch,
enfocado en pipelines de ingest.
Características
- Resaltado de sintaxis para scripts Painless
- Palabras clave (
def, if, for, return, etc.)
- Funciones y llamadas a métodos
- Tipos (
String, Map, List, etc.)
- Comentarios y Javadoc
- Plegado de código para definiciones de funciones
- Detección automática de lenguaje para archivos
.painless
- Ejecutar Simulación Painless - Ejecuta scripts contra Elasticsearch usando la API
_ingest/pipeline/_simulate

Uso
Resaltado de Sintaxis
Simplemente abre cualquier archivo con extensión .painless y el modo de lenguaje se establecerá automáticamente a Painless.
Ejecutar Simulación Painless
- Haz clic derecho en un archivo
.painless
- Selecciona "Run Painless Simulation"
- La extensión ejecutará tu script contra Elasticsearch
- Los resultados se guardan en
.painless/request.json y .painless/response.json
- El archivo
response.json se abrirá automáticamente mostrando los resultados de la ejecución

Requisitos: Debes crear un directorio .painless/ con archivos de configuración (ver Configuración más abajo).
Archivos de Salida
Cada vez que ejecutas una simulación, se crean/actualizan dos archivos en el directorio .painless/:
Ejemplo response.json (éxito):
{
"timestamp": "2025-12-28T19:30:45.456Z",
"painlessFile": "c:\\path\\to\\script.painless",
"http": {
"statusCode": 200,
"statusText": "OK"
},
"success": true,
"data": {
"docs": [...]
}
}
Ejemplo response.json (error):
{
"timestamp": "2025-12-28T19:30:45.456Z",
"painlessFile": "c:\\path\\to\\script.painless",
"http": {
"statusCode": 400,
"statusText": "Bad Request"
},
"success": false,
"error": {
"message": "Elasticsearch returned error",
"body": {
"error": {
"type": "...",
"reason": "..."
}
}
}
}
Configuración para Simulación
Para ejecutar simulaciones Painless, crea un directorio .painless/ en la misma ubicación que tu archivo de script .painless.
Estructura de Directorios
mi-proyecto/
├── transform.painless # Tu script Painless
└── .painless/ # Directorio de configuración
├── .env # Credenciales de Elasticsearch (requerido)
├── params.json # Parámetros del script (opcional)
├── docs.json # Documentos de prueba (requerido)
├── request.json # Detalles de última petición (auto-generado)
└── response.json # Última respuesta (auto-generado)
Archivos Requeridos
.painless/.env
Contiene los detalles de conexión a Elasticsearch:
ELASTIC_URL=http://localhost:9200
ELASTIC_API_KEY=api_key_codificado_en_base64
.painless/params.json (opcional)
Parámetros que estarán disponibles en tu script Painless via params:
{
"delimiter": "-",
"position": 1
}
.painless/docs.json
Array de documentos de prueba para procesar con tu script:
[
{
"_source": {
"env": "es01-prod"
}
}
]
Ejemplo
Si tienes un script en ~/proyectos/mi-script/transform.painless, crea:
~/proyectos/mi-script/.painless/.env
~/proyectos/mi-script/.painless/params.json
~/proyectos/mi-script/.painless/docs.json
Luego haz clic derecho en transform.painless y selecciona "Run Painless Simulation".
Ejemplo Completo de Uso
Veamos un ejemplo completo de cómo usar esta extensión:
Paso 1: Crear la Estructura del Proyecto
mkdir mi-proyecto-painless
cd mi-proyecto-painless
mkdir .painless
Paso 2: Crear Archivos de Configuración
Archivo: .painless/.env
ELASTIC_URL=http://localhost:9200
ELASTIC_API_KEY=tu_api_key_en_base64_aqui
Archivo: .painless/docs.json (documentos de prueba a procesar)
[
{
"_source": {
"message": "Server es01-prod is running",
"timestamp": "2025-12-28T10:30:00Z"
}
},
{
"_source": {
"message": "Database es02-staging connection failed",
"timestamp": "2025-12-28T10:31:00Z"
}
}
]
Archivo: .painless/params.json (opcional - parámetros para tu script)
{
"delimiter": "-",
"position": 0
}
Paso 3: Crear tu Script Painless
Archivo: transform.painless (en el mismo directorio que .painless/)
// Extraer ambiente del nombre del servidor
// Ejemplo: "es01-prod" -> environment = "prod"
def message = ctx.message;
def parts = message.splitOnToken(params.delimiter);
if (parts.length > params.position) {
def serverPart = parts[params.position];
def envParts = serverPart.splitOnToken('-');
if (envParts.length > 1) {
ctx.environment = envParts[1];
}
}
La estructura de tu proyecto debería verse así:
mi-proyecto-painless/
├── transform.painless
└── .painless/
├── .env
├── params.json
└── docs.json
Paso 4: Ejecutar el Script
- Abre
transform.painless en VS Code
- Haz clic derecho en cualquier parte del archivo (o en el archivo en la barra lateral del Explorador)
- Selecciona "Run Painless Simulation"
- La extensión:
- Ejecutará tu script contra Elasticsearch
- Guardará detalles de la petición en
.painless/request.json
- Guardará la respuesta en
.painless/response.json
- Abrirá automáticamente
response.json mostrando los resultados
Paso 5: Revisar los Resultados
.painless/response.json contendrá:
{
"timestamp": "2025-12-28T22:45:12.345Z",
"painlessFile": "C:\\Users\\tu\\mi-proyecto-painless\\transform.painless",
"http": {
"statusCode": 200,
"statusText": "OK"
},
"success": true,
"data": {
"docs": [
{
"doc": {
"_source": {
"message": "Server es01-prod is running",
"timestamp": "2025-12-28T10:30:00Z",
"environment": "prod"
}
}
},
{
"doc": {
"_source": {
"message": "Database es02-staging connection failed",
"timestamp": "2025-12-28T10:31:00Z",
"environment": "staging"
}
}
}
]
}
}
¡Nota cómo el script agregó el campo environment a cada documento!
Si hay un Error de Sintaxis
Si tu script Painless tiene un error de sintaxis, response.json mostrará:
{
"timestamp": "2025-12-28T22:50:00.123Z",
"painlessFile": "C:\\Users\\tu\\mi-proyecto-painless\\transform.painless",
"http": {
"statusCode": 400,
"statusText": "Bad Request"
},
"success": false,
"error": {
"message": "Elasticsearch returned error",
"body": {
"error": {
"type": "script_exception",
"reason": "compile error",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "invalid syntax on line 5..."
}
}
}
}
}
Qué Hace (y Qué NO Hace) Esta Extensión
✅ Lo que SÍ hace
- Resaltado de sintaxis - Colorea tu código Painless (palabras clave, funciones, tipos, comentarios)
- Ejecutar contra Elasticsearch - Corre tu script usando la API
_ingest/pipeline/_simulate
- Capturar logs - Guarda detalles de request/response para debugging
- Visualizar resultados - Abre la respuesta formateada automáticamente
❌ Lo que NO hace
- Validación de sintaxis antes de ejecutar - No verificará la sintaxis hasta que lo ejecutes
- Prevención de errores - Los errores solo aparecen después de que Elasticsearch procese el script
- Autocompletado - Sin IntelliSense ni sugerencias de código
- Ir a definición - No puede navegar a definiciones de funciones/variables
- Verificación de tipos - Sin análisis estático de tipos
Importante: Esta es una herramienta de visualización y ejecución, NO un analizador de código. Te ayuda a:
- Escribir scripts con resaltado de sintaxis (más fácil de leer)
- Ejecutarlos contra Elasticsearch
- Ver resultados o errores
Los errores de sintaxis son detectados por Elasticsearch durante la ejecución, no antes.
Registro de Cambios
0.1.1
- Mejoras en README: Agregadas capturas de pantalla mostrando resaltado de sintaxis y flujo de ejecución
- Mejor Documentación: Ejemplos completos de uso en inglés y español con instrucciones paso a paso
- Paquete Optimizado: Tamaño de extensión reducido de 13MB a 2.14MB (reducción del 84%)
- Listo para Marketplace: Agregadas keywords, licencia y metadata para publicación en VS Code Marketplace
0.1.0
- Logging de Request/Response: Todas las ejecuciones ahora guardan detalles completos de request y response en
.painless/request.json y .painless/response.json
- Manejo Mejorado de Errores: Los errores ahora incluyen códigos de estado HTTP y respuestas completas de error de Elasticsearch
- Seguridad de API Key: Las API keys se sanitizan en los logs de request (mostrando solo los últimos 4 caracteres)
- Apertura Automática de Archivos:
response.json se abre automáticamente después de cada ejecución
- Mejor Debugging: Audit trail completo de todas las peticiones con timestamps y metadata
0.0.7
- Se agregó opción en el menú contextual del explorador de archivos para "Run Painless Simulation"
- Ahora puedes hacer clic derecho en archivos
.painless directamente desde la barra lateral del explorador
0.0.5
- Se agregó funcionalidad de simulación Painless (ejecutar scripts contra Elasticsearch)
- Se agregó comando de menú contextual "Run Painless Simulation"
0.0.2
- Se agregó ícono de archivo para archivos .painless
- Se mejoró el resaltado de sintaxis
Licencia
MIT