Skip to content

Shareed2k/honey

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

honey

CLI to search GCP Compute Engine, AWS EC2, Kubernetes (nodes or pods), Consul catalog nodes, and Proxmox VE instances in parallel, optionally cache results, then use a terminal UI to SSH 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"

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 1m); force refresh
./honey search --refresh foo
./honey search --no-cache foo
./honey search --cache-ttl 5m foo

CUE recipes (experimental)

Validate a playbook-shaped CUE file: each step has host and exactly one of command, put (SFTP upload), get (SFTP download), or script (upload localremote, then run sh <remote> on the same SSH connection). Optional run_as applies to command and script runs (not to SFTP-only put/get). 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. 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).

./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. 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: ssh <user>@<ip> (user from --ssh-user, default $USER) for the selected row
  • t: enter -L spec (e.g. 8080:localhost:8080), then Enter to run ssh -L ... user@ip on the selected host
  • x: toggle a * mark on the current table row (for parallel SSH only). The first column shows * for marked rows.
  • Ctrl+a: mark all rows that have an IP (replaces the previous mark set).
  • c: clear all * marks.
  • e: run the same remote shell command in parallel via goph (golang.org/x/crypto/ssh): only on marked rows that have an IP; if nothing is marked, it runs on every listed host that has an IP. known_hosts host-key checking; auth from ssh-agent (SSH_AUTH_SOCK) and keys under ~/.ssh (id_ed25519, id_rsa, id_ecdsa). 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 SSH session. (Single-host Enter / t still use the system ssh binary, including ~/.ssh/config.)
  • r: run a CUE recipe (same as honey cue-exec) against a chosen subset of the table: only *‑marked rows that have an IP if you marked any rows; otherwise every row that has an IP (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.

Provider auth / flags

Provider Auth / config
GCP Application Default Credentials; set GOOGLE_CLOUD_PROJECT or GCP_PROJECT, or pass --gcp-project. Optional --gcp-zone (default: all zones, aggregated list).
AWS Default credential chain; --aws-profile, --aws-region.
Kubernetes Current kubeconfig; --kube-context, --kubeconfig, --k8s-mode=nodes (default) or pods. For pods, honey seamlessly utilizes Kubernetes exec directly without needing SSH or SFTP.

...

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

...

  1. 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.
  2. 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!
  3. Seamless Experience: Your interactive sessions, parallel commands, and CUE recipes work identically to actual SSH nodes, preserving context, streams, and file permissions, completely daemonless. | Consul | CONSUL_HTTP_ADDR or --consul-addr; --consul-datacenter, --consul-token / CONSUL_HTTP_TOKEN. | | Proxmox | --proxmox-url (e.g. https://10.0.0.1:8006/api2/json); Auth via --proxmox-user / --proxmox-password OR --proxmox-token-id / --proxmox-token-secret. Add --proxmox-insecure to bypass TLS verification. Both LXC and QEMU (VM) types are fully supported.

    Token Creation Example: Proxmox requires the PVEVMRO (Read Only) role to list VMs and fetch networking information.
    1. Log into your Proxmox web UI.
    2. Navigate to Datacenter > Permissions > API Tokens.
    3. Click Add and select your User (e.g., root@pam), name the token honey.
    4. Uncheck Privilege Separation if you want the token to inherit full user privileges, OR assign the PVEVMRO role to /vms explicitly.
    5. Copy the Secret ID.
    Your token_id in the YAML config will be formatted exactly as user@realm!tokenname (e.g. root@pam!honey). |

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

Layout

  • cmd/honey — CLI entrypoint (search, backends, mcp, …)
  • internal/cli — Cobra flags and wiring
  • 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 integrations
  • internal/ui — Bubble Tea table + SSH actions
  • internal/cuetry — CUE validation + decode for remote recipes (cue-validate, cue-exec)

Tests

go test ./...

License

This project is released under the MIT License.

About

where’s my instance, honey? Honey is devops tool to find instances and pods

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors