kovidgoyal/kitty · error
Password usage requested but KITTY_PUBLIC_KEY environment va
Error message
Password usage requested but KITTY_PUBLIC_KEY environment variable is not available
What it means
kitty @ (remote control CLI) was asked to use password-authenticated remote control, but the KITTY_PUBLIC_KEY environment variable is unset or empty. That variable is how kitty passes its public key to child processes so they can encrypt the password; without it no encrypted channel can be established.
Source
Thrown at tools/cmd/at/main.go:77
for i, x := range args {
ans[i] = escaped_string(x)
}
return ans
}
func set_payload_string_field(io_data *rc_io_data, field, data string) {
payload_interface := reflect.ValueOf(&io_data.rc.Payload).Elem()
struct_in_interface := reflect.New(payload_interface.Elem().Type()).Elem()
struct_in_interface.Set(payload_interface.Elem()) // copies the payload to struct_in_interface
struct_in_interface.FieldByName(field).SetString(data)
payload_interface.Set(struct_in_interface) // copies struct_in_interface back to payload
}
func get_pubkey(encoded_key string) (encryption_version string, pubkey []byte, err error) {
if encoded_key == "" {
encoded_key = os.Getenv("KITTY_PUBLIC_KEY")
if encoded_key == "" {
err = fmt.Errorf("Password usage requested but KITTY_PUBLIC_KEY environment variable is not available")
return
}
}
encryption_version, encoded_key, found := strings.Cut(encoded_key, ":")
if !found {
err = fmt.Errorf("KITTY_PUBLIC_KEY environment variable does not have a : in it")
return
}
if encryption_version != kitty.RC_ENCRYPTION_PROTOCOL_VERSION {
err = fmt.Errorf("KITTY_PUBLIC_KEY has unknown version, if you are running on a remote system, update kitty on this system")
return
}
pubkey = make([]byte, base85.DecodedLen(len(encoded_key)))
n, err := base85.Decode(pubkey, []byte(encoded_key))
if err == nil {
pubkey = pubkey[:n]
}
returnView on GitHub (pinned to 6d5d0c4406)
Solutions
- Run kitty @ from a process spawned by the kitty terminal itself (it exports KITTY_PUBLIC_KEY)
- If remote, echo/forward the value: on the local side read it and export it in the remote session, e.g. ssh host 'KITTY_PUBLIC_KEY="$KITTY_PUBLIC_KEY" kitty @ ls'
- Alternatively launch kitty with --execute and env passthrough, or use the remote control socket directly
- Update kitty on both ends so the variable is exported
Defensive patterns
Strategy: validation
Validate before calling
if os.Getenv("KITTY_PUBLIC_KEY") == "" {
return errors.New("run inside kitty or forward KITTY_PUBLIC_KEY")
} Type guard
func hasPublicKey() bool { return os.Getenv("KITTY_PUBLIC_KEY") != "" } Try / catch
if _, _, err := get_pubkey(""); err != nil { /* fall back to --use-password=never or socket auth */ } Prevention
- Run @ commands from shells spawned by kitty
- Forward KITTY_PUBLIC_KEY explicitly over ssh
When it happens
Trigger: Using --use-password with kitty @ (e.g. password required/always) when KITTY_PUBLIC_KEY was not inherited — typically because the command runs over ssh, from cron, or from a shell started before the variable existed.
Common situations: Running kitty @ on a remote host over ssh without forwarding the environment, invoking from systemd/launchd services, or shells whose startup files scrub the environment.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Remote control not enabled, this kitten should be run via a
- The remote control password was invalid: {data!r}
- No password was found
- KITTY_PUBLIC_KEY environment variable does not have a : in i
- This should be run as kitten icat
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/56b9a17da0a30964.
Report an issue: GitHub.