LocalControl is a minimal UNIX-socket control interface for Limnoria bots. It provides a local administrative command channel without exposing a separate remote control interface over IRC.
This project includes:
- A Limnoria plugin (
LocalControl) - A generic command‑line client (
botctl) - Optional wrapper scripts for multi‑bot setups
LocalControl is designed to be self-contained, predictable, and portable across multiple bot instances.
The socket is intended as a local owner-control channel. Local filesystem access
to .localcontrol.sock is therefore equivalent to owner-level bot access.
Clone the repository into your Limnoria plugin directory, usually
~/runbot/plugins:
cd ~/runbot/plugins
git clone https://github.com/Alcheri/LocalControl.gitLoad the plugin into your bot:
/msg yourbot load LocalControl
The plugin creates this UNIX domain socket beside plugin.py:
~/runbot/plugins/LocalControl/.localcontrol.sock
LocalControl restricts the socket file to owner-only permissions (0600) after
binding it. The parent directory must still be protected so that only trusted
local users can reach the socket path.
If you install the plugin somewhere else, adjust the examples below to match that path.
LocalControl generates a synthetic IRC-style prefix for each local request, for example:
LocalControl123!local123@localcontrol.invalid
To allow this synthetic user to execute owner-level commands, you must add a matching hostmask to your Limnoria user account.
In your Limnoria console (or via IRC as the bot owner):
/msg <bot> user hostmask add <your-account> LocalControl*!local*@localcontrol.invalid
Without this step, the bot will reject requests from botctl because they will
not map to an authorized owner identity.
The botctl script communicates with the LocalControl socket.
It is located in the plugin directory:
~/runbot/plugins/LocalControl
Make it executable if needed:
chmod +x ~/runbot/plugins/LocalControl/botctlYou can then run it directly or add that directory to your PATH.
Basic usage:
botctl bot sysinfo
botctl bot say '#channel' Hello from LocalControl
botctl bot config <name> [<value>]
botctl exec "reload LocalControl"exec sends a raw command line. bot accepts command tokens directly, which
makes it convenient for bot commands such as sysinfo or say.
The LocalControl request flow:
flowchart LR
A[botctl CLI] --> B[(UNIX Socket)]
B --> C[LocalControl Plugin]
C --> D[Limnoria Core]
D --> E[Bot Commands / Owner Actions]
The CLI resolves the socket path in this order:
--socketcommand‑line flagBOT_CONTROL_SOCKETenvironment variable- Default path:
~/runbot/plugins/LocalControl/.localcontrol.sock
Example:
botctl --socket /tmp/test.sock bot sysinfoThis usually means the synthetic LocalControl identity is not mapped to your owner account.
Verify that your Limnoria account has this hostmask:
LocalControl*!local*@localcontrol.invalid
If needed, add it again:
/msg <bot> user hostmask add <your-account> LocalControl*!local*@localcontrol.invalid
Check that the plugin is loaded and that the socket file exists at the expected path:
~/runbot/plugins/LocalControl/.localcontrol.sock
If your installation uses a different location, pass it explicitly:
botctl --socket /path/to/.localcontrol.sock bot sysinfoYou can also set it once with an environment variable:
export BOT_CONTROL_SOCKET=/path/to/.localcontrol.sockIf the socket file is missing entirely, reload the plugin and check the bot log for bind or startup errors.
The user running botctl must be able to access the socket file and its parent
directory.
Make sure:
- The bot is running under the expected local user account.
- You are invoking
botctlas a user with permission to access that socket. - The socket directory is not blocked by restrictive filesystem permissions.
If the bot was stopped uncleanly, a stale socket file can also cause problems. Reloading the plugin normally removes and recreates the socket.
Run it from the plugin directory or call it with its full path:
~/runbot/plugins/LocalControl/botctl bot sysinfoIf you want to call it as botctl from anywhere, either add the directory to
your PATH or place a wrapper script on your PATH.
LocalControl logs one line per socket request by default. To disable or enable
this, use the socketRequestLogging plugin configuration option:
Check the current setting:
botctl bot config plugins.LocalControl.socketRequestLoggingDisable logging:
botctl bot config plugins.LocalControl.socketRequestLogging falseRe-enable logging:
botctl bot config plugins.LocalControl.socketRequestLogging trueWhen enabled, each request is logged with its request ID, status, reply count, execution time in milliseconds, command name, argument count, and any errors. Full command text is not logged by default.
To temporarily log full command text for debugging, enable:
botctl bot config plugins.LocalControl.socketRequestFullCommandLogging trueFull command logging redacts obvious sensitive values such as passwords, passphrases, secrets, tokens, API keys, and key-style fields. Leave it disabled unless you specifically need full command text in the bot logs.
Disable full command logging again with:
botctl bot config plugins.LocalControl.socketRequestFullCommandLogging falseLocalControl applies a short timeout to each connected client. A client that connects but does not send a command is disconnected instead of holding a handler thread indefinitely.
Socket dispatches are serialised while LocalControl temporarily captures Limnoria replies, preventing overlapping local requests from racing the shared IRC send and queue hooks.
If you run multiple bots, wrapper scripts can save you from repeatedly passing different socket paths.
#!/usr/bin/env bash
BOT_CONTROL_SOCKET="$HOME/runbot/plugins/LocalControl/.localcontrol.sock" botctl "$@"Place the wrapper somewhere on your PATH, make it executable, and use it just
like botctl.
Copyright © MMXXVI, Barry Suridge