honey

module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2026 License: MIT

README

honey

CLI to search GCP Compute Engine, AWS EC2, Kubernetes (nodes or pods), Docker Engine (containers and Swarm tasks), Consul catalog nodes, and Proxmox VE instances in parallel, optionally cache results, then use a terminal UI to SSH, docker exec into containers, or open an SSH local forward (-L) via the system ssh binary.

Prerequisites

  • Go 1.26.2+ (see go directive in go.mod; use this toolchain or newer so govulncheck reports clean stdlib fixes from Go 1.26.1/1.26.2)
  • Credentials for each backend you enable (see below)

After cloning, generate checksums:

cd honey
go mod tidy

Install

Homebrew (macOS): Because this tool relies on Homebrew Casks, it is installed via the --cask flag:

brew install --cask shareed2k/tap/honey

Build

go build -o honey ./cmd/honey

MCP server (stdio)

honey mcp runs a Model Context Protocol server over stdin/stdout using the official go-sdk. Do not log to stdout (only stderr); stdout is reserved for the JSON-RPC stream.

Tools

Tool Purpose
search_hosts Same parallel search as honey search; arguments mirror flags (snake_case JSON). Optional config_path; otherwise uses HONEY_CONFIG / default paths.
list_backends Returns configured backends from YAML (kind, name, hint). Requires a resolvable config file.

Cursor (example mcp.json fragment):

{
  "mcpServers": {
    "honey": {
      "command": "/absolute/path/to/honey",
      "args": ["mcp"],
      "env": {
        "HONEY_CONFIG": "/absolute/path/to/honey.yaml"
      }
    }
  }
}

LM Studio (MCP docs; app 0.3.17+)

LM Studio uses the same mcpServers shape as Cursor. In the app: open the Program tab (right sidebar) → InstallEdit mcp.json, then merge a honey entry into the top-level mcpServers object (or create the file if it is empty).

Typical file locations:

  • macOS / Linux: ~/.lmstudio/mcp.json
  • Windows: %USERPROFILE%\.lmstudio\mcp.json

Example (replace paths with your real honey binary and YAML config):

{
  "mcpServers": {
    "honey": {
      "command": "/Users/you/bin/honey",
      "args": ["mcp"],
      "env": {
        "HONEY_CONFIG": "/Users/you/.config/honey/config.yaml"
      }
    }
  }
}

If you already have other servers under mcpServers, add only the "honey": { ... } block inside that object—do not duplicate the outer "mcpServers" key. After saving, restart the chat or reload tools if LM Studio does not pick up the server immediately. Enable or allow the honey tools under App settings → Tools & integrations (wording may vary by version) if the UI asks for permission.

OpenCode (MCP servers, config)

OpenCode uses a top-level mcp object (not mcpServers). Local stdio servers use type": "local" and command as an array of executable + args. Environment variables go under environment (not env).

Merge this into ~/.config/opencode/opencode.json (global) or a project opencode.json / opencode.jsonc—see OpenCode’s config precedence docs.

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "honey": {
      "type": "local",
      "command": ["/absolute/path/to/honey", "mcp"],
      "enabled": true,
      "environment": {
        "HONEY_CONFIG": "/absolute/path/to/honey.yaml"
      }
    }
  }
}

Tools from this server appear with the honey_ prefix (e.g. honey_search_hosts). You can mention use honey or a specific tool name in prompts; see OpenCode’s MCP docs for disabling servers or scoping tools per agent.

Config file (optional)

You can define multiple backends per provider (for example two GCP projects or two Consul clusters) and optional defaults. If the file omits backends or leaves every backend list empty, behavior matches the flag-only mode (one implicit backend per provider).

Each list entry may set name (any stable string). Use --backends with a comma-separated list of those names (case-insensitive) to run only those entries—for example only gcp-prod-us2 and k8s-stg2. Unnamed backends are skipped when --backends is set. Combine with --provider to further narrow by type (gcp, k8s, …).

Lookup order (first match wins):

  1. --config /path/to/file.yaml
  2. HONEY_CONFIG
  3. $XDG_CONFIG_HOME/honey/config.yaml
  4. ~/.config/honey/config.yaml when XDG_CONFIG_HOME is unset
  5. ~/.honey.yaml

Precedence: CLI flags override config defaults when you pass the flag (Cobra “changed” semantics). Query flags (--gcp-project, --consul-addr, etc.) override per-backend YAML values at search time.

Example ~/.config/honey/config.yaml:

version: 1
defaults:
  cache_ttl: 5m
  ssh_user: deploy
  k8s_mode: nodes
  k8s_debug_image: "nicolaka/netshoot:latest"
