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]