OMP Discord Bot Integration & Lifecycle
The OMP Discord Bot (pi-discord-remote) provides a bidirectional bridge allowing authorized developers and content editors to interact with and steer active Oh My Pi (OMP) agent sessions directly from a private Discord guild.
This page serves as the Single Source of Truth (SSOT) for the architecture, process management, security, and operation of this service.
1. Core Mandate: Reboot-Survivability & Service Assurance
Because this platform operates on a Plesk-hosted environment under a non-root system user (user_freundeskreis.family), we do not have passwordless sudo rights. System-wide systemd services and Docker daemons are therefore unavailable or heavily restricted.
To guarantee that the OMP Discord Bot is always online and survives server reboots, we implement a systemd user service with lingering:
- User lingering (
loginctl enable-linger): This is enabled (Linger=yesfor the system user). It instructs the host operating system to spawn a persistent user systemd manager instance (systemd --user) immediately on boot, running even when no SSH session is active. - Systemd User Unit: Managed via
~/.config/systemd/user/omp-discord.service. It hooks into systemd’s boot targets (default.target) and automatically spawns the bot wrapper. - PTY (Pseudo-Terminal) Virtualization: The OMP engine and
pi-discord-remoteplugin require an interactive terminal (PTY) to initialize prompt sessions. Running raw binaries as background processes fails. We wrap OMP inside a detached GNU Screen instance (/usr/bin/screen -DmS omp-discord ...) to virtualize the PTY. - Crash Recovery: Managed by systemd with
Restart=alwaysand a10sbackoff.
[ Server Boot ]
│
(systemd PID 1)
│
[ Spawns systemd --user ] <-- Enabled by loginctl linger
│
[ Starts omp-discord ] <-- default.target hook
│
[ /usr/bin/screen ] <-- Virtualizes PTY
│
[ omp-discord-bot ] <-- Shell wrapper (injects Env & Path)
│
[ OMP Engine (v16) ] <-- Loads pi-discord-remote plugin
2. In-Depth Options & Architecture Trade-Offs
Below is a systematic comparison of daemon hosting architectures evaluated for this host.
A. Systemd User Service with Linger (Chosen Perfect Option)
- Mechanics: Configured via
~/.config/systemd/user/omp-discord.service. Uses standard systemd lifecycle control. - PTY Handling: Wrapped via
screen -DmS. - Pros:
- Integrates with system log daemon (
journalctl --user). - Full user-space independence (zero root/sudo required).
- Auto-restarts on crash and survives reboots natively.
- Integrates with system log daemon (
- Cons: Requires screen/tmux for PTY virtualization, which can leave orphaned sessions if not cleanly killed (prevented by
ExecStopconfiguration).
B. System-Wide Systemd Service
- Mechanics: Unit file under
/etc/systemd/system/managed by PID 1. - Pros: Deepest OS-level integration.
- Cons: IMPOSSIBLE on this host. Non-root user has no write access to system directories and no
sudoprivilege.
C. PM2 (Process Manager 2)
- Mechanics: Node.js process supervisor.
- Pros: Rich metrics console, automated log rotation, clustering.
- Cons:
- Configuring PM2 to run on boot (
pm2 startup) requires root. - Running in user space requires launching a secondary supervisor (via cron
@reboot pm2 resurrector systemd), introducing redundant supervisor nesting. - Overhead of a persistent Node.js watcher process.
- Configuring PM2 to run on boot (
D. Docker Container
- Mechanics: Isolating the bot inside a container with
--restart always. - Pros: Sandbox execution.
- Cons:
- No access to the host Docker daemon under this Plesk subscription.
- OMP must read and edit the TYPO3 codebases and file repositories located in
/var/www/vhosts/freundeskreis.family/httpdocs/. Bridging these volumes to a Docker container introduces complex permission and mounting overheads.
E. Cron @reboot with Screen/Tmux
- Mechanics: Crontab entry:
@reboot screen -DmS omp-discord ~/.local/bin/omp-discord-bot. - Pros: Zero-dependency, lightweight, easy to understand.
- Cons: No process watchdog (stays dead if it crashes post-boot), no log management, and no graceful shutdown.
Options Decision Matrix
| Parameter | A. systemd —user | B. systemd System | C. PM2 | D. Docker | E. Cron @reboot |
|---|---|---|---|---|---|
| Plesk Feasibility | 5/5 (Native) | 1/5 (Blocked) | 2/5 (No Sudo) | 1/5 (Blocked) | 5/5 (Native) |
| Crash Recovery | 5/5 (Native) | 5/5 (Native) | 5/5 (Native) | 5/5 (Native) | 1/5 (None) |
| PTY Suitability | 4/5 (via Screen) | 4/5 (via Screen) | 3/5 (Needs hack) | 3/5 (Needs hack) | 4/5 (via Screen) |
| Logging / Ops | 5/5 (Journald) | 5/5 (Journald) | 5/5 (PM2 logs) | 4/5 (Docker logs) | 1/5 (Raw file) |
| Maintenance | 5/5 (Standard) | 5/5 (Standard) | 3/5 (Supervisor) | 2/5 (Isolate) | 3/5 (Brittle) |
| Total Score | 24/25 (Winner) | 20/25 | 18/25 | 15/25 | 14/25 |
3. OMP Plugin Subsystem Mechanics (omp plugin)
OMP manages extensions using a structured plugin controller. The omp plugin CLI command regulates installation, updates, and options.
A. CLI Commands Reference
omp plugin list:- Queries and lists all loaded packages.
- Active on this host:
● @mporenta/pi-discord-remote@0.3.11(provides this Discord bridge).● pi-langfuse@1.4.3(provides OpenTelemetry tracing).
omp plugin doctor:- Assures filesystem health, checks manifest integrity (
package.json), and verifies dynamic module resolutions.
- Assures filesystem health, checks manifest integrity (
omp plugin features <plugin>:- Lists or toggles optional feature sets inside a plugin (e.g.
--enable trace_allor--disable debug_verbose).
- Lists or toggles optional feature sets inside a plugin (e.g.
omp plugin config <action> <plugin> [key] [value]:- Actions:
list,get,set,delete,validate. - Modifies settings schema registered by a plugin in the OMP local store.
- (Note:
@mporenta/pi-discord-remotebypasses this schema in favor of reading raw environment variables from.env.discordfor bootstrap speed).
- Actions:
omp plugin install <package>:- Installs a plugin from npm, local directory, or git.
- Flags:
--scope=user(installs to~/.omp/plugins/),--dry-run,--force.
omp plugin link <path>:- Symlinks a local extension codebase to the plugins folder for development.
B. Plugin Lifecycle Hooks
- Pre-load: OMP parses
~/.omp/plugins/package.jsonto resolve packages. - ESM Import: OMP dynamically imports the plugin’s entry files.
- Event Hooks:
- OMP plugins register handlers on the OMP event bus:
turn_start/turn_end: Triggered when an agent begins or ends executing a task.assistant_message: Fires on every stream token emitted by the LLM.tool_call/tool_result: Intercepts tool usage parameters and output payloads.
pi-discord-remotetapsassistant_messageto stream tokens to Discord, and pipes inbound Discord chat into OMP’s stdin queue usingpi.sendUserMessage(...).pi-langfusehooks into the trace events and exports OpenTelemetry spans to the Langfuse backend. Both plugins function in parallel without conflict.
- OMP plugins register handlers on the OMP event bus:
4. Operational Configuration
A. The systemd Service: ~/.config/systemd/user/omp-discord.service
[Unit]
Description=OMP Discord Bot (pi-discord-remote)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
# Run OMP inside screen so it gets a PTY (the discord extension needs session_start)
ExecStart=/usr/bin/screen -DmS omp-discord %h/.local/bin/omp-discord-bot
ExecStop=-/usr/bin/screen -S omp-discord -X quit
# Environment
Environment=HOME=%h
Environment=TERM=xterm-256color
WorkingDirectory=%h/httpdocs
# Restart policy: always restart with backoff
Restart=always
RestartSec=10
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=omp-discord
[Install]
WantedBy=default.target(Notice the ExecStop=- prefix. The minus sign tells systemd to ignore the exit code of the screen cleanup command, preventing the service from transitioning into a failed state if the screen session was already closed).
B. The Daemon Wrapper: ~/.local/bin/omp-discord-bot
#!/usr/bin/env bash
# omp-discord-bot — keeps an OMP session alive so pi-discord-remote stays connected.
# Designed for systemd: restarts automatically on crash.
set -euo pipefail
# Source profile for PATH, NODE_PATH, BUN_INSTALL, PI_DISCORD_ENV_FILE
[ -f "$HOME/.profile" ] && . "$HOME/.profile"
export PI_DISCORD_ENV_FILE="${PI_DISCORD_ENV_FILE:-$HOME/.env.discord}"
# Working directory for the OMP session
OMP_CWD="${OMP_CWD:-/var/www/vhosts/freundeskreis.family/httpdocs}"
exec omp \
--cwd "$OMP_CWD" \
--allow-home \
--no-title \
--approval-mode yolo \
--no-session \
"$@"5. Security & Isolation Hardening Checklist
Because the Discord bot links directly to OMP (which executes shell commands and edits filesystem assets), allowlisted Discord users gain equivalent capabilities to ssh access.
- Private Bot Application: The Discord bot token belongs to a dedicated application in the Discord Developer portal.
- Isolated Server Guild: The bot is invited only to a private guild, not shared servers.
- Privileged Intents Enabled:
Message Content Intentis explicitly enabled in the Discord Developer panel. - Explicit Allowlist:
PI_DISCORD_USER_IDSis populated in.env.discordwith specific developer Snowflake IDs. The plugin will refuse to start if this is empty. - Secret Isolation: All credentials (bot token, user lists) live in
/var/www/vhosts/freundeskreis.family/.env.discord, which is heavily protected by.htaccessrules and excluded from git versioning.
6. Maintenance & Troubleshooting Cheatsheet
Routine Administration
# Check the status of the background daemon
systemctl --user status omp-discord
# Restart the bot (required to apply changes in .env.discord)
systemctl --user restart omp-discord
# Stop the daemon
systemctl --user stop omp-discord
# View real-time logs
journalctl --user -u omp-discord -n 100 -f
# Verify that the screen session is active
screen -lsCommon Issue Resolution
1. “No screen session found” on Stop
- Diagnosis: The OMP process exited before the systemd stop command executed.
- Remedy: This is normal behavior and is safely handled by the
ExecStop=-configuration. No action is required.
2. Bot is offline but Service is active
- Diagnosis: OMP may be running but unable to connect to the Discord API due to network timeouts, rate limits, or an invalid token.
- Remedy: Check the logs using
journalctl --user -u omp-discord -n 50. If the bot token is invalid, retrieve a new one from the Discord developer console, paste it into~/.env.discord, and runsystemctl --user restart omp-discord.
3. Subdomain not responding
- Diagnosis: Subdomain
q.freundeskreis.familyrequires lingering active on the user session. - Remedy: Run
loginctl show-user $(whoami) | grep Linger. If it displaysLinger=no, request the server admin to runsudo loginctl enable-linger user_freundeskreis.family.