CUE Recipes
Honey can run multi-step playbooks defined in CUE. Each step targets hosts from your current search and performs exactly one action: command, put, get, script, agent_transfer, ai, plugin (WASM — see Plugin development), tunnel (operator-side port forward), or k8s (Kubernetes API — see Kubernetes steps).
Use honey cue-validate to check a file, honey cue-exec to dry-run or execute (same host resolution as honey search). From the search TUI, press r (append ! to the path to execute). The Web UI Recipes tab runs the same engine.
Example recipes: examples/recipe/ on GitHub (see that folder’s README for a full file index).
Quick start
# Validate schema
honey cue-validate examples/recipe/graph_when.cue
# Dry-run plan (default)
honey cue-exec examples/recipe/graph_when.cue my-filter
# Execute over SSH
honey cue-exec --execute examples/recipe/graph_when.cue
CLI details: honey cue-exec, honey cue-validate.
Host matching
Each step has a host field resolved against search results:
host value | Meaning |
|---|---|
| Exact name | Case-insensitive match on Name |
| Literal IP | Match PrimaryIP |
"*" | Every row with a PrimaryIP |
"re:PATTERN" | Go regexp (RE2) on Name (rows with IP only) |
"_" | Local only — required for ai steps |
For agent_transfer, host is the source; agent_transfer.dest_host selects the destination (each must match exactly one row).
Step kinds
| Kind | Remote? | Notes |
|---|---|---|
command | SSH / k8s exec | Optional env, secrets, hooks, kv_tunnel |
script | SSH / k8s exec | Upload local → remote, then sh <remote> |
plugin | SSH / k8s exec | WASM custom step — Plugin development |
tunnel | SSH / k8s / TrueNAS | Operator-side listen (local/remote/dynamic/UDP/tun) — Tunnel steps |
k8s | Kubernetes API | Direct API calls: apply, delete, scale, rollout, get, exec, job — Kubernetes steps |
put / get | SFTP or k8s tar stream | Relative local paths from recipe directory |
agent_transfer | A→cloud→B | Needs honey config for cloud_backend_ref |
ai | Local (operator) | host: "_"; needs OPENAI_API_KEY when executing |
Optional recipe.defaults: run_as, env, secrets, kv_tunnel, max_parallel, ssh_port, ssh_private_key, k8s_debug_image.
SSH customization
ssh_port and ssh_private_key can be set at recipe.defaults (all steps) or on a single step (overrides defaults). ~/ is expanded in ssh_private_key.
recipe: {
name: "with-key"
defaults: {
ssh_private_key: "~/.ssh/my_staging_key"
}
steps: [{
host: "*"
command: "hostname"
}, {
host: "*"
ssh_private_key: "~/.ssh/other_key" // this step uses a different key
command: "whoami"
}]
}
Example: with_ssh_key.cue.
Remote env injection (command/script/plugin): HONEY_HOST_NAME, HONEY_HOST_PRIMARY_IP, HONEY_HOST_PROVIDER, HONEY_HOST_ZONE, HONEY_HOST_REGION, and HONEY_HOST_META_* from host metadata.
Linear vs graph execution
Default (linear): steps run in array order, one after another.
Graph mode: set recipe.type: "graph". Steps need unique id values and optional depends: [id, ...] forming a DAG. Honey runs waves — all steps in a wave may run concurrently (default up to 8 steps per wave; host-level concurrency is capped by max_parallel, default 32).
recipe: {
name: "parallel-restart"
type: "graph"
steps: [
{ id: "fetch", host: "*", command: "echo fetch" },
{ id: "restart_a", host: "*", depends: ["fetch"], command: "echo a" },
{ id: "restart_b", host: "*", depends: ["fetch"], command: "echo b" },
{ id: "verify", host: "*", depends: ["restart_a", "restart_b"], command: "echo ok" },
]
}
Graph extras
env_from maps a dependency step’s output into env vars on the current step (per host). Each entry must reference a step in depends. Supported on command, script, and plugin only.
Each env_from entry uses one of these source fields:
| Field | Source | Description |
|---|---|---|
map: {KEY: "stdout"} | Step stdout | Map raw stdout to KEY |
extract: {KEY: ".field"} | Step stdout (JSON) | JQ path extracted from JSON stdout |
kv: {KEY: "kv_key_name"} | Recipe KV store | Pull value written by a prior remote step |
from_output: "NAME" | Template output | Named capture from a template step on host: "_" |
// Three env_from sources in one step
{
id: "pg_followup"
host: "db-*"
depends: ["pg_query"]
env_from: [{
step: "pg_query"
map: { RAW_OUT: "stdout" } // raw stdout
extract: { COUNT: ".[0].n" } // jq on JSON stdout
}, {
kv: { THRESHOLD: "pg_activity_count" } // value written by a remote step
}]
command: "echo count=$COUNT threshold=$THRESHOLD"
}
Example: postgres_kv_demo.cue.
HONEY_STEP_ID: set on remote env when the step has anid(use to namespace shared KV keys).kv_tunnel: one operator-sidestepkvsession for the whole run; see KV tunnel below.- Failure / skip: if a step fails (or all hosts hit transient SSH errors), descendants are skipped. If an
aistep becomes unreachable, the run aborts. - Web UI: Recipes wizard → Graph tab shows the DAG (
POST /api/v1/recipes/validate-content→graphfield).
Example: graph_parallel.cue.