discord-agent-bridge 0.2.0 โ 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +386 -0
- package/README.md +302 -116
- package/dist/app.js +7 -10
- package/dist/app.js.map +1 -1
- package/dist/cli.js +11 -4
- package/dist/cli.js.map +1 -1
- package/dist/core/configResolver.js +4 -0
- package/dist/core/configResolver.js.map +1 -1
- package/dist/core/configSchema.js +8 -0
- package/dist/core/configSchema.js.map +1 -1
- package/dist/core/providerCatalog.js +10 -35
- package/dist/core/providerCatalog.js.map +1 -1
- package/dist/core/sessionOrchestrator.js +148 -4
- package/dist/core/sessionOrchestrator.js.map +1 -1
- package/dist/discord/configPanel.js +38 -6
- package/dist/discord/configPanel.js.map +1 -1
- package/dist/discord/format.js +30 -11
- package/dist/discord/format.js.map +1 -1
- package/dist/discord/i18n.js +4 -0
- package/dist/discord/i18n.js.map +1 -1
- package/dist/discord/interactionRouter.js +32 -8
- package/dist/discord/interactionRouter.js.map +1 -1
- package/dist/discord/renderers/index.js +63 -11
- package/dist/discord/renderers/index.js.map +1 -1
- package/dist/discord/renderers/streamEmbed.js +11 -0
- package/dist/discord/renderers/streamEmbed.js.map +1 -1
- package/dist/modes/claude/session.js +6 -0
- package/dist/modes/claude/session.js.map +1 -1
- package/dist/modes/codex/index.js +3 -0
- package/dist/modes/codex/index.js.map +1 -1
- package/dist/service/index.js +140 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/launchd.js +106 -0
- package/dist/service/launchd.js.map +1 -0
- package/dist/service/runScript.js +37 -0
- package/dist/service/runScript.js.map +1 -0
- package/dist/service/schtasks.js +78 -0
- package/dist/service/schtasks.js.map +1 -0
- package/dist/service/systemd.js +87 -0
- package/dist/service/systemd.js.map +1 -0
- package/dist/service/types.js +10 -0
- package/dist/service/types.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,201 +1,387 @@
|
|
|
1
1
|
# discord-agent-bridge
|
|
2
2
|
|
|
3
|
+
๐ [ํ๊ตญ์ด](README.ko.md) | **English**
|
|
4
|
+
|
|
3
5
|
> Self-hosted Discord bot that runs AI coding agents โ Claude Code, Codex, and more โ per channel. Role-based access, multi-server, extensible.
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
**A self-hosted Discord bot that connects an AI coding agent โ Claude Code or Codex โ to each channel.** It runs on your own machine, with role-based permissions, multi-server support, and an extensible backend design.
|
|
6
8
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
+
- Currently supports: **Claude Code**, **Codex**
|
|
10
|
+
- Extensible: add a mode plugin to connect other agents (e.g. opencode) in the future
|
|
9
11
|
|
|
10
|
-
>
|
|
12
|
+
> โ
**Published on npm.** Run it instantly with `npx discord-agent-bridge` (recommended), or install globally / build from source. Supports both **Claude Code** and **Codex** backends.
|
|
11
13
|
|
|
12
14
|
---
|
|
13
15
|
|
|
14
|
-
##
|
|
16
|
+
## What is this?
|
|
15
17
|
|
|
16
|
-
Discord
|
|
18
|
+
Send a message in a Discord channel like you're chatting, and Claude Code (or Codex) works on that project's folder from your own computer.
|
|
17
19
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
20
|
+
- **One channel = one session = one project.** When you create a channel, you set its working folder and backend (Claude/Codex).
|
|
21
|
+
- **Invite the same bot to multiple servers** โ each server/project gets its own independent configuration.
|
|
22
|
+
- **Roles control who can use it.**
|
|
21
23
|
|
|
22
24
|
---
|
|
23
25
|
|
|
24
|
-
##
|
|
26
|
+
## Prerequisites
|
|
25
27
|
|
|
26
|
-
- **Node.js 20
|
|
27
|
-
-
|
|
28
|
-
- **Claude
|
|
29
|
-
- **Codex
|
|
30
|
-
- **Discord
|
|
28
|
+
- **Node.js 20 or later**
|
|
29
|
+
- The CLI for whichever backend you use must already be **installed and logged in**:
|
|
30
|
+
- **Claude mode** โ [Claude Code](https://docs.anthropic.com/en/docs/claude-code) authentication (`claude` login, or an `ANTHROPIC_API_KEY`). Viewing the usage/limits panel requires being **logged in with a Claude Pro/Max subscription**.
|
|
31
|
+
- **Codex mode** โ the `codex` CLI installed and logged in.
|
|
32
|
+
- **A Discord bot token** (create one in Step 1 below)
|
|
31
33
|
|
|
32
34
|
---
|
|
33
35
|
|
|
34
|
-
## 1
|
|
36
|
+
## Step 1 โ Create a Discord bot (Developer Portal)
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
You need to create your own bot. Takes about 5 minutes.
|
|
37
39
|
|
|
38
|
-
1. **[Discord Developer Portal](https://discord.com/developers/applications)**
|
|
39
|
-
2.
|
|
40
|
-
- โ ๏ธ
|
|
41
|
-
3.
|
|
42
|
-
- โ
**MESSAGE CONTENT INTENT** โ
|
|
43
|
-
- โ
**SERVER MEMBERS INTENT** โ
|
|
44
|
-
-
|
|
45
|
-
4.
|
|
46
|
-
5.
|
|
40
|
+
1. Go to the **[Discord Developer Portal](https://discord.com/developers/applications)** โ top-right **New Application** โ enter a name (e.g. `my-agent-bot`) โ **Create**.
|
|
41
|
+
2. Left sidebar **Bot** tab โ **Reset Token** โ **copy the token** and keep it somewhere safe.
|
|
42
|
+
- โ ๏ธ This token is a password. If it's ever exposed, reset it immediately with **Reset Token**.
|
|
43
|
+
3. Still under the **Bot** tab, in **Privileged Gateway Intents**:
|
|
44
|
+
- โ
**MESSAGE CONTENT INTENT** โ **required** (the bot needs to read message content)
|
|
45
|
+
- โ
**SERVER MEMBERS INTENT** โ recommended (used for role-based permission checks)
|
|
46
|
+
- Enable them and **Save Changes**.
|
|
47
|
+
4. Left sidebar **OAuth2** tab โ copy the **Client ID (Application ID)** (needed for setup).
|
|
48
|
+
5. **Build an invite link** โ OAuth2 โ **URL Generator**:
|
|
47
49
|
- **Scopes**: `bot`, `applications.commands`
|
|
48
50
|
- **Bot Permissions**: `Manage Channels`, `Send Messages`, `Embed Links`, `Attach Files`, `Read Message History`, `Create Public Threads`, `Send Messages in Threads`, `Manage Threads`, `Add Reactions`
|
|
49
|
-
-
|
|
50
|
-
- (
|
|
51
|
+
- Paste the generated URL into your browser and **invite it to your server**.
|
|
52
|
+
- (The setup wizard can also generate this invite link for you automatically โ see Step 2.)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Step 2 โ Install & run
|
|
57
|
+
|
|
58
|
+
### Install & auto-start (recommended)
|
|
59
|
+
|
|
60
|
+
The simplest path. These three lines take you from install to auto-start on reboot. `service install` registers the right auto-start for your OS โ **launchd on macOS, systemd on Linux, Task Scheduler on Windows**.
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install -g discord-agent-bridge # install
|
|
64
|
+
discord-agent-bridge --setup # first time only (enter token, etc.)
|
|
65
|
+
discord-agent-bridge service install # register auto-start + start now
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Management:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
discord-agent-bridge service status # registered / running?
|
|
72
|
+
discord-agent-bridge service restart # restart
|
|
73
|
+
discord-agent-bridge service uninstall # remove
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
To upgrade, install the latest and restart:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm install -g discord-agent-bridge@latest
|
|
80
|
+
discord-agent-bridge service restart
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
> โ ๏ธ **Windows note**: it registers a Task Scheduler logon trigger, so the bot **starts at login** (no admin needed). It does not guarantee auto-restart on crash (macOS/Linux do). If `service install` doesn't work, see **Manual setup โ Windows (Task Scheduler)** below.
|
|
51
84
|
|
|
52
85
|
---
|
|
53
86
|
|
|
54
|
-
|
|
87
|
+
The rest of this section is the **manual methods**, for when `service install` doesn't work or you want to set it up yourself.
|
|
88
|
+
|
|
89
|
+
### Manual setup โ macOS (launchd)
|
|
90
|
+
|
|
91
|
+
Run the bot directly under **launchd**, the built-in macOS service manager โ it starts at login and restarts automatically if it stops.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# 1) Install globally (and run setup once if you haven't)
|
|
95
|
+
npm install -g discord-agent-bridge
|
|
96
|
+
discord-agent-bridge --setup # skip if already configured
|
|
97
|
+
|
|
98
|
+
# 2) Create a launcher wrapper โ it finds nvm's default node dynamically,
|
|
99
|
+
# so it keeps working even after you switch node versions.
|
|
100
|
+
mkdir -p ~/.discord-agent-bridge
|
|
101
|
+
cat > ~/.discord-agent-bridge/run.sh <<'EOF'
|
|
102
|
+
#!/bin/bash
|
|
103
|
+
export NVM_DIR="$HOME/.nvm"
|
|
104
|
+
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
|
105
|
+
nvm use default >/dev/null 2>&1 || nvm use node >/dev/null 2>&1
|
|
106
|
+
exec discord-agent-bridge
|
|
107
|
+
EOF
|
|
108
|
+
chmod +x ~/.discord-agent-bridge/run.sh
|
|
109
|
+
# Not using nvm? run.sh can just be `#!/bin/bash` + `exec discord-agent-bridge` (node must be on PATH).
|
|
110
|
+
|
|
111
|
+
# 3) Create the LaunchAgent ($HOME is expanded to an absolute path as the file is written)
|
|
112
|
+
cat > ~/Library/LaunchAgents/com.discord-agent-bridge.plist <<EOF
|
|
113
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
114
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
115
|
+
<plist version="1.0">
|
|
116
|
+
<dict>
|
|
117
|
+
<key>Label</key><string>com.discord-agent-bridge</string>
|
|
118
|
+
<key>ProgramArguments</key>
|
|
119
|
+
<array>
|
|
120
|
+
<string>/bin/bash</string>
|
|
121
|
+
<string>$HOME/.discord-agent-bridge/run.sh</string>
|
|
122
|
+
</array>
|
|
123
|
+
<key>EnvironmentVariables</key>
|
|
124
|
+
<dict><key>HOME</key><string>$HOME</string></dict>
|
|
125
|
+
<key>RunAtLoad</key><true/>
|
|
126
|
+
<key>KeepAlive</key><true/>
|
|
127
|
+
<key>StandardOutPath</key><string>$HOME/.discord-agent-bridge/agent.out.log</string>
|
|
128
|
+
<key>StandardErrorPath</key><string>$HOME/.discord-agent-bridge/agent.err.log</string>
|
|
129
|
+
</dict>
|
|
130
|
+
</plist>
|
|
131
|
+
EOF
|
|
132
|
+
|
|
133
|
+
# 4) Start it
|
|
134
|
+
launchctl load -w ~/Library/LaunchAgents/com.discord-agent-bridge.plist
|
|
135
|
+
|
|
136
|
+
# 5) Verify โ seeing 'gateway ready' means success (Ctrl+C only exits the log view; the bot keeps running)
|
|
137
|
+
tail -f ~/.discord-agent-bridge/agent.out.log
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Management:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
launchctl list | grep discord-agent-bridge # status (col 1 = PID, col 2 = last exit code)
|
|
144
|
+
launchctl unload ~/Library/LaunchAgents/com.discord-agent-bridge.plist # stop
|
|
145
|
+
launchctl load -w ~/Library/LaunchAgents/com.discord-agent-bridge.plist # start
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Upgrading:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npm install -g discord-agent-bridge@latest
|
|
152
|
+
launchctl unload ~/Library/LaunchAgents/com.discord-agent-bridge.plist
|
|
153
|
+
launchctl load -w ~/Library/LaunchAgents/com.discord-agent-bridge.plist
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
> โ ๏ธ If you switch node versions with nvm, run `npm install -g discord-agent-bridge` once under the new version (nvm keeps global packages per version). The wrapper follows nvm's default node, so the plist itself never needs editing.
|
|
157
|
+
|
|
158
|
+
### Manual setup โ Windows (Task Scheduler)
|
|
159
|
+
|
|
160
|
+
Register it yourself when `discord-agent-bridge service install` doesn't work.
|
|
55
161
|
|
|
56
|
-
|
|
162
|
+
**Commands (no admin needed)** โ first find the bot's real path in PowerShell:
|
|
57
163
|
|
|
58
|
-
|
|
164
|
+
```powershell
|
|
165
|
+
where.exe discord-agent-bridge # e.g. C:\Users\<you>\AppData\Roaming\npm\discord-agent-bridge.cmd
|
|
166
|
+
|
|
167
|
+
# Register a logon-triggered task using the path from above
|
|
168
|
+
schtasks /create /tn discord-agent-bridge /sc onlogon /tr "C:\Users\<you>\AppData\Roaming\npm\discord-agent-bridge.cmd" /f
|
|
169
|
+
schtasks /query /tn discord-agent-bridge # status
|
|
170
|
+
schtasks /run /tn discord-agent-bridge # start now
|
|
171
|
+
schtasks /delete /tn discord-agent-bridge /f # remove
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**GUI**: Start menu โ **Task Scheduler** โ **Create Basic Task** โ name `discord-agent-bridge`, trigger **When I log on**, action **Start a program** โ the `.cmd` path from `where.exe` โ Finish.
|
|
175
|
+
|
|
176
|
+
> A logon task runs **at login** and does **not** guarantee restart on crash. For crash recovery / running before login you need a real Windows service โ register one with [nssm](https://nssm.cc/) (admin required):
|
|
177
|
+
>
|
|
178
|
+
> ```powershell
|
|
179
|
+
> nssm install discord-agent-bridge "C:\Program Files\nodejs\node.exe" "C:\Users\<you>\AppData\Roaming\npm\node_modules\discord-agent-bridge\dist\cli.js"
|
|
180
|
+
> nssm start discord-agent-bridge
|
|
181
|
+
> ```
|
|
182
|
+
|
|
183
|
+
### Manual setup โ PM2 (Linux / Windows alternative)
|
|
184
|
+
|
|
185
|
+
On Linux/Windows you can also use [PM2](https://pm2.keymetrics.io/) (handy logs, restart, status). **On macOS, use `service install`/launchd instead** โ PM2's fork wrapper can prevent the bot from opening its gateway connection on macOS.
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# 1) Install the bot globally (so PM2 has a stable command to run)
|
|
189
|
+
npm install -g discord-agent-bridge
|
|
190
|
+
|
|
191
|
+
# 2) Run --setup once if you haven't yet
|
|
192
|
+
discord-agent-bridge --setup
|
|
193
|
+
|
|
194
|
+
# 3) Install PM2
|
|
195
|
+
npm install -g pm2
|
|
196
|
+
|
|
197
|
+
# 4) Register the bot with PM2 and start it
|
|
198
|
+
pm2 start discord-agent-bridge --name discord-agent-bridge
|
|
199
|
+
|
|
200
|
+
# 5) Snapshot the current process list (so PM2 knows what to restore on boot)
|
|
201
|
+
pm2 save
|
|
202
|
+
|
|
203
|
+
# 6) Register PM2 to start at boot (on macOS this wires up launchd)
|
|
204
|
+
pm2 startup
|
|
205
|
+
# โ Copy-paste the `sudo ...` command it prints and run it once.
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Day-to-day management:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
pm2 status # is it running?
|
|
212
|
+
pm2 logs discord-agent-bridge # tail logs
|
|
213
|
+
pm2 restart discord-agent-bridge # restart (also do this after upgrading)
|
|
214
|
+
pm2 stop discord-agent-bridge # stop
|
|
215
|
+
pm2 delete discord-agent-bridge # unregister
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Upgrading under PM2:
|
|
59
219
|
|
|
60
220
|
```bash
|
|
61
|
-
|
|
62
|
-
|
|
221
|
+
npm install -g discord-agent-bridge@latest
|
|
222
|
+
pm2 restart discord-agent-bridge
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
> โ ๏ธ If you use nvm/asdf, PM2 needs to find the same `node` at boot time as it does in your shell. Verify with `which node` and make sure that path is available to the boot environment โ otherwise PM2 may fail to start the bot on reboot.
|
|
226
|
+
|
|
227
|
+
### Run with npx (quick try)
|
|
228
|
+
|
|
229
|
+
Use this to spin it up once without installing. `npx` fetches the latest version and runs it; on first run, the setup wizard appears first and the bot starts right after. (Closing the terminal stops the bot โ use PM2 above to keep it running.)
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
# First run โ the setup wizard runs automatically, then the bot starts.
|
|
233
|
+
# (asks for your token/Client ID, checks intents, generates an invite link โ no other defaults are asked)
|
|
63
234
|
npx discord-agent-bridge
|
|
64
235
|
|
|
65
|
-
#
|
|
236
|
+
# Later runs โ if already configured, the bot starts directly.
|
|
66
237
|
npx discord-agent-bridge
|
|
67
238
|
|
|
68
|
-
#
|
|
239
|
+
# To reconfigure only (without starting the bot)
|
|
69
240
|
npx discord-agent-bridge --setup
|
|
70
241
|
```
|
|
71
242
|
|
|
72
|
-
|
|
243
|
+
Global install also works: `npm install -g discord-agent-bridge`, then `discord-agent-bridge` / `discord-agent-bridge --setup`.
|
|
244
|
+
|
|
245
|
+
### Upgrading
|
|
73
246
|
|
|
74
|
-
|
|
247
|
+
When a new version is released:
|
|
75
248
|
|
|
76
249
|
```bash
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
npm install
|
|
80
|
-
npm run build
|
|
250
|
+
# npx users โ appending @latest always fetches the newest version (npx can otherwise cache).
|
|
251
|
+
npx discord-agent-bridge@latest
|
|
81
252
|
|
|
82
|
-
|
|
83
|
-
|
|
253
|
+
# Global-install users
|
|
254
|
+
npm install -g discord-agent-bridge@latest
|
|
84
255
|
```
|
|
85
256
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
257
|
+
Check your installed version with: `discord-agent-bridge --version`.
|
|
258
|
+
|
|
259
|
+
**What the setup wizard (`--setup`) asks for** โ the **token (secret) is the only thing you type into the terminal**. Nothing else is asked here:
|
|
260
|
+
1. Your Discord bot **token** (secret โ paste it only in the terminal)
|
|
261
|
+
2. Your **Client ID**
|
|
262
|
+
3. Confirmation that Message Content Intent is enabled
|
|
263
|
+
4. Generates an invite URL โ invite it to your server
|
|
91
264
|
|
|
92
|
-
>
|
|
93
|
-
> -
|
|
94
|
-
> -
|
|
265
|
+
> **Roles and defaults are never configured in the terminal.** After inviting the bot to your server, configure them in Discord with the **`/config`** command:
|
|
266
|
+
> - **Role tiers** โ assign them by **clicking** a role name (no need to copy a role ID or enable Developer Mode). Until assigned, access is **deny-by-default**.
|
|
267
|
+
> - **Defaults** โ **default backend, model, permission mode, and language (locale)** are saved instantly from a dropdown; the **Codex base path (codexHome)** is set via the "Set Codex Path" button โ a text-input modal. Language choices are `ํ๊ตญ์ด (ko)` / `English (en)`.
|
|
95
268
|
|
|
96
|
-
|
|
269
|
+
Configuration is stored under `~/.discord-agent-bridge/` (token file permissions 600). Per-server roles and defaults are stored in `servers/<guildId>.json`.
|
|
97
270
|
|
|
98
271
|
---
|
|
99
272
|
|
|
100
|
-
## 3
|
|
273
|
+
## Step 3 โ Using it in Discord
|
|
101
274
|
|
|
102
|
-
|
|
275
|
+
Once the bot joins a server, it **automatically creates a control channel (`#session-generator`), a sessions category, and a notifications channel (`#agent-status`)** (as long as it has the Manage Channels permission). From there, the flow is: **`/config` โ `/agent start`**.
|
|
103
276
|
|
|
104
|
-
1.
|
|
105
|
-
2. **`/config`** (
|
|
106
|
-
3. `#session-generator
|
|
107
|
-
|
|
108
|
-
4.
|
|
109
|
-
5.
|
|
277
|
+
1. **(Automatic)** This channel structure is created when the bot starts or is invited to a server. An admin can also recreate it manually with **`/init`** (existing channels are reused โ no duplicates).
|
|
278
|
+
2. **`/config`** (admin) โ set role tiers and defaults. (Server Administrators can always use the bot, even without an assigned role.)
|
|
279
|
+
3. In `#session-generator`, run **`/agent start`** โ the **wizard** walks you through, in order:
|
|
280
|
+
**choose a working folder โ backend (Claude / Codex) โ model โ reasoning effort โ permission mode**. Each step advances with a **"Next" button**. The folder browser supports **navigating to parent/other volumes, creating new folders, and resuming a previous session**. Once confirmed, a **dedicated session channel (`proj-<folder>`) is created** and bound to it, named after the project folder.
|
|
281
|
+
4. In the newly created session channel, **just chat with normal messages**. Claude mode shows streaming output, tool-execution threads, and permission approval buttons.
|
|
282
|
+
5. Use the commands below whenever you need them.
|
|
110
283
|
|
|
111
|
-
###
|
|
112
|
-
|
|
|
284
|
+
### Key commands
|
|
285
|
+
| Command | Description |
|
|
113
286
|
|---|---|
|
|
114
|
-
| `/init` | (
|
|
115
|
-
| `/agent start` |
|
|
116
|
-
| `/agent resume` |
|
|
117
|
-
| `/agent close` |
|
|
118
|
-
| `/
|
|
119
|
-
| `/mode
|
|
120
|
-
| `/
|
|
121
|
-
| `/stop
|
|
122
|
-
| `/
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
- `
|
|
127
|
-
- `
|
|
128
|
-
- `
|
|
129
|
-
|
|
130
|
-
|
|
287
|
+
| `/init` | (admin) Create the control channel + sessions category (reuses them if already present) |
|
|
288
|
+
| `/agent start` | Start a new session โ creates a dedicated session channel once the wizard is confirmed |
|
|
289
|
+
| `/agent resume` | Resume a previous session |
|
|
290
|
+
| `/agent close` | End the session and delete its session channel |
|
|
291
|
+
| `/agent stats` | View active sessions, session statistics, and Claude usage (visible only to you) |
|
|
292
|
+
| `/mode <claude\|codex>` | Switch backend (โ ๏ธ starts a new conversation โ prior context is not carried over) |
|
|
293
|
+
| `/mode perm <mode\|profile>` | Switch permission mode/profile (session context is preserved) |
|
|
294
|
+
| `/stop` | Immediately stop the current session (kill switch) |
|
|
295
|
+
| `/stop-all` | (admin) Stop all sessions |
|
|
296
|
+
| `/config` | (admin) Configure role tiers + defaults (backend, model, permission mode, language, Codex path) โ roles are set by **clicking**, defaults via dropdown/modal |
|
|
297
|
+
|
|
298
|
+
### Permission modes (how autonomous a session is)
|
|
299
|
+
- `default` โ confirms every tool execution with **Allow/Deny buttons** (safest)
|
|
300
|
+
- `acceptEdits` โ file edits are accepted automatically
|
|
301
|
+
- `plan` โ only plans first, holds off on execution
|
|
302
|
+
- `bypassPermissions` โ fully automatic (only for projects you trust)
|
|
303
|
+
|
|
304
|
+
(Codex maps these to the CLI's own approval/sandbox modes.)
|
|
305
|
+
|
|
306
|
+
### Event notifications (`#agent-status`)
|
|
307
|
+
|
|
308
|
+
Summarizes **completions and errors** from all your sessions into a single `#agent-status` channel. Toggle it on/off and change the target channel from `/config` โ **๐ Notification Settings**.
|
|
131
309
|
|
|
132
310
|
---
|
|
133
311
|
|
|
134
|
-
##
|
|
312
|
+
## Permissions & role setup (important)
|
|
135
313
|
|
|
136
|
-
|
|
314
|
+
This bot runs code **on your machine, with your account's permissions**. That means anyone who can command the bot is effectively **someone who can run commands on your computer** โ so role-based access control is essential.
|
|
137
315
|
|
|
138
|
-
-
|
|
139
|
-
- **admin** โ
|
|
140
|
-
- **execute** โ
|
|
141
|
-
- **read-only** โ
|
|
142
|
-
- > `/config`
|
|
143
|
-
-
|
|
144
|
-
-
|
|
145
|
-
-
|
|
316
|
+
- **3 role tiers** โ assign them in Discord via **`/config`** by **clicking** a role name (no role ID or Developer Mode needed). admin โ execute โ read-only:
|
|
317
|
+
- **admin** โ manages settings/`stop-all`/`config`
|
|
318
|
+
- **execute** โ can start sessions and run commands
|
|
319
|
+
- **read-only** โ read access only
|
|
320
|
+
- > `/config` can initially only be opened by someone with **server Administrator** permission (bootstraps even with an empty allow-list); afterward, the admin tier can use it too.
|
|
321
|
+
- **Deny-by-default** โ anyone not on the allow-list can do nothing. Until you configure it via `/config`, no one can run anything.
|
|
322
|
+
- **Per-project access control (ACL)** โ restrict a specific project to only the roles/people you designate.
|
|
323
|
+
- **Audit log** โ who did what and when is recorded in `~/.discord-agent-bridge/audit/`.
|
|
146
324
|
|
|
147
|
-
> โ ๏ธ
|
|
325
|
+
> โ ๏ธ **Security note:** Don't invite the bot to servers you don't trust, and don't grant the execute role too broadly. Access outside the working folder (e.g. `~/.ssh`) is blocked by default.
|
|
148
326
|
|
|
149
327
|
---
|
|
150
328
|
|
|
151
|
-
## Claude
|
|
329
|
+
## Claude mode vs. Codex mode
|
|
152
330
|
|
|
153
|
-
| | Claude
|
|
331
|
+
| | Claude mode | Codex mode |
|
|
154
332
|
|---|---|---|
|
|
155
|
-
|
|
|
156
|
-
|
|
|
157
|
-
|
|
|
158
|
-
|
|
|
159
|
-
|
|
|
333
|
+
| Real-time streaming | โ
| โ (final result only) |
|
|
334
|
+
| Tool-execution threads | โ
| โ |
|
|
335
|
+
| Permission approval buttons | โ
| โ (replaced by approval/sandbox modes) |
|
|
336
|
+
| Session resume | โ
| โ
|
|
|
337
|
+
| **Usage/limits display** | โ
(5-hour ยท weekly ยท context) | โ (Codex CLI limitation) |
|
|
338
|
+
|
|
339
|
+
### Is this the same as using the terminal?
|
|
340
|
+
|
|
341
|
+
- **Claude mode** โ uses the **same engine** as the `claude` terminal (the official Claude Agent SDK). It reads the project's `.claude/` configuration as-is, so **subagents, skills, hooks, and MCP all behave identically**. The only difference is the **presentation**: input comes from Discord messages, output renders as embeds/threads. (TUI-only slash commands you'd type in the interactive terminal are handled through the SDK's mechanism rather than the TUI's own.)
|
|
342
|
+
- **Codex mode** โ runs via `codex exec` (non-interactive). It loads the same Codex engine with your config/MCP, and we've **empirically confirmed hooks (SessionStart/UserPromptSubmit/Stop, etc.) fire correctly in non-interactive mode too**. Approval flow is mapped differently than interactive mode, though (see Permission modes above).
|
|
160
343
|
|
|
161
|
-
###
|
|
344
|
+
### Custom slash commands / skills / plugin commands
|
|
162
345
|
|
|
163
|
-
|
|
164
|
-
- **Codex ๋ชจ๋** โ `codex exec`(๋น๋ํํ)๋ก ๊ตฌ๋ํฉ๋๋ค. ๊ฐ์ Codex ์์ง์ ์ค์ /MCP๋ฅผ ๋ก๋ํ์ง๋ง, **๋น๋ํํ ๋ชจ๋๊ฐ ์ธํฐ๋ํฐ๋ธ ๋ชจ๋์ ์ผ๋ถ ๋ค๋ฅผ ์ ์์ด**(์น์ธ ๋ฐฉ์ยทํน์ ๊ธฐ๋ฅ ๋ฑ) **์๋ธ์์ด์ ํธยท์คํฌยทMCP๊ฐ ๊ทธ๋๋ก ๋๋์ง๋ Phase 2์์ ์ค์ `codex` CLI๋ก ๊ฒ์ฆ**ํ ๋ค ํ์ ํฉ๋๋ค. ๊ฒ์ฆ ์ ๊น์ง๋ ์์ ๋์ผํ๋ค๊ณ ๋ณด์ฅํ์ง ์์ต๋๋ค.
|
|
346
|
+
Messages you send in a session channel are forwarded to Claude/Codex verbatim, so **commands/skills defined under `.claude/commands/`, `.claude/skills/` (Claude) or `.codex/skills/` (Codex), as well as commands installed by plugins**, work exactly as they do in the terminal โ just type `/name` as-is (verified against the real Claude/Codex CLIs). This doesn't conflict with the bot's own Discord slash commands (`/agent`, `/config`, etc.) since it's just a plain text message in a session channel.
|
|
165
347
|
|
|
166
348
|
---
|
|
167
349
|
|
|
168
|
-
##
|
|
350
|
+
## Configuration file locations
|
|
169
351
|
|
|
170
352
|
```
|
|
171
353
|
~/.discord-agent-bridge/
|
|
172
|
-
โโ config.json #
|
|
173
|
-
โโ servers/<guildId>.json #
|
|
174
|
-
โโ state.json #
|
|
175
|
-
โโ audit/audit.jsonl #
|
|
354
|
+
โโ config.json # bot token ยท Client ID ยท defaults ยท limits (permissions 600)
|
|
355
|
+
โโ servers/<guildId>.json # per-server role tiers ยท defaults ยท channel structure (control/sessions/status) IDs ยท notification settings (permissions 600)
|
|
356
|
+
โโ state.json # channelโsession bindings (auto-restored after restart)
|
|
357
|
+
โโ audit/audit.jsonl # audit log
|
|
176
358
|
```
|
|
177
|
-
|
|
359
|
+
Configuration is overridden in the order **global โ server โ project**.
|
|
178
360
|
|
|
179
361
|
---
|
|
180
362
|
|
|
181
|
-
##
|
|
363
|
+
## Troubleshooting
|
|
182
364
|
|
|
183
|
-
-
|
|
184
|
-
-
|
|
185
|
-
-
|
|
186
|
-
-
|
|
365
|
+
- **The bot doesn't respond to messages** โ Check that **Message Content Intent** is enabled in the Developer Portal.
|
|
366
|
+
- **Slash commands don't show up** โ Check that you included the `applications.commands` scope when inviting the bot (registration can take a few minutes).
|
|
367
|
+
- **Channel creation fails with a permission error** โ Check that the bot has the `Manage Channels` permission.
|
|
368
|
+
- **The usage panel doesn't appear** โ You need to be **logged in with a Claude Pro/Max subscription** (`~/.claude`). This panel is hidden (as expected) if you're only using an API key.
|
|
369
|
+
- **"No authorized role for this actor (fail-secure)."** โ The account you signed in with has no role on the allow-list. This is deny-by-default. Fix it with one of these:
|
|
370
|
+
1. **Simplest** โ give that account Discord's **server Administrator** permission. Administrators are unconditionally treated as the admin tier and bypass the allow-list.
|
|
371
|
+
2. **Assign a listed role** โ in the Discord server's member list, give the account one of the roles that's already tied to a tier under `/config`.
|
|
372
|
+
3. **Add the role to a tier** โ from an admin account, open `/config` โ **Role tiers** and click the account's role into the tier you want (admin/execute/read-only).
|
|
187
373
|
|
|
188
374
|
---
|
|
189
375
|
|
|
190
|
-
##
|
|
376
|
+
## Development
|
|
191
377
|
|
|
192
378
|
```bash
|
|
193
379
|
npm install
|
|
194
|
-
npm run dev # tsx watch (
|
|
195
|
-
npm run typecheck #
|
|
196
|
-
npm run test #
|
|
380
|
+
npm run dev # tsx watch (dev mode)
|
|
381
|
+
npm run typecheck # type checking
|
|
382
|
+
npm run test # tests (vitest)
|
|
197
383
|
```
|
|
198
384
|
|
|
199
|
-
##
|
|
385
|
+
## License
|
|
200
386
|
|
|
201
387
|
MIT
|
package/dist/app.js
CHANGED
|
@@ -13,7 +13,7 @@ import { SessionOrchestrator } from './core/sessionOrchestrator.js';
|
|
|
13
13
|
import { createLogger } from './core/logger.js';
|
|
14
14
|
import { ClaudeMode } from './modes/claude/index.js';
|
|
15
15
|
import { CodexMode } from './modes/codex/index.js';
|
|
16
|
-
import { getClaudeModels,
|
|
16
|
+
import { getClaudeModels, getCodexModels } from './core/providerCatalog.js';
|
|
17
17
|
import { MessageRouter } from './discord/messageRouter.js';
|
|
18
18
|
import { InteractionRouter } from './discord/interactionRouter.js';
|
|
19
19
|
import { SessionWiring } from './discord/wiring.js';
|
|
@@ -126,12 +126,13 @@ export function createApp(deps) {
|
|
|
126
126
|
// Per-backend model options from the central provider catalog (ยง providerCatalog).
|
|
127
127
|
// Codex: a documented static default list (Codex has no model-list API; -m is
|
|
128
128
|
// free-form), with config.defaults.codexModel offered first when set. Claude:
|
|
129
|
-
// the SDK's supportedModels(),
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
|
|
129
|
+
// the SDK's supportedModels(), probed live on EVERY /config or /agent start open
|
|
130
|
+
// (no cross-invocation cache) so a model added or removed on the account is
|
|
131
|
+
// reflected immediately. A short in-tick de-dupe still shares one probe across
|
|
132
|
+
// concurrent callers. On failure/timeout falls back to the alias list.
|
|
133
|
+
modelsFor: async (backend) => backend === 'codex'
|
|
133
134
|
? getCodexModels(config.defaults.codexModel)
|
|
134
|
-
:
|
|
135
|
+
: await getClaudeModels({ logger }),
|
|
135
136
|
});
|
|
136
137
|
const discord = new DiscordClient({
|
|
137
138
|
clientId: config.discord.clientId,
|
|
@@ -148,10 +149,6 @@ export function createApp(deps) {
|
|
|
148
149
|
for (const binding of channelRegistry.list().filter((b) => !b.archived)) {
|
|
149
150
|
await wiring.attach(binding.guildId, binding.channelId, binding.mode);
|
|
150
151
|
}
|
|
151
|
-
// Warm the Claude model cache now that auth is available (fire-and-forget): the
|
|
152
|
-
// SDK's supportedModels() is fetched once and cached so the first /config or
|
|
153
|
-
// /agent start shows the real, current model list instead of the alias fallback.
|
|
154
|
-
void getClaudeModels({ logger });
|
|
155
152
|
logger.info('boot complete', { guilds: client.guilds.cache.size });
|
|
156
153
|
},
|
|
157
154
|
// Auto-provision each guild's channel structure on ready / guild-join so /init is
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAe,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAkB,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|