Manage your Linux and Windows servers from Slack. Get real-time alerts for everything that happens in ManageLM, and run tasks, scans and fleet searches without leaving your workspace.
The ManageLM Slack plugin connects your infrastructure to Slack through the same portal API used by the n8n and VS Code integrations, which covers the same features ManageLM gives Claude through MCP. It provides two-way communication:
Agents, tasks, scan reports, monitors, backups, certificates, credentials, keystore, pentests and admin sessions, posted the moment they happen.
/managelm status, run, task, answer, scan, search. Work on your fleet without opening the portal.
When a task needs input, answer it with /managelm answer. Replies stay private, so a password never reaches the channel.
Route warnings and critical events to #ops-alerts and informational events to #ops-general.
Every webhook delivery is signed with HMAC-SHA256 and verified before processing.
Develop locally with Socket Mode (no public URL required), deploy to production with HTTP.
The plugin serves everything on a single HTTP port (PORT, default 3100):
| Path | Purpose |
|---|---|
/slack/events | Slack Bolt app: slash commands, interactive buttons, Slack request verification |
/webhook | ManageLM webhook receiver: event notifications from the portal |
/health | Health check |
Go to api.slack.com/apps and click Create New App > From an app manifest
Select your workspace
Paste the manifest below (YAML tab), replacing <YOUR_HOST> with your plugin's public URL
Click Create
display_information: name: ManageLM description: Manage your servers from Slack. features: bot_user: display_name: ManageLM always_online: true slash_commands: - command: /managelm description: Manage your servers with ManageLM usage_hint: status | run <host> <skill> <task> | task <id> | answer <id> <text> | scan <host> <type> | search <kind> [text] oauth_config: scopes: bot: - chat:write - commands - views:write settings: interactivity: is_enabled: true request_url: https://<YOUR_HOST>/slack/events
Go to api.slack.com/apps > Create New App > From scratch
Under OAuth & Permissions, add bot scopes: chat:write, commands, views:write
Under Slash Commands, create /managelm with Request URL https://<your-host>/slack/events
Under Interactivity, enable and set Request URL to https://<your-host>/slack/events
Install the app to your workspace
Copy the Bot User OAuth Token (xoxb-...) from OAuth & Permissions
Copy the Signing Secret from Basic Information
Tip: For local development, enable Socket Mode in your app settings and generate an App-Level Token with connections:write scope. This way you don't need a public URL.
In the ManageLM portal, go to Settings > MCP & API > API Keys
Create a key and tick the authorizations the bot needs: Reports to start scans, Credentials to search credentials. Only permissions you hold yourself are offered.
Copy the key (mlm_ak_...)
Important: the key acts as the user who created it, limited to the authorizations you ticked, and anyone in the Slack workspace who can reach the bot uses it with that access, in any channel or direct message. Restrict it with SLACK_ALLOWED_USERS and SLACK_ALLOWED_CHANNELS. It sees the servers that user can see. Portal settings and management, such as approving agents, stay in the portal.
Copy the example file and fill in your credentials:
# Slack credentials SLACK_BOT_TOKEN=xoxb-your-token SLACK_SIGNING_SECRET=your-signing-secret # Only for Socket Mode: leave it out for HTTP mode # SLACK_APP_TOKEN=xapp-your-app-token # ManageLM MANAGELM_PORTAL_URL=https://app.managelm.com MANAGELM_API_KEY=mlm_ak_your-key # Webhook # Same secret as on the portal webhook MANAGELM_WEBHOOK_SECRET=your-webhook-secret PORT=3100 # Who may use the bot (optional, comma-separated Slack IDs). Unset: anyone in the workspace SLACK_ALLOWED_USERS=U0123456789,U9876543210 SLACK_ALLOWED_CHANNELS=C0123456789 # Channel routing (optional): warnings and critical events, then all other events SLACK_CHANNEL_ALERTS=C0123456789 SLACK_CHANNEL_INFO=C9876543210
Self-hosted users: Set MANAGELM_PORTAL_URL to your own portal instance URL instead of app.managelm.com.
An admin, in the ManageLM portal, goes to Settings > MCP & API > Webhooks and creates a webhook:
| Field | Value |
|---|---|
| URL | https://<your-host>/webhook |
| Events | Select the event categories you want notifications for |
| Secret | Same value as MANAGELM_WEBHOOK_SECRET in your .env |
The portal signs every delivery with HMAC-SHA256. The plugin verifies the X-Webhook-Signature header before processing any event.
npm install npm run build node --env-file=.env dist/app.js
docker build -t managelm-slack . docker run --env-file .env -p 3100:3100 managelm-slack
services: managelm-slack: build: . env_file: .env ports: - "3100:3100" restart: unless-stopped
Health check: Once running, visit http://<your-host>:3100/health to verify the plugin is up. You should see {"status":"ok"}.
| Command | Description |
|---|---|
/managelm status | List all agents with their status, sorted by state |
/managelm run | Open a form to pick a server, a skill (or Auto) and an instruction |
/managelm run <host> <skill> <instruction> | Submit a task inline and get the result in Slack (auto lets the agent pick the skill) |
/managelm task <task_id> | Show a task's status and result |
/managelm answer <task_id> <answer> | Answer a task waiting for input. Replies are private. |
/managelm scan <host> <type> | Start a security, inventory, access, certificates or activity scan |
/managelm search <kind> [text] | Search agents, inventory, security, activity, monitors, backups, certificates, pki or credentials |
/managelm help | Show available commands |
/managelm status /managelm run web-prod-01 packages List outdated packages /managelm run lb-01 auto Restart nginx /managelm scan db-master security /managelm search security ssh /managelm search monitors
The run command works like submitting a task from Claude or the portal UI. It sends the instruction to the agent, waits up to 100 seconds for the result, and posts it back to the channel. A longer task is reported as still running, with the command to check it later.
When a ManageLM webhook event fires, the plugin posts a Block Kit message with the event details and a View in Portal link:
| Category | Events |
|---|---|
| Agent | agent.enrolled (with a Review in Portal link), agent.approved, agent.online, agent.offline |
| Task | task.completed, task.failed, task.needs_input, with a View Details button |
| Report | report.completed, report.failed, report.stalled |
| Monitor | monitor.down, monitor.up, monitor.stalled, monitor.created, monitor.deleted |
| Backup | backup.completed, backup.failed |
| Certificate | cert.issued, cert.renewed, cert.renewal_failed, cert.revoked, cert.reactivated, cert.deleted |
| Credential | credential.rotated, credential.rotation_failed |
| Keystore | keystore.access_denied, keystore.key_deleted |
| Pentest | pentest.completed, pentest.failed |
| Sessions | console.opened, console.closed, desktop.opened, desktop.closed, files.opened |
Route warnings and critical events to a dedicated alerts channel and informational events elsewhere. Alerts are the events the portal itself flags: agent offline, task failed, monitor down or stalled, backup or credential rotation failed, certificate renewal failed or revoked, keystore refusals and deleted keys, failed or stalled reports and pentests, and admin sessions opened.
# Warnings and critical events SLACK_CHANNEL_ALERTS=C0123456789 # All other events SLACK_CHANNEL_INFO=C9876543210
If only one variable is set, every event goes to that channel. Make sure to invite the bot to the target channels. With neither set, the result of a task started from the run form comes to you as a direct message.
Finding channel IDs: Right-click a channel in Slack > View channel details > scroll to the bottom to find the Channel ID (starts with C).
| Variable | Required | Description |
|---|---|---|
SLACK_BOT_TOKEN | Yes | Bot OAuth token (xoxb-...) |
SLACK_SIGNING_SECRET | Yes | Slack app signing secret |
SLACK_APP_TOKEN | No | App-level token for Socket Mode (xapp-...) |
MANAGELM_PORTAL_URL | Yes | ManageLM portal URL |
MANAGELM_API_KEY | Yes | ManageLM API key (mlm_ak_...) |
MANAGELM_WEBHOOK_SECRET | For notifications | HMAC secret for webhook verification. Without it, /webhook rejects every delivery. |
MANAGELM_PORTAL_PUBLIC_URL | No | Public URL for "View in Portal" links |
PORT | No | HTTP port for Slack events, the webhook and the health check (default: 3100) |
SLACK_CHANNEL_ALERTS | No | Channel ID for alert events |
SLACK_CHANNEL_INFO | No | Channel ID for informational events |
SLACK_ALLOWED_USERS | No | Comma-separated Slack user IDs allowed to use the bot. Unset: anyone in the workspace |
SLACK_ALLOWED_CHANNELS | No | Comma-separated channel IDs the bot answers in. Unset: every channel and direct message |
crypto.timingSafeEqual to verify signatures, preventing timing attacks, refuses a delivery sent more than 5 minutes ago and ignores a repeat of one already received, so a captured one cannot be replayed.SLACK_ALLOWED_USERS and SLACK_ALLOWED_CHANNELS limit who can run commands, submit the run form and use message buttons. Without them, anyone in the workspace can./managelm answer are ephemeral, so an answer such as a password is never shown to the channel.Slack cannot reach your plugin. Verify your Request URL in the Slack app settings points to https://<your-host>/slack/events and the plugin is running. For local development, use Socket Mode instead.
SLACK_CHANNEL_ALERTS or SLACK_CHANNEL_INFO is set and the bot is invited to those channels[webhook] Received event: messagesMANAGELM_WEBHOOK_SECRETThe MANAGELM_WEBHOOK_SECRET in your .env does not match the secret configured on the webhook in the portal. Update one to match the other. A delivery is also refused when the plugin host's clock is more than 5 minutes off: keep it synchronized (NTP).
The name you typed doesn't exactly match an agent the key can see. The plugin matches the full hostname or display_name (case does not matter) and never guesses from a partial name: it suggests close matches instead. Use /managelm status to see exact names.
The key lacks an authorization the command needs (for example Reports for scan, Credentials for search credentials), or the key's creator cannot access that server. Create a key with the right authorizations.
The task took longer than 100 seconds. It keeps running on the agent: check it with /managelm task <task_id>, or subscribe the webhook to task events to be notified when it finishes.