Skip to main content

Plugins

Honey supports plugins that extend CUE recipes with custom steps, secret backends, and log transforms, in two runtimes:

  • wasm (default) — runs locally on the operator's machine inside an Extism sandbox with explicit permission grants.
  • docker — runs a real binary (mongosh, aws, gcloud, duckdb, ffmpeg, …) inside a container, for tools that can't reasonably be reimplemented or wrapped in WASM.

See Plugin development for the full schema of both.

Enable plugins​

Add a plugins block to your honey.yaml:

plugins:
enabled: true
directory: "" # default: ~/.config/honey/plugins
allowlist: [] # optional plugin ids; empty = all discovered
max_memory_mb: 32
timeout_ms: 30000
network_deny: false
network_allow_hosts: []

Plugins are disabled by default — set enabled: true to activate them.

Install a plugin​

honey plugins install downloads or copies a plugin into your plugins directory and validates its manifest.

# From a GitHub release URL
honey plugins install https://github.com/shareed2k/honey/releases/download/v1.2.3/honey-plugin-bash-wasip1-wasm.tar.gz

# From a local directory (must contain plugin.yaml + plugin.wasm)
honey plugins install ./my-plugin/

# From a local archive
honey plugins install ./my-plugin.tar.gz

# Force reinstall (overwrite existing)
honey plugins install --force ./my-plugin/

# Override the install directory
honey plugins install --dir /custom/plugins ./my-plugin/

The plugin is installed to <plugins-dir>/<plugin-id>/. The plugin id comes from the id field in plugin.yaml.

Built-in plugins​

Honey ships pre-built releases for the following plugins. Install any of them from a release URL with honey plugins install.

PluginCapabilityDescription
bashcustom_stepRun bash scripts on remote hosts
shellcustom_stepRun POSIX shell commands on remote hosts
copycustom_stepCopy files between locations
templatecustom_step, cue_transformRender Go templates and push results to hosts
filecustom_stepRead and write files on remote hosts
servicecustom_stepManage systemd services on remote hosts
postgrescustom_stepRun SQL against Postgres instances
sqlitecustom_stepRun embedded SQLite queries inside WASM against mounted DB files
rclonecustom_stepTransfer files via rclone
cve-scannercustom_stepScan hosts for CVEs (grype/trivy) and apply security patches — see Vulnerability & patch management
jscustom_stepRun sandboxed JavaScript (goja) with a capability-gated host API (host.remote_exec, kv, log)

Example Docker-runtime plugins​

No build step — just plugin.yaml (runtime: docker) + plugin.cue (actions/argv). See examples/plugins/:

PluginImageActions
mongodbmongo:latestquery, eval
duckdbduckdb/duckdb:latestquery, export_parquet
awsamazon/aws-cli:latests3_ls, s3_cp, s3_rm, ec2_describe, ec2_start, ec2_stop
gcloudgcr.io/google.com/cloudsdktool/cloud-sdk:slimcompute_list, compute_start, compute_stop, storage_ls, storage_cp, storage_rm
k6grafana/k6:latestversion, run, run_json

gcloud's image is amd64-only — fails with exec format error on Apple Silicon hosts unless your Docker daemon has qemu emulation registered. The other three are multi-arch.

k6 load testing​

k6 reads its JS test script from stdin (no bind-mount): pass it as config.script, tune the run with vus / duration / env (each env entry becomes a --env K=V flag visible to the script as __ENV.K). run returns k6's human text summary; run_json appends a handleSummary() hook so stdout is a single JSON document a later step can parse with env_from.extract — e.g. .metrics.http_req_duration.values."p(95)" for p95 latency or .metrics.http_req_failed.values.rate for the failure rate. See examples/recipe/k6_loadtest.cue.

Two caveats: don't define handleSummary in your own script for run_json (duplicate export → k6 error), and avoid k6 thresholds if a downstream step needs the summary — a threshold breach makes k6 exit non-zero, and Honey only propagates a step's stdout to env_from when the step succeeded. Judge pass/fail in the reporting step from the extracted metrics instead.

List installed plugins​

honey plugins list
honey plugins list --config ~/.config/honey/config.yaml

When plugins.enabled is false, the command shows a reminder to enable plugins. When enabled, it lists each plugin's id, version, capabilities, and disk path as JSON.

Manual installation​

If honey plugins install is not available or you prefer manual control:

mkdir -p ~/.config/honey/plugins/myplugin
cp plugin.yaml ~/.config/honey/plugins/myplugin/
cp plugin.wasm ~/.config/honey/plugins/myplugin/

The directory name does not need to match the plugin id — Honey reads plugin.yaml to discover the id. A runtime: wasm (default) plugin directory must contain plugin.yaml and plugin.wasm; a runtime: docker plugin directory must contain plugin.yaml and plugin.cue instead (no wasm module).

Using plugins in recipes​

Enable in config, then reference a plugin by id in a CUE recipe plugin: step:

recipe: {
steps: [
{
host: "web-*"
plugin: {
id: "bash"
action: "run"
config: {script: "systemctl restart nginx"}
}
}
]
}

See Plugin development for the full step schema and how to write your own plugin.

Security​

  • Plugins run locally on the operator machine, not on remote hosts (unless the plugin itself makes outbound calls via allow_remote_exec or allow_host_exec).

  • Review plugin.yaml permissions before installing — check allow_host_exec, allow_remote_exec, allowed_hosts, and allowed_paths.

  • Use plugins.allowlist in your config to restrict which plugin ids may load:

    plugins:
    enabled: true
    allowlist: [bash, template]