backends:
  gcp:
    - name: gcp-team-a
      project: team-a-prod
    - name: gcp-team-b-zone
      project: team-b-prod
      zone: us-central1-a
  aws:
    - name: aws-prod-use1
      profile: production
      region: us-east-1
  kubernetes:
    - name: k8s-staging
      context: staging
      kubeconfig: ~/.kube/config.staging
      debug_image: "ubuntu:latest"
  consul:
    - name: consul-prod
      addr: "10.0.0.5:8500"
      token: "secret"
  proxmox:
    - name: "pve-cluster"
      url: "https://10.0.0.10:8006/api2/json"
      user: "root@pam"
      password: "my-password"
      insecure: true
    - name: "pve-token"
      url: "https://10.0.0.11:8006/api2/json"
      token_id: "root@pam!mytoken"
      token_secret: "1234abcd-1234-abcd-1234-abcd1234abcd"
  truenas:
    - name: scale-lab
      url: "https://truenas.example.com"
      username: root
      api_key: "1-REPLACE_ME"
      insecure: false
      include_appliance: true
      include_vms: true
      include_virt: true
      ssh_user: root
  docker:
    - name: local
      host: ""              # default: DOCKER_HOST / local socket
      mode: containers      # containers | swarm | both
    - name: vm-docker
      via_local: lab          # backends.local[].name (or host name, or lab/vm1)
      socket: /var/run/docker.sock
      run_as: root            # optional: SSH as defaults.ssh_user, Docker API via sudo + docker system dial-stdio
      platform: linux       # linux | windows (daemon host OS)
      mode: containers
    - name: builder
      via_ssh:
        host: 10.0.0.1
        port: 2222
        user: lab
        identity_file: ~/.ssh/id_ed25519
      socket: /var/run/docker.sock
    - name: moby-ssh
      host: ssh://ops@other-host   # Moby built-in SSH (not Honey SSH)
      mode: both
Docker provider

honey search --provider docker lists containers and/or Swarm tasks via the Docker Engine API (not SSH into container networks). Interactive sessions use docker exec; the TUI/web file browser uses docker cp semantics (CopyTo/CopyFrom API) plus exec helpers for directory listing.

Connection Config / flags SSH stack Notes
Local / DOCKER_HOST host: "" or unix:// / tcp:// Default socket
Moby ssh:// host: ssh://user@host Docker SDK only No ProxyJump / ~/.ssh/config integration
Honey SSH via_local or via_ssh + socket Honey sshclient Dials remote Engine socket over SSH; reuses TUI SSH session when already connected
Auto-discover HONEY_FEATURE_DOCKER_VIA_PROVIDERS=1 + --docker-discover-providers gcp,aws Honey SSH Second search pass; not configurable in YAML
# Local Docker Desktop / Colima (default socket or DOCKER_HOST)
./honey search --provider docker

# Remote daemon over Moby ssh:// (Docker SDK SSH)
./honey search --provider docker --docker-host ssh://ops@docker-host.internal

# Honey SSH to a VM's docker.sock (CLI overrides for default backend)
./honey search --provider docker --docker-via-local ssh-target --docker-socket /var/run/docker.sock

# Windows daemon host (often needs explicit TCP socket)
./honey search --provider docker --docker-via-ssh-host winvm --docker-platform windows --docker-socket tcp://127.0.0.1:2375

# Auto-discover containers on GCP/AWS VMs (feature flag required)
export HONEY_FEATURE_DOCKER_VIA_PROVIDERS=1
./honey search --provider gcp,aws,docker --docker-discover-providers gcp,aws

# GCP/AWS: SSH as ubuntu, docker.sock only for root (passwordless sudo required)
./honey search --provider gcp,aws,docker \
  --docker-discover-providers gcp,aws \
  --ssh-user ubuntu \
  --docker-discover-run-as root

# Swarm tasks only
./honey search --provider docker --docker-mode swarm

# Include stopped containers
./honey search --provider docker --docker-all

TUI tip: Connect SSH to the VM in the table first (c); Honey reuses that session for via_local Docker backends instead of opening a second SSH connection.

Linux VMs: either add the SSH user to the docker group, or set run_as: root on honey-ssh docker backends / --docker-discover-run-as root for auto-discover (uses sudo -n + docker system dial-stdio, Engine 23+, same idea as recipe run_as).

Interactive terminal (TUI / web): On a selected docker row with meta.container_id, Enter opens a TTY shell via docker exec (sh on Linux, powershell.exe on Windows containers)—not SSH into the container network. The web UI uses the same exec attach over GET /ws/ssh (see Web UI). File browser and Run command use Engine API copy/exec.

Parallel e and * marks: Scope includes every executable row: VMs/pods with an IP, k8s pods, and docker containers with container_id (no PrimaryIP required). Ctrl+a marks all executable rows. Commands run through the same executor as Enter (docker exec for containers).

Auto-discover and --backends: Discover runs as a second pass only on VM records already returned by the first search (respecting --provider, --backends, and name filters). Example:

