discord-bridge 0.1.2 → 0.1.4
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/AGENTS.md +28 -0
- package/README.md +46 -10
- package/bin/cli.js +53 -11
- package/package.json +1 -1
- package/server/index.js +1 -1
- package/plugin/.claude-plugin/plugin.json +0 -8
- package/plugin/README.md +0 -17
- package/plugin/hooks/hooks.json +0 -27
- package/plugin/hooks/scripts/notify-discord.sh +0 -36
- package/plugin/hooks/scripts/stop-hook.sh +0 -35
package/AGENTS.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## プロジェクト概要
|
|
4
|
+
|
|
5
|
+
discord-bridge - Claude Code と Discord の双方向通信ブリッジ(npm パッケージ)
|
|
6
|
+
|
|
7
|
+
## 技術スタック
|
|
8
|
+
|
|
9
|
+
- Node.js (ESM)
|
|
10
|
+
- discord.js v14
|
|
11
|
+
- Express v5
|
|
12
|
+
|
|
13
|
+
## プロジェクト構成
|
|
14
|
+
|
|
15
|
+
- `bin/` - CLI エントリーポイント
|
|
16
|
+
- `server/` - HTTP API サーバー・Discord Bot
|
|
17
|
+
- `plugin/` - Claude Code プラグイン(`discord-bridge install` で配置されるファイル群)
|
|
18
|
+
|
|
19
|
+
## バージョニング
|
|
20
|
+
|
|
21
|
+
- 変更を加えたら `package.json` の `version` を更新する
|
|
22
|
+
- 毎回 patch バージョンを上げる(例: `0.1.2` → `0.1.3`)
|
|
23
|
+
- npm publish は手動で行うため、バージョン更新のみ行えばよい
|
|
24
|
+
|
|
25
|
+
## コーディング規約
|
|
26
|
+
|
|
27
|
+
- 作業・コメント・PR は日本語で記載する
|
|
28
|
+
- コミットメッセージは日本語で簡潔に
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Claude Code と Discord の双方向通信ブリッジ。スマホから Claude
|
|
|
10
10
|
- **メッセージ取得** - ユーザーからの指示を取得
|
|
11
11
|
- **リアルタイム待機** - SSE 接続で次の指示を待機
|
|
12
12
|
- **離席モード** - ターミナルを離れても Discord 経由で操作
|
|
13
|
-
- **
|
|
13
|
+
- **Claude Code / Codex 対応** - どちらのプラットフォームにもスキルをインストール可能
|
|
14
14
|
|
|
15
15
|
## インストール
|
|
16
16
|
|
|
@@ -37,6 +37,7 @@ Discord の設定 → 詳細設定 → **開発者モード** を有効化して
|
|
|
37
37
|
|
|
38
38
|
- **チャンネル ID**: チャンネル名を右クリック → "チャンネル ID をコピー"
|
|
39
39
|
- **ユーザー ID**: 自分の名前を右クリック → "ユーザー ID をコピー"
|
|
40
|
+
- Bot に指示を出すユーザー(自分自身)の ID です。Bot があなたからのメッセージだけを処理するために使います
|
|
40
41
|
|
|
41
42
|
### 3. 環境変数の設定
|
|
42
43
|
|
|
@@ -47,7 +48,7 @@ export DISCORD_BRIDGE_TOKEN="your_bot_token_here"
|
|
|
47
48
|
export DISCORD_BRIDGE_USER_ID="your_user_id_here"
|
|
48
49
|
```
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
設定後、現在のターミナルに反映するには `source ~/.zshrc` を実行してください(新しいターミナルを開く場合は不要です)。
|
|
51
52
|
|
|
52
53
|
### 4. プロジェクト設定
|
|
53
54
|
|
|
@@ -59,31 +60,66 @@ Claude Code を使うプロジェクトのルートに `.discord-bridge.json`
|
|
|
59
60
|
}
|
|
60
61
|
```
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
> **Note**: チャンネル ID は秘密情報ではありませんが、プロジェクト固有の設定です。チームで共有する場合はそのままコミットし、個人用の場合は `.gitignore` に追加してください。
|
|
64
|
+
|
|
65
|
+
### 5. スキルのインストール
|
|
66
|
+
|
|
67
|
+
プラットフォームを指定してインストールします:
|
|
63
68
|
|
|
64
69
|
```bash
|
|
65
|
-
|
|
70
|
+
# Claude Code の場合(プロジェクトローカル)
|
|
71
|
+
discord-bridge install claude
|
|
72
|
+
|
|
73
|
+
# Codex の場合(プロジェクトローカル)
|
|
74
|
+
discord-bridge install codex
|
|
66
75
|
```
|
|
67
76
|
|
|
68
|
-
|
|
77
|
+
`--user` を付けるとホームディレクトリにインストールされ、全プロジェクトで利用できます:
|
|
69
78
|
|
|
70
|
-
|
|
79
|
+
```bash
|
|
80
|
+
# Claude Code(ユーザー全体)
|
|
81
|
+
discord-bridge install claude --user
|
|
71
82
|
|
|
72
|
-
|
|
83
|
+
# Codex(ユーザー全体)
|
|
84
|
+
discord-bridge install codex --user
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
| コマンド | インストール先 |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `install claude` | `.claude/skills/discord-comm/` |
|
|
90
|
+
| `install claude --user` | `~/.claude/skills/discord-comm/` |
|
|
91
|
+
| `install codex` | `.agents/skills/discord-comm/` |
|
|
92
|
+
| `install codex --user` | `~/.agents/skills/discord-comm/` |
|
|
93
|
+
|
|
94
|
+
インストール後、エージェントを再起動してスキルを読み込みます。
|
|
95
|
+
|
|
96
|
+
### 6. 動作確認
|
|
97
|
+
|
|
98
|
+
サーバーを起動して接続を確認します:
|
|
73
99
|
|
|
74
100
|
```bash
|
|
75
101
|
discord-bridge start
|
|
76
102
|
```
|
|
77
103
|
|
|
78
|
-
|
|
104
|
+
別のターミナルでヘルスチェック:
|
|
79
105
|
|
|
80
106
|
```bash
|
|
81
107
|
discord-bridge status
|
|
82
108
|
```
|
|
83
109
|
|
|
84
|
-
|
|
110
|
+
`{"status":"ok","bot":"BotName#1234",...}` のようなレスポンスが返れば成功です。
|
|
111
|
+
|
|
112
|
+
## 使い方
|
|
113
|
+
|
|
114
|
+
### サーバーの起動
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
discord-bridge start
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### エージェントでの利用
|
|
85
121
|
|
|
86
|
-
Claude Code で以下のように話しかけてください:
|
|
122
|
+
Claude Code や Codex で以下のように話しかけてください:
|
|
87
123
|
|
|
88
124
|
- 「Discord にテスト通知を送って」 - 通知テスト
|
|
89
125
|
- 「離席する」 - 離席モード(Discord 経由で操作)
|
package/bin/cli.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
|
-
import { dirname, join } from "path";
|
|
4
|
+
import { dirname, join, resolve } from "path";
|
|
5
5
|
import { spawn } from "child_process";
|
|
6
|
-
import { cpSync, existsSync, mkdirSync } from "fs";
|
|
6
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
7
7
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = dirname(__filename);
|
|
@@ -23,24 +23,66 @@ switch (command) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
case "install": {
|
|
26
|
+
const platform = process.argv[3];
|
|
27
|
+
const hasUserFlag = process.argv.includes("--user");
|
|
28
|
+
|
|
29
|
+
if (!platform || !["claude", "codex"].includes(platform)) {
|
|
30
|
+
console.error("Usage: discord-bridge install <claude|codex> [--user]");
|
|
31
|
+
console.error("");
|
|
32
|
+
console.error("Platforms:");
|
|
33
|
+
console.error(" claude Install skill for Claude Code (.claude/skills/)");
|
|
34
|
+
console.error(" codex Install skill for Codex (.agents/skills/)");
|
|
35
|
+
console.error("");
|
|
36
|
+
console.error("Options:");
|
|
37
|
+
console.error(" --user Install to home directory instead of project directory");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
26
41
|
const home = process.env.HOME;
|
|
27
42
|
if (!home) {
|
|
28
43
|
console.error("HOME environment variable is not set");
|
|
29
44
|
process.exit(1);
|
|
30
45
|
}
|
|
31
|
-
|
|
32
|
-
const
|
|
46
|
+
|
|
47
|
+
const skillDirs = {
|
|
48
|
+
claude: ".claude/skills",
|
|
49
|
+
codex: ".agents/skills",
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const base = hasUserFlag ? home : process.cwd();
|
|
53
|
+
const target = join(base, skillDirs[platform], "discord-comm");
|
|
54
|
+
const source = join(packageRoot, "plugin", "skills", "discord-comm");
|
|
33
55
|
|
|
34
56
|
if (!existsSync(source)) {
|
|
35
|
-
console.error("
|
|
57
|
+
console.error("Skill files not found");
|
|
36
58
|
process.exit(1);
|
|
37
59
|
}
|
|
38
60
|
|
|
39
61
|
mkdirSync(target, { recursive: true });
|
|
40
62
|
cpSync(source, target, { recursive: true });
|
|
41
|
-
|
|
63
|
+
|
|
64
|
+
// Replace script path placeholders in SKILL.md
|
|
65
|
+
const skillMdPath = join(target, "SKILL.md");
|
|
66
|
+
if (existsSync(skillMdPath)) {
|
|
67
|
+
const absoluteTarget = resolve(target);
|
|
68
|
+
let content = readFileSync(skillMdPath, "utf-8");
|
|
69
|
+
content = content.replaceAll(
|
|
70
|
+
"$CLAUDE_PLUGIN_ROOT/skills/discord-comm",
|
|
71
|
+
absoluteTarget
|
|
72
|
+
);
|
|
73
|
+
writeFileSync(skillMdPath, content);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const scope = hasUserFlag ? "user" : "project";
|
|
77
|
+
console.log(`Skill installed to ${target}`);
|
|
78
|
+
console.log(` Platform: ${platform}`);
|
|
79
|
+
console.log(` Scope: ${scope}`);
|
|
42
80
|
console.log("");
|
|
43
|
-
|
|
81
|
+
if (platform === "claude") {
|
|
82
|
+
console.log("Restart Claude Code to load the skill.");
|
|
83
|
+
} else {
|
|
84
|
+
console.log("Restart Codex to load the skill.");
|
|
85
|
+
}
|
|
44
86
|
break;
|
|
45
87
|
}
|
|
46
88
|
|
|
@@ -58,13 +100,13 @@ switch (command) {
|
|
|
58
100
|
}
|
|
59
101
|
|
|
60
102
|
default:
|
|
61
|
-
console.log("discord-bridge - Claude Code <-> Discord communication bridge");
|
|
103
|
+
console.log("discord-bridge - Claude Code / Codex <-> Discord communication bridge");
|
|
62
104
|
console.log("");
|
|
63
105
|
console.log("Usage: discord-bridge <command>");
|
|
64
106
|
console.log("");
|
|
65
107
|
console.log("Commands:");
|
|
66
|
-
console.log(" start
|
|
67
|
-
console.log(" install
|
|
68
|
-
console.log(" status
|
|
108
|
+
console.log(" start Start the Discord bridge server");
|
|
109
|
+
console.log(" install <claude|codex> [--user] Install skill for the specified platform");
|
|
110
|
+
console.log(" status Check server health");
|
|
69
111
|
break;
|
|
70
112
|
}
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "discord-bridge",
|
|
3
|
-
"description": "Bidirectional communication bridge between Claude Code and Discord. Send questions, receive instructions, share files, and get progress updates through a dedicated Discord channel.",
|
|
4
|
-
"version": "0.1.0",
|
|
5
|
-
"author": {
|
|
6
|
-
"name": "naichi"
|
|
7
|
-
}
|
|
8
|
-
}
|
package/plugin/README.md
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# Discord Bridge Plugin for Claude Code
|
|
2
|
-
|
|
3
|
-
Claude Code と Discord の双方向通信ブリッジ。スマホから Claude Code を操作できます。
|
|
4
|
-
|
|
5
|
-
## セットアップ
|
|
6
|
-
|
|
7
|
-
このプラグインは `discord-bridge install` コマンドで自動的にインストールされます。
|
|
8
|
-
|
|
9
|
-
詳しいセットアップ手順はリポジトリの README を参照してください:
|
|
10
|
-
https://github.com/naichilab/discord-bridge-server
|
|
11
|
-
|
|
12
|
-
## 使い方
|
|
13
|
-
|
|
14
|
-
Claude Code で以下のように話しかけてください:
|
|
15
|
-
|
|
16
|
-
- 「Discord にテスト通知を送って」 - 通知テスト
|
|
17
|
-
- 「離席する」 - 離席モード(Discord 経由で操作)
|
package/plugin/hooks/hooks.json
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"description": "Discord bridge hooks for forwarding notifications and stop events",
|
|
3
|
-
"hooks": {
|
|
4
|
-
"Notification": [
|
|
5
|
-
{
|
|
6
|
-
"hooks": [
|
|
7
|
-
{
|
|
8
|
-
"type": "command",
|
|
9
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/notify-discord.sh",
|
|
10
|
-
"timeout": 15
|
|
11
|
-
}
|
|
12
|
-
]
|
|
13
|
-
}
|
|
14
|
-
],
|
|
15
|
-
"Stop": [
|
|
16
|
-
{
|
|
17
|
-
"hooks": [
|
|
18
|
-
{
|
|
19
|
-
"type": "command",
|
|
20
|
-
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/stop-hook.sh",
|
|
21
|
-
"timeout": 10
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
}
|
|
25
|
-
]
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
# Read hook input from stdin
|
|
5
|
-
HOOK_INPUT=$(cat)
|
|
6
|
-
|
|
7
|
-
DISCORD_TOKEN="${DISCORD_TOKEN:-}"
|
|
8
|
-
DISCORD_CHANNEL_ID="${DISCORD_CHANNEL_ID:-}"
|
|
9
|
-
|
|
10
|
-
if [[ -z "$DISCORD_TOKEN" ]] || [[ -z "$DISCORD_CHANNEL_ID" ]]; then
|
|
11
|
-
exit 0
|
|
12
|
-
fi
|
|
13
|
-
|
|
14
|
-
# Extract notification message
|
|
15
|
-
NOTIFICATION=$(echo "$HOOK_INPUT" | /usr/bin/python3 -c "
|
|
16
|
-
import sys, json
|
|
17
|
-
try:
|
|
18
|
-
data = json.load(sys.stdin)
|
|
19
|
-
print(data.get('notification', data.get('message', 'Claude Code notification')))
|
|
20
|
-
except:
|
|
21
|
-
print('Claude Code notification')
|
|
22
|
-
" 2>/dev/null || echo "Claude Code notification")
|
|
23
|
-
|
|
24
|
-
# Send via Discord REST API
|
|
25
|
-
curl -s -X POST \
|
|
26
|
-
"https://discord.com/api/v10/channels/${DISCORD_CHANNEL_ID}/messages" \
|
|
27
|
-
-H "Authorization: Bot ${DISCORD_TOKEN}" \
|
|
28
|
-
-H "Content-Type: application/json" \
|
|
29
|
-
-d "$(/usr/bin/python3 -c "
|
|
30
|
-
import json, sys
|
|
31
|
-
msg = sys.argv[1]
|
|
32
|
-
print(json.dumps({'embeds': [{'title': 'Notification', 'description': msg, 'color': 3447003}]}))
|
|
33
|
-
" "$NOTIFICATION")" \
|
|
34
|
-
> /dev/null 2>&1
|
|
35
|
-
|
|
36
|
-
exit 0
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
HOOK_INPUT=$(cat)
|
|
5
|
-
|
|
6
|
-
DISCORD_TOKEN="${DISCORD_TOKEN:-}"
|
|
7
|
-
DISCORD_CHANNEL_ID="${DISCORD_CHANNEL_ID:-}"
|
|
8
|
-
|
|
9
|
-
if [[ -z "$DISCORD_TOKEN" ]] || [[ -z "$DISCORD_CHANNEL_ID" ]]; then
|
|
10
|
-
exit 0
|
|
11
|
-
fi
|
|
12
|
-
|
|
13
|
-
# Extract stop reason
|
|
14
|
-
REASON=$(echo "$HOOK_INPUT" | /usr/bin/python3 -c "
|
|
15
|
-
import sys, json
|
|
16
|
-
try:
|
|
17
|
-
data = json.load(sys.stdin)
|
|
18
|
-
print(data.get('reason', data.get('stopReason', 'Task completed')))
|
|
19
|
-
except:
|
|
20
|
-
print('Task completed')
|
|
21
|
-
" 2>/dev/null || echo "Task completed")
|
|
22
|
-
|
|
23
|
-
# Send stop notification
|
|
24
|
-
curl -s -X POST \
|
|
25
|
-
"https://discord.com/api/v10/channels/${DISCORD_CHANNEL_ID}/messages" \
|
|
26
|
-
-H "Authorization: Bot ${DISCORD_TOKEN}" \
|
|
27
|
-
-H "Content-Type: application/json" \
|
|
28
|
-
-d "$(/usr/bin/python3 -c "
|
|
29
|
-
import json, sys
|
|
30
|
-
msg = sys.argv[1]
|
|
31
|
-
print(json.dumps({'embeds': [{'title': 'Claude Code Stopped', 'description': msg, 'color': 15158332}]}))
|
|
32
|
-
" "$REASON")" \
|
|
33
|
-
> /dev/null 2>&1
|
|
34
|
-
|
|
35
|
-
exit 0
|