basecamp/kamal · error · RuntimeError
Enpass CLI is not installed
Error message
Enpass CLI is not installed
What it means
Raised by check_dependencies! in Kamal::Secrets::Adapters::Enpass when `enpass-cli version 2> /dev/null` fails. The adapter shells out to the third-party enpass-cli tool (not the Enpass desktop app) to read vault data, and Base#fetch probes for it before doing anything else. Note the probe uses the subcommand `version`, not a --version flag.
Source
Thrown at lib/kamal/secrets/adapters/enpass.rb:26
#
# Fetch only DB_PASSWORD from FooBar item
# `kamal secrets fetch --adapter enpass --from /Users/YOUR_USERNAME/Library/Containers/in.sinew.Enpass-Desktop/Data/Documents/Vaults/primary FooBar/DB_PASSWORD`
class Kamal::Secrets::Adapters::Enpass < Kamal::Secrets::Adapters::Base
def requires_account?
false
end
private
def fetch_secrets(secrets, from:, account:, session:)
secrets_titles = fetch_secret_titles(secrets)
result = `enpass-cli -json -vault #{from.shellescape} show #{secrets_titles.map(&:shellescape).join(" ")}`.strip
parse_result_and_take_secrets(result, secrets)
end
def check_dependencies!
raise RuntimeError, "Enpass CLI is not installed" unless cli_installed?
end
def cli_installed?
`enpass-cli version 2> /dev/null`
$?.success?
end
def login(account)
nil
end
def fetch_secret_titles(secrets)
secrets.reduce(Set.new) do |secret_titles, secret|
# Sometimes secrets contain a '/', when the intent is to fetch a single password for an item. Example: FooBar/DB_PASSWORD
# Another case is, when the intent is to fetch all passwords for an item. Example: FooBar (and FooBar may have multiple different passwords)
key, separator, value = secret.rpartition("/")
if key.empty?
secret_titles << valueView on GitHub (pinned to eee0083b38)
Solutions
- Install the enpass-cli tool (e.g. `cargo install enpass-cli` or your platform's release from the project README) and verify `enpass-cli version` succeeds.
- Ensure its install location (e.g. ~/.cargo/bin) is on PATH in the environment that runs kamal.
- In CI/containers, script the install step before invoking `kamal secrets pull`.
Defensive patterns
Strategy: validation
Validate before calling
require "open3"
def enpass_cli_installed?
Open3.capture3("enpass-cli", "version")[2].success?
end
abort "Install enpass-cli (separate from the Enpass app) before pulling secrets" unless enpass_cli_installed? Prevention
- Distinguish the Enpass desktop app from the third-party enpass-cli tool; only the latter satisfies the adapter.
- Verify `enpass-cli version` (subcommand, not --version) works in the deploy environment.
- Script the CLI install for CI since Enpass GUI cannot be used headless.
When it happens
Trigger: adapter.fetch(...) (e.g. `kamal secrets pull` with adapter enpass) on a machine lacking the enpass-cli binary on PATH, or where the binary exists but errors immediately (wrong arch, missing runtime).
Common situations: Assuming the Enpass desktop app is sufficient (it is not — the CLI is a separate community tool, typically installed via cargo/npm/package download); installing enpass-cli in a Rust cargo dir that is not on PATH for the shell/CI running kamal; macOS Gatekeeper blocking an unsigned binary.
Related errors
- Bitwarden Secrets Manager CLI is not installed
- Doppler CLI is not installed
- gcloud CLI is not installed
- LastPass CLI is not installed
- Bitwarden CLI is not installed
AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21).
Data as JSON: /api/errors/0082224fe19ebb0d.
Report an issue: GitHub.