kovidgoyal/kitty · error · ValueError
Remote control is not enabled, remember to use allow_remote_
Error message
Remote control is not enabled, remember to use allow_remote_control=True
What it means
Raised by remote_control() when the handler was created without allow_remote_control=True. The method builds a 'kitten @' command line to talk to kitty's remote control socket; if the flag was not set at construction, no socket/password setup happened, so the call is refused with a corrective hint.
Source
Thrown at kittens/tui/handler.py:104
def __call__(self, args: list[str]) -> str:
self.initialize()
return self.func(args)
def allow_indiscriminate_remote_control(self, enable: bool = True) -> None:
if self.rc_fd > -1:
if enable:
os.set_inheritable(self.rc_fd, True)
if self.password:
os.environ['KITTY_RC_PASSWORD'] = self.password
else:
os.set_inheritable(self.rc_fd, False)
if self.password:
os.environ.pop('KITTY_RC_PASSWORD', None)
def remote_control(self, cmd: str | Sequence[str], **kw: Any) -> Any:
if not self.allow_remote_control:
raise ValueError('Remote control is not enabled, remember to use allow_remote_control=True')
prefix = [kitten_exe(), '@']
r = -1
pass_fds = list(kw.get('pass_fds') or [])
try:
if self.rc_fd > -1:
pass_fds.append(self.rc_fd)
if self.password and self.rc_fd > -1:
r, w = safe_pipe(False)
os.write(w, self.password.encode())
os.close(w)
prefix += ['--password-file', f'fd:{r}', '--use-password', 'always']
pass_fds.append(r)
if pass_fds:
kw['pass_fds'] = tuple(pass_fds)
if isinstance(cmd, str):
cmd = ' '.join(prefix)
else:
cmd = prefix + list(cmd)View on GitHub (pinned to 6d5d0c4406)
Solutions
- Pass allow_remote_control=True when constructing the handler
- Ensure the kitten runs via a kitty.conf map so KITTY_LISTEN_ON exists (required once the flag is on)
- Restructure so remote_control is only called on handlers known to have the flag set
Example fix
# before
handler = ResultHandler(func) # allow_remote_control defaults to False
handler.remote_control('send-text', text='hi')
# after
handler = ResultHandler(func, allow_remote_control=True)
handler.remote_control('send-text', text='hi') Defensive patterns
Strategy: type-guard
Validate before calling
if not handler.allow_remote_control:
raise SystemExit('re-create handler with allow_remote_control=True') Type guard
from kittens.tui.handler import ResultHandler
def supports_remote_control(h: ResultHandler) -> bool:
return bool(getattr(h, 'allow_remote_control', False)) Try / catch
try:
handler.remote_control(cmd)
except ValueError as e:
if 'allow_remote_control=True' in str(e):
# recreate handler with the flag and retry
raise
raise Prevention
- Always construct handlers with allow_remote_control=True if any code path may call remote_control
- Gate remote_control calls behind hasattr/flag checks
When it happens
Trigger: Calling handler.remote_control('set-color', ...) on a handler instantiated with allow_remote_control=False (the default), e.g. when a generic TUI handler is reused and later decides it needs remote control.
Common situations: Copy-pasting a kitten that uses remote_control into a handler created by a base class or template that passes allow_remote_control=False; refactoring where the flag gets lost; conditional code paths that only sometimes need remote control.
Related errors
- Remote control not enabled, this kitten should be run via a
- This should be run as kitten icat
- This should be run as `kitten notify ...`
- No kitten named {original_kitten_name}
- This should be run as kitten show_key
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/933a5d5c3c727b5c.
Report an issue: GitHub.