export HONEY_FEATURE_DOCKER_VIA_PROVIDERS=1
./honey search --backends gcp-stg2 --docker-discover-providers gcp \
  --ssh-user ubuntu --docker-discover-run-as root my-app

Discovered container metadata (JSON meta):

Key Meaning
container_id Engine container ID (required for exec / terminal)
docker_host API endpoint (honey-ssh://… or unix:// / tcp://)
docker_transport honey_ssh when dialed via VM SSH
docker_vm Source VM name from the cloud search
docker_vm_ip Internal IP used for Honey SSH dial to the daemon
docker_vm_external_ip Public IP when the VM has one
via_provider Cloud provider that owned the VM (gcp, aws, …)
docker_discover "1" when the row came from auto-discover

The table IP column may show the VM’s external address while Honey SSH still dials docker_vm_ip (internal). extra_ips can hold the internal address when both exist.

Limitations: t (SSH -L tunnels) is not supported on pure docker container rows. cue-exec / TUI r still resolve step host by name, literal IP, *, or re:—match the container name (or a VM IP for SSH-backed steps); there is no separate docker-specific host syntax beyond normal executor routing when the row matches.

Usage

# Interactive table (default); optional positional name is a substring filter
./honey search my-host

# JSON output, no TUI
./honey search --json my-host

# Explicit config path (otherwise see "Config file" below)
./honey search --config ~/.config/honey/config.yaml my-host

# Limit providers
./honey search --provider aws,k8s web

# Only specific named backends from config (see backends.*.name)
./honey search --backends gcp-team-a,k8s-staging web
./honey search --backends gcp-prod-us2 --provider gcp my-node

# List backends from config (same config resolution as search)
./honey backends
./honey backends --json

# Regex filter
./honey search --name-regex '^prod-'

# Cache (default TTL 10m; flags are global — see `honey --help` Global Flags); force refresh
./honey search --refresh foo
./honey --refresh search foo
./honey search --no-cache foo
./honey search --cache-ttl 5m foo
Ansible inventory (honey inventory)

honey inventory runs the same discovery as honey search (all search flags: --config, --provider, --backends, name filters, cache flags, per-provider auth, and so on) and prints Ansible script-style JSON: a honey group, optional honey_provider_*, honey_region_*, honey_zone_* groups, and _meta.hostvars. Each host gets ansible_host from the discovered primary IP when present, ansible_user from --ssh-user (or defaults.ssh_user in YAML), ansible_port when the row’s meta.ssh_port is a valid TCP port (1–65535; string or number in YAML/JSON), plus honey_* fields and honey_meta_<key> from each record’s meta map. meta.ssh_port is not duplicated as honey_meta_ssh_port—it is promoted to ansible_port only.

# Full inventory JSON (Ansible’s script plugin calls this with --list)
./honey inventory --list --config ~/.config/honey/config.yaml

# Narrow providers or backends like search
./honey inventory --list --provider gcp,aws --backends gcp-team-a

# Optional name substring (same as search positional)
./honey inventory --list web

# Vars for one inventory hostname (script --host); unknown host returns {}
./honey inventory --host web-1

Local Ansible: Ansible’s script inventory expects an executable file on disk. The -i argument must be that file’s path—Ansible does not parse a command line. This fails because the whole string is treated as one path:

# Wrong: no file literally named "/tmp/honey inventory --provider gcp --"
ansible-playbook -i '/tmp/honey inventory --provider gcp --' play.yml

Use a tiny wrapper that execs honey and forwards "$@" (Ansible passes --list or --host <name>), then pass only the wrapper path to -i:

printf '%s\n' '#!/bin/sh' 'exec /path/to/honey inventory "$@"' > honey-ansible-inv && chmod +x honey-ansible-inv
ansible-playbook -i ./honey-ansible-inv site.yml

GCP-only example (wrapper bakes in --provider gcp; Ansible still appends --list / --host after your fixed args—order matters: put "$@" last):

printf '%s\n' '#!/bin/sh' 'exec /tmp/honey inventory --provider gcp "$@"' > /tmp/honey-inv-gcp && chmod +x /tmp/honey-inv-gcp
ansible-playbook -i /tmp/honey-inv-gcp ansible/playbooks/restart_es_playbook.yml

Copy from examples/ansible/honey_inventory_gcp.example.sh and adjust the honey path.

Add other fixed flags inside the wrapper if you want (for example exec /path/to/honey inventory --config "$HOME/.config/honey/config.yaml" --provider gcp "$@").

Without a shell wrapper (inventory plugin): use the YAML-driven inventory plugin shipped in this repo (contrib/ansible/inventory_plugins/honey.py). Install it on Ansible’s inventory plugin path, then pass -i a small YAML file that sets plugin: honey and options such as honey_binary, provider, and config. Example config: contrib/ansible/honey.gcp.example.yml. Quick run from a clone:

export ANSIBLE_INVENTORY_PLUGINS="$PWD/contrib/ansible/inventory_plugins"
ansible-playbook -i contrib/ansible/honey.gcp.example.yml ansible/playbooks/restart_es_playbook.yml -e cluster_name=ddd

Adjust ANSIBLE_INVENTORY_PLUGINS to your checkout path, and edit the YAML (or a copy) so provider / config match your environment. More detail: examples/ansible/README.md.

CI / AWX / Ansible Tower: install the honey binary on the execution environment and supply credentials the same way you would for honey search (for example HONEY_CONFIG pointing at a mounted secret, GOOGLE_APPLICATION_CREDENTIALS, AWS_PROFILE / instance role, KUBECONFIG, CONSUL_HTTP_TOKEN, or Proxmox flags baked into the wrapper or injected via environment). Use either the inventory plugin YAML (set ANSIBLE_INVENTORY_PLUGINS or install honey.py into the execution image’s plugin path) or a custom inventory script wrapper that runs honey inventory with --list / --host. Honey does not replace Tower or AWX; it only feeds inventory JSON from live APIs.

CUE recipes (experimental)

Validate a playbook-shaped CUE file: each step has host and exactly one of command, put (SFTP upload), get (SFTP download), script (upload localremote, then run sh <remote> on the same SSH connection), agent_transfer (source host → cloud object → agent_transfer.dest_host; same A→cloud→B flow as the web UI; optional cloud_backend_ref needs --config / HONEY_CONFIG like the files API), or ai (terminal local summarizer after prior steps; host must be "_"; OPENAI_API_KEY when executing; optional step-level notify { ... } with HONEY_NOTIFY_* env for HTTP, Slack webhook, or Telegram — see honey cue-exec docs). Optional run_as applies to command and script runs (not to SFTP-only put/get, agent_transfer, or ai). Optional recipe.defaults.env and per-step env are export’d on the remote before the command or script (step overrides duplicate keys from defaults); env is not supported on put/get/agent_transfer/ai. Optional recipe.defaults.ssh_port and per-step ssh_port (1–65535) override the numeric TCP port for SSH-backed steps; precedence is step ssh_portdefaults.ssh_port → host row meta.ssh_port~/.ssh/config Port → 22 (invalid or missing values fall through). For agent_transfer, prefer meta.ssh_port on the source and destination rows; recipe-level ssh_port applies to normal single-host steps. Example recipes live under examples/recipe/ — see that folder’s README.md for a table of files (including file_transfer.cue, script_step.cue, with_env.cue, agent_transfer.cue, high_load_processes.cue, postgres_replica_lag.cue, postgres_replica_lag_plugin.cue, postgres_logical_replication_slots.cue, ai_summarize_hosts.cue).

./honey cue-validate examples/recipe/recipe.cue

The document must include a top-level recipe field. Implementation: cuelang.org/go v0.12 (internal/cuetry).

From the search TUI, r runs a recipe against marked * rows (with IP) or all with IP if nothing is marked — same scope as parallel e (dry-run unless the path ends with !). cue-exec on the CLI runs the same search as honey search (all search flags apply), resolves each step’s host using the result set: exact name match (case-insensitive), a literal IP, host: "*" to run on every matching row with a PrimaryIP, or host: "re:PATTERN" for a Go regexp (RE2) matched against each row’s Name (again only rows with an IP). Each step runs in parallel across targets: shell via SSH; SFTP for put / get; script uploads then runs in one session per host; agent_transfer runs once per step (source and dest_host must each match exactly one row). Relative local paths are resolved from the recipe file’s directory. For get with multiple targets, local must be a directory (trailing / or an existing folder); files are written as <dir>/<sanitized_host>_<basename(remote)>. It prints a dry-run plan by default and only runs when you pass --execute. Use (?i) inside regex patterns for case-insensitive matching. Optional recipe.defaults.run_as or per-step run_as applies to command and script runs (sudo -n -u <user> -- sh -lc '...'). Optional defaults.env / step env apply to those same runs.

# Plan only (safe default)
./honey cue-exec examples/recipe/recipe.cue my-name-filter

# Same as search: backends, --name, --ssh-user, etc.
./honey cue-exec --backends gcp-prod-us2 examples/recipe/recipe.cue

# Actually run each step over SSH
./honey cue-exec --execute examples/recipe/recipe.cue

# Extra remote env for command/script steps (repeat -e or --env; overrides recipe keys)
./honey cue-exec -e FOO=bar --env BAZ=qux examples/recipe/with_env.cue my-filter
TUI keys
  • Enter: interactive shell on the selected row—ssh <user>@<ip> for VMs (user from --ssh-user, default $USER), k8s pod exec for pods, docker exec TTY for docker container/swarm rows with container_id. Uses the system ssh binary where applicable (~/.ssh/config honored).
  • t: enter -L spec (e.g. 8080:localhost:8080), then Enter to run ssh -L ... user@ip on the selected host (not supported for pure docker container rows)
  • x: toggle a * mark on the current table row (for parallel e / recipes). The first column shows * for marked rows.
  • Ctrl+a: mark all executable rows (IP, k8s pod, or docker container with container_id; replaces the previous mark set).
  • c: clear all * marks.
  • e: run the same remote shell command in parallel: only on marked executable rows; if nothing is marked, on every executable row in the table. SSH targets use goph (golang.org/x/crypto/ssh) with known_hosts checking; docker rows use docker exec. Auth from ssh-agent (SSH_AUTH_SOCK), IdentityFile entries from ~/.ssh/config for the host/IP honey dials, optional comma-separated HONEY_SSH_IDENTITY_FILES (extra private key paths), then default keys under ~/.ssh: id_ed25519, id_rsa, id_ecdsa, google_compute_engine (GCE), id_dsa if present. Match in ~/.ssh/config is honored when ssh is on PATH (honey uses ssh -G); set HONEY_SSH_OPENSSH_G=0 to use the built-in parser only (Match ignored—duplicate IdentityFile under a plain Host if needed). Non-interactive; one host failing does not stop the others. The command prompt shows the current scope; results include a short scope line. Esc from the prompt returns to the table; Esc from results returns to the table; q / Ctrl+C quits without opening a single-host session.
  • r: run a CUE recipe (same as honey cue-exec) against a chosen subset of the table: only *‑marked executable rows if you marked any rows; otherwise every executable row (same scope as e). No second search. Append ! to the recipe path to execute for real; without ! it is a dry-run plan. Uses the same --ssh-user as the table.
  • q / Ctrl+C: quit without SSH (from the table or from the parallel-results view)

Parallel SSH (e), CUE recipes, and cue-exec share the same in-process host-key check (~/.ssh/known_hosts, etc.). By default, if the server host key changed (e.g. VM rebuild), honey rewrites writable known_hosts files (in-process, same idea as ssh-keygen -R) and appends the new key instead of failing. Set HONEY_SSH_RENEW_STALE_HOST_KEYS=0 to turn that off and require manual ssh-keygen -R <host> on mismatch.

Programmatic SSH (parallel e, web terminal, agent transfer, cue-exec) prefers resolving ~/.ssh/config with the system ssh -G when ssh is on PATH, so Match is evaluated the same way as OpenSSH. Set HONEY_SSH_OPENSSH_G=0 to use honey’s built-in parser only (no subprocess; Match is ignored—duplicate settings under a plain Host entry if needed). Resolved settings include User, HostName, Port, IdentityFile, ProxyJump, and host-key-related paths. When a host row includes meta.ssh_port (valid 1–65535), honey uses that leaf TCP port for goph-based dials, web SSH, tunnels, and inventory ansible_port, still merging the rest from ~/.ssh/config. cue-exec can also set recipe.defaults.ssh_port / per-step ssh_port (see the CUE section above for precedence vs meta.ssh_port and ~/.ssh/config). If ssh user@ip works but honey does not, add IdentityFile for that IP (or set HONEY_SSH_IDENTITY_FILES=/path/to/key with comma-separated paths), ensure ssh-agent has your key, or rely on a default filename under ~/.ssh/ (including google_compute_engine for Google Cloud).

Provider auth / flags

Per-provider setup (minimal auth, YAML, and CLI flags):

Provider Search ID Minimal auth (summary)
GCP gcp Application Default Credentials; roles/compute.viewer (or compute.instances.list)
AWS aws AWS profile / credential chain; ec2:DescribeInstances
Kubernetes k8s kubeconfig + context; get nodes (pods mode: get pods, ephemeral debug)
Consul consul HTTP API; ACL token if enabled
Proxmox proxmox API URL + password or API token; VM read (PVEVMRO)
TrueNAS truenas SCALE 25.04+ API key
Local local None (static list)
Docker docker Engine API (socket, DOCKER_HOST, or SSH hop)

If a provider is unreachable, the command fails (use --provider to narrow scope).

Kubernetes pods (--k8s-mode pods)

When searching for Kubernetes pods (--provider k8s --k8s-mode pods), honey provides advanced, transparent execution capabilities without needing any server daemons:

  1. Direct Pod Exec: Honey talks directly to the Kubernetes API to spawn an interactive shell or run commands inside the pod's primary container.
  2. Ephemeral Containers: To avoid permission issues (like read-only root filesystems), honey injects a lightweight, short-lived alpine Ephemeral Container (honey-debug-*) into the target pod. This container shares the process and filesystem namespace but has its own writable overlay.
  3. Transparent File Transfers: CUE put and get operations, as well as script step uploads, are implemented securely by dynamically streaming tar archives over the exec connection into the ephemeral container (similar to kubectl cp). No SFTP server required!
  4. Seamless Experience: Your interactive sessions, parallel commands, and CUE recipes work identically to actual SSH nodes, preserving context, streams, and file permissions, completely daemonless.

Layout

  • cmd/honey — CLI entrypoint (search, inventory, backends, mcp, …)
  • internal/cli — Cobra flags and wiring
  • internal/inventory — Ansible JSON mapping from hosts.Record
  • contrib/ansible — Ansible inventory plugin (inventory_plugins/honey.py) + example YAML
  • internal/mcpserver — MCP tool handlers
  • internal/searchrun — shared search + provider wiring
  • internal/config — optional YAML (backends, defaults)
  • internal/hostsRecord, Query, cache, parallel orchestration
  • internal/provider/* — GCP, AWS, k8s, Consul, Docker, Proxmox, local integrations
  • internal/ui — Bubble Tea table + SSH actions
  • internal/cuetry — CUE validation + decode for remote recipes (cue-validate, cue-exec)
  • website/docs/add-new-backend.md — contributor guide for adding a new backend (Docusaurus source)
  • website/docs/web-ui.md — web UI, API, session recording, file transfer, AI assist, and prebuilt transfer agent downloads (Docusaurus source)

Web UI (honey web)

Embedded loopback-only web server with a random bearer token (override with HONEY_WEB_TOKEN). Serves a React UI for backends list, search, provider/backend filters, YAML config edit, structured backends CRUD, browser terminal (SSH, Kubernetes exec TTY, and Docker exec attach), optional session recording (--record-dir), local/remote file browser and agent-based cloud transfer (honey-transfer-agent), CUE recipe run/view, and optional AI assist for the terminal and recipes when OPENAI_API_KEY is set (optional OPENAI_BASE_URL for compatible gateways or local inference).

Full documentation: published site Web UI & AI assist (built from website/docs/web-ui.md).

# One-time: build UI assets into internal/webserver/static (CI runs this automatically)
make webui

go build -o honey ./cmd/honey
./honey web --listen 127.0.0.1:8765 --config ~/.config/honey/config.yaml

# Optional Prometheus metrics on a separate loopback port (no auth)
./honey web --listen 127.0.0.1:8765 --metrics-listen 127.0.0.1:9091

Optional flags include --record-dir (session recordings; optional defaults.record_retention such as 30d for automatic purge of stale .hrec.jsonl files, and DELETE /api/v1/recordings/{file_name} from the web UI), --files-root (file browser root; defaults to $HONEY_FILES_ROOT or $HOME), --agent-bin / --agent-build-cache-dir for the transfer agent, and --metrics-listen (loopback-only Prometheus scrape endpoint at /metrics, separate from the token-protected UI). When the server cannot go build the agent (no checkout), Honey downloads prebuilt honey-transfer-agent from the same GitHub release tag as this honey binary (…/releases/download/<vTAG>/honey-transfer-agent-<goos>-<goarch>; dev builds use …/latest/download/…). Override with HONEY_TRANSFER_AGENT_DOWNLOAD_BASE or HONEY_TRANSFER_AGENT_DOWNLOAD_URL, or disable the default with HONEY_TRANSFER_AGENT_DOWNLOAD_DISABLE_DEFAULT=1 (see website/docs/web-ui.md).

Open the URL printed on stderr (includes ?token=…). The web UI API tab embeds Swagger UI against the same OpenAPI document as GET /api/v1/openapi.json (same auth as other routes); regenerate the spec with make openapi or go generate in internal/webserver after changing handler comments. Deep-link the tab with ?tab=api-docs. Notable API routes: GET /api/v1/meta (includes terminal_assist_available, session_recording_available, and metrics_url when --metrics-listen is set), POST /api/v1/search, GET/PUT /api/v1/config, structured backends under /api/v1/config/backends/… (path segment kubernetes matches YAML; search uses provider id k8s), POST /api/v1/upload, GET /api/v1/terminal-assist/models and POST /api/v1/terminal-assist (terminal AI), POST /api/v1/recipes/assist (recipe AI), recordings under /api/v1/recordings, WebSocket GET /ws/ssh?token=…. Authenticate with Authorization: Bearer <token> or X-Honey-Token.

Local UI dev (Vite proxies to the Go server): run honey web on 8765, then cd webui && npm install && npm run dev and open Vite’s URL.

Tests

go test ./...

License

This project is released under the MIT License.

Directories

Path Synopsis
cmd
honey command
Package main is the honey CLI entrypoint.
Package main is the honey CLI entrypoint.
honey-transfer-agent command
Package main implements the honey-transfer-agent: upload/download cloud objects with short-lived credentials (JWE or env), optional interactive setup, and a JSON session mode.
Package main implements the honey-transfer-agent: upload/download cloud objects with short-lived credentials (JWE or env), optional interactive setup, and a JSON session mode.
internal
aichat
Package aichat performs OpenAI-compatible chat HTTP calls for local recipe summarization.
Package aichat performs OpenAI-compatible chat HTTP calls for local recipe summarization.
cli
Package cli implements the honey Cobra commands.
Package cli implements the honey Cobra commands.
cloudtransfer
Package cloudtransfer resolves short-lived cloud credentials for staging (S3 / GCS).
Package cloudtransfer resolves short-lived cloud credentials for staging (S3 / GCS).
config
Package config loads optional YAML settings and backend definitions for honey.
Package config loads optional YAML settings and backend definitions for honey.
cuetry
Package cuetry parses, validates, and resolves CUE remote recipes for honey.
Package cuetry parses, validates, and resolves CUE remote recipes for honey.
cuetry/secrets
Package secrets resolves CUE recipe secret refs.
Package secrets resolves CUE recipe secret refs.
cuetry/secrets/cloud
Package cloud resolves cloud and enterprise secret refs (Vault, AWS), analogous to
Package cloud resolves cloud and enterprise secret refs (Vault, AWS), analogous to
cuetry/secrets/env
Package env resolves env:NAME refs from the process environment (local analogue of cloud:/aws-sm:/aws-kms:/k8s:/age:/age-b64:/age-file:/keyring:/vault).
Package env resolves env:NAME refs from the process environment (local analogue of cloud:/aws-sm:/aws-kms:/k8s:/age:/age-b64:/age-file:/keyring:/vault).
cuetry/secrets/k8s
Package k8s resolves Kubernetes Secret data keys.
Package k8s resolves Kubernetes Secret data keys.
cuetry/secrets/passphrase
Package passphrase resolves age-encrypted material.
Package passphrase resolves age-encrypted material.
cuetry/secrets/ref
Package ref holds shared contracts for recipe secret backends (similar in role to how honey centralizes crypto provider contracts).
Package ref holds shared contracts for recipe secret backends (similar in role to how honey centralizes crypto provider contracts).
cuetry/secrets/service
Package service resolves keyring:// refs via the OS credential store (Zalando keyring), analogous to cloud:/aws-sm:/aws-kms:/k8s:/age:/age-b64:/age-file:/keyring:/vault.
Package service resolves keyring:// refs via the OS credential store (Zalando keyring), analogous to cloud:/aws-sm:/aws-kms:/k8s:/age:/age-b64:/age-file:/keyring:/vault.
cuetry/secrets/stack
Package stack implements symmetric secure:v1 encryption for recipe secrets.
Package stack implements symmetric secure:v1 encryption for recipe secrets.
cuetry/secrets/stackunwrap
Package stackunwrap unwraps stack data keys from secretsprovider URLs (KMS, keyring, age, etc.).
Package stackunwrap unwraps stack data keys from secretsprovider URLs (KMS, keyring, age, etc.).
hostapi
Package hostapi implements shared host search and backend listing for HTTP and MCP surfaces.
Package hostapi implements shared host search and backend listing for HTTP and MCP surfaces.
hostexec
Package hostexec defines the execution surface (HostClient, Executor) shared by the TUI, web server, CUE runner, and provider-specific transports.
Package hostexec defines the execution surface (HostClient, Executor) shared by the TUI, web server, CUE runner, and provider-specific transports.
hosts
Package hosts defines the host search record model and pluggable cloud backends.
Package hosts defines the host search record model and pluggable cloud backends.
inventory
Package inventory converts honey host records into Ansible-compatible JSON inventory.
Package inventory converts honey host records into Ansible-compatible JSON inventory.
k8sdebug
Package k8sdebug provides utilities for Kubernetes debug containers.
Package k8sdebug provides utilities for Kubernetes debug containers.
logger
Package logger provides global debug logging initialization via go.uber.org/zap.
Package logger provides global debug logging initialization via go.uber.org/zap.
mcpserver
Package mcpserver implements the Model Context Protocol (stdio) server for honey.
Package mcpserver implements the Model Context Protocol (stdio) server for honey.
metrics
Package metrics provides Prometheus instrumentation for honey web.
Package metrics provides Prometheus instrumentation for honey web.
plugins
Package plugins loads Extism WASM plugins for honey (CUE transforms, custom steps, secret ref backends, and local hooks).
Package plugins loads Extism WASM plugins for honey (CUE transforms, custom steps, secret ref backends, and local hooks).
plugins/api/v1
Package v1 defines the honey.plugins/v1 JSON contract between the host and WASM plugins.
Package v1 defines the honey.plugins/v1 JSON contract between the host and WASM plugins.
postgres
Package postgres runs host-mediated PostgreSQL queries via pgx on the operator.
Package postgres runs host-mediated PostgreSQL queries via pgx on the operator.
provider/all
Package all automatically invokes the init() registration for every native honey provider.
Package all automatically invokes the init() registration for every native honey provider.
provider/awsprovider
Package awsprovider lists EC2 instances as honey host records.
Package awsprovider lists EC2 instances as honey host records.
provider/consulprovider
Package consulprovider lists Consul catalog nodes as honey host records.
Package consulprovider lists Consul catalog nodes as honey host records.
provider/dockerprovider
Package dockerprovider implements the honey Docker Engine search backend.
Package dockerprovider implements the honey Docker Engine search backend.
provider/gcp
Package gcp lists Compute Engine VMs as honey host records.
Package gcp lists Compute Engine VMs as honey host records.
provider/k8sprovider
Package k8sprovider lists Kubernetes nodes or pods as honey host records.
Package k8sprovider lists Kubernetes nodes or pods as honey host records.
provider/localprovider
Package localprovider provides the ability to manage and search manually defined hosts.
Package localprovider provides the ability to manage and search manually defined hosts.
provider/proxmoxprovider
Package proxmoxprovider provides Proxmox search capabilities for honey.
Package proxmoxprovider provides Proxmox search capabilities for honey.
provider/truenasprovider
Package truenasprovider discovers TrueNAS SCALE hosts via the WebSocket JSON-RPC API.
Package truenasprovider discovers TrueNAS SCALE hosts via the WebSocket JSON-RPC API.
pvelxc
Package pvelxc implements Proxmox VE LXC and QEMU serial console (termproxy/vncwebsocket) bridging for the web UI and TUI.
Package pvelxc implements Proxmox VE LXC and QEMU serial console (termproxy/vncwebsocket) bridging for the web UI and TUI.
recipenotify
Package recipenotify wires github.com/nikoksr/notify from environment variables for CUE recipe step notifications.
Package recipenotify wires github.com/nikoksr/notify from environment variables for CUE recipe step notifications.
recordings
Package recordings parses session .hrec.jsonl files used by the web UI and TUI replay.
Package recordings parses session .hrec.jsonl files used by the web UI and TUI replay.
safepath
Package safepath constrains filesystem paths for user-controlled inputs (cache roots, config discovery, recipe files) and performs reads/writes via os.Root where appropriate.
Package safepath constrains filesystem paths for user-controlled inputs (cache roots, config discovery, recipe files) and performs reads/writes via os.Root where appropriate.
searchrun
Package searchrun wires CLI flags and YAML config to host search and caching.
Package searchrun wires CLI flags and YAML config to host search and caching.
sshclient
Package sshclient provides SSH client dialing, SFTP, tunnels, and known_hosts helpers for honey.
Package sshclient provides SSH client dialing, SFTP, tunnels, and known_hosts helpers for honey.
stepkv
Package stepkv implements a tiny loopback HTTP key/value API backed by an in-memory TTL cache.
Package stepkv implements a tiny loopback HTTP key/value API backed by an in-memory TTL cache.
transferagent
Package transferagent resolves and cross-builds honey-transfer-agent binaries for target GOOS/GOARCH and optional cloud flavor (S3/GCS/full).
Package transferagent resolves and cross-builds honey-transfer-agent binaries for target GOOS/GOARCH and optional cloud flavor (S3/GCS/full).
transferagent/presign
Package presign generates short-lived presigned URLs for transferring files to/from S3 or GCS without requiring an agent binary on the remote host.
Package presign generates short-lived presigned URLs for transferring files to/from S3 or GCS without requiring an agent binary on the remote host.
truenasshell
Package truenasshell bridges honey web terminals to TrueNAS /websocket/shell.
Package truenasshell bridges honey web terminals to TrueNAS /websocket/shell.
ui
Package ui implements the bubbletea TUI, SSH helpers, and CUE recipe execution for honey.
Package ui implements the bubbletea TUI, SSH helpers, and CUE recipe execution for honey.
webserver
Package webserver provides the embedded HTTP server for honey.
Package webserver provides the embedded HTTP server for honey.
webserver/cmd/swag2openapi command
Command swag2openapi converts swag-generated Swagger 2.0 JSON to OpenAPI 3.x JSON for honey web.
Command swag2openapi converts swag-generated Swagger 2.0 JSON to OpenAPI 3.x JSON for honey web.
pkg
pluginpdk
Package pluginpdk provides helpers for honey WASM plugins built with the Extism Go PDK.
Package pluginpdk provides helpers for honey WASM plugins built with the Extism Go PDK.
plugins
bash command
copy command
file command
postgres command
rclone command
Package main implements the honey rclone RC WASM plugin action registry.
Package main implements the honey rclone RC WASM plugin action registry.
service command
shell command
template command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL