Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pixlcore/xyops/llms.txt

Use this file to discover all available pages before exploring further.

Plugins let you extend xyOps functionality by writing code in any language. xyOps ships with several built-in plugins for common tasks, and you can write your own or discover community plugins in the Marketplace.

Plugin types

xyOps supports two main plugin types:

Event plugins

Execute job logic on target servers—the primary plugin type

Monitor plugins

Collect custom metrics for monitoring and alerting

Event plugins

Event plugins are the main type of plugin in xyOps. They execute the code that runs your jobs. When events launch a job (standalone or as part of a workflow), they invoke an event plugin on the target server.

Built-in event plugins

xyOps ships with these event plugins:
PluginDescription
Shell PluginExecute arbitrary shell scripts without learning the plugin API
HTTP Request PluginSend HTTP requests with custom headers, body, and methods
Test PluginOutput sample data and files for testing workflows
Docker PluginRun scripts inside Docker containers

Plugin communication

Event plugins communicate with xyOps using JSON over STDIN/STDOUT. This is called the xyOps Wire Protocol.
  • Input: JSON document on STDIN with job details, parameters, and input files
  • Output: JSON lines on STDOUT to report progress, status, and completion
The wire protocol is language-agnostic—write plugins in Node.js, Python, Go, Rust, or any language that can read/write JSON.

Job input

When your plugin is invoked, it receives a JSON document on STDIN with these properties:
xy
number
required
Wire protocol version (always 1)
type
string
required
Plugin type (event or monitor)
params
object
Plugin parameter values configured in the event
input
object
Input data and files from previous workflow nodes
cwd
string
Current working directory (unique temp directory for this job)
event
string
Event ID that launched this job
id
string
Unique job ID
Example input from ~/workspace/source/docs/plugins.md:44-92:
{
  "xy": 1,
  "type": "event",
  "targets": ["main"],
  "params": {
    "animal": "frog",
    "color": "green"
  },
  "input": {
    "data": { "foo": "bar" },
    "files": []
  },
  "event": "emi11ejdlde",
  "id": "jmi11fqevei",
  "state": "active",
  "started": 1763256572.033,
  "cwd": "/opt/xyops/satellite/temp/jobs/jmi11fqevei",
  "log_file": "/opt/xyops/satellite/logs/jobs/job-jmi11fqevei.log"
}

Input files

Input files are automatically downloaded to your job’s temp directory. Access them through:
  1. File listing: Check input.files array for metadata
  2. Direct access: Files are written to the current working directory
"input": {
  "data": {},
  "files": [
    {
      "id": "fmktcdzp1skybhk9",
      "date": 1769321584,
      "filename": "mario.mp3",
      "size": 309425,
      "username": "admin"
    }
  ]
}

Job output

Your plugin writes JSON to STDOUT to report status. All JSON must be compacted to a single line ending with \n.

Success completion

{ "xy": 1, "code": 0 }

Error completion

{ "xy": 1, "code": 1, "description": "Failed to connect to database" }
Once you send a JSON line with a code property, xyOps considers the job complete. Make this your last JSON output.

Progress updates

Report progress while your job runs:
{ "xy": 1, "progress": 0.5 }
Progress is a float between 0.0 (0%) and 1.0 (100%).

Status messages

Set a status string displayed during job execution:
{ "xy": 1, "status": "Processing file 34 of 68..." }
Combine progress and status:
{ "xy": 1, "progress": 0.5, "status": "Processing client report..." }

Performance metrics

Report how your plugin spent time during execution:
{ "xy": 1, "perf": { "db": 18.51, "http": 3.22, "gzip": 0.84 } }
Metrics are in seconds by default. For milliseconds, include scale:
{ "xy": 1, "perf": { "scale": 1000, "db": 1851, "http": 3220 } }

Output data and files

Pass structured data to downstream workflow nodes:
{ "xy": 1, "data": { "result": "success", "count": 42 } }
Pass file paths to downstream nodes:
{ "xy": 1, "files": ["output.json", "report.pdf"] }
File paths are relative to the job’s temp directory. xyOps uploads them automatically.

Plugin parameters

Define user-configurable parameters in your plugin definition:
"params": [
  {
    "id": "api_key",
    "title": "API Key",
    "type": "text",
    "required": true
  },
  {
    "id": "endpoint",
    "title": "Endpoint URL",
    "type": "text",
    "value": "https://api.example.com"
  },
  {
    "id": "script",
    "title": "Script Code",
    "type": "code",
    "syntax": "python"
  }
]
Parameter types include:
  • text - Single-line text input
  • textarea - Multi-line text input
  • code - Code editor with syntax highlighting
  • select - Dropdown menu
  • checkbox - Boolean toggle
  • hidden - Hidden field for internal values
Parameters are passed to your plugin in the params object and as environment variables.

Monitor plugins

Monitor plugins collect custom metrics on a schedule. They run on target servers and report numeric values back to xyOps for graphing and alerting.

Monitor plugin input

{
  "xy": 1,
  "type": "monitor",
  "params": {
    "database": "mydb",
    "query": "SELECT COUNT(*) FROM users"
  }
}

Monitor plugin output

Return a numeric value:
{ "xy": 1, "value": 42.5 }
For errors:
{ "xy": 1, "error": "Failed to connect to database" }

Plugin examples

The simplest plugin type. Just write shell code:
#!/bin/bash
echo "Starting backup..."
tar -czf backup.tar.gz /data
echo '{"xy":1,"code":0,"files":["backup.tar.gz"]}'
No wire protocol needed for basic shell scripts.
#!/usr/bin/env python3
import sys
import json
import time

# Read input
input_data = json.loads(sys.stdin.read())
total = input_data['params']['count']

# Process with progress
for i in range(total):
    progress = (i + 1) / total
    sys.stdout.write(json.dumps({"xy": 1, "progress": progress}) + "\n")
    sys.stdout.flush()
    time.sleep(0.1)

# Complete
sys.stdout.write(json.dumps({"xy": 1, "code": 0}) + "\n")
#!/usr/bin/env node
const fs = require('fs');
const readline = require('readline');

// Read input from STDIN
let input = '';
const rl = readline.createInterface({
  input: process.stdin,
  terminal: false
});

rl.on('line', (line) => { input += line; });
rl.on('close', () => {
  const data = JSON.parse(input);
  
  // Process input files
  const files = data.input.files;
  console.log(JSON.stringify({ xy: 1, status: `Processing ${files.length} files` }));
  
  // Create output file
  fs.writeFileSync('result.json', JSON.stringify({ result: 'done' }));
  
  // Report completion
  console.log(JSON.stringify({ xy: 1, code: 0, files: ['result.json'] }));
});

Creating custom plugins

1

Choose your language

Pick any language that can read STDIN and write to STDOUT. Popular choices: Node.js, Python, Go, Rust, Bash.
2

Implement the wire protocol

Read JSON from STDIN on startup. Write JSON lines to STDOUT for updates and completion.
Test your plugin locally by piping JSON to it: echo '{"xy":1,"type":"event"}' | ./your-plugin.sh
3

Define plugin metadata

Create your plugin definition in xyOps with:
  • Title and description
  • Command to execute (shell command, Docker run, npx, etc.)
  • Parameters users can configure
  • Icon from Material Design Icons
4

Test with a job

Create a test event using your plugin. Run it manually and check the job log for proper JSON output.

Publishing to the marketplace

Once your plugin is working, share it with the community:
  1. Host your code on GitHub with an OSI-approved license
  2. Add plugin metadata to your repository
  3. Submit to the Marketplace
See Marketplace for full publishing requirements.

Best practices

Flush output

Disable output buffering so progress updates appear immediately. Most languages buffer by default.

Handle errors gracefully

Always report errors with clear descriptions. Include troubleshooting hints in error messages.

Validate input

Check that required parameters are present. Fail fast with helpful error messages.

Use temp directory

Write all output files to the current working directory. xyOps cleans up automatically.

Test edge cases

Test with missing files, invalid parameters, and network failures. Your plugin should never hang.

Document parameters

Use clear parameter titles and include examples in your plugin notes.

See also