Alerts for permission prompts, questions, idle and errors post into a per-tab thread; a reply from an allowlisted user is typed into that tab. Thread creation, thread cleanup on tab delete and pinging are configurable. POST /api/sessions/:id/discord-notify lets a CLI ask for the user. Setup is in docs/discord-bridge.md.
6.5 KiB
Discord bridge
Codeman can post to a private Discord server when a session needs you, give every tab its own thread, and type your thread reply into that tab. It only makes outbound connections, so Codeman is not exposed to the internet and it works when you are away from your network.
Warning
A reply from an allowed Discord account is typed into agents that can run shell commands. Treat that Discord account like a login to the machine: turn on 2FA and use a strong, unique password.
What it does
- Posts when a session asks for permission, asks a question, goes idle, stops or errors.
- Creates one thread per tab in a single parent channel, so a reply always reaches exactly one session.
- Types your reply into that session as a single line followed by Enter.
- Lets a CLI post a deliberate message (for example "press the reset button on the case") with
POST /api/sessions/:id/discord-notify.
Setup
Do these once, in order. Never paste the bot token into a chat or a session.
1. Create a private server
- In Discord choose Add a Server, Create My Own, For me and my friends.
- Invite nobody and create no invite links.
- Create one text channel, for example
#codeman-cli.
2. Copy the IDs
- Open User Settings, Advanced and turn on Developer Mode.
- Right-click the server, the channel and your own avatar, and choose Copy ID for each. You need the guild ID, the parent channel ID and your user ID.
3. Create the application
- Go to https://discord.com/developers/applications and choose New Application.
- Name it
Codeman.
4. Configure the bot
On the Bot tab:
- Choose Reset Token and copy it. It is shown once.
- Turn Public Bot off, so nobody else can add it. Discord refuses this while the app has a default install link, so first open the Installation tab, set Install Link to None (untick Guild Install and User Install if it will not save) and save, then come back here.
- Leave Requires OAuth2 Code Grant off.
- Under Privileged Gateway Intents turn Message Content Intent on. Leave Server Members Intent and Presence Intent off.
5. Invite the bot with minimal permissions
On OAuth2, URL Generator:
-
Tick the scope
botonly. Do not tickapplications.commandsor anything else. -
Tick only these permissions:
Permission Why View Channels See the parent channel Send Messages Post in the parent channel Send Messages in Threads Post in each tab's thread Create Public Threads Make a thread per tab Read Message History Read your replies Add Reactions Acknowledge a reply that was typed -
Open the generated URL, choose your private server and authorise.
-
Check the Installation tab still shows Install Link: None, so there is no public way to add the bot.
The ticked boxes are the source of truth. As a cross-check, these six permissions add up to the permissions integer 309237713984.
6. Optional: allow deleting threads
Only needed for onSessionDelete: delete. Give the bot role Manage Threads on the parent channel only, as a channel permission override and not server-wide. Skip this if you are happy to keep or archive threads.
7. Never grant
Administrator, Manage Channels, Manage Roles, Manage Messages, Mention Everyone, or any voice permission.
8. Configure Codeman
- Open Settings, Discord.
- Enter the bot token, guild ID, parent channel ID and your user ID in the allowlist.
- Choose the options below and press Test. A test message should appear in the channel.
The token is stored in ~/.codeman/discord.json with mode 0600. It is never returned by the API, written to logs or sent over SSE.
9. Phone alerts
In the Discord mobile app set the server to All Messages. Discord's own push notification is what reaches you off-network.
Options
| Option | Values | Default | Effect |
|---|---|---|---|
threadCreation |
lazy, onSessionStart |
lazy |
lazy makes a thread on the first notification. onSessionStart makes one per new tab |
onSessionDelete |
keep, archive, delete |
archive |
What happens to the thread when its tab is deleted. delete needs Manage Threads |
pingMode |
off, critical, all |
critical |
critical pings you for permission prompts, questions, errors and urgent posts |
scope |
attention, all |
attention |
attention skips the quiet "response complete" event. all sends it too |
Security model
- Only messages from IDs in
allowedUserIds, in the configured guild, inside a thread Codeman created, are acted on. Everything else is dropped. - A reply is reduced to one line, stripped of control characters and capped in length before it is typed.
- Replies are rate limited per session.
- A Discord outage or a bad token never affects sessions. The bridge logs once and backs off.
Rotating and revoking
- Rotate: in the Developer Portal choose Bot, Reset Token, paste the new token into Codeman and press Test.
- Revoke: kick the bot from the server or delete the application, then delete
~/.codeman/discord.json. - If the token is ever pasted somewhere it should not be, reset it straight away.
Troubleshooting
| Symptom | Check |
|---|---|
| Test fails with 401 | The token is wrong or was reset. Paste the current one |
| Test fails with 403 or 50001 | The bot cannot see the parent channel. Check the role and the channel ID |
| Posts arrive but replies do nothing | Message Content Intent is off, or your user ID is not in the allowlist |
| Thread is not deleted | The bot lacks Manage Threads on the parent channel |
| Nothing arrives on the phone | Check the Discord app's notification setting for the server |